if low < 0 or low > maxpos: raise parser.error("low attribute out of range: %d" % low) if high < 0 or high > maxpos: raise parser.error("high attribute out of range: %d" % high) if high < low: raise parser.error("low is greater than high: low=%d, high=%d" % (low, high)) if self.type == "boolean"andnot low == high: raise parser.error("booleans should be 1 bit fields") elif self.type == "float"andnot (high - low == 31 or high - low == 15): raise parser.error("floats should be 16 or 32 bit fields") elifnot self.type in builtin_types andnot self.type in parser.enums: raise parser.error("unknown type '%s'" % self.type)
def ctype(self, var_name): if self.type == None:
type = "uint32_t"
val = var_name elif self.type == "boolean":
type = "bool"
val = var_name elif self.type == "uint"or self.type == "hex"or self.type == "a3xx_regid":
type = "uint32_t"
val = var_name elif self.type == "int":
type = "int32_t"
val = var_name elif self.type == "fixed":
type = "float"
val = "((int32_t)(%s * %d.0))" % (var_name, 1 << self.radix) elif self.type == "ufixed":
type = "float"
val = "((uint32_t)(%s * %d.0))" % (var_name, 1 << self.radix) elif self.type == "float"and self.high - self.low == 31:
type = "float"
val = "fui(%s)" % var_name elif self.type == "float"and self.high - self.low == 15:
type = "float"
val = "_mesa_float_to_half(%s)" % var_name elif self.type in [ "address", "waddress" ]:
type = "uint64_t"
val = var_name else:
type = "enum %s" % self.type
val = var_name
if self.shr > 0:
val = "(%s >> %d)" % (val, self.shr)
def field_name(reg, f): if f.name:
name = f.name.lower() else: # We hit this path when a reg is defined with no bitset fields, ie. # <reg32 offset="0x88db" name="RB_BLIT_DST_ARRAY_PITCH" low="0" high="28" shr="6" type="uint"/>
name = reg.name.lower()
if (name in [ "double", "float", "int" ]) ornot (name[0].isalpha()):
name = "_" + name
return name
# indices - array of (ctype, stride, __offsets_NAME) def indices_varlist(indices): return", ".join(["i%d" % i for i in range(len(indices))])
def indices_prototype(indices): return", ".join(["%s i%d" % (ctype, idx) for (idx, (ctype, stride, offset)) in enumerate(indices)])
def indices_strides(indices): return" + ".join(["0x%x*i%d" % (stride, idx) if stride else "%s(i%d)" % (offset, idx) for (idx, (ctype, stride, offset)) in enumerate(indices)])
class Bitset(object): def __init__(self, name, template):
self.name = name
self.inline = False
self.reg = None if template:
self.fields = template.fields[:] else:
self.fields = []
# Get address field if there is one in the bitset, else return None: def get_address_field(self): for f in self.fields: if f.type in [ "address", "waddress" ]: return f returnNone
def dump_regpair_builder(self, reg):
print("#ifndef NDEBUG")
known_mask = 0 for f in self.fields:
known_mask |= mask(f.low, f.high) if f.type in [ "boolean", "address", "waddress" ]: continue
type, val = f.ctype("fields.%s" % field_name(reg, f))
print(" assert((%-40s & 0x%08x) == 0);" % (val, 0xffffffff ^ mask(0 , f.high - f.low)))
print(" assert((%-40s & 0x%08x) == 0);" % ("fields.unknown", known_mask))
print("#endif\n")
print("struct %s {" % prefix) for f in self.fields: if f.type in [ "address", "waddress" ]:
tab_to(" __bo_type", "bo;")
tab_to(" uint32_t", "bo_offset;") continue
name = field_name(reg, f)
# Generate array of (ctype, stride, __offsets_NAME) def indices(self): if self.parent:
indices = self.parent.indices() else:
indices = [] if self.length != 1: if self.fixed_offsets:
indices.append((self.index_ctype(), None, "__offset_%s" % self.local_name)) else:
indices.append((self.index_ctype(), self.stride, None)) return indices
# Generate array of (ctype, stride, __offsets_NAME) def indices(self): if self.array:
indices = self.array.indices() else:
indices = [] if self.stride:
indices.append(("uint32_t", self.stride, None)) return indices
class Parser(object): def __init__(self):
self.current_array = None
self.current_domain = None
self.current_prefix = None
self.current_prefix_type = None
self.current_stripe = None
self.current_bitset = None
self.current_bitsize = 32 # The varset attribute on the domain specifies the enum which # specifies all possible hw variants:
self.current_varset = None # 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 = []
self.xml_files = []
self.copyright_year = None
self.authors = []
self.license = None
if type == "fixed"or type == "ufixed":
b.radix = int(attrs["radix"], 0)
self.current_bitset.fields.append(b) except ValueError as e: raise self.error(e)
def parse_varset(self, attrs): # Inherit the varset from the enclosing domain if not overriden:
varset = self.current_varset if"varset"in attrs:
varset = self.enums[attrs["varset"]] return varset
def add_all_variants(self, reg, attrs, parent_variant): # TODO this should really handle *all* variants, including dealing # with open ended ranges (ie. "A2XX,A4XX-") (we have the varset # enum now to make that possible)
variant = self.parse_variants(attrs) ifnot variant:
variant = parent_variant
if reg.name notin self.variant_regs:
self.variant_regs[reg.name] = {} else: # All variants must be same size:
v = next(iter(self.variant_regs[reg.name])) assert self.variant_regs[reg.name][v].bit_size == reg.bit_size
# we expect this to look like <namespace url> schema.xsd.. I think # technically it is supposed to be just a URL, but that doesn't # quite match up to what we do.. Just skip over everything up to # and including the first whitespace character:
schemafile = schemafile[schemafile.rindex(" ")+1:]
# this is a bit cheezy, but the xml file to validate could be # in a child director, ie. we don't really know where the schema # file is, the way the rnn C code does. So if it doesn't exist # just look one level up ifnot os.path.exists(dirname + "/" + schemafile):
schemafile = "../" + schemafile
def start_element(self, name, attrs):
self.cdata = "" if name == "import":
filename = attrs["file"]
self.do_parse(os.path.join(self.path, filename)) elif name == "domain":
self.current_domain = attrs["name"] if"prefix"in attrs:
self.current_prefix = self.parse_variants(attrs)
self.current_prefix_type = attrs["prefix"] else:
self.current_prefix = None
self.current_prefix_type = None if"varset"in attrs:
self.current_varset = self.enums[attrs["varset"]] elif name == "stripe":
self.current_stripe = self.parse_variants(attrs) elif name == "enum":
self.current_enum_value = 0
self.current_enum = Enum(attrs["name"])
self.enums[attrs["name"]] = self.current_enum if len(self.stack) == 1:
self.file.append(self.current_enum) elif name == "value": if"value"in attrs:
value = int(attrs["value"], 0) else:
value = self.current_enum_value
self.current_enum.values.append((attrs["name"], value)) elif name == "reg32":
self.parse_reg(attrs, 32) elif name == "reg64":
self.parse_reg(attrs, 64) elif name == "array":
self.current_bitsize = 32
variant = self.parse_variants(attrs)
index_type = self.enums[attrs["index"]] if"index"in attrs elseNone
self.current_array = Array(attrs, self.prefix(variant), variant, self.current_array, index_type) if len(self.stack) == 1:
self.file.append(self.current_array) elif name == "bitset":
self.current_bitset = Bitset(attrs["name"], None) if"inline"in attrs and attrs["inline"] == "yes":
self.current_bitset.inline = True
self.bitsets[self.current_bitset.name] = self.current_bitset if len(self.stack) == 1 andnot self.current_bitset.inline:
self.file.append(self.current_bitset) elif name == "bitfield"and self.current_bitset:
self.parse_field(attrs["name"], attrs) elif name == "database":
self.do_validate(attrs["xsi:schemaLocation"]) elif name == "copyright":
self.copyright_year = attrs["year"] elif name == "author":
self.authors.append(attrs["name"] + " <" + attrs["email"] + "> " + attrs["name"])
def end_element(self, name): if name == "domain":
self.current_domain = None
self.current_prefix = None
self.current_prefix_type = None elif name == "stripe":
self.current_stripe = None elif name == "bitset":
self.current_bitset = None elif name == "reg32":
self.current_reg = None elif name == "array":
self.current_array = self.current_array.parent elif name == "enum":
self.current_enum = None elif name == "license":
self.license = self.cdata
def character_data(self, data):
self.cdata += data
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 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 = []
regs = [] for e in self.file: if isinstance(e, Enum):
enums.append(e) elif isinstance(e, Bitset):
bitsets.append(e) else:
regs.append(e)
for e in enums + bitsets + regs:
e.dump()
self.dump_reg_usages()
def dump_regs_py(self):
regs = [] for e in self.file: if isinstance(e, Reg):
regs.append(e)
for e in regs:
e.dump_py()
def dump_reg_variants(self, regname, variants): # Don't bother for things that only have a single variant: if len(variants) == 1: return
print("#ifdef __cplusplus")
print("struct __%s {" % regname) # TODO be more clever.. we should probably figure out which # fields have the same type in all variants (in which they # appear) and stuff everything else in a variant specific # sub-structure.
seen_fields = []
bit_size = 32
array = False
address = None for variant in variants.keys():
print(" /* %s fields: */" % variant)
reg = variants[variant]
bit_size = reg.bit_size
array = reg.array for f in reg.bitset.fields:
fld_name = field_name(reg, f) if fld_name in seen_fields: continue
seen_fields.append(fld_name)
name = fld_name.lower() if f.type in [ "address", "waddress" ]: if address: continue
address = f
tab_to(" __bo_type", "bo;")
tab_to(" uint32_t", "bo_offset;") continue
type, val = f.ctype("var")
tab_to(" %s" %type, "%s;" %name)
print(" /* fallback fields: */") if bit_size == 64:
tab_to(" uint64_t", "unknown;")
tab_to(" uint64_t", "qword;") else:
tab_to(" uint32_t", "unknown;")
tab_to(" uint32_t", "dword;")
print("};") # TODO don't hardcode the varset enum name
varenum = "chip"
print("template <%s %s>" % (varenum, varenum.upper()))
print("static inline struct fd_reg_pair")
xtra = ""
xtravar = "" if array:
xtra = "int __i, "
xtravar = "__i, "
print("__%s(%sstruct __%s fields) {" % (regname, xtra, regname)) for variant in variants.keys():
print(" if (%s == %s) {" % (varenum.upper(), variant))
reg = variants[variant]
reg.dump_regpair_builder()
print(" } else")
print(" assert(!\"invalid variant\");")
print("}")
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.