mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2025-12-23 11:10:10 +01:00
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 <dylan@pnwbakers.com>
Co-authored-by: Jason Ekstrand <jason@jlekstrand.net>
Reviewed-by: Jason Ekstrand <jason@jlekstrand.net> (v5)
Reviewed-by: Dylan Baker <dylan@pnwbakers.com> (v6)
This commit is contained in:
parent
3974cfea25
commit
f0eaf38db2
5 changed files with 300 additions and 3 deletions
|
|
@ -46,9 +46,16 @@ LOCAL_GENERATED_SOURCES += $(addprefix $(intermediates)/, $(GENXML_GENERATED_FIL
|
|||
define header-gen
|
||||
@mkdir -p $(dir $@)
|
||||
@echo "Gen Header: $(PRIVATE_MODULE) <= $(notdir $(@))"
|
||||
$(hide) $(PRIVATE_SCRIPT) $(PRIVATE_XML) > $@
|
||||
$(hide) $(PRIVATE_SCRIPT) $(PRIVATE_SCRIPT_FLAGS) $(PRIVATE_XML) > $@
|
||||
endef
|
||||
|
||||
$(intermediates)/genxml/genX_bits.h: PRIVATE_SCRIPT := $(MESA_PYTHON2) $(LOCAL_PATH)/genxml/gen_bits_header.py
|
||||
$(intermediates)/genxml/genX_bits.h: PRIVATE_SCRIPT_FLAGS := --cpp-guard=GENX_BITS_H
|
||||
$(intermediates)/genxml/genX_bits.h: PRIVATE_XML := $(addprefix $(LOCAL_PATH)/,$(GENXML_XML_FILES))
|
||||
$(intermediates)/genxml/genX_bits.h: $(LOCAL_PATH)/genxml/gen_bits_header.py
|
||||
$(intermediates)/genxml/genX_bits.h: $(addprefix $(LOCAL_PATH)/,$(GENXML_XML_FILES))
|
||||
$(call header-gen)
|
||||
|
||||
$(intermediates)/genxml/gen4_pack.h: PRIVATE_SCRIPT := $(MESA_PYTHON2) $(LOCAL_PATH)/genxml/gen_pack_header.py
|
||||
$(intermediates)/genxml/gen4_pack.h: PRIVATE_XML := $(LOCAL_PATH)/genxml/gen4.xml
|
||||
$(intermediates)/genxml/gen4_pack.h: $(LOCAL_PATH)/genxml/gen4.xml $(LOCAL_PATH)/genxml/gen_pack_header.py
|
||||
|
|
|
|||
|
|
@ -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 $@ $(addprefix $(srcdir)/,$(GENXML_XML_FILES))
|
||||
|
||||
EXTRA_DIST += \
|
||||
genxml/genX_pack.h \
|
||||
genxml/gen_macros.h \
|
||||
|
|
|
|||
|
|
@ -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 \
|
||||
|
|
|
|||
1
src/intel/genxml/.gitignore
vendored
1
src/intel/genxml/.gitignore
vendored
|
|
@ -1,2 +1,3 @@
|
|||
gen*_bits.h
|
||||
gen*_pack.h
|
||||
gen*_xml.h
|
||||
|
|
|
|||
281
src/intel/genxml/gen_bits_header.py
Normal file
281
src/intel/genxml/gen_bits_header.py
Normal file
|
|
@ -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()
|
||||
Loading…
Add table
Reference in a new issue