<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>