import argparse
import os
-import sys
+import re
import xml.parsers.expat
from mako.template import Template
#include <stdint.h>
-#include "common/gen_device_info.h"
+#include "dev/gen_device_info.h"
#include "util/macros.h"
<%def name="emit_per_gen_prop_func(item, prop)">
${item.token_name}_${prop}(const struct gen_device_info *devinfo)
{
switch (devinfo->gen) {
+ case 12: return ${item.get_prop(prop, 12)};
+ case 11: return ${item.get_prop(prop, 11)};
+ case 10: return ${item.get_prop(prop, 10)};
case 9: return ${item.get_prop(prop, 9)};
case 8: return ${item.get_prop(prop, 8)};
case 7:
#ifdef __cplusplus
extern "C" {
#endif
-% for _, container in sorted(containers.iteritems(), key=itemgetter(0)):
-% for _, field in sorted(container.fields.iteritems(), key=itemgetter(0)):
+% for _, container in sorted(containers.items(), key=itemgetter(0)):
+
+/* ${container.name} */
+
+${emit_per_gen_prop_func(container, 'length')}
+
+% for _, field in sorted(container.fields.items(), key=itemgetter(0)):
/* ${container.name}::${field.name} */
${emit_per_gen_prop_func(field, 'bits')}
+${emit_per_gen_prop_func(field, 'start')}
+
% endfor
% endfor
#endif /* ${guard} */""", output_encoding='utf-8')
+alphanum_nono = re.compile(r'[ /\[\]()\-:.,=>#&*"+\\]+')
def to_alphanum(name):
- substitutions = {
- ' ': '',
- '/': '',
- '[': '',
- ']': '',
- '(': '',
- ')': '',
- '-': '',
- ':': '',
- '.': '',
- ',': '',
- '=': '',
- '>': '',
- '#': '',
- 'α': 'alpha',
- '&': '',
- '*': '',
- '"': '',
- '+': '',
- '\'': '',
- }
-
- for i, j in substitutions.items():
- name = name.replace(i, j)
-
- return name
+ global alphanum_nono
+ return alphanum_nono.sub('', name)
def safe_name(name):
name = to_alphanum(name)
def __init__(self, z):
# Convert potential "major.minor" string
- z = float(z)
- if z < 10:
- z *= 10
- self.tenx = int(z)
+ self.tenx = int(float(z) * 10)
def __lt__(self, other):
return self.tenx < other.tenx
def __init__(self, name):
self.name = name
+ self.token_name = safe_name(name)
+ self.length_by_gen = {}
self.fields = {}
+ def add_gen(self, gen, xml_attrs):
+ assert isinstance(gen, Gen)
+ if 'length' in xml_attrs:
+ self.length_by_gen[gen] = xml_attrs['length']
+
def get_field(self, field_name, create=False):
- if field_name not in self.fields:
+ key = to_alphanum(field_name)
+ if key not in self.fields:
if create:
- self.fields[field_name] = Field(self, field_name)
+ self.fields[key] = Field(self, field_name)
else:
return None
- return self.fields[field_name]
+ return self.fields[key]
+
+ def has_prop(self, prop):
+ if prop == 'length':
+ return bool(self.length_by_gen)
+ else:
+ raise ValueError('Invalid property: "{0}"'.format(prop))
+
+ def iter_prop(self, prop):
+ if prop == 'length':
+ return self.length_by_gen.items()
+ else:
+ raise ValueError('Invalid property: "{0}"'.format(prop))
+
+ def get_prop(self, prop, gen):
+ if not isinstance(gen, Gen):
+ gen = Gen(gen)
+
+ if prop == 'length':
+ return self.length_by_gen.get(gen, 0)
+ else:
+ raise ValueError('Invalid property: "{0}"'.format(prop))
class Field(object):
self.name = name
self.token_name = safe_name('_'.join([container.name, self.name]))
self.bits_by_gen = {}
+ self.start_by_gen = {}
def add_gen(self, gen, xml_attrs):
assert isinstance(gen, Gen)
start = int(xml_attrs['start'])
end = int(xml_attrs['end'])
+ self.start_by_gen[gen] = start
self.bits_by_gen[gen] = 1 + end - start
def has_prop(self, prop):
def iter_prop(self, prop):
if prop == 'bits':
- return self.bits_by_gen.iteritems()
+ return self.bits_by_gen.items()
+ elif prop == 'start':
+ return self.start_by_gen.items()
else:
raise ValueError('Invalid property: "{0}"'.format(prop))
if prop == 'bits':
return self.bits_by_gen.get(gen, 0)
+ elif prop == 'start':
+ return self.start_by_gen.get(gen, 0)
else:
raise ValueError('Invalid property: "{0}"'.format(prop))
self.container = None
def parse(self, filename):
- with open(filename) as f:
+ with open(filename, 'rb') as f:
self.parser.ParseFile(f)
def start_element(self, name, attrs):
if name == 'genxml':
self.gen = Gen(attrs['gen'])
elif name in ('instruction', 'struct', 'register'):
+ if name == 'instruction' and 'engine' in attrs:
+ engines = set(attrs['engine'].split('|'))
+ if not engines & self.engines:
+ return
self.start_container(attrs)
elif name == 'field':
self.start_field(attrs)
if name not in self.containers:
self.containers[name] = Container(name)
self.container = self.containers[name]
+ self.container.add_gen(self.gen, attrs)
def start_field(self, attrs):
if self.container is None:
help="If OUTPUT is unset or '-', then it defaults to '/dev/stdout'")
p.add_argument('--cpp-guard', type=str,
help='If unset, then CPP_GUARD is derived from OUTPUT.')
+ p.add_argument('--engines', nargs='?', type=str, default='render',
+ help="Comma-separated list of engines whose instructions should be parsed (default: %(default)s)")
p.add_argument('xml_sources', metavar='XML_SOURCE', nargs='+')
pargs = p.parse_args()
def main():
pargs = parse_args()
+ engines = pargs.engines.split(',')
+ valid_engines = [ 'render', 'blitter', 'video' ]
+ if set(engines) - set(valid_engines):
+ print("Invalid engine specified, valid engines are:\n")
+ for e in valid_engines:
+ print("\t%s" % e)
+ sys.exit(1)
+
# Maps name => Container
containers = {}
for source in pargs.xml_sources:
- XmlParser(containers).parse(source)
+ p = XmlParser(containers)
+ p.engines = set(engines)
+ p.parse(source)
with open(pargs.output, 'wb') as f:
f.write(TEMPLATE.render(containers=containers, guard=pargs.cpp_guard))