Path: blob/21.2-virgl/src/freedreno/registers/gen_header.py
7326 views
#!/usr/bin/python312import xml.parsers.expat3import sys4import os56class Error(Exception):7def __init__(self, message):8self.message = message910class Enum(object):11def __init__(self, name):12self.name = name13self.values = []1415def dump(self):16prev = 017use_hex = False18for (name, value) in self.values:19if value > 0x1000:20use_hex = True2122print("enum %s {" % self.name)23for (name, value) in self.values:24if use_hex:25print("\t%s = 0x%08x," % (name, value))26else:27print("\t%s = %d," % (name, value))28print("};\n")2930def dump_pack_struct(self):31pass3233class Field(object):34def __init__(self, name, low, high, shr, type, parser):35self.name = name36self.low = low37self.high = high38self.shr = shr39self.type = type4041builtin_types = [ None, "a3xx_regid", "boolean", "uint", "hex", "int", "fixed", "ufixed", "float", "address", "waddress" ]4243if low < 0 or low > 31:44raise parser.error("low attribute out of range: %d" % low)45if high < 0 or high > 31:46raise parser.error("high attribute out of range: %d" % high)47if high < low:48raise parser.error("low is greater than high: low=%d, high=%d" % (low, high))49if self.type == "boolean" and not low == high:50raise parser.error("booleans should be 1 bit fields");51elif self.type == "float" and not (high - low == 31 or high - low == 15):52raise parser.error("floats should be 16 or 32 bit fields")53elif not self.type in builtin_types and not self.type in parser.enums:54raise parser.error("unknown type '%s'" % self.type);5556def ctype(self, var_name):57if self.type == None:58type = "uint32_t"59val = var_name60elif self.type == "boolean":61type = "bool"62val = var_name63elif self.type == "uint" or self.type == "hex" or self.type == "a3xx_regid":64type = "uint32_t"65val = var_name66elif self.type == "int":67type = "int32_t"68val = var_name69elif self.type == "fixed":70type = "float"71val = "((int32_t)(%s * %d.0))" % (var_name, 1 << self.radix)72elif self.type == "ufixed":73type = "float"74val = "((uint32_t)(%s * %d.0))" % (var_name, 1 << self.radix)75elif self.type == "float" and self.high - self.low == 31:76type = "float"77val = "fui(%s)" % var_name78elif self.type == "float" and self.high - self.low == 15:79type = "float"80val = "_mesa_float_to_half(%s)" % var_name81elif self.type in [ "address", "waddress" ]:82type = "uint64_t"83val = var_name84else:85type = "enum %s" % self.type86val = var_name8788if self.shr > 0:89val = "(%s >> %d)" % (val, self.shr)9091return (type, val)9293def tab_to(name, value):94tab_count = (68 - (len(name) & ~7)) // 895if tab_count <= 0:96tab_count = 197print(name + ('\t' * tab_count) + value)9899def mask(low, high):100return ((0xffffffff >> (32 - (high + 1 - low))) << low)101102class Bitset(object):103def __init__(self, name, template):104self.name = name105self.inline = False106if template:107self.fields = template.fields[:]108else:109self.fields = []110111def dump_pack_struct(self, prefix=None, array=None, bit_size=32):112def field_name(prefix, name):113if f.name:114name = f.name.lower()115else:116name = prefix.lower()117118if (name in [ "double", "float", "int" ]) or not (name[0].isalpha()):119name = "_" + name120121return name122123if not prefix:124return125if prefix == None:126prefix = self.name127128value_name = "dword"129print("struct %s {" % prefix)130for f in self.fields:131if f.type in [ "address", "waddress" ]:132tab_to(" __bo_type", "bo;")133tab_to(" uint32_t", "bo_offset;")134if bit_size == 64:135value_name = "qword"136continue137name = field_name(prefix, f.name)138139type, val = f.ctype("var")140141tab_to(" %s" % type, "%s;" % name)142if value_name == "qword":143tab_to(" uint64_t", "unknown;")144tab_to(" uint64_t", "qword;")145else:146tab_to(" uint32_t", "unknown;")147tab_to(" uint32_t", "dword;")148print("};\n")149150address = None;151for f in self.fields:152if f.type in [ "address", "waddress" ]:153address = f154if array:155print("static inline struct fd_reg_pair\npack_%s(uint32_t i, struct %s fields)\n{" %156(prefix, prefix));157else:158print("static inline struct fd_reg_pair\npack_%s(struct %s fields)\n{" %159(prefix, prefix));160161print("#ifndef NDEBUG")162known_mask = 0163for f in self.fields:164known_mask |= mask(f.low, f.high)165if f.type in [ "boolean", "address", "waddress" ]:166continue167type, val = f.ctype("fields.%s" % field_name(prefix, f.name))168print(" assert((%-40s & 0x%08x) == 0);" % (val, 0xffffffff ^ mask(0 , f.high - f.low)))169print(" assert((%-40s & 0x%08x) == 0);" % ("fields.unknown", known_mask))170print("#endif\n")171172print(" return (struct fd_reg_pair) {")173if array:174print(" .reg = REG_%s(i)," % prefix)175else:176print(" .reg = REG_%s," % prefix)177178print(" .value =")179for f in self.fields:180if f.type in [ "address", "waddress" ]:181continue182else:183type, val = f.ctype("fields.%s" % field_name(prefix, f.name))184print(" (%-40s << %2d) |" % (val, f.low))185print(" fields.unknown | fields.%s," % (value_name,))186187if address:188print(" .is_address = true,")189print(" .bo = fields.bo,")190if f.type == "waddress":191print(" .bo_write = true,")192print(" .bo_offset = fields.bo_offset,")193print(" .bo_shift = %d" % address.shr)194195print(" };\n}\n")196197if address:198skip = ", { .reg = 0 }"199else:200skip = ""201202if array:203print("#define %s(i, ...) pack_%s(i, (struct %s) { __VA_ARGS__ })%s\n" %204(prefix, prefix, prefix, skip))205else:206print("#define %s(...) pack_%s((struct %s) { __VA_ARGS__ })%s\n" %207(prefix, prefix, prefix, skip))208209210def dump(self, prefix=None):211if prefix == None:212prefix = self.name213for f in self.fields:214if f.name:215name = prefix + "_" + f.name216else:217name = prefix218219if not f.name and f.low == 0 and f.shr == 0 and not f.type in ["float", "fixed", "ufixed"]:220pass221elif f.type == "boolean" or (f.type == None and f.low == f.high):222tab_to("#define %s" % name, "0x%08x" % (1 << f.low))223else:224tab_to("#define %s__MASK" % name, "0x%08x" % mask(f.low, f.high))225tab_to("#define %s__SHIFT" % name, "%d" % f.low)226type, val = f.ctype("val")227228print("static inline uint32_t %s(%s val)\n{" % (name, type))229if f.shr > 0:230print("\tassert(!(val & 0x%x));" % mask(0, f.shr - 1))231print("\treturn ((%s) << %s__SHIFT) & %s__MASK;\n}" % (val, name, name))232print()233234class Array(object):235def __init__(self, attrs, domain):236if "name" in attrs:237self.name = attrs["name"]238else:239self.name = ""240self.domain = domain241self.offset = int(attrs["offset"], 0)242self.stride = int(attrs["stride"], 0)243self.length = int(attrs["length"], 0)244245def dump(self):246print("#define REG_%s_%s(i0) (0x%08x + 0x%x*(i0))\n" % (self.domain, self.name, self.offset, self.stride))247248def dump_pack_struct(self):249pass250251class Reg(object):252def __init__(self, attrs, domain, array, bit_size):253self.name = attrs["name"]254self.domain = domain255self.array = array256self.offset = int(attrs["offset"], 0)257self.type = None258self.bit_size = bit_size259260if self.array:261self.full_name = self.domain + "_" + self.array.name + "_" + self.name262else:263self.full_name = self.domain + "_" + self.name264265def dump(self):266if self.array:267offset = self.array.offset + self.offset268print("static inline uint32_t REG_%s(uint32_t i0) { return 0x%08x + 0x%x*i0; }" % (self.full_name, offset, self.array.stride))269else:270tab_to("#define REG_%s" % self.full_name, "0x%08x" % self.offset)271272if self.bitset.inline:273self.bitset.dump(self.full_name)274print("")275276def dump_pack_struct(self):277if self.bitset.inline:278self.bitset.dump_pack_struct(self.full_name, not self.array == None, self.bit_size)279280281def parse_variants(attrs):282if not "variants" in attrs:283return None284variant = attrs["variants"].split(",")[0]285if "-" in variant:286variant = variant[:variant.index("-")]287288return variant289290class Parser(object):291def __init__(self):292self.current_array = None293self.current_domain = None294self.current_prefix = None295self.current_stripe = None296self.current_bitset = None297self.bitsets = {}298self.enums = {}299self.file = []300301def error(self, message):302parser, filename = self.stack[-1]303return Error("%s:%d:%d: %s" % (filename, parser.CurrentLineNumber, parser.CurrentColumnNumber, message))304305def prefix(self):306if self.current_stripe:307return self.current_stripe + "_" + self.current_domain308elif self.current_prefix:309return self.current_prefix + "_" + self.current_domain310else:311return self.current_domain312313def parse_field(self, name, attrs):314try:315if "pos" in attrs:316high = low = int(attrs["pos"], 0)317elif "high" in attrs and "low" in attrs:318high = int(attrs["high"], 0)319low = int(attrs["low"], 0)320else:321low = 0322high = 31323324if "type" in attrs:325type = attrs["type"]326else:327type = None328329if "shr" in attrs:330shr = int(attrs["shr"], 0)331else:332shr = 0333334b = Field(name, low, high, shr, type, self)335336if type == "fixed" or type == "ufixed":337b.radix = int(attrs["radix"], 0)338339self.current_bitset.fields.append(b)340except ValueError as e:341raise self.error(e);342343def do_parse(self, filename):344file = open(filename, "rb")345parser = xml.parsers.expat.ParserCreate()346self.stack.append((parser, filename))347parser.StartElementHandler = self.start_element348parser.EndElementHandler = self.end_element349parser.ParseFile(file)350self.stack.pop()351file.close()352353def parse(self, rnn_path, filename):354self.path = rnn_path355self.stack = []356self.do_parse(filename)357358def parse_reg(self, attrs, bit_size):359if "type" in attrs and attrs["type"] in self.bitsets:360bitset = self.bitsets[attrs["type"]]361if bitset.inline:362self.current_bitset = Bitset(attrs["name"], bitset)363self.current_bitset.inline = True364else:365self.current_bitset = bitset366else:367self.current_bitset = Bitset(attrs["name"], None)368self.current_bitset.inline = True369if "type" in attrs:370self.parse_field(None, attrs)371372self.current_reg = Reg(attrs, self.prefix(), self.current_array, bit_size)373self.current_reg.bitset = self.current_bitset374375if len(self.stack) == 1:376self.file.append(self.current_reg)377378def start_element(self, name, attrs):379if name == "import":380filename = attrs["file"]381self.do_parse(os.path.join(self.path, filename))382elif name == "domain":383self.current_domain = attrs["name"]384if "prefix" in attrs and attrs["prefix"] == "chip":385self.current_prefix = parse_variants(attrs)386elif name == "stripe":387self.current_stripe = parse_variants(attrs)388elif name == "enum":389self.current_enum_value = 0390self.current_enum = Enum(attrs["name"])391self.enums[attrs["name"]] = self.current_enum392if len(self.stack) == 1:393self.file.append(self.current_enum)394elif name == "value":395if "value" in attrs:396value = int(attrs["value"], 0)397else:398value = self.current_enum_value399self.current_enum.values.append((attrs["name"], value))400# self.current_enum_value = value + 1401elif name == "reg32":402self.parse_reg(attrs, 32)403elif name == "reg64":404self.parse_reg(attrs, 64)405elif name == "array":406self.current_array = Array(attrs, self.prefix())407if len(self.stack) == 1:408self.file.append(self.current_array)409elif name == "bitset":410self.current_bitset = Bitset(attrs["name"], None)411if "inline" in attrs and attrs["inline"] == "yes":412self.current_bitset.inline = True413self.bitsets[self.current_bitset.name] = self.current_bitset414if len(self.stack) == 1 and not self.current_bitset.inline:415self.file.append(self.current_bitset)416elif name == "bitfield" and self.current_bitset:417self.parse_field(attrs["name"], attrs)418419def end_element(self, name):420if name == "domain":421self.current_domain = None422self.current_prefix = None423elif name == "stripe":424self.current_stripe = None425elif name == "bitset":426self.current_bitset = None427elif name == "reg32":428self.current_reg = None429elif name == "array":430self.current_array = None;431elif name == "enum":432self.current_enum = None433434def dump(self):435enums = []436bitsets = []437regs = []438for e in self.file:439if isinstance(e, Enum):440enums.append(e)441elif isinstance(e, Bitset):442bitsets.append(e)443else:444regs.append(e)445446for e in enums + bitsets + regs:447e.dump()448449def dump_structs(self):450for e in self.file:451e.dump_pack_struct()452453454def main():455p = Parser()456rnn_path = sys.argv[1]457xml_file = sys.argv[2]458if len(sys.argv) > 3 and sys.argv[3] == '--pack-structs':459do_structs = True460guard = str.replace(os.path.basename(xml_file), '.', '_').upper() + '_STRUCTS'461else:462do_structs = False463guard = str.replace(os.path.basename(xml_file), '.', '_').upper()464465print("#ifndef %s\n#define %s\n" % (guard, guard))466467try:468p.parse(rnn_path, xml_file)469except Error as e:470print(e)471exit(1)472473if do_structs:474p.dump_structs()475else:476p.dump()477478print("\n#endif /* %s */" % guard)479480if __name__ == '__main__':481main()482483484