• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/usr/bin/python3
2
3import xml.parsers.expat
4import sys
5import os
6
7class Error(Exception):
8	def __init__(self, message):
9		self.message = message
10
11class 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
34class 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
94def 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
100def mask(low, high):
101	return ((0xffffffff >> (32 - (high + 1 - low))) << low)
102
103class 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		value_name = "dword"
130		print("struct %s {" % prefix)
131		for f in self.fields:
132			if f.type == "waddress":
133				value_name = "qword"
134			if f.type in [ "address", "waddress" ]:
135				tab_to("    __bo_type", "bo;")
136				tab_to("    uint32_t", "bo_offset;")
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
235class 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("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))
248
249	def dump_pack_struct(self):
250		pass
251
252class 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)
280
281
282def 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
291class 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			self.current_bitset = self.bitsets[attrs["type"]]
362		else:
363			self.current_bitset = Bitset(attrs["name"], None)
364			self.current_bitset.inline = True
365			if "type" in attrs:
366				self.parse_field(None, attrs)
367
368		self.current_reg = Reg(attrs, self.prefix(), self.current_array, bit_size)
369		self.current_reg.bitset = self.current_bitset
370
371		if len(self.stack) == 1:
372			self.file.append(self.current_reg)
373
374	def start_element(self, name, attrs):
375		if name == "import":
376			filename = attrs["file"]
377			self.do_parse(os.path.join(self.path, filename))
378		elif name == "domain":
379			self.current_domain = attrs["name"]
380			if "prefix" in attrs and attrs["prefix"] == "chip":
381				self.current_prefix = parse_variants(attrs)
382		elif name == "stripe":
383			self.current_stripe = parse_variants(attrs)
384		elif name == "enum":
385			self.current_enum_value = 0
386			self.current_enum = Enum(attrs["name"])
387			self.enums[attrs["name"]] = self.current_enum
388			if len(self.stack) == 1:
389				self.file.append(self.current_enum)
390		elif name == "value":
391			if "value" in attrs:
392				value = int(attrs["value"], 0)
393			else:
394				value = self.current_enum_value
395			self.current_enum.values.append((attrs["name"], value))
396			# self.current_enum_value = value + 1
397		elif name == "reg32":
398			self.parse_reg(attrs, 32)
399		elif name == "reg64":
400			self.parse_reg(attrs, 64)
401		elif name == "array":
402			self.current_array = Array(attrs, self.prefix())
403			if len(self.stack) == 1:
404				self.file.append(self.current_array)
405		elif name == "bitset":
406			self.current_bitset = Bitset(attrs["name"], None)
407			if "inline" in attrs and attrs["inline"] == "yes":
408				self.current_bitset.inline = True
409			self.bitsets[self.current_bitset.name] = self.current_bitset
410			if len(self.stack) == 1 and not self.current_bitset.inline:
411				self.file.append(self.current_bitset)
412		elif name == "bitfield" and self.current_bitset:
413			self.parse_field(attrs["name"], attrs)
414
415	def end_element(self, name):
416		if name == "domain":
417			self.current_domain = None
418			self.current_prefix = None
419		elif name == "stripe":
420			self.current_stripe = None
421		elif name == "bitset":
422			self.current_bitset = None
423		elif name == "reg32":
424			self.current_reg = None
425		elif name == "array":
426			self.current_array = None;
427		elif name == "enum":
428			self.current_enum = None
429
430	def dump(self):
431		enums = []
432		bitsets = []
433		regs = []
434		for e in self.file:
435			if isinstance(e, Enum):
436				enums.append(e)
437			elif isinstance(e, Bitset):
438				bitsets.append(e)
439			else:
440				regs.append(e)
441
442		for e in enums + bitsets + regs:
443			e.dump()
444
445	def dump_structs(self):
446		for e in self.file:
447			e.dump_pack_struct()
448
449
450def main():
451	p = Parser()
452	rnn_path = sys.argv[1]
453	xml_file = sys.argv[2]
454	if len(sys.argv) > 3 and sys.argv[3] == '--pack-structs':
455		do_structs = True
456		guard = str.replace(os.path.basename(xml_file), '.', '_').upper() + '_STRUCTS'
457	else:
458		do_structs = False
459		guard = str.replace(os.path.basename(xml_file), '.', '_').upper()
460
461	print("#ifndef %s\n#define %s\n" % (guard, guard))
462
463	try:
464		p.parse(rnn_path, xml_file)
465	except Error as e:
466		print(e)
467		exit(1)
468
469	if do_structs:
470		p.dump_structs()
471	else:
472		p.dump()
473
474	print("\n#endif /* %s */" % guard)
475
476if __name__ == '__main__':
477	main()
478