1#!/usr/bin/python3 2 3import xml.parsers.expat 4import sys 5import os 6 7class Error(Exception): 8 def __init__(self, message): 9 self.message = message 10 11class Enum(object): 12 def __init__(self, name): 13 self.name = name 14 self.values = [] 15 16 def dump(self): 17 prev = 0 18 use_hex = False 19 for (name, value) in self.values: 20 if value > 0x1000: 21 use_hex = True 22 23 print("enum %s {" % self.name) 24 for (name, value) in self.values: 25 if use_hex: 26 print("\t%s = 0x%08x," % (name, value)) 27 else: 28 print("\t%s = %d," % (name, value)) 29 print("};\n") 30 31 def dump_pack_struct(self): 32 pass 33 34class Field(object): 35 def __init__(self, name, low, high, shr, type, parser): 36 self.name = name 37 self.low = low 38 self.high = high 39 self.shr = shr 40 self.type = type 41 42 builtin_types = [ None, "a3xx_regid", "boolean", "uint", "hex", "int", "fixed", "ufixed", "float", "address", "waddress" ] 43 44 if low < 0 or low > 31: 45 raise parser.error("low attribute out of range: %d" % low) 46 if high < 0 or high > 31: 47 raise parser.error("high attribute out of range: %d" % high) 48 if high < low: 49 raise parser.error("low is greater than high: low=%d, high=%d" % (low, high)) 50 if self.type == "boolean" and not low == high: 51 raise parser.error("booleans should be 1 bit fields"); 52 elif self.type == "float" and not (high - low == 31 or high - low == 15): 53 raise parser.error("floats should be 16 or 32 bit fields") 54 elif not self.type in builtin_types and not self.type in parser.enums: 55 raise parser.error("unknown type '%s'" % self.type); 56 57 def ctype(self, var_name): 58 if self.type == None: 59 type = "uint32_t" 60 val = var_name 61 elif self.type == "boolean": 62 type = "bool" 63 val = var_name 64 elif self.type == "uint" or self.type == "hex" or self.type == "a3xx_regid": 65 type = "uint32_t" 66 val = var_name 67 elif self.type == "int": 68 type = "int32_t" 69 val = var_name 70 elif self.type == "fixed": 71 type = "float" 72 val = "((int32_t)(%s * %d.0))" % (var_name, 1 << self.radix) 73 elif self.type == "ufixed": 74 type = "float" 75 val = "((uint32_t)(%s * %d.0))" % (var_name, 1 << self.radix) 76 elif self.type == "float" and self.high - self.low == 31: 77 type = "float" 78 val = "fui(%s)" % var_name 79 elif self.type == "float" and self.high - self.low == 15: 80 type = "float" 81 val = "_mesa_float_to_half(%s)" % var_name 82 elif self.type in [ "address", "waddress" ]: 83 type = "uint64_t" 84 val = var_name 85 else: 86 type = "enum %s" % self.type 87 val = var_name 88 89 if self.shr > 0: 90 val = "(%s >> %d)" % (val, self.shr) 91 92 return (type, val) 93 94def tab_to(name, value): 95 tab_count = (68 - (len(name) & ~7)) // 8 96 if tab_count <= 0: 97 tab_count = 1 98 print(name + ('\t' * tab_count) + value) 99 100def mask(low, high): 101 return ((0xffffffff >> (32 - (high + 1 - low))) << low) 102 103class Bitset(object): 104 def __init__(self, name, template): 105 self.name = name 106 self.inline = False 107 if template: 108 self.fields = template.fields 109 else: 110 self.fields = [] 111 112 def dump_pack_struct(self, prefix=None, array=None): 113 def field_name(prefix, name): 114 if f.name: 115 name = f.name.lower() 116 else: 117 name = prefix.lower() 118 119 if (name in [ "double", "float", "int" ]) or not (name[0].isalpha()): 120 name = "_" + name 121 122 return name 123 124 if not prefix: 125 return 126 if prefix == None: 127 prefix = self.name 128 129 value_name = "dword" 130 print("struct %s {" % prefix) 131 for f in self.fields: 132 if f.type == "waddress": 133 value_name = "qword" 134 if f.type in [ "address", "waddress" ]: 135 tab_to(" __bo_type", "bo;") 136 tab_to(" uint32_t", "bo_offset;") 137 continue 138 name = field_name(prefix, f.name) 139 140 type, val = f.ctype("var") 141 142 tab_to(" %s" % type, "%s;" % name) 143 if value_name == "qword": 144 tab_to(" uint64_t", "unknown;") 145 tab_to(" uint64_t", "qword;") 146 else: 147 tab_to(" uint32_t", "unknown;") 148 tab_to(" uint32_t", "dword;") 149 print("};\n") 150 151 address = None; 152 for f in self.fields: 153 if f.type in [ "address", "waddress" ]: 154 address = f 155 if array: 156 print("static inline struct fd_reg_pair\npack_%s(uint32_t i, struct %s fields)\n{" % 157 (prefix, prefix)); 158 else: 159 print("static inline struct fd_reg_pair\npack_%s(struct %s fields)\n{" % 160 (prefix, prefix)); 161 162 print("#ifndef NDEBUG") 163 known_mask = 0 164 for f in self.fields: 165 known_mask |= mask(f.low, f.high) 166 if f.type in [ "boolean", "address", "waddress" ]: 167 continue 168 type, val = f.ctype("fields.%s" % field_name(prefix, f.name)) 169 print(" assert((%-40s & 0x%08x) == 0);" % (val, 0xffffffff ^ mask(0 , f.high - f.low))) 170 print(" assert((%-40s & 0x%08x) == 0);" % ("fields.unknown", known_mask)) 171 print("#endif\n") 172 173 print(" return (struct fd_reg_pair) {") 174 if array: 175 print(" .reg = REG_%s(i)," % prefix) 176 else: 177 print(" .reg = REG_%s," % prefix) 178 179 print(" .value =") 180 for f in self.fields: 181 if f.type in [ "address", "waddress" ]: 182 continue 183 else: 184 type, val = f.ctype("fields.%s" % field_name(prefix, f.name)) 185 print(" (%-40s << %2d) |" % (val, f.low)) 186 print(" fields.unknown | fields.%s," % (value_name,)) 187 188 if address: 189 print(" .is_address = true,") 190 print(" .bo = fields.bo,") 191 if f.type == "waddress": 192 print(" .bo_write = true,") 193 print(" .bo_offset = fields.bo_offset,") 194 print(" .bo_shift = %d" % address.shr) 195 196 print(" };\n}\n") 197 198 if address: 199 skip = ", { .reg = 0 }" 200 else: 201 skip = "" 202 203 if array: 204 print("#define %s(i, ...) pack_%s(i, (struct %s) { __VA_ARGS__ })%s\n" % 205 (prefix, prefix, prefix, skip)) 206 else: 207 print("#define %s(...) pack_%s((struct %s) { __VA_ARGS__ })%s\n" % 208 (prefix, prefix, prefix, skip)) 209 210 211 def dump(self, prefix=None): 212 if prefix == None: 213 prefix = self.name 214 for f in self.fields: 215 if f.name: 216 name = prefix + "_" + f.name 217 else: 218 name = prefix 219 220 if not f.name and f.low == 0 and f.shr == 0 and not f.type in ["float", "fixed", "ufixed"]: 221 pass 222 elif f.type == "boolean" or (f.type == None and f.low == f.high): 223 tab_to("#define %s" % name, "0x%08x" % (1 << f.low)) 224 else: 225 tab_to("#define %s__MASK" % name, "0x%08x" % mask(f.low, f.high)) 226 tab_to("#define %s__SHIFT" % name, "%d" % f.low) 227 type, val = f.ctype("val") 228 229 print("static inline uint32_t %s(%s val)\n{" % (name, type)) 230 if f.shr > 0: 231 print("\tassert(!(val & 0x%x));" % mask(0, f.shr - 1)) 232 print("\treturn ((%s) << %s__SHIFT) & %s__MASK;\n}" % (val, name, name)) 233 print() 234 235class Array(object): 236 def __init__(self, attrs, domain): 237 if "name" in attrs: 238 self.name = attrs["name"] 239 else: 240 self.name = "" 241 self.domain = domain 242 self.offset = int(attrs["offset"], 0) 243 self.stride = int(attrs["stride"], 0) 244 self.length = int(attrs["length"], 0) 245 246 def dump(self): 247 print("static inline uint32_t REG_%s_%s(uint32_t i0) { return 0x%08x + 0x%x*i0; }\n" % (self.domain, self.name, self.offset, self.stride)) 248 249 def dump_pack_struct(self): 250 pass 251 252class Reg(object): 253 def __init__(self, attrs, domain, array, bit_size): 254 self.name = attrs["name"] 255 self.domain = domain 256 self.array = array 257 self.offset = int(attrs["offset"], 0) 258 self.type = None 259 self.bit_size = bit_size 260 261 if self.array: 262 self.full_name = self.domain + "_" + self.array.name + "_" + self.name 263 else: 264 self.full_name = self.domain + "_" + self.name 265 266 def dump(self): 267 if self.array: 268 offset = self.array.offset + self.offset 269 print("static inline uint32_t REG_%s(uint32_t i0) { return 0x%08x + 0x%x*i0; }" % (self.full_name, offset, self.array.stride)) 270 else: 271 tab_to("#define REG_%s" % self.full_name, "0x%08x" % self.offset) 272 273 if self.bitset.inline: 274 self.bitset.dump(self.full_name) 275 print("") 276 277 def dump_pack_struct(self): 278 if self.bitset.inline: 279 self.bitset.dump_pack_struct(self.full_name, not self.array == None) 280 281 282def parse_variants(attrs): 283 if not "variants" in attrs: 284 return None 285 variant = attrs["variants"].split(",")[0] 286 if "-" in variant: 287 variant = variant[:variant.index("-")] 288 289 return variant 290 291class Parser(object): 292 def __init__(self): 293 self.current_array = None 294 self.current_domain = None 295 self.current_prefix = None 296 self.current_stripe = None 297 self.current_bitset = None 298 self.bitsets = {} 299 self.enums = {} 300 self.file = [] 301 302 def error(self, message): 303 parser, filename = self.stack[-1] 304 return Error("%s:%d:%d: %s" % (filename, parser.CurrentLineNumber, parser.CurrentColumnNumber, message)) 305 306 def prefix(self): 307 if self.current_stripe: 308 return self.current_stripe + "_" + self.current_domain 309 elif self.current_prefix: 310 return self.current_prefix + "_" + self.current_domain 311 else: 312 return self.current_domain 313 314 def parse_field(self, name, attrs): 315 try: 316 if "pos" in attrs: 317 high = low = int(attrs["pos"], 0) 318 elif "high" in attrs and "low" in attrs: 319 high = int(attrs["high"], 0) 320 low = int(attrs["low"], 0) 321 else: 322 low = 0 323 high = 31 324 325 if "type" in attrs: 326 type = attrs["type"] 327 else: 328 type = None 329 330 if "shr" in attrs: 331 shr = int(attrs["shr"], 0) 332 else: 333 shr = 0 334 335 b = Field(name, low, high, shr, type, self) 336 337 if type == "fixed" or type == "ufixed": 338 b.radix = int(attrs["radix"], 0) 339 340 self.current_bitset.fields.append(b) 341 except ValueError as e: 342 raise self.error(e); 343 344 def do_parse(self, filename): 345 file = open(filename, "rb") 346 parser = xml.parsers.expat.ParserCreate() 347 self.stack.append((parser, filename)) 348 parser.StartElementHandler = self.start_element 349 parser.EndElementHandler = self.end_element 350 parser.ParseFile(file) 351 self.stack.pop() 352 file.close() 353 354 def parse(self, rnn_path, filename): 355 self.path = rnn_path 356 self.stack = [] 357 self.do_parse(filename) 358 359 def parse_reg(self, attrs, bit_size): 360 if "type" in attrs and attrs["type"] in self.bitsets: 361 self.current_bitset = self.bitsets[attrs["type"]] 362 else: 363 self.current_bitset = Bitset(attrs["name"], None) 364 self.current_bitset.inline = True 365 if "type" in attrs: 366 self.parse_field(None, attrs) 367 368 self.current_reg = Reg(attrs, self.prefix(), self.current_array, bit_size) 369 self.current_reg.bitset = self.current_bitset 370 371 if len(self.stack) == 1: 372 self.file.append(self.current_reg) 373 374 def start_element(self, name, attrs): 375 if name == "import": 376 filename = attrs["file"] 377 self.do_parse(os.path.join(self.path, filename)) 378 elif name == "domain": 379 self.current_domain = attrs["name"] 380 if "prefix" in attrs and attrs["prefix"] == "chip": 381 self.current_prefix = parse_variants(attrs) 382 elif name == "stripe": 383 self.current_stripe = parse_variants(attrs) 384 elif name == "enum": 385 self.current_enum_value = 0 386 self.current_enum = Enum(attrs["name"]) 387 self.enums[attrs["name"]] = self.current_enum 388 if len(self.stack) == 1: 389 self.file.append(self.current_enum) 390 elif name == "value": 391 if "value" in attrs: 392 value = int(attrs["value"], 0) 393 else: 394 value = self.current_enum_value 395 self.current_enum.values.append((attrs["name"], value)) 396 # self.current_enum_value = value + 1 397 elif name == "reg32": 398 self.parse_reg(attrs, 32) 399 elif name == "reg64": 400 self.parse_reg(attrs, 64) 401 elif name == "array": 402 self.current_array = Array(attrs, self.prefix()) 403 if len(self.stack) == 1: 404 self.file.append(self.current_array) 405 elif name == "bitset": 406 self.current_bitset = Bitset(attrs["name"], None) 407 if "inline" in attrs and attrs["inline"] == "yes": 408 self.current_bitset.inline = True 409 self.bitsets[self.current_bitset.name] = self.current_bitset 410 if len(self.stack) == 1 and not self.current_bitset.inline: 411 self.file.append(self.current_bitset) 412 elif name == "bitfield" and self.current_bitset: 413 self.parse_field(attrs["name"], attrs) 414 415 def end_element(self, name): 416 if name == "domain": 417 self.current_domain = None 418 self.current_prefix = None 419 elif name == "stripe": 420 self.current_stripe = None 421 elif name == "bitset": 422 self.current_bitset = None 423 elif name == "reg32": 424 self.current_reg = None 425 elif name == "array": 426 self.current_array = None; 427 elif name == "enum": 428 self.current_enum = None 429 430 def dump(self): 431 enums = [] 432 bitsets = [] 433 regs = [] 434 for e in self.file: 435 if isinstance(e, Enum): 436 enums.append(e) 437 elif isinstance(e, Bitset): 438 bitsets.append(e) 439 else: 440 regs.append(e) 441 442 for e in enums + bitsets + regs: 443 e.dump() 444 445 def dump_structs(self): 446 for e in self.file: 447 e.dump_pack_struct() 448 449 450def main(): 451 p = Parser() 452 rnn_path = sys.argv[1] 453 xml_file = sys.argv[2] 454 if len(sys.argv) > 3 and sys.argv[3] == '--pack-structs': 455 do_structs = True 456 guard = str.replace(os.path.basename(xml_file), '.', '_').upper() + '_STRUCTS' 457 else: 458 do_structs = False 459 guard = str.replace(os.path.basename(xml_file), '.', '_').upper() 460 461 print("#ifndef %s\n#define %s\n" % (guard, guard)) 462 463 try: 464 p.parse(rnn_path, xml_file) 465 except Error as e: 466 print(e) 467 exit(1) 468 469 if do_structs: 470 p.dump_structs() 471 else: 472 p.dump() 473 474 print("\n#endif /* %s */" % guard) 475 476if __name__ == '__main__': 477 main() 478