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