2 # Copyright © 2017 Intel Corporation
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:
11 # The above copyright notice and this permission notice shall be included in
12 # all copies or substantial portions of the Software.
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
22 from __future__
import (
23 absolute_import
, division
, print_function
, unicode_literals
29 import xml
.parsers
.expat
31 from mako
.template
import Template
33 TEMPLATE
= Template("""\
35 from operator import itemgetter
38 * Copyright © 2017 Intel Corporation
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:
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
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
60 /* THIS FILE HAS BEEN GENERATED, DO NOT HAND EDIT.
62 * Sizes of bitfields in genxml instructions, structures, and registers.
70 #include "dev/gen_device_info.h"
71 #include "util/macros.h"
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}
79 static inline uint32_t ATTRIBUTE_PURE
80 ${item.token_name}_${prop}(const struct gen_device_info *devinfo)
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)};
89 if (devinfo->is_haswell) {
90 return ${item.get_prop(prop, 7.5)};
92 return ${item.get_prop(prop, 7)};
94 case 6: return ${item.get_prop(prop, 6)};
95 case 5: return ${item.get_prop(prop, 5)};
97 if (devinfo->is_g4x) {
98 return ${item.get_prop(prop, 4.5)};
100 return ${item.get_prop(prop, 4)};
103 unreachable("Invalid hardware generation");
112 % for _, container in sorted(containers.items(), key=itemgetter(0)):
114 /* ${container.name} */
116 ${emit_per_gen_prop_func(container, 'length')}
118 % for _, field in sorted(container.fields.items(), key=itemgetter(0)):
120 /* ${container.name}::${field.name} */
122 ${emit_per_gen_prop_func(field, 'bits')}
124 ${emit_per_gen_prop_func(field, 'start')}
133 #endif /* ${guard} */""", output_encoding
='utf-8')
135 alphanum_nono
= re
.compile(r
'[ /\[\]()\-:.,=>#&*"+\\]+')
136 def to_alphanum(name
):
138 return alphanum_nono
.sub('', name
).replace('α', 'alpha')
141 name
= to_alphanum(name
)
142 if not name
[0].isalpha():
148 def __init__(self
, z
):
149 # Convert potential "major.minor" string
150 self
.tenx
= int(float(z
) * 10)
152 def __lt__(self
, other
):
153 return self
.tenx
< other
.tenx
156 return hash(self
.tenx
)
158 def __eq__(self
, other
):
159 return self
.tenx
== other
.tenx
161 def prefix(self
, token
):
170 return 'GEN{}_{}'.format(gen
, token
)
172 class Container(object):
174 def __init__(self
, name
):
176 self
.token_name
= safe_name(name
)
177 self
.length_by_gen
= {}
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']
185 def get_field(self
, field_name
, create
=False):
186 key
= to_alphanum(field_name
)
187 if key
not in self
.fields
:
189 self
.fields
[key
] = Field(self
, field_name
)
192 return self
.fields
[key
]
194 def has_prop(self
, prop
):
196 return bool(self
.length_by_gen
)
198 raise ValueError('Invalid property: "{0}"'.format(prop
))
200 def iter_prop(self
, prop
):
202 return self
.length_by_gen
.items()
204 raise ValueError('Invalid property: "{0}"'.format(prop
))
206 def get_prop(self
, prop
, gen
):
207 if not isinstance(gen
, Gen
):
211 return self
.length_by_gen
.get(gen
, 0)
213 raise ValueError('Invalid property: "{0}"'.format(prop
))
217 def __init__(self
, container
, name
):
219 self
.token_name
= safe_name('_'.join([container
.name
, self
.name
]))
220 self
.bits_by_gen
= {}
221 self
.start_by_gen
= {}
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
230 def has_prop(self
, prop
):
233 def iter_prop(self
, prop
):
235 return self
.bits_by_gen
.items()
236 elif prop
== 'start':
237 return self
.start_by_gen
.items()
239 raise ValueError('Invalid property: "{0}"'.format(prop
))
241 def get_prop(self
, prop
, gen
):
242 if not isinstance(gen
, Gen
):
246 return self
.bits_by_gen
.get(gen
, 0)
247 elif prop
== 'start':
248 return self
.start_by_gen
.get(gen
, 0)
250 raise ValueError('Invalid property: "{0}"'.format(prop
))
252 class XmlParser(object):
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
260 self
.containers
= containers
261 self
.container
= None
263 def parse(self
, filename
):
264 with
open(filename
, 'rb') as f
:
265 self
.parser
.ParseFile(f
)
267 def start_element(self
, name
, attrs
):
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
:
275 self
.start_container(attrs
)
276 elif name
== 'field':
277 self
.start_field(attrs
)
281 def end_element(self
, name
):
284 elif name
in ('instruction', 'struct', 'register'):
285 self
.container
= None
289 def start_container(self
, attrs
):
290 assert self
.container
is None
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
)
297 def start_field(self
, attrs
):
298 if self
.container
is None:
301 field_name
= attrs
.get('name', None)
305 self
.container
.get_field(field_name
, True).add_gen(self
.gen
, attrs
)
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
='+')
317 pargs
= p
.parse_args()
319 if pargs
.output
in (None, '-'):
320 pargs
.output
= '/dev/stdout'
322 if pargs
.cpp_guard
is None:
323 pargs
.cpp_guard
= os
.path
.basename(pargs
.output
).upper().replace('.', '_')
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
:
338 # Maps name => Container
341 for source
in pargs
.xml_sources
:
342 p
= XmlParser(containers
)
343 p
.engines
= set(engines
)
346 with
open(pargs
.output
, 'wb') as f
:
347 f
.write(TEMPLATE
.render(containers
=containers
, guard
=pargs
.cpp_guard
))
349 if __name__
== '__main__':