freedreno/ir3: track # of driver params
[mesa.git] / src / freedreno / registers / gen_header.py
1 #!/usr/bin/python3
2
3 import xml.parsers.expat
4 import sys
5 import os
6
7 class Error(Exception):
8 def __init__(self, message):
9 self.message = message
10
11 class Enum(object):
12 def __init__(self, name):
13 self.name = name
14 self.values = []
15
16 def dump(self):
17 prev = 0
18 use_hex = False
19 for (name, value) in self.values:
20 if value > 0x1000:
21 use_hex = True
22
23 print("enum %s {" % self.name)
24 for (name, value) in self.values:
25 if use_hex:
26 print("\t%s = 0x%08x," % (name, value))
27 else:
28 print("\t%s = %d," % (name, value))
29 print("};\n")
30
31 class Field(object):
32 def __init__(self, name, low, high, shr, type, parser):
33 self.name = name
34 self.low = low
35 self.high = high
36 self.shr = shr
37 self.type = type
38
39 builtin_types = [ None, "boolean", "uint", "hex", "int", "fixed", "ufixed", "float" ]
40
41 if low < 0 or low > 31:
42 raise parser.error("low attribute out of range: %d" % low)
43 if high < 0 or high > 31:
44 raise parser.error("high attribute out of range: %d" % high)
45 if high < low:
46 raise parser.error("low is greater than high: low=%d, high=%d" % (low, high))
47 if self.type == "boolean" and not low == high:
48 raise parser.error("booleans should be 1 bit fields");
49 elif self.type == "float" and not (high - low == 31 or high - low == 15):
50 raise parser.error("floats should be 16 or 32 bit fields")
51 elif not self.type in builtin_types and not self.type in parser.enums:
52 raise parser.error("unknown type '%s'" % self.type);
53
54 def ctype(self):
55 if self.type == None:
56 type = "uint32_t"
57 val = "val"
58 elif self.type == "boolean":
59 type = "bool"
60 val = "val"
61 elif self.type == "uint" or self.type == "hex":
62 type = "uint32_t"
63 val = "val"
64 elif self.type == "int":
65 type = "int32_t"
66 val = "val"
67 elif self.type == "fixed":
68 type = "float"
69 val = "((int32_t)(val * %d.0))" % (1 << self.radix)
70 elif self.type == "ufixed":
71 type = "float"
72 val = "((uint32_t)(val * %d.0))" % (1 << self.radix)
73 elif self.type == "float" and self.high - self.low == 31:
74 type = "float"
75 val = "fui(val)"
76 elif self.type == "float" and self.high - self.low == 15:
77 type = "float"
78 val = "util_float_to_half(val)"
79 else:
80 type = "enum %s" % self.type
81 val = "val"
82
83 if self.shr > 0:
84 val = "%s >> %d" % (val, self.shr)
85
86 return (type, val)
87
88 def tab_to(name, value):
89 tab_count = (68 - (len(name) & ~7)) // 8
90 if tab_count == 0:
91 tab_count = 1
92 print(name + ('\t' * tab_count) + value)
93
94 def mask(low, high):
95 return ((0xffffffff >> (32 - (high + 1 - low))) << low)
96
97 class Bitset(object):
98 def __init__(self, name, template):
99 self.name = name
100 self.inline = False
101 if template:
102 self.fields = template.fields
103 else:
104 self.fields = []
105
106 def dump(self, prefix=None):
107 if prefix == None:
108 prefix = self.name
109 for f in self.fields:
110 if f.name:
111 name = prefix + "_" + f.name
112 else:
113 name = prefix
114
115 if not f.name and f.low == 0 and f.shr == 0 and not f.type in ["float", "fixed", "ufixed"]:
116 pass
117 elif f.type == "boolean" or (f.type == None and f.low == f.high):
118 tab_to("#define %s" % name, "0x%08x" % (1 << f.low))
119 else:
120 tab_to("#define %s__MASK" % name, "0x%08x" % mask(f.low, f.high))
121 tab_to("#define %s__SHIFT" % name, "%d" % f.low)
122 type, val = f.ctype()
123
124 print("static inline uint32_t %s(%s val)\n{" % (name, type))
125 if f.shr > 0:
126 print("\tassert(!(val & 0x%x));" % mask(0, f.shr - 1))
127 print("\treturn ((%s) << %s__SHIFT) & %s__MASK;\n}" % (val, name, name))
128
129 class Array(object):
130 def __init__(self, attrs, domain):
131 self.name = attrs["name"]
132 self.domain = domain
133 self.offset = int(attrs["offset"], 0)
134 self.stride = int(attrs["stride"], 0)
135 self.length = int(attrs["length"], 0)
136
137 def dump(self):
138 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))
139
140 class Reg(object):
141 def __init__(self, attrs, domain, array):
142 self.name = attrs["name"]
143 self.domain = domain
144 self.array = array
145 self.offset = int(attrs["offset"], 0)
146 self.type = None
147
148 def dump(self):
149 if self.array:
150 name = self.domain + "_" + self.array.name + "_" + self.name
151 offset = self.array.offset + self.offset
152 print("static inline uint32_t REG_%s(uint32_t i0) { return 0x%08x + 0x%x*i0; }" % (name, offset, self.array.stride))
153 else:
154 name = self.domain + "_" + self.name
155 tab_to("#define REG_%s" % name, "0x%08x" % self.offset)
156
157 if self.bitset.inline:
158 self.bitset.dump(name)
159 print("")
160
161 def parse_variants(attrs):
162 if not "variants" in attrs:
163 return None
164 variant = attrs["variants"].split(",")[0]
165 if "-" in variant:
166 variant = variant[:variant.index("-")]
167
168 return variant
169
170 class Parser(object):
171 def __init__(self):
172 self.current_array = None
173 self.current_domain = None
174 self.current_prefix = None
175 self.current_stripe = None
176 self.current_bitset = None
177 self.bitsets = {}
178 self.enums = {}
179 self.file = []
180
181 def error(self, message):
182 parser, filename = self.stack[-1]
183 return Error("%s:%d:%d: %s" % (filename, parser.CurrentLineNumber, parser.CurrentColumnNumber, message))
184
185 def prefix(self):
186 if self.current_stripe:
187 return self.current_stripe + "_" + self.current_domain
188 elif self.current_prefix:
189 return self.current_prefix + "_" + self.current_domain
190 else:
191 return self.current_domain
192
193 def parse_field(self, name, attrs):
194 try:
195 if "pos" in attrs:
196 high = low = int(attrs["pos"], 0)
197 elif "high" in attrs and "low" in attrs:
198 high = int(attrs["high"], 0)
199 low = int(attrs["low"], 0)
200 else:
201 low = 0
202 high = 31
203
204 if "type" in attrs:
205 type = attrs["type"]
206 else:
207 type = None
208
209 if "shr" in attrs:
210 shr = int(attrs["shr"], 0)
211 else:
212 shr = 0
213
214 b = Field(name, low, high, shr, type, self)
215
216 if type == "fixed" or type == "ufixed":
217 b.radix = int(attrs["radix"], 0)
218
219 self.current_bitset.fields.append(b)
220 except ValueError as e:
221 raise self.error(e);
222
223 def do_parse(self, filename):
224 file = open(filename, "rb")
225 parser = xml.parsers.expat.ParserCreate()
226 self.stack.append((parser, filename))
227 parser.StartElementHandler = self.start_element
228 parser.EndElementHandler = self.end_element
229 parser.ParseFile(file)
230 self.stack.pop()
231 file.close()
232
233 def parse(self, filename):
234 self.path = os.path.dirname(filename)
235 self.stack = []
236 self.do_parse(filename)
237
238 def start_element(self, name, attrs):
239 if name == "import":
240 filename = os.path.basename(attrs["file"])
241 self.do_parse(os.path.join(self.path, filename))
242 elif name == "domain":
243 self.current_domain = attrs["name"]
244 if "prefix" in attrs and attrs["prefix"] == "chip":
245 self.current_prefix = parse_variants(attrs)
246 elif name == "stripe":
247 self.current_stripe = parse_variants(attrs)
248 elif name == "enum":
249 self.current_enum_value = 0
250 self.current_enum = Enum(attrs["name"])
251 self.enums[attrs["name"]] = self.current_enum
252 if len(self.stack) == 1:
253 self.file.append(self.current_enum)
254 elif name == "value":
255 if "value" in attrs:
256 value = int(attrs["value"], 0)
257 else:
258 value = self.current_enum_value
259 self.current_enum.values.append((attrs["name"], value))
260 # self.current_enum_value = value + 1
261 elif name == "reg32":
262 if "type" in attrs and attrs["type"] in self.bitsets:
263 self.current_bitset = self.bitsets[attrs["type"]]
264 else:
265 self.current_bitset = Bitset(attrs["name"], None)
266 self.current_bitset.inline = True
267 if "type" in attrs:
268 self.parse_field(None, attrs)
269
270 self.current_reg = Reg(attrs, self.prefix(), self.current_array)
271 self.current_reg.bitset = self.current_bitset
272
273 if len(self.stack) == 1:
274 self.file.append(self.current_reg)
275 elif name == "array":
276 self.current_array = Array(attrs, self.prefix())
277 if len(self.stack) == 1:
278 self.file.append(self.current_array)
279 elif name == "bitset":
280 self.current_bitset = Bitset(attrs["name"], None)
281 if "inline" in attrs and attrs["inline"] == "yes":
282 self.current_bitset.inline = True
283 self.bitsets[self.current_bitset.name] = self.current_bitset
284 if len(self.stack) == 1 and not self.current_bitset.inline:
285 self.file.append(self.current_bitset)
286 elif name == "bitfield" and self.current_bitset:
287 self.parse_field(attrs["name"], attrs)
288
289 def end_element(self, name):
290 if name == "domain":
291 self.current_domain = None
292 self.current_prefix = None
293 elif name == "stripe":
294 self.current_stripe = None
295 elif name == "bitset":
296 self.current_bitset = None
297 elif name == "reg32":
298 self.current_reg = None
299 elif name == "array":
300 self.current_array = None;
301 elif name == "enum":
302 self.current_enum = None
303
304 def dump(self):
305 enums = []
306 bitsets = []
307 regs = []
308 for e in self.file:
309 if isinstance(e, Enum):
310 enums.append(e)
311 elif isinstance(e, Bitset):
312 bitsets.append(e)
313 else:
314 regs.append(e)
315
316 for e in enums + bitsets + regs:
317 e.dump()
318
319 def main():
320 p = Parser()
321 xml_file = sys.argv[1]
322
323 guard = str.replace(os.path.basename(xml_file), '.', '_').upper()
324 print("#ifndef %s\n#define %s\n" % (guard, guard))
325
326 try:
327 p.parse(xml_file)
328 except Error as e:
329 print(e)
330 exit(1)
331
332 p.dump()
333
334 print("\n#endif /* %s */" % guard)
335
336 if __name__ == '__main__':
337 main()