Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

drm/msm: import gen_header.py script from Mesa

Import the gen_headers.py script from Mesa, commit b5414e716684
("freedreno/registers: Add license header"). This script will be used to
generate MSM register files on the fly during compilation.

Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
Patchwork: https://patchwork.freedesktop.org/patch/585864/
Link: https://lore.kernel.org/r/20240401-fd-xml-shipped-v5-10-4bdb277a85a1@linaro.org

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