1bf215546Sopenharmony_ci# Copyright © 2021 Collabora, Ltd.
2bf215546Sopenharmony_ci# Author: Antonio Caggiano <antonio.caggiano@collabora.com>
3bf215546Sopenharmony_ci
4bf215546Sopenharmony_ci# Permission is hereby granted, free of charge, to any person obtaining a copy
5bf215546Sopenharmony_ci# of this software and associated documentation files (the "Software"), to deal
6bf215546Sopenharmony_ci# in the Software without restriction, including without limitation the rights
7bf215546Sopenharmony_ci# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8bf215546Sopenharmony_ci# copies of the Software, and to permit persons to whom the Software is
9bf215546Sopenharmony_ci# furnished to do so, subject to the following conditions:
10bf215546Sopenharmony_ci
11bf215546Sopenharmony_ci# The above copyright notice and this permission notice shall be included in
12bf215546Sopenharmony_ci# all copies or substantial portions of the Software.
13bf215546Sopenharmony_ci
14bf215546Sopenharmony_ci# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15bf215546Sopenharmony_ci# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16bf215546Sopenharmony_ci# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17bf215546Sopenharmony_ci# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18bf215546Sopenharmony_ci# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19bf215546Sopenharmony_ci# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20bf215546Sopenharmony_ci# THE SOFTWARE.
21bf215546Sopenharmony_ci
22bf215546Sopenharmony_ciimport argparse
23bf215546Sopenharmony_ciimport textwrap
24bf215546Sopenharmony_ciimport os
25bf215546Sopenharmony_ci
26bf215546Sopenharmony_ciimport xml.etree.ElementTree as et
27bf215546Sopenharmony_ci
28bf215546Sopenharmony_ci
29bf215546Sopenharmony_ciclass SourceFile:
30bf215546Sopenharmony_ci   def __init__(self, filename):
31bf215546Sopenharmony_ci      self.file = open(filename, 'w')
32bf215546Sopenharmony_ci      self._indent = 0
33bf215546Sopenharmony_ci
34bf215546Sopenharmony_ci   def write(self, *args):
35bf215546Sopenharmony_ci      code = ' '.join(map(str,args))
36bf215546Sopenharmony_ci      for line in code.splitlines():
37bf215546Sopenharmony_ci         text = ''.rjust(self._indent) + line
38bf215546Sopenharmony_ci         self.file.write(text.rstrip() + "\n")
39bf215546Sopenharmony_ci
40bf215546Sopenharmony_ci   def indent(self, n):
41bf215546Sopenharmony_ci      self._indent += n
42bf215546Sopenharmony_ci
43bf215546Sopenharmony_ci   def outdent(self, n):
44bf215546Sopenharmony_ci      self._indent -= n
45bf215546Sopenharmony_ci
46bf215546Sopenharmony_ci
47bf215546Sopenharmony_ciclass Counter:
48bf215546Sopenharmony_ci   # category Category owning the counter
49bf215546Sopenharmony_ci   # xml XML representation of itself
50bf215546Sopenharmony_ci   def __init__(self, category, xml):
51bf215546Sopenharmony_ci      self.category = category
52bf215546Sopenharmony_ci      self.xml = xml
53bf215546Sopenharmony_ci      self.name = self.xml.get("name")
54bf215546Sopenharmony_ci      self.desc = self.xml.get("description")
55bf215546Sopenharmony_ci      self.units = self.xml.get("units")
56bf215546Sopenharmony_ci      self.offset = int(self.xml.get("offset"))
57bf215546Sopenharmony_ci      self.underscore_name = self.xml.get("counter").lower()
58bf215546Sopenharmony_ci
59bf215546Sopenharmony_ci
60bf215546Sopenharmony_ciclass Category:
61bf215546Sopenharmony_ci   # product Product owning the gategory
62bf215546Sopenharmony_ci   # xml XML representation of itself
63bf215546Sopenharmony_ci   def __init__(self, product, xml):
64bf215546Sopenharmony_ci      self.product = product
65bf215546Sopenharmony_ci      self.xml = xml
66bf215546Sopenharmony_ci      self.name = self.xml.get("name")
67bf215546Sopenharmony_ci      self.underscore_name = self.name.lower().replace(' ', '_')
68bf215546Sopenharmony_ci
69bf215546Sopenharmony_ci      xml_counters = self.xml.findall("event")
70bf215546Sopenharmony_ci      self.counters = []
71bf215546Sopenharmony_ci      for xml_counter in xml_counters:
72bf215546Sopenharmony_ci         self.counters.append(Counter(self, xml_counter))
73bf215546Sopenharmony_ci
74bf215546Sopenharmony_ci
75bf215546Sopenharmony_ci# Wraps an entire *.xml file.
76bf215546Sopenharmony_ciclass Product:
77bf215546Sopenharmony_ci   def __init__(self, filename):
78bf215546Sopenharmony_ci      self.filename = filename
79bf215546Sopenharmony_ci      self.xml = et.parse(self.filename)
80bf215546Sopenharmony_ci      self.name = self.xml.getroot().get('id')
81bf215546Sopenharmony_ci      self.id = self.name.lower()
82bf215546Sopenharmony_ci      self.categories = []
83bf215546Sopenharmony_ci
84bf215546Sopenharmony_ci      for xml_cat in self.xml.findall(".//category"):
85bf215546Sopenharmony_ci         self.categories.append(Category(self, xml_cat))
86bf215546Sopenharmony_ci
87bf215546Sopenharmony_ci
88bf215546Sopenharmony_cidef main():
89bf215546Sopenharmony_ci   parser = argparse.ArgumentParser()
90bf215546Sopenharmony_ci   parser.add_argument("--header", help="Header file to write", required=True)
91bf215546Sopenharmony_ci   parser.add_argument("--code", help="C file to write", required=True)
92bf215546Sopenharmony_ci   parser.add_argument("xml_files", nargs='+', help="List of xml metrics files to process")
93bf215546Sopenharmony_ci
94bf215546Sopenharmony_ci   args = parser.parse_args()
95bf215546Sopenharmony_ci
96bf215546Sopenharmony_ci   c = SourceFile(args.code)
97bf215546Sopenharmony_ci   h = SourceFile(args.header)
98bf215546Sopenharmony_ci
99bf215546Sopenharmony_ci   prods = []
100bf215546Sopenharmony_ci   for xml_file in args.xml_files:
101bf215546Sopenharmony_ci      prods.append(Product(xml_file))
102bf215546Sopenharmony_ci
103bf215546Sopenharmony_ci   tab_size = 3
104bf215546Sopenharmony_ci
105bf215546Sopenharmony_ci   copyright = textwrap.dedent("""\
106bf215546Sopenharmony_ci      /* Autogenerated file, DO NOT EDIT manually! generated by {}
107bf215546Sopenharmony_ci       *
108bf215546Sopenharmony_ci       * Copyright © 2021 Arm Limited
109bf215546Sopenharmony_ci       * Copyright © 2021 Collabora Ltd.
110bf215546Sopenharmony_ci       *
111bf215546Sopenharmony_ci       * Permission is hereby granted, free of charge, to any person obtaining a
112bf215546Sopenharmony_ci       * copy of this software and associated documentation files (the "Software"),
113bf215546Sopenharmony_ci       * to deal in the Software without restriction, including without limitation
114bf215546Sopenharmony_ci       * the rights to use, copy, modify, merge, publish, distribute, sublicense,
115bf215546Sopenharmony_ci       * and/or sell copies of the Software, and to permit persons to whom the
116bf215546Sopenharmony_ci       * Software is furnished to do so, subject to the following conditions:
117bf215546Sopenharmony_ci       *
118bf215546Sopenharmony_ci       * The above copyright notice and this permission notice (including the next
119bf215546Sopenharmony_ci       * paragraph) shall be included in all copies or substantial portions of the
120bf215546Sopenharmony_ci       * Software.
121bf215546Sopenharmony_ci       *
122bf215546Sopenharmony_ci       * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
123bf215546Sopenharmony_ci       * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
124bf215546Sopenharmony_ci       * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
125bf215546Sopenharmony_ci       * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
126bf215546Sopenharmony_ci       * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
127bf215546Sopenharmony_ci       * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
128bf215546Sopenharmony_ci       * DEALINGS IN THE SOFTWARE.
129bf215546Sopenharmony_ci       */
130bf215546Sopenharmony_ci
131bf215546Sopenharmony_ci      """).format(os.path.basename(__file__))
132bf215546Sopenharmony_ci
133bf215546Sopenharmony_ci   h.write(copyright)
134bf215546Sopenharmony_ci   h.write(textwrap.dedent("""\
135bf215546Sopenharmony_ci      #ifndef PAN_PERF_METRICS_H
136bf215546Sopenharmony_ci      #define PAN_PERF_METRICS_H
137bf215546Sopenharmony_ci
138bf215546Sopenharmony_ci      #include "perf/pan_perf.h"
139bf215546Sopenharmony_ci
140bf215546Sopenharmony_ci      """))
141bf215546Sopenharmony_ci
142bf215546Sopenharmony_ci   c.write(copyright)
143bf215546Sopenharmony_ci   c.write("#include \"" + os.path.basename(args.header) + "\"")
144bf215546Sopenharmony_ci   c.write(textwrap.dedent("""\
145bf215546Sopenharmony_ci
146bf215546Sopenharmony_ci      #include <util/macros.h>
147bf215546Sopenharmony_ci      """))
148bf215546Sopenharmony_ci
149bf215546Sopenharmony_ci   for prod in prods:
150bf215546Sopenharmony_ci      c.write(textwrap.dedent("""
151bf215546Sopenharmony_ci      static void UNUSED
152bf215546Sopenharmony_ci      static_asserts_%s(void)
153bf215546Sopenharmony_ci      {
154bf215546Sopenharmony_ci      """ % prod.id))
155bf215546Sopenharmony_ci      c.indent(tab_size)
156bf215546Sopenharmony_ci
157bf215546Sopenharmony_ci      n_categories = len(prod.categories)
158bf215546Sopenharmony_ci      c.write("STATIC_ASSERT(%u <= PAN_PERF_MAX_CATEGORIES);" % n_categories)
159bf215546Sopenharmony_ci      n_counters = 0
160bf215546Sopenharmony_ci      for category in prod.categories:
161bf215546Sopenharmony_ci         category_counters_count = len(category.counters)
162bf215546Sopenharmony_ci         c.write("STATIC_ASSERT(%u <= PAN_PERF_MAX_COUNTERS);" % category_counters_count)
163bf215546Sopenharmony_ci         n_counters += category_counters_count
164bf215546Sopenharmony_ci
165bf215546Sopenharmony_ci      c.outdent(tab_size)
166bf215546Sopenharmony_ci      c.write("}\n")
167bf215546Sopenharmony_ci
168bf215546Sopenharmony_ci
169bf215546Sopenharmony_ci      current_struct_name = "panfrost_perf_config_%s" % prod.id
170bf215546Sopenharmony_ci      c.write("\nconst struct panfrost_perf_config %s = {" % current_struct_name)
171bf215546Sopenharmony_ci      c.indent(tab_size)
172bf215546Sopenharmony_ci
173bf215546Sopenharmony_ci      c.write(".name = \"%s\"," % prod.name)
174bf215546Sopenharmony_ci      c.write(".n_categories = %u," % len(prod.categories))
175bf215546Sopenharmony_ci
176bf215546Sopenharmony_ci      c.write(".categories = {")
177bf215546Sopenharmony_ci      c.indent(tab_size)
178bf215546Sopenharmony_ci
179bf215546Sopenharmony_ci      counter_id = 0
180bf215546Sopenharmony_ci
181bf215546Sopenharmony_ci      for i in range(0, len(prod.categories)):
182bf215546Sopenharmony_ci         category = prod.categories[i]
183bf215546Sopenharmony_ci
184bf215546Sopenharmony_ci         c.write("{")
185bf215546Sopenharmony_ci         c.indent(tab_size)
186bf215546Sopenharmony_ci         c.write(".name = \"%s\"," % (category.name))
187bf215546Sopenharmony_ci         c.write(".n_counters = %u," % (len(category.counters)))
188bf215546Sopenharmony_ci         c.write(".counters = {")
189bf215546Sopenharmony_ci         c.indent(tab_size)
190bf215546Sopenharmony_ci
191bf215546Sopenharmony_ci         for j in range(0, len(category.counters)):
192bf215546Sopenharmony_ci            counter = category.counters[j]
193bf215546Sopenharmony_ci
194bf215546Sopenharmony_ci            assert counter_id < n_counters
195bf215546Sopenharmony_ci            c.write("{")
196bf215546Sopenharmony_ci            c.indent(tab_size)
197bf215546Sopenharmony_ci
198bf215546Sopenharmony_ci            c.write(".name = \"%s\"," % (counter.name))
199bf215546Sopenharmony_ci            c.write(".desc = \"%s\"," % (counter.desc.replace("\\", "\\\\")))
200bf215546Sopenharmony_ci            c.write(".symbol_name = \"%s\"," % (counter.underscore_name))
201bf215546Sopenharmony_ci            c.write(".units = PAN_PERF_COUNTER_UNITS_%s," % (counter.units.upper()))
202bf215546Sopenharmony_ci            c.write(".offset = %u," % (counter.offset))
203bf215546Sopenharmony_ci            c.write(".category_index = %u," % i)
204bf215546Sopenharmony_ci
205bf215546Sopenharmony_ci            c.outdent(tab_size)
206bf215546Sopenharmony_ci            c.write("}, // counter")
207bf215546Sopenharmony_ci
208bf215546Sopenharmony_ci            counter_id += 1
209bf215546Sopenharmony_ci
210bf215546Sopenharmony_ci         c.outdent(tab_size)
211bf215546Sopenharmony_ci         c.write("}, // counters")
212bf215546Sopenharmony_ci
213bf215546Sopenharmony_ci         c.outdent(tab_size)
214bf215546Sopenharmony_ci         c.write("}, // category")
215bf215546Sopenharmony_ci
216bf215546Sopenharmony_ci      c.outdent(tab_size)
217bf215546Sopenharmony_ci      c.write("}, // categories")
218bf215546Sopenharmony_ci
219bf215546Sopenharmony_ci      c.outdent(tab_size)
220bf215546Sopenharmony_ci      c.write("}; // %s\n" % current_struct_name)
221bf215546Sopenharmony_ci
222bf215546Sopenharmony_ci   h.write("extern const struct panfrost_perf_config * panfrost_perf_configs[%u];\n" % len(prods))
223bf215546Sopenharmony_ci
224bf215546Sopenharmony_ci   c.write("\nconst struct panfrost_perf_config * panfrost_perf_configs[] = {")
225bf215546Sopenharmony_ci   c.indent(tab_size)
226bf215546Sopenharmony_ci   for prod in prods:
227bf215546Sopenharmony_ci       c.write("&panfrost_perf_config_%s," % prod.id)
228bf215546Sopenharmony_ci   c.outdent(tab_size)
229bf215546Sopenharmony_ci   c.write("};")
230bf215546Sopenharmony_ci
231bf215546Sopenharmony_ci   h.write("\n#endif // PAN_PERF_METRICS_H")
232bf215546Sopenharmony_ci
233bf215546Sopenharmony_ci
234bf215546Sopenharmony_ciif __name__ == '__main__':
235bf215546Sopenharmony_ci   main()
236