mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-05-06 20:18:12 +02:00
freedreno/registers: Generate perfcntr tables
Use the register xml in combination with the json describing the different perfcntr groups to generate perfcntr tables. Signed-off-by: Rob Clark <rob.clark@oss.qualcomm.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/40522>
This commit is contained in:
parent
2b81514c3e
commit
546d4daa6d
2 changed files with 160 additions and 0 deletions
|
|
@ -17,6 +17,13 @@ xml_reg_files = [
|
|||
'a8xx_perfcntrs.xml',
|
||||
]
|
||||
|
||||
perfcntr_files = [
|
||||
[ 'a2xx.xml', 'a2xx_perfcntrs.json' ],
|
||||
[ 'a5xx.xml', 'a5xx_perfcntrs.json' ],
|
||||
[ 'a6xx.xml', 'a6xx_perfcntrs.json' ],
|
||||
[ 'a6xx.xml', 'a7xx_perfcntrs.json' ],
|
||||
]
|
||||
|
||||
xml_files = xml_reg_files
|
||||
xml_files += [
|
||||
'a6xx_gmu.xml',
|
||||
|
|
@ -82,6 +89,17 @@ foreach f : xml_files
|
|||
endif
|
||||
endforeach
|
||||
|
||||
foreach e : perfcntr_files
|
||||
_name = e[1] + '.h'
|
||||
freedreno_xml_header_files += custom_target(
|
||||
_name,
|
||||
input: [gen_header_py, e[0], e[1], freedreno_schema, freedreno_copyright],
|
||||
output: _name,
|
||||
command: [prog_python, '@INPUT0@', '--validate', '--rnn', rnn_src_path, '--xml', '@INPUT1@', 'perfcntrs', '--json', '@INPUT2@'],
|
||||
capture: true,
|
||||
)
|
||||
endforeach
|
||||
|
||||
freedreno_xml_header_files += custom_target(
|
||||
'a6xx-pack.xml.h',
|
||||
input: [gen_header_py, 'a6xx.xml', freedreno_schema, freedreno_copyright],
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ import collections
|
|||
import argparse
|
||||
import time
|
||||
import datetime
|
||||
import json
|
||||
|
||||
|
||||
class Error(Exception):
|
||||
|
|
@ -32,6 +33,11 @@ class Enum(object):
|
|||
def names(self):
|
||||
return [n for (n, value) in self.values]
|
||||
|
||||
def value(self, name):
|
||||
for (n, v) in self.values:
|
||||
if n == name:
|
||||
return v
|
||||
|
||||
def dump(self, has_variants):
|
||||
use_hex = False
|
||||
for (name, value) in self.values:
|
||||
|
|
@ -1017,6 +1023,138 @@ def dump_c_pack_structs(args):
|
|||
dump_c(args, guard, lambda p: p.dump_structs())
|
||||
|
||||
|
||||
def dump_perfcntrs(args):
|
||||
p = Parser()
|
||||
|
||||
try:
|
||||
p.parse(args.rnn, args.xml, args.validate)
|
||||
except Error as e:
|
||||
print(e, file=sys.stderr)
|
||||
exit(1)
|
||||
|
||||
perfcntrs = json.load(open(args.json, "r", encoding="utf-8"))
|
||||
|
||||
chip_type = p.enums['chip']
|
||||
chip = perfcntrs['chip']
|
||||
if not chip_type.has_name(chip):
|
||||
raise Error("Invalid chip: " + chip)
|
||||
|
||||
groups = perfcntrs['groups']
|
||||
|
||||
guard = "__" + chip + "_PERFCNTRS_"
|
||||
print("#ifndef %s\n#define %s\n" % (guard, guard))
|
||||
print("/* Autogenerated file, DO NOT EDIT manually! */")
|
||||
print()
|
||||
print("#ifdef __KERNEL__")
|
||||
print("#include \"msm_perfcntr.h\"")
|
||||
print("#endif")
|
||||
print()
|
||||
|
||||
def has_variant(variant):
|
||||
if variant is None:
|
||||
return True
|
||||
if "-" in variant:
|
||||
start = chip_type.value(variant[:variant.index("-")])
|
||||
end = chip_type.value(variant[variant.index("-") + 1:])
|
||||
chipn = chip_type.value(chip)
|
||||
|
||||
return (start is None or chipn >= start) and (end is None or chipn <= end)
|
||||
return chip == variant
|
||||
|
||||
# Split out arrays and regs for later access:
|
||||
arrays = {}
|
||||
regs = {}
|
||||
for e in p.file:
|
||||
if isinstance(e, Array) and has_variant(e.variant):
|
||||
arrays[e.local_name] = e
|
||||
if isinstance(e, Reg):
|
||||
regs[e.name] = e
|
||||
|
||||
# For variant regs, overwrite 'regs' entries with correct variant:
|
||||
for regname in p.variant_regs:
|
||||
for (variant, reg) in p.variant_regs[regname].items():
|
||||
if has_variant(variant):
|
||||
regs[regname] = reg
|
||||
break
|
||||
|
||||
for group in groups:
|
||||
name = group['name']
|
||||
name_low = name.lower()
|
||||
num = group['num']
|
||||
countable_type_name = group['countable_type']
|
||||
|
||||
if not countable_type_name in p.enums:
|
||||
raise Error("Invalid type: " + countable_type_name)
|
||||
|
||||
countable_type = p.enums[countable_type_name]
|
||||
|
||||
print("#ifndef __KERNEL__")
|
||||
print("static const struct fd_perfcntr_countable " + name_low + "_countables[] = {")
|
||||
for (name, value) in countable_type.values:
|
||||
# if the countable is prefixed with the chip, strip that:
|
||||
# (note: avoid py3.9 dependency for kernel)
|
||||
if name.startswith(chip + "_"):
|
||||
name = name[len(chip)+1:]
|
||||
print(" { \"" + name + "\", " + str(value) + " },")
|
||||
print("};")
|
||||
print("#endif")
|
||||
|
||||
print("static const struct fd_perfcntr_counter " + name_low + "_counters[] = {")
|
||||
for i in range(0, num):
|
||||
if "reserved" in group and i in group["reserved"]:
|
||||
continue
|
||||
def get_reg(name):
|
||||
# if reg has {} pattern, expand that first:
|
||||
name = name.format(i)
|
||||
|
||||
if name in arrays:
|
||||
arr = arrays[name]
|
||||
return arr.offset + (i * arr.stride)
|
||||
|
||||
if not name in regs:
|
||||
raise Error("Invalid reg: " + name)
|
||||
|
||||
reg = regs[name]
|
||||
return reg.offset
|
||||
|
||||
def get_counter():
|
||||
# if the counter is <reg64> just a single "counter" value
|
||||
# should be specified in the json, but for legacy separate
|
||||
# hi/lo <reg32> pairs "counter_lo" and "counter_hi" should
|
||||
# be specified
|
||||
if "counter" in group:
|
||||
counter = get_reg(group["counter"])
|
||||
return [counter, counter+1]
|
||||
counter_lo = get_reg(group["counter_lo"])
|
||||
counter_hi = get_reg(group["counter_hi"])
|
||||
return [counter_lo, counter_hi]
|
||||
|
||||
(counter_lo, counter_hi) = get_counter()
|
||||
select = get_reg(group['select'])
|
||||
|
||||
if "select_offset" in group:
|
||||
select = select + int(group["select_offset"])
|
||||
|
||||
# TODO add support for things that need enable/clear regs
|
||||
|
||||
print(" { 0x%04x, 0x%04x, 0x%04x }," % (select, counter_lo, counter_hi))
|
||||
print("};")
|
||||
|
||||
print()
|
||||
|
||||
print("const struct fd_perfcntr_group " + chip.lower() + "_perfcntr_groups[] = {")
|
||||
for group in groups:
|
||||
name = group['name']
|
||||
name_low = name.lower()
|
||||
|
||||
print(" GROUP(\"%s\", %s_counters, %s_countables)," % (name, name_low, name_low))
|
||||
|
||||
print("};")
|
||||
print("const unsigned " + chip.lower() + "_num_perfcntr_groups = ARRAY_SIZE(" + chip.lower() + "_perfcntr_groups);")
|
||||
|
||||
print()
|
||||
print("#endif /* %s */" % guard)
|
||||
|
||||
def dump_py_defines(args):
|
||||
p = Parser()
|
||||
|
||||
|
|
@ -1052,6 +1190,10 @@ def main():
|
|||
parser_c_pack_structs = subparsers.add_parser('c-pack-structs')
|
||||
parser_c_pack_structs.set_defaults(func=dump_c_pack_structs)
|
||||
|
||||
parser_perfcntrs = subparsers.add_parser('perfcntrs')
|
||||
parser_perfcntrs.add_argument('--json', type=str, required=True)
|
||||
parser_perfcntrs.set_defaults(func=dump_perfcntrs)
|
||||
|
||||
parser_py_defines = subparsers.add_parser('py-defines')
|
||||
parser_py_defines.set_defaults(func=dump_py_defines)
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue