[Mesa-dev] [PATCH 8/8] genxml: New generated header genX_bits.h (v2)

Jason Ekstrand jason at jlekstrand.net
Fri Mar 24 21:35:24 UTC 2017


From: Chad Versace <chadversary at chromium.org>

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(const struct gen_device_info *devinfo);

    which returns the number of bits in that field or 0 if the field
    does not exist on the specified hardware.

v2 (Chad Versace):
  - 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.

v3 (Dylan Baker):
  - Port to Mako

v4 (Jason Ekstrand):
  - Make the _bits functions take a gen_device_info

Co-authored-by: Dylan Baker <dylan at pnwbakers.com>
Co-authored-by: Jason Ekstrand <jason at jlekstrand.net>
---
 src/intel/Makefile.genxml.am        |   6 +-
 src/intel/Makefile.sources          |   6 +-
 src/intel/genxml/.gitignore         |   1 +
 src/intel/genxml/gen_bits_header.py | 293 ++++++++++++++++++++++++++++++++++++
 4 files changed, 304 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 01a02b6..4e59a91 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 88bcf60..c568916 100644
--- a/src/intel/Makefile.sources
+++ b/src/intel/Makefile.sources
@@ -119,7 +119,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 \
@@ -129,6 +129,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 c5672b5..3e2f1cf 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 0000000..53a980e
--- /dev/null
+++ b/src/intel/genxml/gen_bits_header.py
@@ -0,0 +1,293 @@
+#encoding=utf-8
+# Copyright © 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 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.
+
+from __future__ import (
+    absolute_import, division, print_function, unicode_literals
+)
+
+from textwrap import dedent
+import argparse
+import os
+import sys
+import xml.parsers.expat
+
+from mako.template import Template
+
+TEMPLATE = Template("""\
+/*
+ * Copyright © 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.
+ */
+
+#ifndef ${guard}
+#define ${guard}
+
+#include <stdint.h>
+
+#include "util/macros.h"
+#include "common/gen_device_info.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+% for _, field in sorted(fields.fields.iteritems(), key=lambda x: x[0]):
+
+   /* ${field.container_name}::${field.name} */
+
+   % for gen, bits in sorted(field.bits_by_gen.iteritems()):
+      #define ${gen.prefix(field.token_name())} ${bits}
+   % endfor
+
+   static inline uint32_t __attribute__((const))
+   ${field.token_name()}_bits(const struct gen_device_info *devinfo)
+   {
+      switch (devinfo->gen) {
+      case 4:
+         if (devinfo->is_g4x) {
+            return ${field.bits(4.5)};
+         } else {
+            return ${field.bits(4)};
+         }
+      case 5: return ${field.bits(5)};
+      case 6: return ${field.bits(6)};
+      case 7:
+         if (devinfo->is_haswell) {
+            return ${field.bits(7.5)};
+         } else {
+            return ${field.bits(7)};
+         }
+      case 8: return ${field.bits(8)};
+      case 9: return ${field.bits(9)};
+      default:
+         unreachable("Invalid hardware generation");
+      }
+   }
+
+% endfor
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ${guard} */""",
+output_encoding='utf-8')
+
+def to_alphanum(name):
+    substitutions = {
+        ' ': '',
+        '/': '',
+        '[': '',
+        ']': '',
+        '(': '',
+        ')': '',
+        '-': '',
+        ':': '',
+        '.': '',
+        ',': '',
+        '=': '',
+        '>': '',
+        '#': '',
+        'α': 'alpha',
+        '&': '',
+        '*': '',
+        '"': '',
+        '+': '',
+        '\'': '',
+    }
+
+    for i, j in substitutions.items():
+        name = name.replace(i, j)
+
+    return name
+
+def safe_name(name):
+    name = to_alphanum(name)
+    if not name[0].isalpha():
+        name = '_' + name
+
+    return name
+
+class Gen(object):
+
+    def __init__(self, z):
+        # Convert potential "major.minor" string
+        z = float(z)
+        if z < 10:
+            z *= 10
+        self.tenx = int(z)
+
+    def __lt__(self, other):
+        return self.tenx < other.tenx
+
+    def __hash__(self):
+        return hash(self.tenx)
+
+    def __eq__(self, other):
+        return self.tenx == other.tenx
+
+    def prefix(self, token):
+        gen = self.tenx
+
+        if gen % 10 == 0:
+            gen //= 10
+
+        if token[0] == '_':
+            token = token[1:]
+
+        return 'GEN{}_{}'.format(gen, token)
+
+class Field(object):
+
+    def __init__(self, container_name, name):
+        self.container_name = container_name
+        self.name = name
+        self.bits_by_gen = {}
+
+    def add_gen_field(self, gen, xml_attrs):
+        assert isinstance(gen, Gen)
+        start = int(xml_attrs['start'])
+        end = int(xml_attrs['end'])
+        self.bits_by_gen[gen] = 1 + end - start
+
+    def token_name(self):
+        return '_'.join([safe_name(self.container_name),
+                         safe_name(self.name)])
+
+    def bits(self, gen):
+        if not isinstance(gen, Gen):
+            gen = Gen(gen)
+        return self.bits_by_gen[gen] if gen in self.bits_by_gen else 0
+
+class FieldCollection(object):
+
+    def __init__(self):
+        self.fields = {}
+
+    def add_field(self, gen, container_name, xml_attrs):
+        field_name = xml_attrs['name']
+        field_key = (container_name, field_name)
+        if field_key not in self.fields.keys():
+            self.fields[field_key] = Field(container_name, field_name)
+        self.fields[field_key].add_gen_field(gen, xml_attrs)
+
+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.gen = None
+        self.container_name = None
+        self.fields = field_collection
+
+    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']
+
+        self.container_name = name
+
+    def start_field(self, attrs):
+        if self.container_name is None:
+            return
+
+        name = attrs.get('name', None)
+        if not name:
+            return
+
+        self.fields.add_field(self.gen, self.container_name, attrs)
+
+
+def parse_args():
+    p = argparse.ArgumentParser()
+    p.add_argument('-o', '--output', type=str)
+    p.add_argument('sources', metavar='SOURCES', nargs='+')
+
+    pargs = p.parse_args()
+
+    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, 'wb') as f:
+        f.write(TEMPLATE.render(
+            fields=fields,
+            guard=os.path.basename(f.name).upper().replace('.', '_')))
+
+
+if __name__ == '__main__':
+    main()
-- 
2.5.0.400.gff86faf



More information about the mesa-dev mailing list