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