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