summaryrefslogtreecommitdiffstats
path: root/src/intel/genxml
diff options
context:
space:
mode:
authorChad Versace <[email protected]>2017-03-24 14:35:24 -0700
committerChad Versace <[email protected]>2017-03-28 09:44:44 -0700
commitf0eaf38db2c7ed5dd3cbc62ad078bf9d08924640 (patch)
tree84f9348308627317a58cb76a2af1bbc5691e7832 /src/intel/genxml
parent3974cfea2531b86fb394d8501b106e69f00c5f89 (diff)
genxml: New generated header genX_bits.h (v6)
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: - Each CONTAINER::Field from gen*.xml that has a bitsize has a macro in genX_bits.h: #define GEN{N}_CONTAINER_Field_bits {bitsize} - For each set of macros whose name, after stripping the GEN prefix, is the same, genX_bits.h contains a query function: static inline uint32_t __attribute__((pure)) CONTAINER_Field_bits(const struct gen_device_info *devinfo); v2 (Chad Versace): - Parse the XML instead of scraping the generated gen*_pack.h headers. v3 (Dylan Baker): - Port to Mako. v4 (Jason Ekstrand): - Make the _bits functions take a gen_device_info. v5 (Chad Versace): - Fix autotools out-of-tree build. - Fix Android build. Tested with git://github.com/android-ia/manifest. - Fix macro names. They were all missing the "_bits" suffix. - Fix macros names more. Remove all double-underscores. - Unindent all generated code. (It was floating in a sea of whitespace). - Reformat header to appear human-written not machine-generated. - Sort gens from high to low. Newest gens should come first because, when we read code, we likely want to read the gen8/9 code and ignore the gen4 code. So put the gen4 code at the bottom. - Replace 'const' attributes with 'pure', because the functions now have a pointer parameter. - Add --cpp-guard flag. Used by Android. - Kill class FieldCollection. After Jason's rewrite, it was just a dict. v6 (Chad Versace): - Replace `key not in d.keys()` with `key not in d`. [for dylan] Co-authored-by: Dylan Baker <[email protected]> Co-authored-by: Jason Ekstrand <[email protected]> Reviewed-by: Jason Ekstrand <[email protected]> (v5) Reviewed-by: Dylan Baker <[email protected]> (v6)
Diffstat (limited to 'src/intel/genxml')
-rw-r--r--src/intel/genxml/.gitignore1
-rw-r--r--src/intel/genxml/gen_bits_header.py281
2 files changed, 282 insertions, 0 deletions
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..808e6cf3f92
--- /dev/null
+++ b/src/intel/genxml/gen_bits_header.py
@@ -0,0 +1,281 @@
+#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
+)
+
+import argparse
+import os
+import sys
+import xml.parsers.expat
+
+from mako.template import Template
+
+TEMPLATE = Template("""\
+<%!
+from operator import itemgetter
+%>\
+/*
+ * 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 "common/gen_device_info.h"
+#include "util/macros.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+% for _, field in sorted(fields.iteritems(), key=itemgetter(0)):
+
+/* ${field.container_name}::${field.name} */
+% for gen, bits in sorted(field.bits_by_gen.iteritems(), reverse=True):
+#define ${gen.prefix(field.token_name, padded=True)} ${bits}
+% endfor
+
+static inline uint32_t ATTRIBUTE_PURE
+${field.token_name}(const struct gen_device_info *devinfo)
+{
+ switch (devinfo->gen) {
+ case 9: return ${field.bits(9)};
+ case 8: return ${field.bits(8)};
+ case 7:
+ if (devinfo->is_haswell) {
+ return ${field.bits(7.5)};
+ } else {
+ return ${field.bits(7)};
+ }
+ case 6: return ${field.bits(6)};
+ case 5: return ${field.bits(5)};
+ case 4:
+ if (devinfo->is_g4x) {
+ return ${field.bits(4.5)};
+ } else {
+ return ${field.bits(4)};
+ }
+ 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, padded=False):
+ gen = self.tenx
+ pad = ''
+
+ if gen % 10 == 0:
+ gen //= 10
+ if padded:
+ pad = ' '
+
+ if token[0] == '_':
+ token = token[1:]
+
+ return 'GEN{}_{}{}'.format(gen, token, pad)
+
+class Field(object):
+
+ def __init__(self, container_name, name):
+ self.container_name = container_name
+ self.name = name
+ self.token_name = safe_name('_'.join([self.container_name, self.name, 'bits']))
+ self.bits_by_gen = {}
+
+ def add_gen(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 bits(self, gen):
+ if not isinstance(gen, Gen):
+ gen = Gen(gen)
+ return self.bits_by_gen.get(gen, 0)
+
+class XmlParser(object):
+
+ def __init__(self, fields):
+ 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 = fields
+
+ 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
+ self.container_name = attrs['name']
+
+ def start_field(self, attrs):
+ if self.container_name is None:
+ return
+
+ field_name = attrs.get('name', None)
+ if not field_name:
+ return
+
+ key = (self.container_name, field_name)
+ if key not in self.fields:
+ self.fields[key] = Field(self.container_name, field_name)
+ self.fields[key].add_gen(self.gen, attrs)
+
+def parse_args():
+ p = argparse.ArgumentParser()
+ p.add_argument('-o', '--output', type=str,
+ help="If OUTPUT is unset or '-', then it defaults to '/dev/stdout'")
+ p.add_argument('--cpp-guard', type=str,
+ help='If unset, then CPP_GUARD is derived from OUTPUT.')
+ p.add_argument('xml_sources', metavar='XML_SOURCE', nargs='+')
+
+ pargs = p.parse_args()
+
+ if pargs.output in (None, '-'):
+ pargs.output = '/dev/stdout'
+
+ if pargs.cpp_guard is None:
+ pargs.cpp_guard = os.path.basename(pargs.output).upper().replace('.', '_')
+
+ return pargs
+
+def main():
+ pargs = parse_args()
+
+ # Maps (container_name, field_name) => Field
+ fields = {}
+
+ for source in pargs.xml_sources:
+ XmlParser(fields).parse(source)
+
+ with open(pargs.output, 'wb') as f:
+ f.write(TEMPLATE.render(fields=fields, guard=pargs.cpp_guard))
+
+if __name__ == '__main__':
+ main()