mirror of https://gitlab.freedesktop.org/mesa/mesa
236 lines
7.6 KiB
Python
236 lines
7.6 KiB
Python
# Copyright © 2021 Collabora, Ltd.
|
|
# Author: Antonio Caggiano <antonio.caggiano@collabora.com>
|
|
|
|
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
# of this software and associated documentation files (the "Software"), to deal
|
|
# in the Software without restriction, including without limitation the rights
|
|
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
# copies of the Software, and to permit persons to whom the Software is
|
|
# furnished to do so, subject to the following conditions:
|
|
|
|
# The above copyright notice and this permission notice shall be included in
|
|
# all copies or substantial portions of the Software.
|
|
|
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
# THE SOFTWARE.
|
|
|
|
import argparse
|
|
import textwrap
|
|
import os
|
|
|
|
import xml.etree.ElementTree as et
|
|
|
|
|
|
class SourceFile:
|
|
def __init__(self, filename):
|
|
self.file = open(filename, 'w')
|
|
self._indent = 0
|
|
|
|
def write(self, *args):
|
|
code = ' '.join(map(str,args))
|
|
for line in code.splitlines():
|
|
text = ''.rjust(self._indent) + line
|
|
self.file.write(text.rstrip() + "\n")
|
|
|
|
def indent(self, n):
|
|
self._indent += n
|
|
|
|
def outdent(self, n):
|
|
self._indent -= n
|
|
|
|
|
|
class Counter:
|
|
# category Category owning the counter
|
|
# xml XML representation of itself
|
|
def __init__(self, category, xml):
|
|
self.category = category
|
|
self.xml = xml
|
|
self.name = self.xml.get("name")
|
|
self.desc = self.xml.get("description")
|
|
self.units = self.xml.get("units")
|
|
self.offset = int(self.xml.get("offset"))
|
|
self.underscore_name = self.xml.get("counter").lower()
|
|
|
|
|
|
class Category:
|
|
# product Product owning the gategory
|
|
# xml XML representation of itself
|
|
def __init__(self, product, xml):
|
|
self.product = product
|
|
self.xml = xml
|
|
self.name = self.xml.get("name")
|
|
self.underscore_name = self.name.lower().replace(' ', '_')
|
|
|
|
xml_counters = self.xml.findall("event")
|
|
self.counters = []
|
|
for xml_counter in xml_counters:
|
|
self.counters.append(Counter(self, xml_counter))
|
|
|
|
|
|
# Wraps an entire *.xml file.
|
|
class Product:
|
|
def __init__(self, filename):
|
|
self.filename = filename
|
|
self.xml = et.parse(self.filename)
|
|
self.name = self.xml.getroot().get('id')
|
|
self.id = self.name.lower()
|
|
self.categories = []
|
|
|
|
for xml_cat in self.xml.findall(".//category"):
|
|
self.categories.append(Category(self, xml_cat))
|
|
|
|
|
|
def main():
|
|
parser = argparse.ArgumentParser()
|
|
parser.add_argument("--header", help="Header file to write", required=True)
|
|
parser.add_argument("--code", help="C file to write", required=True)
|
|
parser.add_argument("xml_files", nargs='+', help="List of xml metrics files to process")
|
|
|
|
args = parser.parse_args()
|
|
|
|
c = SourceFile(args.code)
|
|
h = SourceFile(args.header)
|
|
|
|
prods = []
|
|
for xml_file in args.xml_files:
|
|
prods.append(Product(xml_file))
|
|
|
|
tab_size = 3
|
|
|
|
copyright = textwrap.dedent("""\
|
|
/* Autogenerated file, DO NOT EDIT manually! generated by {}
|
|
*
|
|
* Copyright © 2021 Arm Limited
|
|
* Copyright © 2021 Collabora Ltd.
|
|
*
|
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
|
* copy of this software and associated documentation files (the "Software"),
|
|
* to deal in the Software without restriction, including without limitation
|
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
* and/or sell copies of the Software, and to permit persons to whom the
|
|
* Software is furnished to do so, subject to the following conditions:
|
|
*
|
|
* The above copyright notice and this permission notice (including the next
|
|
* paragraph) shall be included in all copies or substantial portions of the
|
|
* Software.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
|
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
* DEALINGS IN THE SOFTWARE.
|
|
*/
|
|
|
|
""").format(os.path.basename(__file__))
|
|
|
|
h.write(copyright)
|
|
h.write(textwrap.dedent("""\
|
|
#ifndef PAN_PERF_METRICS_H
|
|
#define PAN_PERF_METRICS_H
|
|
|
|
#include "perf/pan_perf.h"
|
|
|
|
"""))
|
|
|
|
c.write(copyright)
|
|
c.write("#include \"" + os.path.basename(args.header) + "\"")
|
|
c.write(textwrap.dedent("""\
|
|
|
|
#include <util/macros.h>
|
|
"""))
|
|
|
|
for prod in prods:
|
|
c.write(textwrap.dedent("""
|
|
static void UNUSED
|
|
static_asserts_%s(void)
|
|
{
|
|
""" % prod.id))
|
|
c.indent(tab_size)
|
|
|
|
n_categories = len(prod.categories)
|
|
c.write("STATIC_ASSERT(%u <= PAN_PERF_MAX_CATEGORIES);" % n_categories)
|
|
n_counters = 0
|
|
for category in prod.categories:
|
|
category_counters_count = len(category.counters)
|
|
c.write("STATIC_ASSERT(%u <= PAN_PERF_MAX_COUNTERS);" % category_counters_count)
|
|
n_counters += category_counters_count
|
|
|
|
c.outdent(tab_size)
|
|
c.write("}\n")
|
|
|
|
|
|
current_struct_name = "panfrost_perf_config_%s" % prod.id
|
|
c.write("\nconst struct panfrost_perf_config %s = {" % current_struct_name)
|
|
c.indent(tab_size)
|
|
|
|
c.write(".name = \"%s\"," % prod.name)
|
|
c.write(".n_categories = %u," % len(prod.categories))
|
|
|
|
c.write(".categories = {")
|
|
c.indent(tab_size)
|
|
|
|
counter_id = 0
|
|
|
|
for i in range(0, len(prod.categories)):
|
|
category = prod.categories[i]
|
|
|
|
c.write("{")
|
|
c.indent(tab_size)
|
|
c.write(".name = \"%s\"," % (category.name))
|
|
c.write(".n_counters = %u," % (len(category.counters)))
|
|
c.write(".counters = {")
|
|
c.indent(tab_size)
|
|
|
|
for j in range(0, len(category.counters)):
|
|
counter = category.counters[j]
|
|
|
|
assert counter_id < n_counters
|
|
c.write("{")
|
|
c.indent(tab_size)
|
|
|
|
c.write(".name = \"%s\"," % (counter.name))
|
|
c.write(".desc = \"%s\"," % (counter.desc.replace("\\", "\\\\")))
|
|
c.write(".symbol_name = \"%s\"," % (counter.underscore_name))
|
|
c.write(".units = PAN_PERF_COUNTER_UNITS_%s," % (counter.units.upper()))
|
|
c.write(".offset = %u," % (counter.offset))
|
|
c.write(".category_index = %u," % i)
|
|
|
|
c.outdent(tab_size)
|
|
c.write("}, // counter")
|
|
|
|
counter_id += 1
|
|
|
|
c.outdent(tab_size)
|
|
c.write("}, // counters")
|
|
|
|
c.outdent(tab_size)
|
|
c.write("}, // category")
|
|
|
|
c.outdent(tab_size)
|
|
c.write("}, // categories")
|
|
|
|
c.outdent(tab_size)
|
|
c.write("}; // %s\n" % current_struct_name)
|
|
|
|
h.write("extern const struct panfrost_perf_config * panfrost_perf_configs[%u];\n" % len(prods))
|
|
|
|
c.write("\nconst struct panfrost_perf_config * panfrost_perf_configs[] = {")
|
|
c.indent(tab_size)
|
|
for prod in prods:
|
|
c.write("&panfrost_perf_config_%s," % prod.id)
|
|
c.outdent(tab_size)
|
|
c.write("};")
|
|
|
|
h.write("\n#endif // PAN_PERF_METRICS_H")
|
|
|
|
|
|
if __name__ == '__main__':
|
|
main()
|