[Mesa-dev] [PATCH 3/9] genxml: New generated header genX_bits.h (v2)
Jason Ekstrand
jason at jlekstrand.net
Thu Mar 23 18:54:00 UTC 2017
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 <chadversary at 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 at lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/mesa-dev
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.freedesktop.org/archives/mesa-dev/attachments/20170323/f67687c6/attachment-0001.html>
More information about the mesa-dev
mailing list