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