101e04c3fSmrg#encoding=utf-8
201e04c3fSmrg# Copyright © 2017 Intel Corporation
301e04c3fSmrg
401e04c3fSmrg# Permission is hereby granted, free of charge, to any person obtaining a copy
501e04c3fSmrg# of this software and associated documentation files (the "Software"), to deal
601e04c3fSmrg# in the Software without restriction, including without limitation the rights
701e04c3fSmrg# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
801e04c3fSmrg# copies of the Software, and to permit persons to whom the Software is
901e04c3fSmrg# furnished to do so, subject to the following conditions:
1001e04c3fSmrg
1101e04c3fSmrg# The above copyright notice and this permission notice shall be included in
1201e04c3fSmrg# all copies or substantial portions of the Software.
1301e04c3fSmrg
1401e04c3fSmrg# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1501e04c3fSmrg# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1601e04c3fSmrg# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
1701e04c3fSmrg# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
1801e04c3fSmrg# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
1901e04c3fSmrg# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
2001e04c3fSmrg# SOFTWARE.
2101e04c3fSmrg
2201e04c3fSmrgimport argparse
2301e04c3fSmrgimport os
2401e04c3fSmrgimport xml.parsers.expat
2501e04c3fSmrg
2601e04c3fSmrgfrom mako.template import Template
277ec681f3Smrgfrom util import *
2801e04c3fSmrg
2901e04c3fSmrgTEMPLATE = Template("""\
3001e04c3fSmrg<%!
3101e04c3fSmrgfrom operator import itemgetter
3201e04c3fSmrg%>\
3301e04c3fSmrg/*
3401e04c3fSmrg * Copyright © 2017 Intel Corporation
3501e04c3fSmrg *
3601e04c3fSmrg * Permission is hereby granted, free of charge, to any person obtaining a
3701e04c3fSmrg * copy of this software and associated documentation files (the "Software"),
3801e04c3fSmrg * to deal in the Software without restriction, including without limitation
3901e04c3fSmrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
4001e04c3fSmrg * and/or sell copies of the Software, and to permit persons to whom the
4101e04c3fSmrg * Software is furnished to do so, subject to the following conditions:
4201e04c3fSmrg *
4301e04c3fSmrg * The above copyright notice and this permission notice (including the next
4401e04c3fSmrg * paragraph) shall be included in all copies or substantial portions of the
4501e04c3fSmrg * Software.
4601e04c3fSmrg *
4701e04c3fSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
4801e04c3fSmrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
4901e04c3fSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
5001e04c3fSmrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
5101e04c3fSmrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
5201e04c3fSmrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
5301e04c3fSmrg * IN THE SOFTWARE.
5401e04c3fSmrg */
5501e04c3fSmrg
5601e04c3fSmrg/* THIS FILE HAS BEEN GENERATED, DO NOT HAND EDIT.
5701e04c3fSmrg *
5801e04c3fSmrg * Sizes of bitfields in genxml instructions, structures, and registers.
5901e04c3fSmrg */
6001e04c3fSmrg
6101e04c3fSmrg#ifndef ${guard}
6201e04c3fSmrg#define ${guard}
6301e04c3fSmrg
6401e04c3fSmrg#include <stdint.h>
6501e04c3fSmrg
667ec681f3Smrg#include "dev/intel_device_info.h"
6701e04c3fSmrg#include "util/macros.h"
6801e04c3fSmrg
6901e04c3fSmrg<%def name="emit_per_gen_prop_func(item, prop)">
7001e04c3fSmrg%if item.has_prop(prop):
7101e04c3fSmrg% for gen, value in sorted(item.iter_prop(prop), reverse=True):
7201e04c3fSmrg#define ${gen.prefix(item.token_name)}_${prop}  ${value}
7301e04c3fSmrg% endfor
7401e04c3fSmrg
7501e04c3fSmrgstatic inline uint32_t ATTRIBUTE_PURE
767ec681f3Smrg${item.token_name}_${prop}(const struct intel_device_info *devinfo)
7701e04c3fSmrg{
787ec681f3Smrg   switch (devinfo->verx10) {
797ec681f3Smrg   case 125: return ${item.get_prop(prop, 12.5)};
807ec681f3Smrg   case 120: return ${item.get_prop(prop, 12)};
817ec681f3Smrg   case 110: return ${item.get_prop(prop, 11)};
827ec681f3Smrg   case 90: return ${item.get_prop(prop, 9)};
837ec681f3Smrg   case 80: return ${item.get_prop(prop, 8)};
847ec681f3Smrg   case 75: return ${item.get_prop(prop, 7.5)};
857ec681f3Smrg   case 70: return ${item.get_prop(prop, 7)};
867ec681f3Smrg   case 60: return ${item.get_prop(prop, 6)};
877ec681f3Smrg   case 50: return ${item.get_prop(prop, 5)};
887ec681f3Smrg   case 45: return ${item.get_prop(prop, 4.5)};
897ec681f3Smrg   case 40: return ${item.get_prop(prop, 4)};
9001e04c3fSmrg   default:
9101e04c3fSmrg      unreachable("Invalid hardware generation");
9201e04c3fSmrg   }
9301e04c3fSmrg}
9401e04c3fSmrg%endif
9501e04c3fSmrg</%def>
9601e04c3fSmrg
9701e04c3fSmrg#ifdef __cplusplus
9801e04c3fSmrgextern "C" {
9901e04c3fSmrg#endif
10001e04c3fSmrg% for _, container in sorted(containers.items(), key=itemgetter(0)):
10101e04c3fSmrg
10201e04c3fSmrg/* ${container.name} */
10301e04c3fSmrg
10401e04c3fSmrg${emit_per_gen_prop_func(container, 'length')}
10501e04c3fSmrg
10601e04c3fSmrg% for _, field in sorted(container.fields.items(), key=itemgetter(0)):
10701e04c3fSmrg
10801e04c3fSmrg/* ${container.name}::${field.name} */
10901e04c3fSmrg
11001e04c3fSmrg${emit_per_gen_prop_func(field, 'bits')}
11101e04c3fSmrg
11201e04c3fSmrg${emit_per_gen_prop_func(field, 'start')}
11301e04c3fSmrg
11401e04c3fSmrg% endfor
11501e04c3fSmrg% endfor
11601e04c3fSmrg
11701e04c3fSmrg#ifdef __cplusplus
11801e04c3fSmrg}
11901e04c3fSmrg#endif
12001e04c3fSmrg
1217ec681f3Smrg#endif /* ${guard} */""")
12201e04c3fSmrg
12301e04c3fSmrgclass Gen(object):
12401e04c3fSmrg
12501e04c3fSmrg    def __init__(self, z):
12601e04c3fSmrg        # Convert potential "major.minor" string
12701e04c3fSmrg        self.tenx = int(float(z) * 10)
12801e04c3fSmrg
12901e04c3fSmrg    def __lt__(self, other):
13001e04c3fSmrg        return self.tenx < other.tenx
13101e04c3fSmrg
13201e04c3fSmrg    def __hash__(self):
13301e04c3fSmrg        return hash(self.tenx)
13401e04c3fSmrg
13501e04c3fSmrg    def __eq__(self, other):
13601e04c3fSmrg        return self.tenx == other.tenx
13701e04c3fSmrg
13801e04c3fSmrg    def prefix(self, token):
13901e04c3fSmrg        gen = self.tenx
14001e04c3fSmrg
14101e04c3fSmrg        if gen % 10 == 0:
14201e04c3fSmrg            gen //= 10
14301e04c3fSmrg
14401e04c3fSmrg        if token[0] == '_':
14501e04c3fSmrg            token = token[1:]
14601e04c3fSmrg
1477ec681f3Smrg        return 'GFX{}_{}'.format(gen, token)
14801e04c3fSmrg
14901e04c3fSmrgclass Container(object):
15001e04c3fSmrg
15101e04c3fSmrg    def __init__(self, name):
15201e04c3fSmrg        self.name = name
15301e04c3fSmrg        self.token_name = safe_name(name)
15401e04c3fSmrg        self.length_by_gen = {}
15501e04c3fSmrg        self.fields = {}
15601e04c3fSmrg
15701e04c3fSmrg    def add_gen(self, gen, xml_attrs):
15801e04c3fSmrg        assert isinstance(gen, Gen)
15901e04c3fSmrg        if 'length' in xml_attrs:
16001e04c3fSmrg            self.length_by_gen[gen] = xml_attrs['length']
16101e04c3fSmrg
16201e04c3fSmrg    def get_field(self, field_name, create=False):
1637ec681f3Smrg        key = to_alphanum(field_name)
1647ec681f3Smrg        if key not in self.fields:
16501e04c3fSmrg            if create:
1667ec681f3Smrg                self.fields[key] = Field(self, field_name)
16701e04c3fSmrg            else:
16801e04c3fSmrg                return None
1697ec681f3Smrg        return self.fields[key]
17001e04c3fSmrg
17101e04c3fSmrg    def has_prop(self, prop):
17201e04c3fSmrg        if prop == 'length':
17301e04c3fSmrg            return bool(self.length_by_gen)
17401e04c3fSmrg        else:
17501e04c3fSmrg            raise ValueError('Invalid property: "{0}"'.format(prop))
17601e04c3fSmrg
17701e04c3fSmrg    def iter_prop(self, prop):
17801e04c3fSmrg        if prop == 'length':
17901e04c3fSmrg            return self.length_by_gen.items()
18001e04c3fSmrg        else:
18101e04c3fSmrg            raise ValueError('Invalid property: "{0}"'.format(prop))
18201e04c3fSmrg
18301e04c3fSmrg    def get_prop(self, prop, gen):
18401e04c3fSmrg        if not isinstance(gen, Gen):
18501e04c3fSmrg            gen = Gen(gen)
18601e04c3fSmrg
18701e04c3fSmrg        if prop == 'length':
18801e04c3fSmrg            return self.length_by_gen.get(gen, 0)
18901e04c3fSmrg        else:
19001e04c3fSmrg            raise ValueError('Invalid property: "{0}"'.format(prop))
19101e04c3fSmrg
19201e04c3fSmrgclass Field(object):
19301e04c3fSmrg
19401e04c3fSmrg    def __init__(self, container, name):
19501e04c3fSmrg        self.name = name
19601e04c3fSmrg        self.token_name = safe_name('_'.join([container.name, self.name]))
19701e04c3fSmrg        self.bits_by_gen = {}
19801e04c3fSmrg        self.start_by_gen = {}
19901e04c3fSmrg
20001e04c3fSmrg    def add_gen(self, gen, xml_attrs):
20101e04c3fSmrg        assert isinstance(gen, Gen)
20201e04c3fSmrg        start = int(xml_attrs['start'])
20301e04c3fSmrg        end = int(xml_attrs['end'])
20401e04c3fSmrg        self.start_by_gen[gen] = start
20501e04c3fSmrg        self.bits_by_gen[gen] = 1 + end - start
20601e04c3fSmrg
20701e04c3fSmrg    def has_prop(self, prop):
20801e04c3fSmrg        return True
20901e04c3fSmrg
21001e04c3fSmrg    def iter_prop(self, prop):
21101e04c3fSmrg        if prop == 'bits':
21201e04c3fSmrg            return self.bits_by_gen.items()
21301e04c3fSmrg        elif prop == 'start':
21401e04c3fSmrg            return self.start_by_gen.items()
21501e04c3fSmrg        else:
21601e04c3fSmrg            raise ValueError('Invalid property: "{0}"'.format(prop))
21701e04c3fSmrg
21801e04c3fSmrg    def get_prop(self, prop, gen):
21901e04c3fSmrg        if not isinstance(gen, Gen):
22001e04c3fSmrg            gen = Gen(gen)
22101e04c3fSmrg
22201e04c3fSmrg        if prop == 'bits':
22301e04c3fSmrg            return self.bits_by_gen.get(gen, 0)
22401e04c3fSmrg        elif prop == 'start':
22501e04c3fSmrg            return self.start_by_gen.get(gen, 0)
22601e04c3fSmrg        else:
22701e04c3fSmrg            raise ValueError('Invalid property: "{0}"'.format(prop))
22801e04c3fSmrg
22901e04c3fSmrgclass XmlParser(object):
23001e04c3fSmrg
23101e04c3fSmrg    def __init__(self, containers):
23201e04c3fSmrg        self.parser = xml.parsers.expat.ParserCreate()
23301e04c3fSmrg        self.parser.StartElementHandler = self.start_element
23401e04c3fSmrg        self.parser.EndElementHandler = self.end_element
23501e04c3fSmrg
23601e04c3fSmrg        self.gen = None
23701e04c3fSmrg        self.containers = containers
2387ec681f3Smrg        self.container_stack = []
2397ec681f3Smrg        self.container_stack.append(None)
24001e04c3fSmrg
24101e04c3fSmrg    def parse(self, filename):
24201e04c3fSmrg        with open(filename, 'rb') as f:
24301e04c3fSmrg            self.parser.ParseFile(f)
24401e04c3fSmrg
24501e04c3fSmrg    def start_element(self, name, attrs):
24601e04c3fSmrg        if name == 'genxml':
24701e04c3fSmrg            self.gen = Gen(attrs['gen'])
24801e04c3fSmrg        elif name in ('instruction', 'struct', 'register'):
2499f464c52Smaya            if name == 'instruction' and 'engine' in attrs:
2509f464c52Smaya                engines = set(attrs['engine'].split('|'))
2519f464c52Smaya                if not engines & self.engines:
2527ec681f3Smrg                    self.container_stack.append(None)
2539f464c52Smaya                    return
25401e04c3fSmrg            self.start_container(attrs)
2557ec681f3Smrg        elif name == 'group':
2567ec681f3Smrg            self.container_stack.append(None)
25701e04c3fSmrg        elif name == 'field':
25801e04c3fSmrg            self.start_field(attrs)
25901e04c3fSmrg        else:
26001e04c3fSmrg            pass
26101e04c3fSmrg
26201e04c3fSmrg    def end_element(self, name):
26301e04c3fSmrg        if name == 'genxml':
26401e04c3fSmrg            self.gen = None
2657ec681f3Smrg        elif name in ('instruction', 'struct', 'register', 'group'):
2667ec681f3Smrg            self.container_stack.pop()
26701e04c3fSmrg        else:
26801e04c3fSmrg            pass
26901e04c3fSmrg
27001e04c3fSmrg    def start_container(self, attrs):
2717ec681f3Smrg        assert self.container_stack[-1] is None
27201e04c3fSmrg        name = attrs['name']
27301e04c3fSmrg        if name not in self.containers:
27401e04c3fSmrg            self.containers[name] = Container(name)
2757ec681f3Smrg        self.container_stack.append(self.containers[name])
2767ec681f3Smrg        self.container_stack[-1].add_gen(self.gen, attrs)
27701e04c3fSmrg
27801e04c3fSmrg    def start_field(self, attrs):
2797ec681f3Smrg        if self.container_stack[-1] is None:
28001e04c3fSmrg            return
28101e04c3fSmrg
28201e04c3fSmrg        field_name = attrs.get('name', None)
28301e04c3fSmrg        if not field_name:
28401e04c3fSmrg            return
28501e04c3fSmrg
2867ec681f3Smrg        self.container_stack[-1].get_field(field_name, True).add_gen(self.gen, attrs)
28701e04c3fSmrg
28801e04c3fSmrgdef parse_args():
28901e04c3fSmrg    p = argparse.ArgumentParser()
29001e04c3fSmrg    p.add_argument('-o', '--output', type=str,
29101e04c3fSmrg                   help="If OUTPUT is unset or '-', then it defaults to '/dev/stdout'")
29201e04c3fSmrg    p.add_argument('--cpp-guard', type=str,
29301e04c3fSmrg                   help='If unset, then CPP_GUARD is derived from OUTPUT.')
2949f464c52Smaya    p.add_argument('--engines', nargs='?', type=str, default='render',
2959f464c52Smaya                   help="Comma-separated list of engines whose instructions should be parsed (default: %(default)s)")
29601e04c3fSmrg    p.add_argument('xml_sources', metavar='XML_SOURCE', nargs='+')
29701e04c3fSmrg
29801e04c3fSmrg    pargs = p.parse_args()
29901e04c3fSmrg
30001e04c3fSmrg    if pargs.output in (None, '-'):
30101e04c3fSmrg        pargs.output = '/dev/stdout'
30201e04c3fSmrg
30301e04c3fSmrg    if pargs.cpp_guard is None:
30401e04c3fSmrg        pargs.cpp_guard = os.path.basename(pargs.output).upper().replace('.', '_')
30501e04c3fSmrg
30601e04c3fSmrg    return pargs
30701e04c3fSmrg
30801e04c3fSmrgdef main():
30901e04c3fSmrg    pargs = parse_args()
31001e04c3fSmrg
3119f464c52Smaya    engines = pargs.engines.split(',')
3129f464c52Smaya    valid_engines = [ 'render', 'blitter', 'video' ]
3139f464c52Smaya    if set(engines) - set(valid_engines):
3149f464c52Smaya        print("Invalid engine specified, valid engines are:\n")
3159f464c52Smaya        for e in valid_engines:
3169f464c52Smaya            print("\t%s" % e)
3179f464c52Smaya        sys.exit(1)
3189f464c52Smaya
31901e04c3fSmrg    # Maps name => Container
32001e04c3fSmrg    containers = {}
32101e04c3fSmrg
32201e04c3fSmrg    for source in pargs.xml_sources:
3239f464c52Smaya        p = XmlParser(containers)
3249f464c52Smaya        p.engines = set(engines)
3259f464c52Smaya        p.parse(source)
32601e04c3fSmrg
3277ec681f3Smrg    with open(pargs.output, 'w') as f:
32801e04c3fSmrg        f.write(TEMPLATE.render(containers=containers, guard=pargs.cpp_guard))
32901e04c3fSmrg
33001e04c3fSmrgif __name__ == '__main__':
33101e04c3fSmrg    main()
332