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