1#!/usr/bin/python3 2 3import xml.parsers.expat 4import sys 5import os 6import collections 7import argparse 8import time 9import datetime 10 11class Error(Exception): 12 def __init__(self, message): 13 self.message = message 14 15class Enum(object): 16 def __init__(self, name): 17 self.name = name 18 self.values = [] 19 20 def has_name(self, name): 21 for (n, value) in self.values: 22 if n == name: 23 return True 24 return False 25 26 def dump(self): 27 use_hex = False 28 for (name, value) in self.values: 29 if value > 0x1000: 30 use_hex = True 31 32 print("enum %s {" % self.name) 33 for (name, value) in self.values: 34 if use_hex: 35 print("\t%s = 0x%08x," % (name, value)) 36 else: 37 print("\t%s = %d," % (name, value)) 38 print("};\n") 39 40 def dump_pack_struct(self): 41 pass 42 43class Field(object): 44 def __init__(self, name, low, high, shr, type, parser): 45 self.name = name 46 self.low = low 47 self.high = high 48 self.shr = shr 49 self.type = type 50 51 builtin_types = [ None, "a3xx_regid", "boolean", "uint", "hex", "int", "fixed", "ufixed", "float", "address", "waddress" ] 52 53 maxpos = parser.current_bitsize - 1 54 55 if low < 0 or low > maxpos: 56 raise parser.error("low attribute out of range: %d" % low) 57 if high < 0 or high > maxpos: 58 raise parser.error("high attribute out of range: %d" % high) 59 if high < low: 60 raise parser.error("low is greater than high: low=%d, high=%d" % (low, high)) 61 if self.type == "boolean" and not low == high: 62 raise parser.error("booleans should be 1 bit fields") 63 elif self.type == "float" and not (high - low == 31 or high - low == 15): 64 raise parser.error("floats should be 16 or 32 bit fields") 65 elif not self.type in builtin_types and not self.type in parser.enums: 66 raise parser.error("unknown type '%s'" % self.type) 67 68 def ctype(self, var_name): 69 if self.type == None: 70 type = "uint32_t" 71 val = var_name 72 elif self.type == "boolean": 73 type = "bool" 74 val = var_name 75 elif self.type == "uint" or self.type == "hex" or self.type == "a3xx_regid": 76 type = "uint32_t" 77 val = var_name 78 elif self.type == "int": 79 type = "int32_t" 80 val = var_name 81 elif self.type == "fixed": 82 type = "float" 83 val = "((int32_t)(%s * %d.0))" % (var_name, 1 << self.radix) 84 elif self.type == "ufixed": 85 type = "float" 86 val = "((uint32_t)(%s * %d.0))" % (var_name, 1 << self.radix) 87 elif self.type == "float" and self.high - self.low == 31: 88 type = "float" 89 val = "fui(%s)" % var_name 90 elif self.type == "float" and self.high - self.low == 15: 91 type = "float" 92 val = "_mesa_float_to_half(%s)" % var_name 93 elif self.type in [ "address", "waddress" ]: 94 type = "uint64_t" 95 val = var_name 96 else: 97 type = "enum %s" % self.type 98 val = var_name 99 100 if self.shr > 0: 101 val = "(%s >> %d)" % (val, self.shr) 102 103 return (type, val) 104 105def tab_to(name, value): 106 tab_count = (68 - (len(name) & ~7)) // 8 107 if tab_count <= 0: 108 tab_count = 1 109 print(name + ('\t' * tab_count) + value) 110 111def mask(low, high): 112 return ((0xffffffffffffffff >> (64 - (high + 1 - low))) << low) 113 114def field_name(reg, f): 115 if f.name: 116 name = f.name.lower() 117 else: 118 # We hit this path when a reg is defined with no bitset fields, ie. 119 # <reg32 offset="0x88db" name="RB_BLIT_DST_ARRAY_PITCH" low="0" high="28" shr="6" type="uint"/> 120 name = reg.name.lower() 121 122 if (name in [ "double", "float", "int" ]) or not (name[0].isalpha()): 123 name = "_" + name 124 125 return name 126 127class Bitset(object): 128 def __init__(self, name, template): 129 self.name = name 130 self.inline = False 131 if template: 132 self.fields = template.fields[:] 133 else: 134 self.fields = [] 135 136 # Get address field if there is one in the bitset, else return None: 137 def get_address_field(self): 138 for f in self.fields: 139 if f.type in [ "address", "waddress" ]: 140 return f 141 return None 142 143 def dump_regpair_builder(self, reg): 144 print("#ifndef NDEBUG") 145 known_mask = 0 146 for f in self.fields: 147 known_mask |= mask(f.low, f.high) 148 if f.type in [ "boolean", "address", "waddress" ]: 149 continue 150 type, val = f.ctype("fields.%s" % field_name(reg, f)) 151 print(" assert((%-40s & 0x%08x) == 0);" % (val, 0xffffffff ^ mask(0 , f.high - f.low))) 152 print(" assert((%-40s & 0x%08x) == 0);" % ("fields.unknown", known_mask)) 153 print("#endif\n") 154 155 print(" return (struct fd_reg_pair) {") 156 if reg.array: 157 print(" .reg = REG_%s(__i)," % reg.full_name) 158 else: 159 print(" .reg = REG_%s," % reg.full_name) 160 161 print(" .value =") 162 for f in self.fields: 163 if f.type in [ "address", "waddress" ]: 164 continue 165 else: 166 type, val = f.ctype("fields.%s" % field_name(reg, f)) 167 print(" (%-40s << %2d) |" % (val, f.low)) 168 value_name = "dword" 169 if reg.bit_size == 64: 170 value_name = "qword" 171 print(" fields.unknown | fields.%s," % (value_name,)) 172 173 address = self.get_address_field() 174 if address: 175 print(" .bo = fields.bo,") 176 print(" .is_address = true,") 177 if f.type == "waddress": 178 print(" .bo_write = true,") 179 print(" .bo_offset = fields.bo_offset,") 180 print(" .bo_shift = %d," % address.shr) 181 print(" .bo_low = %d," % address.low) 182 183 print(" };") 184 185 def dump_pack_struct(self, reg=None): 186 if not reg: 187 return 188 189 prefix = reg.full_name 190 191 print("struct %s {" % prefix) 192 for f in self.fields: 193 if f.type in [ "address", "waddress" ]: 194 tab_to(" __bo_type", "bo;") 195 tab_to(" uint32_t", "bo_offset;") 196 continue 197 name = field_name(reg, f) 198 199 type, val = f.ctype("var") 200 201 tab_to(" %s" % type, "%s;" % name) 202 if reg.bit_size == 64: 203 tab_to(" uint64_t", "unknown;") 204 tab_to(" uint64_t", "qword;") 205 else: 206 tab_to(" uint32_t", "unknown;") 207 tab_to(" uint32_t", "dword;") 208 print("};\n") 209 210 if reg.array: 211 print("static inline struct fd_reg_pair\npack_%s(uint32_t __i, struct %s fields)\n{" % 212 (prefix, prefix)) 213 else: 214 print("static inline struct fd_reg_pair\npack_%s(struct %s fields)\n{" % 215 (prefix, prefix)) 216 217 self.dump_regpair_builder(reg) 218 219 print("\n}\n") 220 221 if self.get_address_field(): 222 skip = ", { .reg = 0 }" 223 else: 224 skip = "" 225 226 if reg.array: 227 print("#define %s(__i, ...) pack_%s(__i, __struct_cast(%s) { __VA_ARGS__ })%s\n" % 228 (prefix, prefix, prefix, skip)) 229 else: 230 print("#define %s(...) pack_%s(__struct_cast(%s) { __VA_ARGS__ })%s\n" % 231 (prefix, prefix, prefix, skip)) 232 233 234 def dump(self, prefix=None): 235 if prefix == None: 236 prefix = self.name 237 for f in self.fields: 238 if f.name: 239 name = prefix + "_" + f.name 240 else: 241 name = prefix 242 243 if not f.name and f.low == 0 and f.shr == 0 and not f.type in ["float", "fixed", "ufixed"]: 244 pass 245 elif f.type == "boolean" or (f.type == None and f.low == f.high): 246 tab_to("#define %s" % name, "0x%08x" % (1 << f.low)) 247 else: 248 tab_to("#define %s__MASK" % name, "0x%08x" % mask(f.low, f.high)) 249 tab_to("#define %s__SHIFT" % name, "%d" % f.low) 250 type, val = f.ctype("val") 251 252 print("static inline uint32_t %s(%s val)\n{" % (name, type)) 253 if f.shr > 0: 254 print("\tassert(!(val & 0x%x));" % mask(0, f.shr - 1)) 255 print("\treturn ((%s) << %s__SHIFT) & %s__MASK;\n}" % (val, name, name)) 256 print() 257 258class Array(object): 259 def __init__(self, attrs, domain, variant): 260 if "name" in attrs: 261 self.name = attrs["name"] 262 else: 263 self.name = "" 264 self.domain = domain 265 self.variant = variant 266 self.offset = int(attrs["offset"], 0) 267 self.stride = int(attrs["stride"], 0) 268 self.length = int(attrs["length"], 0) 269 if "usage" in attrs: 270 self.usages = attrs["usage"].split(',') 271 else: 272 self.usages = None 273 274 def dump(self): 275 print("#define REG_%s_%s(i0) (0x%08x + 0x%x*(i0))\n" % (self.domain, self.name, self.offset, self.stride)) 276 277 def dump_pack_struct(self): 278 pass 279 280 def dump_regpair_builder(self): 281 pass 282 283class Reg(object): 284 def __init__(self, attrs, domain, array, bit_size): 285 self.name = attrs["name"] 286 self.domain = domain 287 self.array = array 288 self.offset = int(attrs["offset"], 0) 289 self.type = None 290 self.bit_size = bit_size 291 if array: 292 self.name = array.name + "_" + self.name 293 self.full_name = self.domain + "_" + self.name 294 295 def dump(self): 296 if self.array: 297 offset = self.array.offset + self.offset 298 print("static inline uint32_t REG_%s(uint32_t i0) { return 0x%08x + 0x%x*i0; }" % (self.full_name, offset, self.array.stride)) 299 else: 300 tab_to("#define REG_%s" % self.full_name, "0x%08x" % self.offset) 301 302 if self.bitset.inline: 303 self.bitset.dump(self.full_name) 304 305 def dump_pack_struct(self): 306 if self.bitset.inline: 307 self.bitset.dump_pack_struct(self) 308 309 def dump_regpair_builder(self): 310 if self.bitset.inline: 311 self.bitset.dump_regpair_builder(self) 312 313 def dump_py(self): 314 print("\tREG_%s = 0x%08x" % (self.full_name, self.offset)) 315 316 317class Parser(object): 318 def __init__(self): 319 self.current_array = None 320 self.current_domain = None 321 self.current_prefix = None 322 self.current_prefix_type = None 323 self.current_stripe = None 324 self.current_bitset = None 325 self.current_bitsize = 32 326 # The varset attribute on the domain specifies the enum which 327 # specifies all possible hw variants: 328 self.current_varset = None 329 # Regs that have multiple variants.. we only generated the C++ 330 # template based struct-packers for these 331 self.variant_regs = {} 332 # Information in which contexts regs are used, to be used in 333 # debug options 334 self.usage_regs = collections.defaultdict(list) 335 self.bitsets = {} 336 self.enums = {} 337 self.variants = set() 338 self.file = [] 339 self.xml_files = [] 340 self.copyright_year = None 341 self.authors = [] 342 self.license = None 343 344 def error(self, message): 345 parser, filename = self.stack[-1] 346 return Error("%s:%d:%d: %s" % (filename, parser.CurrentLineNumber, parser.CurrentColumnNumber, message)) 347 348 def prefix(self, variant=None): 349 if self.current_prefix_type == "variant" and variant: 350 return variant 351 elif self.current_stripe: 352 return self.current_stripe + "_" + self.current_domain 353 elif self.current_prefix: 354 return self.current_prefix + "_" + self.current_domain 355 else: 356 return self.current_domain 357 358 def parse_field(self, name, attrs): 359 try: 360 if "pos" in attrs: 361 high = low = int(attrs["pos"], 0) 362 elif "high" in attrs and "low" in attrs: 363 high = int(attrs["high"], 0) 364 low = int(attrs["low"], 0) 365 else: 366 low = 0 367 high = self.current_bitsize - 1 368 369 if "type" in attrs: 370 type = attrs["type"] 371 else: 372 type = None 373 374 if "shr" in attrs: 375 shr = int(attrs["shr"], 0) 376 else: 377 shr = 0 378 379 b = Field(name, low, high, shr, type, self) 380 381 if type == "fixed" or type == "ufixed": 382 b.radix = int(attrs["radix"], 0) 383 384 self.current_bitset.fields.append(b) 385 except ValueError as e: 386 raise self.error(e) 387 388 def parse_varset(self, attrs): 389 # Inherit the varset from the enclosing domain if not overriden: 390 varset = self.current_varset 391 if "varset" in attrs: 392 varset = self.enums[attrs["varset"]] 393 return varset 394 395 def parse_variants(self, attrs): 396 if not "variants" in attrs: 397 return None 398 variant = attrs["variants"].split(",")[0] 399 if "-" in variant: 400 variant = variant[:variant.index("-")] 401 402 varset = self.parse_varset(attrs) 403 404 assert varset.has_name(variant) 405 406 return variant 407 408 def add_all_variants(self, reg, attrs, parent_variant): 409 # TODO this should really handle *all* variants, including dealing 410 # with open ended ranges (ie. "A2XX,A4XX-") (we have the varset 411 # enum now to make that possible) 412 variant = self.parse_variants(attrs) 413 if not variant: 414 variant = parent_variant 415 416 if reg.name not in self.variant_regs: 417 self.variant_regs[reg.name] = {} 418 else: 419 # All variants must be same size: 420 v = next(iter(self.variant_regs[reg.name])) 421 assert self.variant_regs[reg.name][v].bit_size == reg.bit_size 422 423 self.variant_regs[reg.name][variant] = reg 424 425 def add_all_usages(self, reg, usages): 426 if not usages: 427 return 428 429 for usage in usages: 430 self.usage_regs[usage].append(reg) 431 432 self.variants.add(reg.domain) 433 434 def do_validate(self, schemafile): 435 try: 436 from lxml import etree 437 438 parser, filename = self.stack[-1] 439 dirname = os.path.dirname(filename) 440 441 # we expect this to look like <namespace url> schema.xsd.. I think 442 # technically it is supposed to be just a URL, but that doesn't 443 # quite match up to what we do.. Just skip over everything up to 444 # and including the first whitespace character: 445 schemafile = schemafile[schemafile.rindex(" ")+1:] 446 447 # this is a bit cheezy, but the xml file to validate could be 448 # in a child director, ie. we don't really know where the schema 449 # file is, the way the rnn C code does. So if it doesn't exist 450 # just look one level up 451 if not os.path.exists(dirname + "/" + schemafile): 452 schemafile = "../" + schemafile 453 454 if not os.path.exists(dirname + "/" + schemafile): 455 raise self.error("Cannot find schema for: " + filename) 456 457 xmlschema_doc = etree.parse(dirname + "/" + schemafile) 458 xmlschema = etree.XMLSchema(xmlschema_doc) 459 460 xml_doc = etree.parse(filename) 461 if not xmlschema.validate(xml_doc): 462 error_str = str(xmlschema.error_log.filter_from_errors()[0]) 463 raise self.error("Schema validation failed for: " + filename + "\n" + error_str) 464 except ImportError: 465 print("lxml not found, skipping validation", file=sys.stderr) 466 467 def do_parse(self, filename): 468 filepath = os.path.abspath(filename) 469 if filepath in self.xml_files: 470 return 471 self.xml_files.append(filepath) 472 file = open(filename, "rb") 473 parser = xml.parsers.expat.ParserCreate() 474 self.stack.append((parser, filename)) 475 parser.StartElementHandler = self.start_element 476 parser.EndElementHandler = self.end_element 477 parser.CharacterDataHandler = self.character_data 478 parser.buffer_text = True 479 parser.ParseFile(file) 480 self.stack.pop() 481 file.close() 482 483 def parse(self, rnn_path, filename): 484 self.path = rnn_path 485 self.stack = [] 486 self.do_parse(filename) 487 488 def parse_reg(self, attrs, bit_size): 489 self.current_bitsize = bit_size 490 if "type" in attrs and attrs["type"] in self.bitsets: 491 bitset = self.bitsets[attrs["type"]] 492 if bitset.inline: 493 self.current_bitset = Bitset(attrs["name"], bitset) 494 self.current_bitset.inline = True 495 else: 496 self.current_bitset = bitset 497 else: 498 self.current_bitset = Bitset(attrs["name"], None) 499 self.current_bitset.inline = True 500 if "type" in attrs: 501 self.parse_field(None, attrs) 502 503 variant = self.parse_variants(attrs) 504 if not variant and self.current_array: 505 variant = self.current_array.variant 506 507 self.current_reg = Reg(attrs, self.prefix(variant), self.current_array, bit_size) 508 self.current_reg.bitset = self.current_bitset 509 510 if len(self.stack) == 1: 511 self.file.append(self.current_reg) 512 513 if variant is not None: 514 self.add_all_variants(self.current_reg, attrs, variant) 515 516 usages = None 517 if "usage" in attrs: 518 usages = attrs["usage"].split(',') 519 elif self.current_array: 520 usages = self.current_array.usages 521 522 self.add_all_usages(self.current_reg, usages) 523 524 def start_element(self, name, attrs): 525 self.cdata = "" 526 if name == "import": 527 filename = attrs["file"] 528 self.do_parse(os.path.join(self.path, filename)) 529 elif name == "domain": 530 self.current_domain = attrs["name"] 531 if "prefix" in attrs: 532 self.current_prefix = self.parse_variants(attrs) 533 self.current_prefix_type = attrs["prefix"] 534 else: 535 self.current_prefix = None 536 self.current_prefix_type = None 537 if "varset" in attrs: 538 self.current_varset = self.enums[attrs["varset"]] 539 elif name == "stripe": 540 self.current_stripe = self.parse_variants(attrs) 541 elif name == "enum": 542 self.current_enum_value = 0 543 self.current_enum = Enum(attrs["name"]) 544 self.enums[attrs["name"]] = self.current_enum 545 if len(self.stack) == 1: 546 self.file.append(self.current_enum) 547 elif name == "value": 548 if "value" in attrs: 549 value = int(attrs["value"], 0) 550 else: 551 value = self.current_enum_value 552 self.current_enum.values.append((attrs["name"], value)) 553 elif name == "reg32": 554 self.parse_reg(attrs, 32) 555 elif name == "reg64": 556 self.parse_reg(attrs, 64) 557 elif name == "array": 558 self.current_bitsize = 32 559 variant = self.parse_variants(attrs) 560 self.current_array = Array(attrs, self.prefix(variant), variant) 561 if len(self.stack) == 1: 562 self.file.append(self.current_array) 563 elif name == "bitset": 564 self.current_bitset = Bitset(attrs["name"], None) 565 if "inline" in attrs and attrs["inline"] == "yes": 566 self.current_bitset.inline = True 567 self.bitsets[self.current_bitset.name] = self.current_bitset 568 if len(self.stack) == 1 and not self.current_bitset.inline: 569 self.file.append(self.current_bitset) 570 elif name == "bitfield" and self.current_bitset: 571 self.parse_field(attrs["name"], attrs) 572 elif name == "database": 573 self.do_validate(attrs["xsi:schemaLocation"]) 574 elif name == "copyright": 575 self.copyright_year = attrs["year"] 576 elif name == "author": 577 self.authors.append(attrs["name"] + " <" + attrs["email"] + "> " + attrs["name"]) 578 579 def end_element(self, name): 580 if name == "domain": 581 self.current_domain = None 582 self.current_prefix = None 583 self.current_prefix_type = None 584 elif name == "stripe": 585 self.current_stripe = None 586 elif name == "bitset": 587 self.current_bitset = None 588 elif name == "reg32": 589 self.current_reg = None 590 elif name == "array": 591 self.current_array = None 592 elif name == "enum": 593 self.current_enum = None 594 elif name == "license": 595 self.license = self.cdata 596 597 def character_data(self, data): 598 self.cdata += data 599 600 def dump_reg_usages(self): 601 d = collections.defaultdict(list) 602 for usage, regs in self.usage_regs.items(): 603 for reg in regs: 604 variants = self.variant_regs.get(reg.name) 605 if variants: 606 for variant, vreg in variants.items(): 607 if reg == vreg: 608 d[(usage, variant)].append(reg) 609 else: 610 for variant in self.variants: 611 d[(usage, variant)].append(reg) 612 613 print("#ifdef __cplusplus") 614 615 for usage, regs in self.usage_regs.items(): 616 print("template<chip CHIP> constexpr inline uint16_t %s_REGS[] = {};" % (usage.upper())) 617 618 for (usage, variant), regs in d.items(): 619 offsets = [] 620 621 for reg in regs: 622 if reg.array: 623 for i in range(reg.array.length): 624 offsets.append(reg.array.offset + reg.offset + i * reg.array.stride) 625 if reg.bit_size == 64: 626 offsets.append(offsets[-1] + 1) 627 else: 628 offsets.append(reg.offset) 629 if reg.bit_size == 64: 630 offsets.append(offsets[-1] + 1) 631 632 offsets.sort() 633 634 print("template<> constexpr inline uint16_t %s_REGS<%s>[] = {" % (usage.upper(), variant)) 635 for offset in offsets: 636 print("\t%s," % hex(offset)) 637 print("};") 638 639 print("#endif") 640 641 def dump(self): 642 enums = [] 643 bitsets = [] 644 regs = [] 645 for e in self.file: 646 if isinstance(e, Enum): 647 enums.append(e) 648 elif isinstance(e, Bitset): 649 bitsets.append(e) 650 else: 651 regs.append(e) 652 653 for e in enums + bitsets + regs: 654 e.dump() 655 656 self.dump_reg_usages() 657 658 659 def dump_regs_py(self): 660 regs = [] 661 for e in self.file: 662 if isinstance(e, Reg): 663 regs.append(e) 664 665 for e in regs: 666 e.dump_py() 667 668 669 def dump_reg_variants(self, regname, variants): 670 # Don't bother for things that only have a single variant: 671 if len(variants) == 1: 672 return 673 print("#ifdef __cplusplus") 674 print("struct __%s {" % regname) 675 # TODO be more clever.. we should probably figure out which 676 # fields have the same type in all variants (in which they 677 # appear) and stuff everything else in a variant specific 678 # sub-structure. 679 seen_fields = [] 680 bit_size = 32 681 array = False 682 address = None 683 for variant in variants.keys(): 684 print(" /* %s fields: */" % variant) 685 reg = variants[variant] 686 bit_size = reg.bit_size 687 array = reg.array 688 for f in reg.bitset.fields: 689 fld_name = field_name(reg, f) 690 if fld_name in seen_fields: 691 continue 692 seen_fields.append(fld_name) 693 name = fld_name.lower() 694 if f.type in [ "address", "waddress" ]: 695 if address: 696 continue 697 address = f 698 tab_to(" __bo_type", "bo;") 699 tab_to(" uint32_t", "bo_offset;") 700 continue 701 type, val = f.ctype("var") 702 tab_to(" %s" %type, "%s;" %name) 703 print(" /* fallback fields: */") 704 if bit_size == 64: 705 tab_to(" uint64_t", "unknown;") 706 tab_to(" uint64_t", "qword;") 707 else: 708 tab_to(" uint32_t", "unknown;") 709 tab_to(" uint32_t", "dword;") 710 print("};") 711 # TODO don't hardcode the varset enum name 712 varenum = "chip" 713 print("template <%s %s>" % (varenum, varenum.upper())) 714 print("static inline struct fd_reg_pair") 715 xtra = "" 716 xtravar = "" 717 if array: 718 xtra = "int __i, " 719 xtravar = "__i, " 720 print("__%s(%sstruct __%s fields) {" % (regname, xtra, regname)) 721 for variant in variants.keys(): 722 print(" if (%s == %s) {" % (varenum.upper(), variant)) 723 reg = variants[variant] 724 reg.dump_regpair_builder() 725 print(" } else") 726 print(" assert(!\"invalid variant\");") 727 print("}") 728 729 if bit_size == 64: 730 skip = ", { .reg = 0 }" 731 else: 732 skip = "" 733 734 print("#define %s(VARIANT, %s...) __%s<VARIANT>(%s{__VA_ARGS__})%s" % (regname, xtravar, regname, xtravar, skip)) 735 print("#endif /* __cplusplus */") 736 737 def dump_structs(self): 738 for e in self.file: 739 e.dump_pack_struct() 740 741 for regname in self.variant_regs: 742 self.dump_reg_variants(regname, self.variant_regs[regname]) 743 744 745def dump_c(args, guard, func): 746 p = Parser() 747 748 try: 749 p.parse(args.rnn, args.xml) 750 except Error as e: 751 print(e, file=sys.stderr) 752 exit(1) 753 754 print("#ifndef %s\n#define %s\n" % (guard, guard)) 755 756 print("""/* Autogenerated file, DO NOT EDIT manually! 757 758This file was generated by the rules-ng-ng gen_header.py tool in this git repository: 759http://gitlab.freedesktop.org/mesa/mesa/ 760git clone https://gitlab.freedesktop.org/mesa/mesa.git 761 762The rules-ng-ng source files this header was generated from are: 763""") 764 maxlen = 0 765 for filepath in p.xml_files: 766 maxlen = max(maxlen, len(filepath)) 767 for filepath in p.xml_files: 768 pad = " " * (maxlen - len(filepath)) 769 filesize = str(os.path.getsize(filepath)) 770 filesize = " " * (7 - len(filesize)) + filesize 771 filetime = time.ctime(os.path.getmtime(filepath)) 772 print("- " + filepath + pad + " (" + filesize + " bytes, from " + filetime + ")") 773 if p.copyright_year: 774 current_year = str(datetime.date.today().year) 775 print() 776 print("Copyright (C) %s-%s by the following authors:" % (p.copyright_year, current_year)) 777 for author in p.authors: 778 print("- " + author) 779 if p.license: 780 print(p.license) 781 print("*/") 782 783 print() 784 print("#ifdef __KERNEL__") 785 print("#include <linux/bug.h>") 786 print("#define assert(x) BUG_ON(!(x))") 787 print("#else") 788 print("#include <assert.h>") 789 print("#endif") 790 print() 791 792 print("#ifdef __cplusplus") 793 print("#define __struct_cast(X)") 794 print("#else") 795 print("#define __struct_cast(X) (struct X)") 796 print("#endif") 797 print() 798 799 func(p) 800 801 print("\n#endif /* %s */" % guard) 802 803 804def dump_c_defines(args): 805 guard = str.replace(os.path.basename(args.xml), '.', '_').upper() 806 dump_c(args, guard, lambda p: p.dump()) 807 808 809def dump_c_pack_structs(args): 810 guard = str.replace(os.path.basename(args.xml), '.', '_').upper() + '_STRUCTS' 811 dump_c(args, guard, lambda p: p.dump_structs()) 812 813 814def dump_py_defines(args): 815 p = Parser() 816 817 try: 818 p.parse(args.rnn, args.xml) 819 except Error as e: 820 print(e, file=sys.stderr) 821 exit(1) 822 823 file_name = os.path.splitext(os.path.basename(args.xml))[0] 824 825 print("from enum import IntEnum") 826 print("class %sRegs(IntEnum):" % file_name.upper()) 827 828 os.path.basename(args.xml) 829 830 p.dump_regs_py() 831 832 833def main(): 834 parser = argparse.ArgumentParser() 835 parser.add_argument('--rnn', type=str, required=True) 836 parser.add_argument('--xml', type=str, required=True) 837 838 subparsers = parser.add_subparsers(required=True) 839 840 parser_c_defines = subparsers.add_parser('c-defines') 841 parser_c_defines.set_defaults(func=dump_c_defines) 842 843 parser_c_pack_structs = subparsers.add_parser('c-pack-structs') 844 parser_c_pack_structs.set_defaults(func=dump_c_pack_structs) 845 846 parser_py_defines = subparsers.add_parser('py-defines') 847 parser_py_defines.set_defaults(func=dump_py_defines) 848 849 args = parser.parse_args() 850 args.func(args) 851 852 853if __name__ == '__main__': 854 main() 855