From 001f207ee091de9d3d071ba10269075a17bdafdf Mon Sep 17 00:00:00 2001 From: Caio Oliveira Date: Mon, 21 Jul 2025 22:43:38 -0700 Subject: [PATCH] intel/genxml: Add support for dword/bits in fields to gen_sort_tags.py script Add a `--bits-format` argument to normalize the output to either of the formats described below. For now, defaults to the old format. The documentation in PRMs and BSpec describe the fields with the dword and the bit range. Using the same convention makes easier to spot issues. Old format: ``` ``` New format: ``` ``` For Groups, we store the dword and if needed a offset_bits, in case a group starts in a non-aligned position. Size and count for groups are not changed. Do this first for gen_sort_tags.py in case is convenient to have for the stable tree to convert future patches from the new back into the old format. Later patches will add support to the rest of the code. Reviewed-by: Jordan Justen Part-of: --- src/intel/genxml/gen_sort_tags.py | 7 +++ src/intel/genxml/intel_genxml.py | 74 +++++++++++++++++++++++++++++-- 2 files changed, 77 insertions(+), 4 deletions(-) diff --git a/src/intel/genxml/gen_sort_tags.py b/src/intel/genxml/gen_sort_tags.py index dcdba333fe6..2ef6431f5f1 100755 --- a/src/intel/genxml/gen_sort_tags.py +++ b/src/intel/genxml/gen_sort_tags.py @@ -18,6 +18,8 @@ def main() -> None: type=pathlib.Path) parser.add_argument('--validate', action='store_true') parser.add_argument('--quiet', action='store_true') + parser.add_argument('--bits-format', choices=['new', 'old'], default='old', + help="'new' for dword/bits; 'old' for start/end (default=%(default)s)") args: Args = parser.parse_args() for filename in args.files: @@ -26,6 +28,11 @@ def main() -> None: genxml = intel_genxml.GenXml(filename) + if args.bits_format == 'old': + genxml.normalize_to_old_bits_format() + elif args.bits_format == 'new': + genxml.normalize_to_new_bits_format() + if args.validate: assert genxml.is_equivalent_xml(genxml.sorted_copy()), \ f'{filename} is invalid, run gen_sort_tags.py and commit that' diff --git a/src/intel/genxml/intel_genxml.py b/src/intel/genxml/intel_genxml.py index 72d7b67b1aa..1e276fcf1cf 100755 --- a/src/intel/genxml/intel_genxml.py +++ b/src/intel/genxml/intel_genxml.py @@ -30,7 +30,20 @@ def get_value(element: et.Element) -> int: return int(element.attrib['value'], 0) def get_start(element: et.Element) -> int: - return int(element.attrib['start'], 0) + attrs = element.attrib + + if 'start' in attrs: + return int(attrs['start'], 0) + + dword = int(attrs['dword']) + offset = 0 + + if 'bits' in attrs: + offset = int(attrs['bits'].split(':')[1]) + elif 'offset_bits' in attrs: + offset = int(attrs['offset_bits']) + + return dword * 32 + offset BASE_TYPES = { @@ -87,17 +100,17 @@ GENXML_DESC = { 'exclude' : [ 'name', ], 'enum' : [ 'name', 'value', 'prefix', ], 'struct' : [ 'name', 'length', ], - 'field' : [ 'name', 'start', 'end', 'type', 'default', 'prefix', 'nonzero' ], + 'field' : [ 'name', 'dword', 'bits', 'start', 'end', 'type', 'default', 'prefix', 'nonzero' ], 'instruction' : [ 'name', 'bias', 'length', 'engine', ], 'value' : [ 'name', 'value', 'dont_use', ], - 'group' : [ 'count', 'start', 'size', ], + 'group' : [ 'count', 'dword', 'offset_bits', 'start', 'size', ], 'register' : [ 'name', 'length', 'num', ], } def node_validator(old: et.Element, new: et.Element) -> bool: """Compare to ElementTree Element nodes. - + There is no builtin equality method, so calling `et.Element == et.Element` is equivalent to calling `et.Element is et.Element`. We instead want to compare that the contents are the same, including the order of children and attributes @@ -210,6 +223,7 @@ def genxml_path_to_key(path): def sort_genxml_files(files): files.sort(key=genxml_path_to_key) + class GenXml(object): def __init__(self, filename, import_xml=False, files=None): if files is not None: @@ -466,6 +480,58 @@ class GenXml(object): return all(node_validator(old, new) for old, new in zip(self.et.getroot(), other.et.getroot())) + def normalize_to_old_bits_format(self): + def convert_elem(elem): + attrs = elem.attrib + if elem.tag == 'field' and 'dword' in attrs and 'bits' in attrs: + dword = int(attrs['dword']) + end_bit, start_bit = map(int, attrs['bits'].split(':')) + + attrs['start'] = str(dword * 32 + start_bit) + attrs['end'] = str(dword * 32 + end_bit) + + attrs.pop('dword', None) + attrs.pop('bits', None) + + elif elem.tag == 'group' and 'dword' in attrs: + dword = int(attrs['dword']) + offset_bits = int(attrs.get('offset_bits', 0)) + + attrs['start'] = str(dword * 32 + offset_bits) + + attrs.pop('dword', None) + attrs.pop('offset_bits', None) + + for child in elem: + convert_elem(child) + convert_elem(self.et.getroot()) + + def normalize_to_new_bits_format(self): + def convert_elem(elem): + attrs = elem.attrib + if elem.tag == 'field' and 'start' in attrs and 'end' in attrs: + dword, start = divmod(int(attrs['start']), 32) + end = int(attrs['end']) - (dword * 32) + + attrs['dword'] = str(dword) + attrs['bits'] = f"{end}:{start}" + + attrs.pop('start', None) + attrs.pop('end', None) + + elif elem.tag == 'group' and 'start' in attrs: + dword, offset_bits = divmod(int(attrs['start']), 32) + + attrs['dword'] = str(dword) + if offset_bits: + attrs['offset_bits'] = str(offset_bits) + + attrs.pop('start', None) + + for child in elem: + convert_elem(child) + convert_elem(self.et.getroot()) + def write_file(self): try: old_genxml = GenXml(self.filename)