genxml: Change 3DSTATE_DEPTH_BOUNDS bias.
[mesa.git] / src / intel / genxml / gen_bits_header.py
1 #encoding=utf-8
2 # Copyright © 2017 Intel Corporation
3
4 # Permission is hereby granted, free of charge, to any person obtaining a copy
5 # of this software and associated documentation files (the "Software"), to deal
6 # in the Software without restriction, including without limitation the rights
7 # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 # copies of the Software, and to permit persons to whom the Software is
9 # furnished to do so, subject to the following conditions:
10
11 # The above copyright notice and this permission notice shall be included in
12 # all copies or substantial portions of the Software.
13
14 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20 # SOFTWARE.
21
22 from __future__ import (
23 absolute_import, division, print_function, unicode_literals
24 )
25
26 import argparse
27 import os
28 import re
29 import xml.parsers.expat
30
31 from mako.template import Template
32
33 TEMPLATE = Template("""\
34 <%!
35 from operator import itemgetter
36 %>\
37 /*
38 * Copyright © 2017 Intel Corporation
39 *
40 * Permission is hereby granted, free of charge, to any person obtaining a
41 * copy of this software and associated documentation files (the "Software"),
42 * to deal in the Software without restriction, including without limitation
43 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
44 * and/or sell copies of the Software, and to permit persons to whom the
45 * Software is furnished to do so, subject to the following conditions:
46 *
47 * The above copyright notice and this permission notice (including the next
48 * paragraph) shall be included in all copies or substantial portions of the
49 * Software.
50 *
51 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
52 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
53 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
54 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
55 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
56 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
57 * IN THE SOFTWARE.
58 */
59
60 /* THIS FILE HAS BEEN GENERATED, DO NOT HAND EDIT.
61 *
62 * Sizes of bitfields in genxml instructions, structures, and registers.
63 */
64
65 #ifndef ${guard}
66 #define ${guard}
67
68 #include <stdint.h>
69
70 #include "dev/gen_device_info.h"
71 #include "util/macros.h"
72
73 <%def name="emit_per_gen_prop_func(item, prop)">
74 %if item.has_prop(prop):
75 % for gen, value in sorted(item.iter_prop(prop), reverse=True):
76 #define ${gen.prefix(item.token_name)}_${prop} ${value}
77 % endfor
78
79 static inline uint32_t ATTRIBUTE_PURE
80 ${item.token_name}_${prop}(const struct gen_device_info *devinfo)
81 {
82 switch (devinfo->gen) {
83 case 12: return ${item.get_prop(prop, 12)};
84 case 11: return ${item.get_prop(prop, 11)};
85 case 10: return ${item.get_prop(prop, 10)};
86 case 9: return ${item.get_prop(prop, 9)};
87 case 8: return ${item.get_prop(prop, 8)};
88 case 7:
89 if (devinfo->is_haswell) {
90 return ${item.get_prop(prop, 7.5)};
91 } else {
92 return ${item.get_prop(prop, 7)};
93 }
94 case 6: return ${item.get_prop(prop, 6)};
95 case 5: return ${item.get_prop(prop, 5)};
96 case 4:
97 if (devinfo->is_g4x) {
98 return ${item.get_prop(prop, 4.5)};
99 } else {
100 return ${item.get_prop(prop, 4)};
101 }
102 default:
103 unreachable("Invalid hardware generation");
104 }
105 }
106 %endif
107 </%def>
108
109 #ifdef __cplusplus
110 extern "C" {
111 #endif
112 % for _, container in sorted(containers.items(), key=itemgetter(0)):
113
114 /* ${container.name} */
115
116 ${emit_per_gen_prop_func(container, 'length')}
117
118 % for _, field in sorted(container.fields.items(), key=itemgetter(0)):
119
120 /* ${container.name}::${field.name} */
121
122 ${emit_per_gen_prop_func(field, 'bits')}
123
124 ${emit_per_gen_prop_func(field, 'start')}
125
126 % endfor
127 % endfor
128
129 #ifdef __cplusplus
130 }
131 #endif
132
133 #endif /* ${guard} */""", output_encoding='utf-8')
134
135 alphanum_nono = re.compile(r'[ /\[\]()\-:.,=>#&*"+\\]+')
136 def to_alphanum(name):
137 global alphanum_nono
138 return alphanum_nono.sub('', name)
139
140 def safe_name(name):
141 name = to_alphanum(name)
142 if not name[0].isalpha():
143 name = '_' + name
144 return name
145
146 class Gen(object):
147
148 def __init__(self, z):
149 # Convert potential "major.minor" string
150 self.tenx = int(float(z) * 10)
151
152 def __lt__(self, other):
153 return self.tenx < other.tenx
154
155 def __hash__(self):
156 return hash(self.tenx)
157
158 def __eq__(self, other):
159 return self.tenx == other.tenx
160
161 def prefix(self, token):
162 gen = self.tenx
163
164 if gen % 10 == 0:
165 gen //= 10
166
167 if token[0] == '_':
168 token = token[1:]
169
170 return 'GEN{}_{}'.format(gen, token)
171
172 class Container(object):
173
174 def __init__(self, name):
175 self.name = name
176 self.token_name = safe_name(name)
177 self.length_by_gen = {}
178 self.fields = {}
179
180 def add_gen(self, gen, xml_attrs):
181 assert isinstance(gen, Gen)
182 if 'length' in xml_attrs:
183 self.length_by_gen[gen] = xml_attrs['length']
184
185 def get_field(self, field_name, create=False):
186 key = to_alphanum(field_name)
187 if key not in self.fields:
188 if create:
189 self.fields[key] = Field(self, field_name)
190 else:
191 return None
192 return self.fields[key]
193
194 def has_prop(self, prop):
195 if prop == 'length':
196 return bool(self.length_by_gen)
197 else:
198 raise ValueError('Invalid property: "{0}"'.format(prop))
199
200 def iter_prop(self, prop):
201 if prop == 'length':
202 return self.length_by_gen.items()
203 else:
204 raise ValueError('Invalid property: "{0}"'.format(prop))
205
206 def get_prop(self, prop, gen):
207 if not isinstance(gen, Gen):
208 gen = Gen(gen)
209
210 if prop == 'length':
211 return self.length_by_gen.get(gen, 0)
212 else:
213 raise ValueError('Invalid property: "{0}"'.format(prop))
214
215 class Field(object):
216
217 def __init__(self, container, name):
218 self.name = name
219 self.token_name = safe_name('_'.join([container.name, self.name]))
220 self.bits_by_gen = {}
221 self.start_by_gen = {}
222
223 def add_gen(self, gen, xml_attrs):
224 assert isinstance(gen, Gen)
225 start = int(xml_attrs['start'])
226 end = int(xml_attrs['end'])
227 self.start_by_gen[gen] = start
228 self.bits_by_gen[gen] = 1 + end - start
229
230 def has_prop(self, prop):
231 return True
232
233 def iter_prop(self, prop):
234 if prop == 'bits':
235 return self.bits_by_gen.items()
236 elif prop == 'start':
237 return self.start_by_gen.items()
238 else:
239 raise ValueError('Invalid property: "{0}"'.format(prop))
240
241 def get_prop(self, prop, gen):
242 if not isinstance(gen, Gen):
243 gen = Gen(gen)
244
245 if prop == 'bits':
246 return self.bits_by_gen.get(gen, 0)
247 elif prop == 'start':
248 return self.start_by_gen.get(gen, 0)
249 else:
250 raise ValueError('Invalid property: "{0}"'.format(prop))
251
252 class XmlParser(object):
253
254 def __init__(self, containers):
255 self.parser = xml.parsers.expat.ParserCreate()
256 self.parser.StartElementHandler = self.start_element
257 self.parser.EndElementHandler = self.end_element
258
259 self.gen = None
260 self.containers = containers
261 self.container = None
262
263 def parse(self, filename):
264 with open(filename, 'rb') as f:
265 self.parser.ParseFile(f)
266
267 def start_element(self, name, attrs):
268 if name == 'genxml':
269 self.gen = Gen(attrs['gen'])
270 elif name in ('instruction', 'struct', 'register'):
271 if name == 'instruction' and 'engine' in attrs:
272 engines = set(attrs['engine'].split('|'))
273 if not engines & self.engines:
274 return
275 self.start_container(attrs)
276 elif name == 'field':
277 self.start_field(attrs)
278 else:
279 pass
280
281 def end_element(self, name):
282 if name == 'genxml':
283 self.gen = None
284 elif name in ('instruction', 'struct', 'register'):
285 self.container = None
286 else:
287 pass
288
289 def start_container(self, attrs):
290 assert self.container is None
291 name = attrs['name']
292 if name not in self.containers:
293 self.containers[name] = Container(name)
294 self.container = self.containers[name]
295 self.container.add_gen(self.gen, attrs)
296
297 def start_field(self, attrs):
298 if self.container is None:
299 return
300
301 field_name = attrs.get('name', None)
302 if not field_name:
303 return
304
305 self.container.get_field(field_name, True).add_gen(self.gen, attrs)
306
307 def parse_args():
308 p = argparse.ArgumentParser()
309 p.add_argument('-o', '--output', type=str,
310 help="If OUTPUT is unset or '-', then it defaults to '/dev/stdout'")
311 p.add_argument('--cpp-guard', type=str,
312 help='If unset, then CPP_GUARD is derived from OUTPUT.')
313 p.add_argument('--engines', nargs='?', type=str, default='render',
314 help="Comma-separated list of engines whose instructions should be parsed (default: %(default)s)")
315 p.add_argument('xml_sources', metavar='XML_SOURCE', nargs='+')
316
317 pargs = p.parse_args()
318
319 if pargs.output in (None, '-'):
320 pargs.output = '/dev/stdout'
321
322 if pargs.cpp_guard is None:
323 pargs.cpp_guard = os.path.basename(pargs.output).upper().replace('.', '_')
324
325 return pargs
326
327 def main():
328 pargs = parse_args()
329
330 engines = pargs.engines.split(',')
331 valid_engines = [ 'render', 'blitter', 'video' ]
332 if set(engines) - set(valid_engines):
333 print("Invalid engine specified, valid engines are:\n")
334 for e in valid_engines:
335 print("\t%s" % e)
336 sys.exit(1)
337
338 # Maps name => Container
339 containers = {}
340
341 for source in pargs.xml_sources:
342 p = XmlParser(containers)
343 p.engines = set(engines)
344 p.parse(source)
345
346 with open(pargs.output, 'wb') as f:
347 f.write(TEMPLATE.render(containers=containers, guard=pargs.cpp_guard))
348
349 if __name__ == '__main__':
350 main()