17ec681f3Smrg# Copyright © 2021 Collabora, Ltd.
27ec681f3Smrg# Author: Antonio Caggiano <antonio.caggiano@collabora.com>
37ec681f3Smrg
47ec681f3Smrg# Permission is hereby granted, free of charge, to any person obtaining a copy
57ec681f3Smrg# of this software and associated documentation files (the "Software"), to deal
67ec681f3Smrg# in the Software without restriction, including without limitation the rights
77ec681f3Smrg# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
87ec681f3Smrg# copies of the Software, and to permit persons to whom the Software is
97ec681f3Smrg# furnished to do so, subject to the following conditions:
107ec681f3Smrg
117ec681f3Smrg# The above copyright notice and this permission notice shall be included in
127ec681f3Smrg# all copies or substantial portions of the Software.
137ec681f3Smrg
147ec681f3Smrg# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
157ec681f3Smrg# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
167ec681f3Smrg# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
177ec681f3Smrg# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
187ec681f3Smrg# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
197ec681f3Smrg# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
207ec681f3Smrg# THE SOFTWARE.
217ec681f3Smrg
227ec681f3Smrgimport argparse
237ec681f3Smrgimport textwrap
247ec681f3Smrgimport os
257ec681f3Smrg
267ec681f3Smrgimport xml.etree.ElementTree as et
277ec681f3Smrg
287ec681f3Smrg
297ec681f3Smrgclass SourceFile:
307ec681f3Smrg   def __init__(self, filename):
317ec681f3Smrg      self.file = open(filename, 'w')
327ec681f3Smrg      self._indent = 0
337ec681f3Smrg
347ec681f3Smrg   def write(self, *args):
357ec681f3Smrg      code = ' '.join(map(str,args))
367ec681f3Smrg      for line in code.splitlines():
377ec681f3Smrg         text = ''.rjust(self._indent) + line
387ec681f3Smrg         self.file.write(text.rstrip() + "\n")
397ec681f3Smrg
407ec681f3Smrg   def indent(self, n):
417ec681f3Smrg      self._indent += n
427ec681f3Smrg
437ec681f3Smrg   def outdent(self, n):
447ec681f3Smrg      self._indent -= n
457ec681f3Smrg
467ec681f3Smrg
477ec681f3Smrgclass Counter:
487ec681f3Smrg   # category Category owning the counter
497ec681f3Smrg   # xml XML representation of itself
507ec681f3Smrg   def __init__(self, category, xml):
517ec681f3Smrg      self.category = category
527ec681f3Smrg      self.xml = xml
537ec681f3Smrg      self.name = self.xml.get("name")
547ec681f3Smrg      self.desc = self.xml.get("description")
557ec681f3Smrg      self.units = self.xml.get("units")
567ec681f3Smrg      self.offset = int(self.xml.get("offset"))
577ec681f3Smrg      self.underscore_name = self.xml.get("counter").lower()
587ec681f3Smrg
597ec681f3Smrg
607ec681f3Smrgclass Category:
617ec681f3Smrg   # product Product owning the gategory
627ec681f3Smrg   # xml XML representation of itself
637ec681f3Smrg   def __init__(self, product, xml):
647ec681f3Smrg      self.product = product
657ec681f3Smrg      self.xml = xml
667ec681f3Smrg      self.name = self.xml.get("name")
677ec681f3Smrg      self.underscore_name = self.name.lower().replace(' ', '_')
687ec681f3Smrg
697ec681f3Smrg      xml_counters = self.xml.findall("event")
707ec681f3Smrg      self.counters = []
717ec681f3Smrg      for xml_counter in xml_counters:
727ec681f3Smrg         self.counters.append(Counter(self, xml_counter))
737ec681f3Smrg
747ec681f3Smrg
757ec681f3Smrg# Wraps an entire *.xml file.
767ec681f3Smrgclass Product:
777ec681f3Smrg   def __init__(self, filename):
787ec681f3Smrg      self.filename = filename
797ec681f3Smrg      self.xml = et.parse(self.filename)
807ec681f3Smrg      self.id = self.xml.getroot().get('id').lower()
817ec681f3Smrg      self.categories = []
827ec681f3Smrg
837ec681f3Smrg      for xml_cat in self.xml.findall(".//category"):
847ec681f3Smrg         self.categories.append(Category(self, xml_cat))
857ec681f3Smrg
867ec681f3Smrg
877ec681f3Smrgdef main():
887ec681f3Smrg   parser = argparse.ArgumentParser()
897ec681f3Smrg   parser.add_argument("--header", help="Header file to write", required=True)
907ec681f3Smrg   parser.add_argument("--code", help="C file to write", required=True)
917ec681f3Smrg   parser.add_argument("xml_files", nargs='+', help="List of xml metrics files to process")
927ec681f3Smrg
937ec681f3Smrg   args = parser.parse_args()
947ec681f3Smrg
957ec681f3Smrg   c = SourceFile(args.code)
967ec681f3Smrg   h = SourceFile(args.header)
977ec681f3Smrg
987ec681f3Smrg   prods = []
997ec681f3Smrg   for xml_file in args.xml_files:
1007ec681f3Smrg      prods.append(Product(xml_file))
1017ec681f3Smrg
1027ec681f3Smrg   tab_size = 3
1037ec681f3Smrg
1047ec681f3Smrg   copyright = textwrap.dedent("""\
1057ec681f3Smrg      /* Autogenerated file, DO NOT EDIT manually! generated by {}
1067ec681f3Smrg       *
1077ec681f3Smrg       * Copyright © 2021 Arm Limited
1087ec681f3Smrg       * Copyright © 2021 Collabora Ltd.
1097ec681f3Smrg       *
1107ec681f3Smrg       * Permission is hereby granted, free of charge, to any person obtaining a
1117ec681f3Smrg       * copy of this software and associated documentation files (the "Software"),
1127ec681f3Smrg       * to deal in the Software without restriction, including without limitation
1137ec681f3Smrg       * the rights to use, copy, modify, merge, publish, distribute, sublicense,
1147ec681f3Smrg       * and/or sell copies of the Software, and to permit persons to whom the
1157ec681f3Smrg       * Software is furnished to do so, subject to the following conditions:
1167ec681f3Smrg       *
1177ec681f3Smrg       * The above copyright notice and this permission notice (including the next
1187ec681f3Smrg       * paragraph) shall be included in all copies or substantial portions of the
1197ec681f3Smrg       * Software.
1207ec681f3Smrg       *
1217ec681f3Smrg       * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1227ec681f3Smrg       * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1237ec681f3Smrg       * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
1247ec681f3Smrg       * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
1257ec681f3Smrg       * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
1267ec681f3Smrg       * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
1277ec681f3Smrg       * DEALINGS IN THE SOFTWARE.
1287ec681f3Smrg       */
1297ec681f3Smrg
1307ec681f3Smrg      """).format(os.path.basename(__file__))
1317ec681f3Smrg
1327ec681f3Smrg   h.write(copyright)
1337ec681f3Smrg   h.write(textwrap.dedent("""\
1347ec681f3Smrg      #ifndef PAN_PERF_METRICS_H
1357ec681f3Smrg      #define PAN_PERF_METRICS_H
1367ec681f3Smrg
1377ec681f3Smrg      #include "perf/pan_perf.h"
1387ec681f3Smrg
1397ec681f3Smrg      """))
1407ec681f3Smrg
1417ec681f3Smrg   c.write(copyright)
1427ec681f3Smrg   c.write("#include \"" + os.path.basename(args.header) + "\"")
1437ec681f3Smrg   c.write(textwrap.dedent("""\
1447ec681f3Smrg
1457ec681f3Smrg      #include <util/macros.h>
1467ec681f3Smrg      """))
1477ec681f3Smrg
1487ec681f3Smrg   for prod in prods:
1497ec681f3Smrg      h.write("extern const struct panfrost_perf_config panfrost_perf_config_%s;\n" % prod.id)
1507ec681f3Smrg
1517ec681f3Smrg   for prod in prods:
1527ec681f3Smrg      c.write(textwrap.dedent("""
1537ec681f3Smrg      static void UNUSED
1547ec681f3Smrg      static_asserts_%s(void)
1557ec681f3Smrg      {
1567ec681f3Smrg      """ % prod.id))
1577ec681f3Smrg      c.indent(tab_size)
1587ec681f3Smrg
1597ec681f3Smrg      n_categories = len(prod.categories)
1607ec681f3Smrg      c.write("STATIC_ASSERT(%u <= PAN_PERF_MAX_CATEGORIES);" % n_categories)
1617ec681f3Smrg      n_counters = 0
1627ec681f3Smrg      for category in prod.categories:
1637ec681f3Smrg         category_counters_count = len(category.counters)
1647ec681f3Smrg         c.write("STATIC_ASSERT(%u <= PAN_PERF_MAX_COUNTERS);" % category_counters_count)
1657ec681f3Smrg         n_counters += category_counters_count
1667ec681f3Smrg
1677ec681f3Smrg      c.outdent(tab_size)
1687ec681f3Smrg      c.write("}\n")
1697ec681f3Smrg
1707ec681f3Smrg
1717ec681f3Smrg      current_struct_name = "panfrost_perf_config_%s" % prod.id
1727ec681f3Smrg      c.write("\nconst struct panfrost_perf_config %s = {" % current_struct_name)
1737ec681f3Smrg      c.indent(tab_size)
1747ec681f3Smrg
1757ec681f3Smrg      c.write(".n_categories = %u," % len(prod.categories))
1767ec681f3Smrg
1777ec681f3Smrg      c.write(".categories = {")
1787ec681f3Smrg      c.indent(tab_size)
1797ec681f3Smrg
1807ec681f3Smrg      counter_id = 0
1817ec681f3Smrg
1827ec681f3Smrg      for i in range(0, len(prod.categories)):
1837ec681f3Smrg         category = prod.categories[i]
1847ec681f3Smrg
1857ec681f3Smrg         c.write("{")
1867ec681f3Smrg         c.indent(tab_size)
1877ec681f3Smrg         c.write(".name = \"%s\"," % (category.name))
1887ec681f3Smrg         c.write(".n_counters = %u," % (len(category.counters)))
1897ec681f3Smrg         c.write(".counters = {")
1907ec681f3Smrg         c.indent(tab_size)
1917ec681f3Smrg
1927ec681f3Smrg         for j in range(0, len(category.counters)):
1937ec681f3Smrg            counter = category.counters[j]
1947ec681f3Smrg
1957ec681f3Smrg            assert counter_id < n_counters
1967ec681f3Smrg            c.write("{")
1977ec681f3Smrg            c.indent(tab_size)
1987ec681f3Smrg
1997ec681f3Smrg            c.write(".name = \"%s\"," % (counter.name))
2007ec681f3Smrg            c.write(".desc = \"%s\"," % (counter.desc.replace("\\", "\\\\")))
2017ec681f3Smrg            c.write(".symbol_name = \"%s\"," % (counter.underscore_name))
2027ec681f3Smrg            c.write(".units = PAN_PERF_COUNTER_UNITS_%s," % (counter.units.upper()))
2037ec681f3Smrg            c.write(".offset = %u," % (counter.offset))
2047ec681f3Smrg            c.write(".category = &%s.categories[%u]," % (current_struct_name, i))
2057ec681f3Smrg
2067ec681f3Smrg            c.outdent(tab_size)
2077ec681f3Smrg            c.write("}, // counter")
2087ec681f3Smrg
2097ec681f3Smrg            counter_id += 1
2107ec681f3Smrg
2117ec681f3Smrg         c.outdent(tab_size)
2127ec681f3Smrg         c.write("}, // counters")
2137ec681f3Smrg
2147ec681f3Smrg         c.outdent(tab_size)
2157ec681f3Smrg         c.write("}, // category")
2167ec681f3Smrg
2177ec681f3Smrg      c.outdent(tab_size)
2187ec681f3Smrg      c.write("}, // categories")
2197ec681f3Smrg
2207ec681f3Smrg      c.outdent(tab_size)
2217ec681f3Smrg      c.write("}; // %s\n" % current_struct_name)
2227ec681f3Smrg
2237ec681f3Smrg   h.write("\n#endif // PAN_PERF_METRICS_H")
2247ec681f3Smrg
2257ec681f3Smrg
2267ec681f3Smrgif __name__ == '__main__':
2277ec681f3Smrg   main()
228