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