diff options
Diffstat (limited to 'src/intel/genxml/gen_pack_header.py')
-rw-r--r-- | src/intel/genxml/gen_pack_header.py | 435 |
1 files changed, 194 insertions, 241 deletions
diff --git a/src/intel/genxml/gen_pack_header.py b/src/intel/genxml/gen_pack_header.py index 45bbb30c464..899bc0f9e22 100644 --- a/src/intel/genxml/gen_pack_header.py +++ b/src/intel/genxml/gen_pack_header.py @@ -2,7 +2,7 @@ import argparse import ast -import xml.parsers.expat +import intel_genxml import re import sys import copy @@ -43,155 +43,12 @@ pack_header = """%(license)s #ifndef %(guard)s #define %(guard)s +#ifndef __OPENCL_VERSION__ #include <stdio.h> -#include <stdint.h> -#include <stdbool.h> -#include <assert.h> -#include <math.h> - -#ifndef __gen_validate_value -#define __gen_validate_value(x) -#endif - -#ifndef __intel_field_functions -#define __intel_field_functions - -#ifdef NDEBUG -#define NDEBUG_UNUSED __attribute__((unused)) +#include "util/bitpack_helpers.h" +#include "genX_helpers.h" #else -#define NDEBUG_UNUSED -#endif - -union __intel_value { - float f; - uint32_t dw; -}; - -static inline __attribute__((always_inline)) uint64_t -__gen_mbo(uint32_t start, uint32_t end) -{ - return (~0ull >> (64 - (end - start + 1))) << start; -} - -static inline __attribute__((always_inline)) uint64_t -__gen_uint(uint64_t v, uint32_t start, NDEBUG_UNUSED uint32_t end) -{ - __gen_validate_value(v); - -#ifndef NDEBUG - const int width = end - start + 1; - if (width < 64) { - const uint64_t max = (1ull << width) - 1; - assert(v <= max); - } -#endif - - return v << start; -} - -static inline __attribute__((always_inline)) uint64_t -__gen_sint(int64_t v, uint32_t start, uint32_t end) -{ - const int width = end - start + 1; - - __gen_validate_value(v); - -#ifndef NDEBUG - if (width < 64) { - const int64_t max = (1ll << (width - 1)) - 1; - const int64_t min = -(1ll << (width - 1)); - assert(min <= v && v <= max); - } -#endif - - const uint64_t mask = ~0ull >> (64 - width); - - return (v & mask) << start; -} - -static inline __attribute__((always_inline)) uint64_t -__gen_offset(uint64_t v, NDEBUG_UNUSED uint32_t start, NDEBUG_UNUSED uint32_t end) -{ - __gen_validate_value(v); -#ifndef NDEBUG - uint64_t mask = (~0ull >> (64 - (end - start + 1))) << start; - - assert((v & ~mask) == 0); -#endif - - return v; -} - -static inline __attribute__((always_inline)) uint64_t -__gen_address(__gen_user_data *data, void *location, - __gen_address_type address, uint32_t delta, - __attribute__((unused)) uint32_t start, uint32_t end) -{ - uint64_t addr_u64 = __gen_combine_address(data, location, address, delta); - if (end == 31) { - return addr_u64; - } else if (end < 63) { - const unsigned shift = 63 - end; - return (addr_u64 << shift) >> shift; - } else { - return addr_u64; - } -} - -static inline __attribute__((always_inline)) uint32_t -__gen_float(float v) -{ - __gen_validate_value(v); - return ((union __intel_value) { .f = (v) }).dw; -} - -static inline __attribute__((always_inline)) uint64_t -__gen_sfixed(float v, uint32_t start, uint32_t end, uint32_t fract_bits) -{ - __gen_validate_value(v); - - const float factor = (1 << fract_bits); - -#ifndef NDEBUG - const float max = ((1 << (end - start)) - 1) / factor; - const float min = -(1 << (end - start)) / factor; - assert(min <= v && v <= max); -#endif - - const int64_t int_val = llroundf(v * factor); - const uint64_t mask = ~0ull >> (64 - (end - start + 1)); - - return (int_val & mask) << start; -} - -static inline __attribute__((always_inline)) uint64_t -__gen_ufixed(float v, uint32_t start, NDEBUG_UNUSED uint32_t end, uint32_t fract_bits) -{ - __gen_validate_value(v); - - const float factor = (1 << fract_bits); - -#ifndef NDEBUG - const float max = ((1 << (end - start + 1)) - 1) / factor; - const float min = 0.0f; - assert(min <= v && v <= max); -#endif - - const uint64_t uint_val = llroundf(v * factor); - - return uint_val << start; -} - -#ifndef __gen_address_type -#error #define __gen_address_type before including this file -#endif - -#ifndef __gen_user_data -#error #define __gen_combine_address before including this file -#endif - -#undef NDEBUG_UNUSED - +#include "genX_cl_helpers.h" #endif """ @@ -203,6 +60,10 @@ def num_from_str(num_str): assert not num_str.startswith('0'), 'octals numbers not allowed' return int(num_str) +def bool_from_str(bool_str): + options = { "true": True, "false": False } + return options[bool_str]; + class Field(object): ufixed_pattern = re.compile(r"u(\d+)\.(\d+)") sfixed_pattern = re.compile(r"s(\d+)\.(\d+)") @@ -214,6 +75,8 @@ class Field(object): self.start = int(attrs["start"]) self.end = int(attrs["end"]) self.type = attrs["type"] + self.nonzero = bool_from_str(attrs.get("nonzero", "false")) + self.prefix = attrs["prefix"] if "prefix" in attrs else None assert self.start <= self.end, \ 'field {} has end ({}) < start ({})'.format(self.name, self.end, @@ -222,11 +85,6 @@ class Field(object): assert self.end == self.start, \ 'bool field ({}) is too wide'.format(self.name) - if "prefix" in attrs: - self.prefix = attrs["prefix"] - else: - self.prefix = None - if "default" in attrs: # Base 0 recognizes 0x, 0o, 0b prefixes in addition to decimal ints. self.default = int(attrs["default"], base=0) @@ -245,7 +103,8 @@ class Field(object): def is_builtin_type(self): builtins = [ 'address', 'bool', 'float', 'ufixed', - 'offset', 'sfixed', 'offset', 'int', 'uint', 'mbo' ] + 'offset', 'sfixed', 'offset', 'int', 'uint', + 'mbo', 'mbz' ] return self.type in builtins def is_struct_type(self): @@ -256,7 +115,7 @@ class Field(object): def emit_template_struct(self, dim): if self.type == 'address': - type = '__gen_address_type' + type = 'uint64_t' if self.parser.opencl else '__gen_address_type' elif self.type == 'bool': type = 'bool' elif self.type == 'float': @@ -277,7 +136,7 @@ class Field(object): type = 'struct ' + self.parser.gen_prefix(safe_name(self.type)) elif self.is_enum_type(): type = 'enum ' + self.parser.gen_prefix(safe_name(self.type)) - elif self.type == 'mbo': + elif self.type == 'mbo' or self.type == 'mbz': return else: print("#error unhandled type: %s" % self.type) @@ -285,13 +144,14 @@ class Field(object): print(" %-36s %s%s;" % (type, self.name, dim)) - prefix = "" - if self.values and self.default is None: - if self.prefix: - prefix = self.prefix + "_" + prefix = self.prefix + '_' if self.prefix else '' for value in self.values: - print("#define %-40s %d" % (prefix + value.name, value.value)) + name = value.name + if self.prefix and value.name[0] == '_': + name = name[1:] + + print("#define %-40s %d" % (prefix + name, value.value)) class Group(object): def __init__(self, parser, parent, start, count, size): @@ -355,7 +215,7 @@ class Group(object): dwords[index + 1] = dwords[index] index = index + 1 - def collect_dwords_and_length(self): + def collect_dwords_and_length(self, repack=False): dwords = {} self.collect_dwords(dwords, 0, "") @@ -372,7 +232,7 @@ class Group(object): return (dwords, length) - def emit_pack_function(self, dwords, length): + def emit_pack_function(self, dwords, length, repack=False): for index in range(length): # Handle MBZ dwords if not index in dwords: @@ -396,8 +256,20 @@ class Group(object): name = field.name + field.dim if field.is_struct_type() and field.start % 32 == 0: print("") - print(" %s_pack(data, &dw[%d], &values->%s);" % - (self.parser.gen_prefix(safe_name(field.type)), index, name)) + if repack: + if self.parser.opencl: + print(" %s_repack(&dw[%d], &origin[%d], &values->%s);" % + (self.parser.gen_prefix(safe_name(field.type)), index, index, name)) + else: + print(" %s_pack(data, &dw[%d], &origin[%d], &values->%s);" % + (self.parser.gen_prefix(safe_name(field.type)), index, index, name)) + else: + if self.parser.opencl: + print(" %s_pack(&dw[%d], &values->%s);" % + (self.parser.gen_prefix(safe_name(field.type)), index, name)) + else: + print(" %s_pack(data, &dw[%d], &values->%s);" % + (self.parser.gen_prefix(safe_name(field.type)), index, name)) continue # Pack any fields of struct type first so we have integer values @@ -408,8 +280,20 @@ class Group(object): name = field.name + field.dim print("") print(" uint32_t v%d_%d;" % (index, field_index)) - print(" %s_pack(data, &v%d_%d, &values->%s);" % - (self.parser.gen_prefix(safe_name(field.type)), index, field_index, name)) + if repack: + if self.parser.opencl: + print(" %s_repack(&v%d_%d, &origin[%d], &values->%s);" % + (self.parser.gen_prefix(safe_name(field.type)), index, field_index, index, name)) + else: + print(" %s_repack(data, &v%d_%d, &origin[%d], &values->%s);" % + (self.parser.gen_prefix(safe_name(field.type)), index, field_index, index, name)) + else: + if self.parser.opencl: + print(" %s_pack(&v%d_%d, &values->%s);" % + (self.parser.gen_prefix(safe_name(field.type)), index, field_index, name)) + else: + print(" %s_pack(data, &v%d_%d, &values->%s);" % + (self.parser.gen_prefix(safe_name(field.type)), index, field_index, name)) field_index = field_index + 1 print("") @@ -419,10 +303,17 @@ class Group(object): else: address_count = 1 + # Assert in dont_use values + for field in dw.fields: + for value in field.values: + if value.dont_use: + print(" assert(values->%s != %s);" % + (field.name, field.prefix + "_" + value.name)) + if dw.size == 32 and dw.address == None: v = None print(" dw[%d] =" % index) - elif len(dw.fields) > address_count: + elif len(dw.fields) > address_count or repack: v = "v%d" % index print(" const uint%d_t %s =" % (dw.size, v)) else: @@ -430,40 +321,52 @@ class Group(object): field_index = 0 non_address_fields = [] + + if repack: + non_address_fields.append("origin[%d]" % index) + if dw.size > 32: + non_address_fields.append("((uint64_t)origin[%d] << 32)" % (index + 1)) + for field in dw.fields: - if field.type != "mbo": + if field.type != "mbo" and field.type != "mbz" and field.type != "repack": name = field.name + field.dim - if field.type == "mbo": - non_address_fields.append("__gen_mbo(%d, %d)" % \ + nz = "_nonzero" if field.nonzero else "" + + if field.type == "repack": + non_address_fields.append("origin[%d]" % index) + elif field.type == "mbo": + non_address_fields.append("util_bitpack_ones(%d, %d)" % \ (field.start - dword_start, field.end - dword_start)) + elif field.type == "mbz": + assert not field.nonzero elif field.type == "address": pass elif field.type == "uint": - non_address_fields.append("__gen_uint(values->%s, %d, %d)" % \ - (name, field.start - dword_start, field.end - dword_start)) + non_address_fields.append("util_bitpack_uint%s(values->%s, %d, %d)" % \ + (nz, name, field.start - dword_start, field.end - dword_start)) elif field.is_enum_type(): - non_address_fields.append("__gen_uint(values->%s, %d, %d)" % \ - (name, field.start - dword_start, field.end - dword_start)) + non_address_fields.append("util_bitpack_uint%s(values->%s, %d, %d)" % \ + (nz, name, field.start - dword_start, field.end - dword_start)) elif field.type == "int": - non_address_fields.append("__gen_sint(values->%s, %d, %d)" % \ - (name, field.start - dword_start, field.end - dword_start)) + non_address_fields.append("util_bitpack_sint%s(values->%s, %d, %d)" % \ + (nz, name, field.start - dword_start, field.end - dword_start)) elif field.type == "bool": - non_address_fields.append("__gen_uint(values->%s, %d, %d)" % \ - (name, field.start - dword_start, field.end - dword_start)) + non_address_fields.append("util_bitpack_uint%s(values->%s, %d, %d)" % \ + (nz, name, field.start - dword_start, field.end - dword_start)) elif field.type == "float": - non_address_fields.append("__gen_float(values->%s)" % name) + non_address_fields.append("util_bitpack_float%s(values->%s)" % (nz, name)) elif field.type == "offset": - non_address_fields.append("__gen_offset(values->%s, %d, %d)" % \ - (name, field.start - dword_start, field.end - dword_start)) + non_address_fields.append("__gen_offset%s(values->%s, %d, %d)" % \ + (nz, name, field.start - dword_start, field.end - dword_start)) elif field.type == 'ufixed': - non_address_fields.append("__gen_ufixed(values->%s, %d, %d, %d)" % \ - (name, field.start - dword_start, field.end - dword_start, field.fractional_size)) + non_address_fields.append("util_bitpack_ufixed%s(values->%s, %d, %d, %d)" % \ + (nz, name, field.start - dword_start, field.end - dword_start, field.fractional_size)) elif field.type == 'sfixed': - non_address_fields.append("__gen_sfixed(values->%s, %d, %d, %d)" % \ - (name, field.start - dword_start, field.end - dword_start, field.fractional_size)) + non_address_fields.append("util_bitpack_sfixed%s(values->%s, %d, %d, %d)" % \ + (nz, name, field.start - dword_start, field.end - dword_start, field.fractional_size)) elif field.is_struct_type(): - non_address_fields.append("__gen_uint(v%d_%d, %d, %d)" % \ + non_address_fields.append("util_bitpack_uint(v%d_%d, %d, %d)" % \ (index, field_index, field.start - dword_start, field.end - dword_start)) field_index = field_index + 1 else: @@ -475,16 +378,26 @@ class Group(object): if dw.size == 32: if dw.address: - print(" dw[%d] = __gen_address(data, &dw[%d], values->%s, %s, %d, %d);" % - (index, index, dw.address.name + field.dim, v, - dw.address.start - dword_start, dw.address.end - dword_start)) + if self.parser.opencl: + print(" dw[%d] = __gen_address(values->%s, %d, %d) | %s;" % + (index, dw.address.name + field.dim, + dw.address.start - dword_start, dw.address.end - dword_start, v)) + else: + print(" dw[%d] = __gen_address(data, &dw[%d], values->%s, %s, %d, %d);" % + (index, index, dw.address.name + field.dim, v, + dw.address.start - dword_start, dw.address.end - dword_start)) continue if dw.address: v_address = "v%d_address" % index - print(" const uint64_t %s =\n __gen_address(data, &dw[%d], values->%s, %s, %d, %d);" % - (v_address, index, dw.address.name + field.dim, v, - dw.address.start - dword_start, dw.address.end - dword_start)) + if self.parser.opencl: + print(" const uint64_t %s =\n __gen_address(values->%s, %d, %d) | %s;" % + (v_address, dw.address.name + field.dim, + dw.address.start - dword_start, dw.address.end - dword_start, v)) + else: + print(" const uint64_t %s =\n __gen_address(data, &dw[%d], values->%s, %s, %d, %d);" % + (v_address, index, dw.address.name + field.dim, v, + dw.address.start - dword_start, dw.address.end - dword_start)) if len(dw.fields) > address_count: print(" dw[%d] = %s;" % (index, v_address)) print(" dw[%d] = (%s >> 32) | (%s >> 32);" % (index + 1, v_address, v)) @@ -498,18 +411,17 @@ class Value(object): def __init__(self, attrs): self.name = safe_name(attrs["name"]) self.value = ast.literal_eval(attrs["value"]) + self.dont_use = int(attrs["dont_use"]) != 0 if "dont_use" in attrs else False class Parser(object): - def __init__(self): - self.parser = xml.parsers.expat.ParserCreate() - self.parser.StartElementHandler = self.start_element - self.parser.EndElementHandler = self.end_element - + def __init__(self, opencl, repack): self.instruction = None self.structs = {} # Set of enum names we've seen. self.enums = set() self.registers = {} + self.opencl = opencl + self.repack = repack def gen_prefix(self, name): if name[0] == "_": @@ -517,24 +429,19 @@ class Parser(object): return 'GFX%s_%s' % (self.gen, name) def gen_guard(self): - return self.gen_prefix("PACK_H") - - def start_element(self, name, attrs): - if name == "genxml": - self.platform = attrs["name"] - self.gen = attrs["gen"].replace('.', '') - print(pack_header % {'license': license, 'platform': self.platform, 'guard': self.gen_guard()}) - elif name in ("instruction", "struct", "register"): + if self.opencl: + return self.gen_prefix("{0}_CL_PACK_H".format(self.platform)) + return self.gen_prefix("{0}_PACK_H".format(self.platform)) + + def process_item(self, item): + name = item.tag + assert name != "genxml" + attrs = item.attrib + + if name in ("instruction", "struct", "register"): if name == "instruction": self.instruction = safe_name(attrs["name"]) self.length_bias = int(attrs["bias"]) - if "engine" in attrs: - self.instruction_engines = set(attrs["engine"].split('|')) - else: - # When an instruction doesn't have the engine specified, - # it is considered to be for all engines, so 'None' is used - # to signify that the instruction belongs to all engines. - self.instruction_engines = None elif name == "struct": self.struct = safe_name(attrs["name"]) self.structs[attrs["name"]] = 1 @@ -565,11 +472,17 @@ class Parser(object): if "prefix" in attrs: self.prefix = safe_name(attrs["prefix"]) else: - self.prefix= None + self.prefix = None elif name == "value": self.values.append(Value(attrs)) + elif name in ("import", "exclude"): + pass + else: + assert False + + for child_item in item: + self.process_item(child_item) - def end_element(self, name): if name == "instruction": self.emit_instruction() self.instruction = None @@ -590,36 +503,61 @@ class Parser(object): elif name == "enum": self.emit_enum() self.enum = None - elif name == "genxml": - print('#endif /* %s */' % self.gen_guard()) + elif name in ("import", "exclude", "value"): + pass + else: + assert False def emit_template_struct(self, name, group): print("struct %s {" % self.gen_prefix(name)) group.emit_template_struct("") print("};\n") - def emit_pack_function(self, name, group): + def emit_pack_function(self, name, group, repack=False): name = self.gen_prefix(name) - print(textwrap.dedent("""\ - static inline __attribute__((always_inline)) void - %s_pack(__attribute__((unused)) __gen_user_data *data, - %s__attribute__((unused)) void * restrict dst, - %s__attribute__((unused)) const struct %s * restrict values) - {""") % (name, ' ' * len(name), ' ' * len(name), name)) - - (dwords, length) = group.collect_dwords_and_length() + if repack: + if self.opencl: + print(textwrap.dedent("""\ + static inline __attribute__((always_inline)) void + %s_repack(__attribute__((unused)) global void * restrict dst, + %s__attribute__((unused)) global const uint32_t * origin, + %s__attribute__((unused)) private const struct %s * restrict values) + {""") % (name, ' ' * len(name), ' ' * len(name), name)) + else: + print(textwrap.dedent("""\ + static inline __attribute__((always_inline)) void + %s_repack(__attribute__((unused)) __gen_user_data *data, + %s__attribute__((unused)) void * restrict dst, + %s__attribute__((unused)) global const uint32_t * origin, + %s__attribute__((unused)) const struct %s * restrict values) + {""") % (name, ' ' * len(name), ' ' * len(name), ' ' * len(name), name)) + else: + if self.opencl: + print(textwrap.dedent("""\ + static inline __attribute__((always_inline)) void + %s_pack(__attribute__((unused)) global void * restrict dst, + %s__attribute__((unused)) private const struct %s * restrict values) + {""") % (name, ' ' * len(name), name)) + else: + print(textwrap.dedent("""\ + static inline __attribute__((always_inline)) void + %s_pack(__attribute__((unused)) __gen_user_data *data, + %s__attribute__((unused)) void * restrict dst, + %s__attribute__((unused)) const struct %s * restrict values) + {""") % (name, ' ' * len(name), ' ' * len(name), name)) + + (dwords, length) = group.collect_dwords_and_length(repack) if length: # Cast dst to make header C++ friendly - print(" uint32_t * restrict dw = (uint32_t * restrict) dst;") + type_name = "global uint32_t *" if self.opencl else "uint32_t * restrict" + print(" %s dw = (%s) dst;" % (type_name, type_name)) - group.emit_pack_function(dwords, length) + group.emit_pack_function(dwords, length, repack) print("}\n") def emit_instruction(self): name = self.instruction - if self.instruction_engines and not self.instruction_engines & self.engines: - return if not self.length is None: print('#define %-33s %6d' % @@ -647,8 +585,9 @@ class Parser(object): print('') self.emit_template_struct(self.instruction, self.group) - self.emit_pack_function(self.instruction, self.group) + if self.repack: + self.emit_pack_function(self.instruction, self.group, repack=True) def emit_register(self): name = self.register @@ -671,6 +610,8 @@ class Parser(object): self.emit_template_struct(self.struct, self.group) self.emit_pack_function(self.struct, self.group) + if self.repack: + self.emit_pack_function(self.struct, self.group, repack=True) def emit_enum(self): print('enum %s {' % self.gen_prefix(self.enum)) @@ -682,10 +623,14 @@ class Parser(object): print(' %-36s = %6d,' % (name.upper(), value.value)) print('};\n') - def parse(self, filename): - file = open(filename, "rb") - self.parser.ParseFile(file) - file.close() + def emit_genxml(self, genxml): + root = genxml.et.getroot() + self.platform = root.attrib["name"] + self.gen = root.attrib["gen"].replace('.', '') + print(pack_header % {'license': license, 'platform': self.platform, 'guard': self.gen_guard()}) + for item in root: + self.process_item(item) + print('#endif /* %s */' % self.gen_guard()) def parse_args(): p = argparse.ArgumentParser() @@ -693,6 +638,10 @@ def parse_args(): help="Input xml file") p.add_argument('--engines', nargs='?', type=str, default='render', help="Comma-separated list of engines whose instructions should be parsed (default: %(default)s)") + p.add_argument('--include-symbols', nargs='?', type=str, action='store', + help="List of instruction/structures to generate") + p.add_argument('--opencl', action='store_true', help="Generate OpenCL code") + p.add_argument('--repack', action='store_true', help="Emit repacking code") pargs = p.parse_args() @@ -705,18 +654,22 @@ def parse_args(): def main(): pargs = parse_args() - input_file = pargs.xml_source - engines = pargs.engines.split(',') + engines = set(pargs.engines.split(',')) valid_engines = [ 'render', 'blitter', 'video' ] - if set(engines) - set(valid_engines): + if engines - set(valid_engines): print("Invalid engine specified, valid engines are:\n") for e in valid_engines: print("\t%s" % e) sys.exit(1) - p = Parser() - p.engines = set(engines) - p.parse(input_file) + genxml = intel_genxml.GenXml(pargs.xml_source) + + genxml.merge_imported() + genxml.filter_engines(engines) + if pargs.include_symbols: + genxml.filter_symbols(pargs.include_symbols.split(',')) + p = Parser(pargs.opencl, pargs.repack) + p.emit_genxml(genxml) if __name__ == '__main__': main() |