Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mesa
Path: blob/21.2-virgl/src/freedreno/registers/gen_header.py
7326 views
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 = "_mesa_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, bit_size=32):
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
value_name = "dword"
130
print("struct %s {" % prefix)
131
for f in self.fields:
132
if f.type in [ "address", "waddress" ]:
133
tab_to(" __bo_type", "bo;")
134
tab_to(" uint32_t", "bo_offset;")
135
if bit_size == 64:
136
value_name = "qword"
137
continue
138
name = field_name(prefix, f.name)
139
140
type, val = f.ctype("var")
141
142
tab_to(" %s" % type, "%s;" % name)
143
if value_name == "qword":
144
tab_to(" uint64_t", "unknown;")
145
tab_to(" uint64_t", "qword;")
146
else:
147
tab_to(" uint32_t", "unknown;")
148
tab_to(" uint32_t", "dword;")
149
print("};\n")
150
151
address = None;
152
for f in self.fields:
153
if f.type in [ "address", "waddress" ]:
154
address = f
155
if array:
156
print("static inline struct fd_reg_pair\npack_%s(uint32_t i, struct %s fields)\n{" %
157
(prefix, prefix));
158
else:
159
print("static inline struct fd_reg_pair\npack_%s(struct %s fields)\n{" %
160
(prefix, prefix));
161
162
print("#ifndef NDEBUG")
163
known_mask = 0
164
for f in self.fields:
165
known_mask |= mask(f.low, f.high)
166
if f.type in [ "boolean", "address", "waddress" ]:
167
continue
168
type, val = f.ctype("fields.%s" % field_name(prefix, f.name))
169
print(" assert((%-40s & 0x%08x) == 0);" % (val, 0xffffffff ^ mask(0 , f.high - f.low)))
170
print(" assert((%-40s & 0x%08x) == 0);" % ("fields.unknown", known_mask))
171
print("#endif\n")
172
173
print(" return (struct fd_reg_pair) {")
174
if array:
175
print(" .reg = REG_%s(i)," % prefix)
176
else:
177
print(" .reg = REG_%s," % prefix)
178
179
print(" .value =")
180
for f in self.fields:
181
if f.type in [ "address", "waddress" ]:
182
continue
183
else:
184
type, val = f.ctype("fields.%s" % field_name(prefix, f.name))
185
print(" (%-40s << %2d) |" % (val, f.low))
186
print(" fields.unknown | fields.%s," % (value_name,))
187
188
if address:
189
print(" .is_address = true,")
190
print(" .bo = fields.bo,")
191
if f.type == "waddress":
192
print(" .bo_write = true,")
193
print(" .bo_offset = fields.bo_offset,")
194
print(" .bo_shift = %d" % address.shr)
195
196
print(" };\n}\n")
197
198
if address:
199
skip = ", { .reg = 0 }"
200
else:
201
skip = ""
202
203
if array:
204
print("#define %s(i, ...) pack_%s(i, (struct %s) { __VA_ARGS__ })%s\n" %
205
(prefix, prefix, prefix, skip))
206
else:
207
print("#define %s(...) pack_%s((struct %s) { __VA_ARGS__ })%s\n" %
208
(prefix, prefix, prefix, skip))
209
210
211
def dump(self, prefix=None):
212
if prefix == None:
213
prefix = self.name
214
for f in self.fields:
215
if f.name:
216
name = prefix + "_" + f.name
217
else:
218
name = prefix
219
220
if not f.name and f.low == 0 and f.shr == 0 and not f.type in ["float", "fixed", "ufixed"]:
221
pass
222
elif f.type == "boolean" or (f.type == None and f.low == f.high):
223
tab_to("#define %s" % name, "0x%08x" % (1 << f.low))
224
else:
225
tab_to("#define %s__MASK" % name, "0x%08x" % mask(f.low, f.high))
226
tab_to("#define %s__SHIFT" % name, "%d" % f.low)
227
type, val = f.ctype("val")
228
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
235
class Array(object):
236
def __init__(self, attrs, domain):
237
if "name" in attrs:
238
self.name = attrs["name"]
239
else:
240
self.name = ""
241
self.domain = domain
242
self.offset = int(attrs["offset"], 0)
243
self.stride = int(attrs["stride"], 0)
244
self.length = int(attrs["length"], 0)
245
246
def dump(self):
247
print("#define REG_%s_%s(i0) (0x%08x + 0x%x*(i0))\n" % (self.domain, self.name, self.offset, self.stride))
248
249
def dump_pack_struct(self):
250
pass
251
252
class Reg(object):
253
def __init__(self, attrs, domain, array, bit_size):
254
self.name = attrs["name"]
255
self.domain = domain
256
self.array = array
257
self.offset = int(attrs["offset"], 0)
258
self.type = None
259
self.bit_size = bit_size
260
261
if self.array:
262
self.full_name = self.domain + "_" + self.array.name + "_" + self.name
263
else:
264
self.full_name = self.domain + "_" + self.name
265
266
def dump(self):
267
if self.array:
268
offset = self.array.offset + self.offset
269
print("static inline uint32_t REG_%s(uint32_t i0) { return 0x%08x + 0x%x*i0; }" % (self.full_name, offset, self.array.stride))
270
else:
271
tab_to("#define REG_%s" % self.full_name, "0x%08x" % self.offset)
272
273
if self.bitset.inline:
274
self.bitset.dump(self.full_name)
275
print("")
276
277
def dump_pack_struct(self):
278
if self.bitset.inline:
279
self.bitset.dump_pack_struct(self.full_name, not self.array == None, self.bit_size)
280
281
282
def parse_variants(attrs):
283
if not "variants" in attrs:
284
return None
285
variant = attrs["variants"].split(",")[0]
286
if "-" in variant:
287
variant = variant[:variant.index("-")]
288
289
return variant
290
291
class Parser(object):
292
def __init__(self):
293
self.current_array = None
294
self.current_domain = None
295
self.current_prefix = None
296
self.current_stripe = None
297
self.current_bitset = None
298
self.bitsets = {}
299
self.enums = {}
300
self.file = []
301
302
def error(self, message):
303
parser, filename = self.stack[-1]
304
return Error("%s:%d:%d: %s" % (filename, parser.CurrentLineNumber, parser.CurrentColumnNumber, message))
305
306
def prefix(self):
307
if self.current_stripe:
308
return self.current_stripe + "_" + self.current_domain
309
elif self.current_prefix:
310
return self.current_prefix + "_" + self.current_domain
311
else:
312
return self.current_domain
313
314
def parse_field(self, name, attrs):
315
try:
316
if "pos" in attrs:
317
high = low = int(attrs["pos"], 0)
318
elif "high" in attrs and "low" in attrs:
319
high = int(attrs["high"], 0)
320
low = int(attrs["low"], 0)
321
else:
322
low = 0
323
high = 31
324
325
if "type" in attrs:
326
type = attrs["type"]
327
else:
328
type = None
329
330
if "shr" in attrs:
331
shr = int(attrs["shr"], 0)
332
else:
333
shr = 0
334
335
b = Field(name, low, high, shr, type, self)
336
337
if type == "fixed" or type == "ufixed":
338
b.radix = int(attrs["radix"], 0)
339
340
self.current_bitset.fields.append(b)
341
except ValueError as e:
342
raise self.error(e);
343
344
def do_parse(self, filename):
345
file = open(filename, "rb")
346
parser = xml.parsers.expat.ParserCreate()
347
self.stack.append((parser, filename))
348
parser.StartElementHandler = self.start_element
349
parser.EndElementHandler = self.end_element
350
parser.ParseFile(file)
351
self.stack.pop()
352
file.close()
353
354
def parse(self, rnn_path, filename):
355
self.path = rnn_path
356
self.stack = []
357
self.do_parse(filename)
358
359
def parse_reg(self, attrs, bit_size):
360
if "type" in attrs and attrs["type"] in self.bitsets:
361
bitset = self.bitsets[attrs["type"]]
362
if bitset.inline:
363
self.current_bitset = Bitset(attrs["name"], bitset)
364
self.current_bitset.inline = True
365
else:
366
self.current_bitset = bitset
367
else:
368
self.current_bitset = Bitset(attrs["name"], None)
369
self.current_bitset.inline = True
370
if "type" in attrs:
371
self.parse_field(None, attrs)
372
373
self.current_reg = Reg(attrs, self.prefix(), self.current_array, bit_size)
374
self.current_reg.bitset = self.current_bitset
375
376
if len(self.stack) == 1:
377
self.file.append(self.current_reg)
378
379
def start_element(self, name, attrs):
380
if name == "import":
381
filename = attrs["file"]
382
self.do_parse(os.path.join(self.path, filename))
383
elif name == "domain":
384
self.current_domain = attrs["name"]
385
if "prefix" in attrs and attrs["prefix"] == "chip":
386
self.current_prefix = parse_variants(attrs)
387
elif name == "stripe":
388
self.current_stripe = parse_variants(attrs)
389
elif name == "enum":
390
self.current_enum_value = 0
391
self.current_enum = Enum(attrs["name"])
392
self.enums[attrs["name"]] = self.current_enum
393
if len(self.stack) == 1:
394
self.file.append(self.current_enum)
395
elif name == "value":
396
if "value" in attrs:
397
value = int(attrs["value"], 0)
398
else:
399
value = self.current_enum_value
400
self.current_enum.values.append((attrs["name"], value))
401
# self.current_enum_value = value + 1
402
elif name == "reg32":
403
self.parse_reg(attrs, 32)
404
elif name == "reg64":
405
self.parse_reg(attrs, 64)
406
elif name == "array":
407
self.current_array = Array(attrs, self.prefix())
408
if len(self.stack) == 1:
409
self.file.append(self.current_array)
410
elif name == "bitset":
411
self.current_bitset = Bitset(attrs["name"], None)
412
if "inline" in attrs and attrs["inline"] == "yes":
413
self.current_bitset.inline = True
414
self.bitsets[self.current_bitset.name] = self.current_bitset
415
if len(self.stack) == 1 and not self.current_bitset.inline:
416
self.file.append(self.current_bitset)
417
elif name == "bitfield" and self.current_bitset:
418
self.parse_field(attrs["name"], attrs)
419
420
def end_element(self, name):
421
if name == "domain":
422
self.current_domain = None
423
self.current_prefix = None
424
elif name == "stripe":
425
self.current_stripe = None
426
elif name == "bitset":
427
self.current_bitset = None
428
elif name == "reg32":
429
self.current_reg = None
430
elif name == "array":
431
self.current_array = None;
432
elif name == "enum":
433
self.current_enum = None
434
435
def dump(self):
436
enums = []
437
bitsets = []
438
regs = []
439
for e in self.file:
440
if isinstance(e, Enum):
441
enums.append(e)
442
elif isinstance(e, Bitset):
443
bitsets.append(e)
444
else:
445
regs.append(e)
446
447
for e in enums + bitsets + regs:
448
e.dump()
449
450
def dump_structs(self):
451
for e in self.file:
452
e.dump_pack_struct()
453
454
455
def main():
456
p = Parser()
457
rnn_path = sys.argv[1]
458
xml_file = sys.argv[2]
459
if len(sys.argv) > 3 and sys.argv[3] == '--pack-structs':
460
do_structs = True
461
guard = str.replace(os.path.basename(xml_file), '.', '_').upper() + '_STRUCTS'
462
else:
463
do_structs = False
464
guard = str.replace(os.path.basename(xml_file), '.', '_').upper()
465
466
print("#ifndef %s\n#define %s\n" % (guard, guard))
467
468
try:
469
p.parse(rnn_path, xml_file)
470
except Error as e:
471
print(e)
472
exit(1)
473
474
if do_structs:
475
p.dump_structs()
476
else:
477
p.dump()
478
479
print("\n#endif /* %s */" % guard)
480
481
if __name__ == '__main__':
482
main()
483
484