gen_header.py 27 KB

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