3 import xml
.parsers
.expat
7 class Error(Exception):
8 def __init__(self
, message
):
12 def __init__(self
, name
):
19 for (name
, value
) in self
.values
:
23 print("enum %s {" % self
.name
)
24 for (name
, value
) in self
.values
:
26 print("\t%s = 0x%08x," % (name
, value
))
28 print("\t%s = %d," % (name
, value
))
31 def dump_pack_struct(self
):
35 def __init__(self
, name
, low
, high
, shr
, type, parser
):
42 builtin_types
= [ None, "a3xx_regid", "boolean", "uint", "hex", "int", "fixed", "ufixed", "float", "address", "waddress" ]
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
)
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);
57 def ctype(self
, var_name
):
61 elif self
.type == "boolean":
64 elif self
.type == "uint" or self
.type == "hex" or self
.type == "a3xx_regid":
67 elif self
.type == "int":
70 elif self
.type == "fixed":
72 val
= "((int32_t)(%s * %d.0))" % (var_name
, 1 << self
.radix
)
73 elif self
.type == "ufixed":
75 val
= "((uint32_t)(%s * %d.0))" % (var_name
, 1 << self
.radix
)
76 elif self
.type == "float" and self
.high
- self
.low
== 31:
78 val
= "fui(%s)" % var_name
79 elif self
.type == "float" and self
.high
- self
.low
== 15:
81 val
= "util_float_to_half(%s)" % var_name
82 elif self
.type in [ "address", "waddress" ]:
86 type = "enum %s" % self
.type
90 val
= "(%s >> %d)" % (val
, self
.shr
)
94 def tab_to(name
, value
):
95 tab_count
= (68 - (len(name
) & ~
7)) // 8
98 print(name
+ ('\t' * tab_count
) + value
)
101 return ((0xffffffff >> (32 - (high
+ 1 - low
))) << low
)
103 class Bitset(object):
104 def __init__(self
, name
, template
):
108 self
.fields
= template
.fields
112 def dump_pack_struct(self
, prefix
=None, array
=None):
113 def field_name(prefix
, name
):
115 name
= f
.name
.lower()
117 name
= prefix
.lower()
119 if (name
in [ "double", "float", "int" ]) or not (name
[0].isalpha()):
129 print("struct %s {" % prefix
)
130 for f
in self
.fields
:
131 if f
.type in [ "address", "waddress" ]:
132 tab_to(" __bo_type", "bo;")
133 tab_to(" uint32_t", "bo_offset;")
135 name
= field_name(prefix
, f
.name
)
137 type, val
= f
.ctype("var")
139 tab_to(" %s" % type, "%s;" % name
)
140 tab_to(" uint32_t", "unknown;")
141 tab_to(" uint32_t", "dword;")
145 for f
in self
.fields
:
146 if f
.type in [ "address", "waddress" ]:
149 print("static inline struct fd_reg_pair\npack_%s(uint32_t i, struct %s fields)\n{" %
152 print("static inline struct fd_reg_pair\npack_%s(struct %s fields)\n{" %
155 print("#ifndef NDEBUG")
157 for f
in self
.fields
:
158 known_mask |
= mask(f
.low
, f
.high
)
159 if f
.type in [ "boolean", "address", "waddress" ]:
161 type, val
= f
.ctype("fields.%s" % field_name(prefix
, f
.name
))
162 print(" assert((%-40s & 0x%08x) == 0);" % (val
, 0xffffffff ^
mask(0 , f
.high
- f
.low
)))
163 print(" assert((%-40s & 0x%08x) == 0);" % ("fields.unknown", known_mask
))
166 print(" return (struct fd_reg_pair) {")
168 print(" .reg = REG_%s(i)," % prefix
)
170 print(" .reg = REG_%s," % prefix
)
173 for f
in self
.fields
:
174 if f
.type in [ "address", "waddress" ]:
177 type, val
= f
.ctype("fields.%s" % field_name(prefix
, f
.name
))
178 print(" (%-40s << %2d) |" % (val
, f
.low
))
179 print(" fields.unknown | fields.dword,")
182 print(" .is_address = true,")
183 print(" .bo = fields.bo,")
184 if f
.type == "waddress":
185 print(" .bo_write = true,")
186 print(" .bo_offset = fields.bo_offset,")
187 print(" .bo_shift = %d" % address
.shr
)
192 skip
= ", { .reg = 0 }"
197 print("#define %s(i, ...) pack_%s(i, (struct %s) { __VA_ARGS__ })%s\n" %
198 (prefix
, prefix
, prefix
, skip
))
200 print("#define %s(...) pack_%s((struct %s) { __VA_ARGS__ })%s\n" %
201 (prefix
, prefix
, prefix
, skip
))
204 def dump(self
, prefix
=None):
207 for f
in self
.fields
:
209 name
= prefix
+ "_" + f
.name
213 if not f
.name
and f
.low
== 0 and f
.shr
== 0 and not f
.type in ["float", "fixed", "ufixed"]:
215 elif f
.type == "boolean" or (f
.type == None and f
.low
== f
.high
):
216 tab_to("#define %s" % name
, "0x%08x" % (1 << f
.low
))
218 tab_to("#define %s__MASK" % name
, "0x%08x" % mask(f
.low
, f
.high
))
219 tab_to("#define %s__SHIFT" % name
, "%d" % f
.low
)
220 type, val
= f
.ctype("val")
222 print("static inline uint32_t %s(%s val)\n{" % (name
, type))
224 print("\tassert(!(val & 0x%x));" % mask(0, f
.shr
- 1))
225 print("\treturn ((%s) << %s__SHIFT) & %s__MASK;\n}" % (val
, name
, name
))
229 def __init__(self
, attrs
, domain
):
230 self
.name
= attrs
["name"]
232 self
.offset
= int(attrs
["offset"], 0)
233 self
.stride
= int(attrs
["stride"], 0)
234 self
.length
= int(attrs
["length"], 0)
237 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
))
239 def dump_pack_struct(self
):
243 def __init__(self
, attrs
, domain
, array
, bit_size
):
244 self
.name
= attrs
["name"]
247 self
.offset
= int(attrs
["offset"], 0)
249 self
.bit_size
= bit_size
252 self
.full_name
= self
.domain
+ "_" + self
.array
.name
+ "_" + self
.name
254 self
.full_name
= self
.domain
+ "_" + self
.name
258 offset
= self
.array
.offset
+ self
.offset
259 print("static inline uint32_t REG_%s(uint32_t i0) { return 0x%08x + 0x%x*i0; }" % (self
.full_name
, offset
, self
.array
.stride
))
261 tab_to("#define REG_%s" % self
.full_name
, "0x%08x" % self
.offset
)
263 if self
.bitset
.inline
:
264 self
.bitset
.dump(self
.full_name
)
267 def dump_pack_struct(self
):
268 if self
.bitset
.inline
:
269 self
.bitset
.dump_pack_struct(self
.full_name
, not self
.array
== None)
272 def parse_variants(attrs
):
273 if not "variants" in attrs
:
275 variant
= attrs
["variants"].split(",")[0]
277 variant
= variant
[:variant
.index("-")]
281 class Parser(object):
283 self
.current_array
= None
284 self
.current_domain
= None
285 self
.current_prefix
= None
286 self
.current_stripe
= None
287 self
.current_bitset
= None
292 def error(self
, message
):
293 parser
, filename
= self
.stack
[-1]
294 return Error("%s:%d:%d: %s" % (filename
, parser
.CurrentLineNumber
, parser
.CurrentColumnNumber
, message
))
297 if self
.current_stripe
:
298 return self
.current_stripe
+ "_" + self
.current_domain
299 elif self
.current_prefix
:
300 return self
.current_prefix
+ "_" + self
.current_domain
302 return self
.current_domain
304 def parse_field(self
, name
, attrs
):
307 high
= low
= int(attrs
["pos"], 0)
308 elif "high" in attrs
and "low" in attrs
:
309 high
= int(attrs
["high"], 0)
310 low
= int(attrs
["low"], 0)
321 shr
= int(attrs
["shr"], 0)
325 b
= Field(name
, low
, high
, shr
, type, self
)
327 if type == "fixed" or type == "ufixed":
328 b
.radix
= int(attrs
["radix"], 0)
330 self
.current_bitset
.fields
.append(b
)
331 except ValueError as e
:
334 def do_parse(self
, filename
):
335 file = open(filename
, "rb")
336 parser
= xml
.parsers
.expat
.ParserCreate()
337 self
.stack
.append((parser
, filename
))
338 parser
.StartElementHandler
= self
.start_element
339 parser
.EndElementHandler
= self
.end_element
340 parser
.ParseFile(file)
344 def parse(self
, filename
):
345 self
.path
= os
.path
.dirname(filename
)
347 self
.do_parse(filename
)
349 def parse_reg(self
, attrs
, bit_size
):
350 if "type" in attrs
and attrs
["type"] in self
.bitsets
:
351 self
.current_bitset
= self
.bitsets
[attrs
["type"]]
353 self
.current_bitset
= Bitset(attrs
["name"], None)
354 self
.current_bitset
.inline
= True
356 self
.parse_field(None, attrs
)
358 self
.current_reg
= Reg(attrs
, self
.prefix(), self
.current_array
, bit_size
)
359 self
.current_reg
.bitset
= self
.current_bitset
361 if len(self
.stack
) == 1:
362 self
.file.append(self
.current_reg
)
364 def start_element(self
, name
, attrs
):
366 filename
= os
.path
.basename(attrs
["file"])
367 self
.do_parse(os
.path
.join(self
.path
, filename
))
368 elif name
== "domain":
369 self
.current_domain
= attrs
["name"]
370 if "prefix" in attrs
and attrs
["prefix"] == "chip":
371 self
.current_prefix
= parse_variants(attrs
)
372 elif name
== "stripe":
373 self
.current_stripe
= parse_variants(attrs
)
375 self
.current_enum_value
= 0
376 self
.current_enum
= Enum(attrs
["name"])
377 self
.enums
[attrs
["name"]] = self
.current_enum
378 if len(self
.stack
) == 1:
379 self
.file.append(self
.current_enum
)
380 elif name
== "value":
382 value
= int(attrs
["value"], 0)
384 value
= self
.current_enum_value
385 self
.current_enum
.values
.append((attrs
["name"], value
))
386 # self.current_enum_value = value + 1
387 elif name
== "reg32":
388 self
.parse_reg(attrs
, 32)
389 elif name
== "reg64":
390 self
.parse_reg(attrs
, 64)
391 elif name
== "array":
392 self
.current_array
= Array(attrs
, self
.prefix())
393 if len(self
.stack
) == 1:
394 self
.file.append(self
.current_array
)
395 elif name
== "bitset":
396 self
.current_bitset
= Bitset(attrs
["name"], None)
397 if "inline" in attrs
and attrs
["inline"] == "yes":
398 self
.current_bitset
.inline
= True
399 self
.bitsets
[self
.current_bitset
.name
] = self
.current_bitset
400 if len(self
.stack
) == 1 and not self
.current_bitset
.inline
:
401 self
.file.append(self
.current_bitset
)
402 elif name
== "bitfield" and self
.current_bitset
:
403 self
.parse_field(attrs
["name"], attrs
)
405 def end_element(self
, name
):
407 self
.current_domain
= None
408 self
.current_prefix
= None
409 elif name
== "stripe":
410 self
.current_stripe
= None
411 elif name
== "bitset":
412 self
.current_bitset
= None
413 elif name
== "reg32":
414 self
.current_reg
= None
415 elif name
== "array":
416 self
.current_array
= None;
418 self
.current_enum
= None
425 if isinstance(e
, Enum
):
427 elif isinstance(e
, Bitset
):
432 for e
in enums
+ bitsets
+ regs
:
435 def dump_structs(self
):
442 xml_file
= sys
.argv
[1]
443 if len(sys
.argv
) > 2 and sys
.argv
[2] == '--pack-structs':
445 guard
= str.replace(os
.path
.basename(xml_file
), '.', '_').upper() + '_STRUCTS'
448 guard
= str.replace(os
.path
.basename(xml_file
), '.', '_').upper()
450 print("#ifndef %s\n#define %s\n" % (guard
, guard
))
463 print("\n#endif /* %s */" % guard
)
465 if __name__
== '__main__':