freedreno/regs: Generate per-gen reg usage tables

"reg" and "array" now could have `usage="a,b,c"` attribute, for each
usage a separate array is generated.

Would be used for register stomping debug option.

Signed-off-by: Danylo Piliaiev <dpiliaiev@igalia.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/23881>
This commit is contained in:
Danylo Piliaiev 2023-04-20 17:03:29 +02:00 committed by Marge Bot
parent 463db34258
commit c62b0cd4f8
3 changed files with 75 additions and 0 deletions

View file

@ -3,6 +3,7 @@
import xml.parsers.expat
import sys
import os
import collections
class Error(Exception):
def __init__(self, message):
@ -263,6 +264,10 @@ class Array(object):
self.offset = int(attrs["offset"], 0)
self.stride = int(attrs["stride"], 0)
self.length = int(attrs["length"], 0)
if "usage" in attrs:
self.usages = attrs["usage"].split(',')
else:
self.usages = None
def dump(self):
print("#define REG_%s_%s(i0) (0x%08x + 0x%x*(i0))\n" % (self.domain, self.name, self.offset, self.stride))
@ -319,8 +324,12 @@ class Parser(object):
# Regs that have multiple variants.. we only generated the C++
# template based struct-packers for these
self.variant_regs = {}
# Information in which contexts regs are used, to be used in
# debug options
self.usage_regs = collections.defaultdict(list)
self.bitsets = {}
self.enums = {}
self.variants = set()
self.file = []
def error(self, message):
@ -404,6 +413,15 @@ class Parser(object):
self.variant_regs[reg.name][variant] = reg;
def add_all_usages(self, reg, usages):
if not usages:
return
for usage in usages:
self.usage_regs[usage].append(reg)
self.variants.add(reg.domain)
def do_validate(self, schemafile):
try:
from lxml import etree
@ -480,6 +498,14 @@ class Parser(object):
if variant is not None:
self.add_all_variants(self.current_reg, attrs, variant)
usages = None
if "usage" in attrs:
usages = attrs["usage"].split(',')
elif self.current_array:
usages = self.current_array.usages
self.add_all_usages(self.current_reg, usages)
def start_element(self, name, attrs):
if name == "import":
filename = attrs["file"]
@ -548,6 +574,47 @@ class Parser(object):
elif name == "enum":
self.current_enum = None
def dump_reg_usages(self):
d = collections.defaultdict(list)
for usage, regs in self.usage_regs.items():
for reg in regs:
variants = self.variant_regs.get(reg.name)
if variants:
for variant, vreg in variants.items():
if reg == vreg:
d[(usage, variant)].append(reg)
else:
for variant in self.variants:
d[(usage, variant)].append(reg)
print("#ifdef __cplusplus")
for usage, regs in self.usage_regs.items():
print("template<chip CHIP> constexpr inline uint16_t %s_REGS[] = {};" % (usage.upper()))
for (usage, variant), regs in d.items():
offsets = []
for reg in regs:
if reg.array:
for i in range(reg.array.length):
offsets.append(reg.array.offset + reg.offset + i * reg.array.stride)
if reg.bit_size == 64:
offsets.append(offsets[-1] + 1)
else:
offsets.append(reg.offset)
if reg.bit_size == 64:
offsets.append(offsets[-1] + 1)
offsets.sort()
print("template<> constexpr inline uint16_t %s_REGS<%s>[] = {" % (usage.upper(), variant))
for offset in offsets:
print("\t%s," % hex(offset))
print("};")
print("#endif")
def dump(self):
enums = []
bitsets = []
@ -563,6 +630,8 @@ class Parser(object):
for e in enums + bitsets + regs:
e.dump()
self.dump_reg_usages()
def dump_reg_variants(self, regname, variants):
# Don't bother for things that only have a single variant:
if len(variants) == 1:

View file

@ -157,6 +157,7 @@
<attribute name="length" type="rng:HexOrNumber" use="required" />
<attribute name="varset" type="NMTOKEN" use="optional" />
<attribute name="variants" type="string" use="optional" />
<attribute name="usage" type="string" use="optional" />
</complexType>
<complexType name="stripeType">
@ -203,6 +204,7 @@
<attribute name="pos" type="nonNegativeInteger" use="optional" />
<attribute name="align" type="nonNegativeInteger" use="optional" />
<attribute name="radix" type="nonNegativeInteger" use="optional" />
<attribute name="usage" type="string" use="optional" />
</complexType>
<complexType name="bitsetType">

View file

@ -533,6 +533,8 @@ static struct rnndelem *trydelem(struct rnndb *db, char *file, xmlNode *node) {
if (!res->index) {
rnn_err(db, "%s:%d: invalid enum name \"%s\"\n", file, node->line, enumname);
}
} else if (!strcmp(attr->name, "usage")) {
// no-op
} else {
rnn_err(db, "%s:%d: wrong attribute \"%s\" for %s\n", file, node->line, attr->name, node->name);
}
@ -601,6 +603,8 @@ static struct rnndelem *trydelem(struct rnndb *db, char *file, xmlNode *node) {
res->access = RNN_ACCESS_RW;
else
fprintf (stderr, "%s:%d: wrong access type \"%s\" for register\n", file, node->line, str);
} else if (!strcmp(attr->name, "usage")) {
// no-op
} else if (!trytypeattr(db, file, node, attr, &res->typeinfo)) {
rnn_err(db, "%s:%d: wrong attribute \"%s\" for register\n", file, node->line, attr->name);
}