I'm not going to ask you to rewrite it in mako but that's what we should do in the future. :-) Someone can rewrite later. I want things to land. :-)
On Wed, Mar 22, 2017 at 6:03 PM, Chad Versace <chadvers...@chromium.org> wrote: > genX_bits.h contains the sizes of bitfields in genxml instructions, > structures, and registers. It also defines some functions to query those > sizes. > > isl_surf_init() will use the new header to validate that requested > pitches fit in their destination bitfields. > > What's currently in genX_bits.h: > > - For each CONTAINER::Field in gen{n}.xml whose name matches > /.*Surface(Q?)Pitch_bits$/, genX_bits.h contains the line: > > #define GEN{n}_CONTAINER_Field_bits {number of bits in field} > > STREAMOUT fields are omitted because isl doesn't care about them. > > - For each set of macros whose name, after stripping the GEN prefix, > is the same, genX_bits.h contains the query function: > > static inline uint32_t __attribute__((const)) > CONTAINER_Field_bits(int gen_10x) > If it's practical, I would much rather they just take a devinfo. The GENx10 thing is a hack that I don't think we can trust to work indefinitely. Also, it makes it much easier for the caller to deal with. I think Dylan is going to see if he can quickly cook up a mako version and I'll see how hard devinfo is. Don't spend time on this yet. --Jason > { > switch (gen_10x) { > case {n0}: return GEN{n0}_CONTAINER_Field_bits; > case {n1}: return GEN{n1}_CONTAINER_Field_bits; > ... > default: return 0; > } > > v2: Parse the XML instead of scraping the generated gen*_pack.h headers. > [for jekstrand] > > Jason and I tentatively agreed that I should just hand-write the > header. But my conscience refused. The XML way is the right way. > Anyway, the generator script are about the same number of lines (259 > vs 222), so the generator is the clear winner in my opinion. > --- > src/intel/Makefile.genxml.am | 6 +- > src/intel/Makefile.sources | 6 +- > src/intel/genxml/.gitignore | 1 + > src/intel/genxml/gen_bits_header.py | 259 ++++++++++++++++++++++++++++++ > ++++++ > 4 files changed, 270 insertions(+), 2 deletions(-) > create mode 100644 src/intel/genxml/gen_bits_header.py > > diff --git a/src/intel/Makefile.genxml.am b/src/intel/Makefile.genxml.am > index 01a02b63b44..4e59a918618 100644 > --- a/src/intel/Makefile.genxml.am > +++ b/src/intel/Makefile.genxml.am > @@ -30,7 +30,7 @@ EXTRA_DIST += \ > > SUFFIXES = _pack.h _xml.h .xml > > -$(GENXML_GENERATED_FILES): genxml/gen_pack_header.py > +$(GENXML_GENERATED_PACK_FILES): genxml/gen_pack_header.py > > .xml_pack.h: > $(MKDIR_GEN) > @@ -42,6 +42,10 @@ $(AUBINATOR_GENERATED_FILES): genxml/gen_zipped_file.py > $(MKDIR_GEN) > $(AM_V_GEN) $(PYTHON2) $(srcdir)/genxml/gen_zipped_file.py $< > > $@ || ($(RM) $@; false) > > +genxml/genX_bits.h: genxml/gen_bits_header.py $(GENXML_XML_FILES) > + $(MKDIR_GEN) > + $(PYTHON_GEN) $< -o $@ $(GENXML_XML_FILES) > + > EXTRA_DIST += \ > genxml/genX_pack.h \ > genxml/gen_macros.h \ > diff --git a/src/intel/Makefile.sources b/src/intel/Makefile.sources > index 801797d2768..ec43f06a495 100644 > --- a/src/intel/Makefile.sources > +++ b/src/intel/Makefile.sources > @@ -117,7 +117,7 @@ GENXML_XML_FILES = \ > genxml/gen8.xml \ > genxml/gen9.xml > > -GENXML_GENERATED_FILES = \ > +GENXML_GENERATED_PACK_FILES = \ > genxml/gen4_pack.h \ > genxml/gen45_pack.h \ > genxml/gen5_pack.h \ > @@ -127,6 +127,10 @@ GENXML_GENERATED_FILES = \ > genxml/gen8_pack.h \ > genxml/gen9_pack.h > > +GENXML_GENERATED_FILES = \ > + $(GENXML_GENERATED_PACK_FILES) \ > + genxml/genX_bits.h > + > AUBINATOR_GENERATED_FILES = \ > genxml/gen6_xml.h \ > genxml/gen7_xml.h \ > diff --git a/src/intel/genxml/.gitignore b/src/intel/genxml/.gitignore > index c5672b5595c..3e2f1cfa9f0 100644 > --- a/src/intel/genxml/.gitignore > +++ b/src/intel/genxml/.gitignore > @@ -1,2 +1,3 @@ > +gen*_bits.h > gen*_pack.h > gen*_xml.h > diff --git a/src/intel/genxml/gen_bits_header.py > b/src/intel/genxml/gen_bits_header.py > new file mode 100644 > index 00000000000..0315c6251e7 > --- /dev/null > +++ b/src/intel/genxml/gen_bits_header.py > @@ -0,0 +1,259 @@ > +#encoding=utf-8 > + > +from __future__ import ( > + absolute_import, division, print_function, unicode_literals > +) > + > +import argparse > +import io > +import os > +import os.path > +import re > +import sys > +from sys import stdout, stderr > +from textwrap import dedent > +import xml.parsers.expat > + > +def safe_token(t): > + t = t.replace(' ', '') > + if t[0].isdigit(): > + t = '_' + t > + return t > + > +class Gen(object): > + > + def __init__(self, z): > + # Convert potential "major.minor" string > + z = float(z) > + if z < 10: > + z *= 10 > + self._10x = int(z) > + > + def prefix(self, token): > + gen = self._10x > + > + if gen % 10 == 0: > + gen //= 10 > + > + if token[0] == '_': > + token = token[1:] > + > + return 'GEN{}_{}'.format(gen, token) > + > +class Header(object): > + > + def __init__(self, buf): > + self.buf = buf > + self.cpp_guard = os.path.basename(buf.name).upper().replace('.', > '_') > + > + def write(self, *args, **kwargs): > + self.buf.write(*args, **kwargs) > + > + def write_prologue(self): > + self.write(dedent("""\ > + /* > + * Copyright (C) 2017 Intel Corporation > + * > + * Permission is hereby granted, free of charge, to any > person obtaining a > + * copy of this software and associated documentation files > (the "Software"), > + * to deal in the Software without restriction, including > without limitation > + * the rights to use, copy, modify, merge, publish, > distribute, sublicense, > + * and/or sell copies of the Software, and to permit persons > to whom the > + * Software is furnished to do so, subject to the following > conditions: > + * > + * The above copyright notice and this permission notice > (including the next > + * paragraph) shall be included in all copies or substantial > portions of the > + * Software. > + * > + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY > KIND, EXPRESS OR > + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF > MERCHANTABILITY, > + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN > NO EVENT SHALL > + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, > DAMAGES OR OTHER > + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR > OTHERWISE, ARISING > + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE > OR OTHER DEALINGS > + * IN THE SOFTWARE. > + */ > + > + /* THIS FILE HAS BEEN GENERATED, DO NOT HAND EDIT. > + * > + * Sizes of bitfields in genxml instructions, structures, and > registers. > + */ > + > + """)) > + > + self.write('#ifndef {}\n'.format(self.cpp_guard)) > + self.write('#define {}\n'.format(self.cpp_guard)) > + > + self.write(dedent(""" > + #include <stdint.h> > + > + #ifdef __cplusplus > + extern "C" { > + #endif > + > + """)) > + > + def write_epilogue(self): > + self.write(dedent("""\ > + #ifdef __cplusplus > + } > + #endif > + > + """)) > + > + self.write('#endif /* {} */\n'.format(self.cpp_guard)) > + > + def write_macros(self, fields): > + for gen_10x in sorted(fields.by_gen_10x.keys(), reverse=True): > + for f in fields.by_gen_10x[gen_10x]: > + self.write('#define {:56} {:2}'.format(f.token_name, > f.bits)) > + if f.comment: > + self.write(' /* {} */'.format(f.comment)) > + self.write('\n') > + self.write('\n') > + > + def write_funcs(self, fields): > + def gen_10x(field): > + return field.gen._10x > + > + for basename in sorted(fields.by_token_basenames.keys()): > + self.write('static inline uint32_t __attribute__((const))\n') > + self.write('{}(int gen_10x)\n'.format(basename)) > + self.write('{\n') > + self.write(' switch (gen_10x) {\n') > + > + for f in sorted(fields.by_token_basenames[basename], > + key=gen_10x, reverse=True): > + self.write(' case {}: return {};\n' > + .format(f.gen._10x, f.token_name)) > + > + self.write(' default: return 0;\n') > + self.write(' }\n') > + self.write('}\n') > + self.write('\n') > + > +class Field(object): > + > + SURFACE_PITCH_REGEX = re.compile(r'.*Surface (Q?)Pitch$') > + > + def __init__(self, gen, container_name, xml_attrs, comment=None): > + assert isinstance(gen, Gen) > + assert container_name > + > + self.gen = gen > + self.container_name = container_name > + self.name = xml_attrs['name'] > + self.start = int(xml_attrs['start']) > + self.end = int(xml_attrs['end']) > + self.bits = 1 + self.end - self.start > + self.token_basename = '_'.join([safe_token(container_name), > safe_token(self.name), 'bits']) > + self.token_name = gen.prefix(self.token_basename) > + self.comment = comment > + > +class FieldCollection(object): > + > + def __init__(self): > + self.by_gen_10x = {} > + self.by_token_basenames = {} > + > + def add(self, field): > + self.by_gen_10x.setdefault(field.gen._10x, []).append(field) > + self.by_token_basenames.setdefault(field.token_basename, > []).append(field) > + > +class XmlParser(object): > + > + def __init__(self, field_collection): > + self.parser = xml.parsers.expat.ParserCreate() > + self.parser.StartElementHandler = self.start_element > + self.parser.EndElementHandler = self.end_element > + > + self.fields = field_collection > + self.container_name = None > + > + def parse(self, filename): > + with open(filename) 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'): > + self.start_container(attrs) > + elif name == 'field': > + self.start_field(attrs) > + else: > + pass > + > + def end_element(self, name): > + if name == 'genxml': > + self.gen = None > + elif name in ('instruction', 'struct', 'register'): > + self.container_name = None > + else: > + pass > + > + def start_container(self, attrs): > + assert self.container_name is None > + name = attrs['name'] > + > + # We don't care about these > + if re.search(r'STREAMOUT|3DSTATE_SO', name): > + return > + > + self.container_name = safe_token(name) > + > + def start_field(self, attrs): > + if self.container_name is None: > + return > + > + name = attrs.get('name', None) > + if not name: > + return > + > + match = Field.SURFACE_PITCH_REGEX.match(name) > + if not match: > + return > + > + self.fields.add(Field(self.gen, self.container_name, attrs)) > + > + if name == 'MCS Surface Pitch': > + # MCSSurfacePitch in older gens is analogous to > + # AuxiliarySurfacePitch in newer gens. > + aux_attrs = attrs.copy() > + aux_attrs['name'] = 'Auxiliary Surface Pitch' > + self.fields.add(Field(self.gen, self.container_name, > aux_attrs, > + comment='alias of MCSSurfacePitch')) > + > +def parse_args(): > + p = argparse.ArgumentParser() > + p.add_argument('-o', '--output', type=str) > + p.add_argument('sources', metavar='SOURCES', nargs=argparse.REMAINDER) > + > + pargs = p.parse_args() > + > + if len(pargs.sources) == 0: > + stderr.write('error: no source files\n') > + sys.exit(1) > + > + if pargs.output in (None, '-'): > + pargs.output = '/dev/stdout' > + > + return pargs > + > +def main(): > + pargs = parse_args() > + > + fields = FieldCollection() > + > + for source in pargs.sources: > + XmlParser(fields).parse(source) > + > + with open(pargs.output, 'w') as outfile: > + header = Header(outfile) > + header.write_prologue() > + header.write_macros(fields) > + header.write_funcs(fields) > + header.write_epilogue() > + > +if __name__ == '__main__': > + main() > -- > 2.12.0 > > _______________________________________________ > mesa-dev mailing list > mesa-dev@lists.freedesktop.org > https://lists.freedesktop.org/mailman/listinfo/mesa-dev >
_______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/mesa-dev