diff options
Diffstat (limited to 'target/hexagon/dectree.py')
-rwxr-xr-x | target/hexagon/dectree.py | 396 |
1 files changed, 224 insertions, 172 deletions
diff --git a/target/hexagon/dectree.py b/target/hexagon/dectree.py index 29467ec7d7..3b32948a04 100755 --- a/target/hexagon/dectree.py +++ b/target/hexagon/dectree.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 ## -## Copyright(c) 2019-2021 Qualcomm Innovation Center, Inc. All Rights Reserved. +## Copyright(c) 2019-2023 Qualcomm Innovation Center, Inc. All Rights Reserved. ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by @@ -23,94 +23,109 @@ import re import sys import iset -encs = {tag : ''.join(reversed(iset.iset[tag]['enc'].replace(' ', ''))) - for tag in iset.tags if iset.iset[tag]['enc'] != 'MISSING ENCODING'} +encs = { + tag: "".join(reversed(iset.iset[tag]["enc"].replace(" ", ""))) + for tag in iset.tags + if iset.iset[tag]["enc"] != "MISSING ENCODING" +} -enc_classes = set([iset.iset[tag]['enc_class'] for tag in encs.keys()]) -subinsn_enc_classes = \ - set([enc_class for enc_class in enc_classes \ - if enc_class.startswith('SUBINSN_')]) -ext_enc_classes = \ - set([enc_class for enc_class in enc_classes \ - if enc_class not in ('NORMAL', '16BIT') and \ - not enc_class.startswith('SUBINSN_')]) +enc_classes = set([iset.iset[tag]["enc_class"] for tag in encs.keys()]) +subinsn_enc_classes = set( + [enc_class for enc_class in enc_classes if enc_class.startswith("SUBINSN_")] +) +ext_enc_classes = set( + [ + enc_class + for enc_class in enc_classes + if enc_class not in ("NORMAL", "16BIT") and not enc_class.startswith("SUBINSN_") + ] +) try: subinsn_groupings = iset.subinsn_groupings except AttributeError: subinsn_groupings = {} -for (tag, subinsn_grouping) in subinsn_groupings.items(): - encs[tag] = ''.join(reversed(subinsn_grouping['enc'].replace(' ', ''))) +for tag, subinsn_grouping in subinsn_groupings.items(): + encs[tag] = "".join(reversed(subinsn_grouping["enc"].replace(" ", ""))) -dectree_normal = {'leaves' : set()} -dectree_16bit = {'leaves' : set()} -dectree_subinsn_groupings = {'leaves' : set()} -dectree_subinsns = {name : {'leaves' : set()} for name in subinsn_enc_classes} -dectree_extensions = {name : {'leaves' : set()} for name in ext_enc_classes} +dectree_normal = {"leaves": set()} +dectree_16bit = {"leaves": set()} +dectree_subinsn_groupings = {"leaves": set()} +dectree_subinsns = {name: {"leaves": set()} for name in subinsn_enc_classes} +dectree_extensions = {name: {"leaves": set()} for name in ext_enc_classes} for tag in encs.keys(): if tag in subinsn_groupings: - dectree_subinsn_groupings['leaves'].add(tag) + dectree_subinsn_groupings["leaves"].add(tag) continue - enc_class = iset.iset[tag]['enc_class'] - if enc_class.startswith('SUBINSN_'): + enc_class = iset.iset[tag]["enc_class"] + if enc_class.startswith("SUBINSN_"): if len(encs[tag]) != 32: - encs[tag] = encs[tag] + '0' * (32 - len(encs[tag])) - dectree_subinsns[enc_class]['leaves'].add(tag) - elif enc_class == '16BIT': + encs[tag] = encs[tag] + "0" * (32 - len(encs[tag])) + dectree_subinsns[enc_class]["leaves"].add(tag) + elif enc_class == "16BIT": if len(encs[tag]) != 16: - raise Exception('Tag "{}" has enc_class "{}" and not an encoding ' + - 'width of 16 bits!'.format(tag, enc_class)) - dectree_16bit['leaves'].add(tag) + raise Exception( + 'Tag "{}" has enc_class "{}" and not an encoding ' + + "width of 16 bits!".format(tag, enc_class) + ) + dectree_16bit["leaves"].add(tag) else: if len(encs[tag]) != 32: - raise Exception('Tag "{}" has enc_class "{}" and not an encoding ' + - 'width of 32 bits!'.format(tag, enc_class)) - if enc_class == 'NORMAL': - dectree_normal['leaves'].add(tag) + raise Exception( + 'Tag "{}" has enc_class "{}" and not an encoding ' + + "width of 32 bits!".format(tag, enc_class) + ) + if enc_class == "NORMAL": + dectree_normal["leaves"].add(tag) else: - dectree_extensions[enc_class]['leaves'].add(tag) + dectree_extensions[enc_class]["leaves"].add(tag) faketags = set() -for (tag, enc) in iset.enc_ext_spaces.items(): +for tag, enc in iset.enc_ext_spaces.items(): faketags.add(tag) - encs[tag] = ''.join(reversed(enc.replace(' ', ''))) - dectree_normal['leaves'].add(tag) + encs[tag] = "".join(reversed(enc.replace(" ", ""))) + dectree_normal["leaves"].add(tag) faketags |= set(subinsn_groupings.keys()) + def every_bit_counts(bitset): for i in range(1, len(next(iter(bitset)))): - if len(set([bits[:i] + bits[i+1:] for bits in bitset])) == len(bitset): + if len(set([bits[:i] + bits[i + 1 :] for bits in bitset])) == len(bitset): return False return True + def auto_separate(node): - tags = node['leaves'] + tags = node["leaves"] if len(tags) <= 1: return enc_width = len(encs[next(iter(tags))]) - opcode_bit_for_all = \ - [all([encs[tag][i] in '01' \ - for tag in tags]) for i in range(enc_width)] - opcode_bit_is_0_for_all = \ - [opcode_bit_for_all[i] and all([encs[tag][i] == '0' \ - for tag in tags]) for i in range(enc_width)] - opcode_bit_is_1_for_all = \ - [opcode_bit_for_all[i] and all([encs[tag][i] == '1' \ - for tag in tags]) for i in range(enc_width)] - differentiator_opcode_bit = \ - [opcode_bit_for_all[i] and \ - not (opcode_bit_is_0_for_all[i] or \ - opcode_bit_is_1_for_all[i]) \ - for i in range(enc_width)] + opcode_bit_for_all = [ + all([encs[tag][i] in "01" for tag in tags]) for i in range(enc_width) + ] + opcode_bit_is_0_for_all = [ + opcode_bit_for_all[i] and all([encs[tag][i] == "0" for tag in tags]) + for i in range(enc_width) + ] + opcode_bit_is_1_for_all = [ + opcode_bit_for_all[i] and all([encs[tag][i] == "1" for tag in tags]) + for i in range(enc_width) + ] + differentiator_opcode_bit = [ + opcode_bit_for_all[i] + and not (opcode_bit_is_0_for_all[i] or opcode_bit_is_1_for_all[i]) + for i in range(enc_width) + ] best_width = 0 for width in range(4, 0, -1): for lsb in range(enc_width - width, -1, -1): - bitset = set([encs[tag][lsb:lsb+width] for tag in tags]) - if all(differentiator_opcode_bit[lsb:lsb+width]) and \ - (len(bitset) == len(tags) or every_bit_counts(bitset)): + bitset = set([encs[tag][lsb : lsb + width] for tag in tags]) + if all(differentiator_opcode_bit[lsb : lsb + width]) and ( + len(bitset) == len(tags) or every_bit_counts(bitset) + ): best_width = width best_lsb = lsb caught_all_tags = len(bitset) == len(tags) @@ -118,33 +133,37 @@ def auto_separate(node): if best_width != 0: break if best_width == 0: - raise Exception('Could not find a way to differentiate the encodings ' + - 'of the following tags:\n{}'.format('\n'.join(tags))) + raise Exception( + "Could not find a way to differentiate the encodings " + + "of the following tags:\n{}".format("\n".join(tags)) + ) if caught_all_tags: for width in range(1, best_width): for lsb in range(enc_width - width, -1, -1): - bitset = set([encs[tag][lsb:lsb+width] for tag in tags]) - if all(differentiator_opcode_bit[lsb:lsb+width]) and \ - len(bitset) == len(tags): + bitset = set([encs[tag][lsb : lsb + width] for tag in tags]) + if all(differentiator_opcode_bit[lsb : lsb + width]) and len( + bitset + ) == len(tags): best_width = width best_lsb = lsb break else: continue break - node['separator_lsb'] = best_lsb - node['separator_width'] = best_width - node['children'] = [] - for value in range(2 ** best_width): + node["separator_lsb"] = best_lsb + node["separator_width"] = best_width + node["children"] = [] + for value in range(2**best_width): child = {} - bits = ''.join(reversed('{:0{}b}'.format(value, best_width))) - child['leaves'] = \ - set([tag for tag in tags \ - if encs[tag][best_lsb:best_lsb+best_width] == bits]) - node['children'].append(child) - for child in node['children']: + bits = "".join(reversed("{:0{}b}".format(value, best_width))) + child["leaves"] = set( + [tag for tag in tags if encs[tag][best_lsb : best_lsb + best_width] == bits] + ) + node["children"].append(child) + for child in node["children"]: auto_separate(child) + auto_separate(dectree_normal) auto_separate(dectree_16bit) if subinsn_groupings: @@ -157,144 +176,173 @@ for dectree_ext in dectree_extensions.values(): for tag in faketags: del encs[tag] + def table_name(parents, node): path = parents + [node] root = path[0] - tag = next(iter(node['leaves'])) + tag = next(iter(node["leaves"])) if tag in subinsn_groupings: - enc_width = len(subinsn_groupings[tag]['enc'].replace(' ', '')) + enc_width = len(subinsn_groupings[tag]["enc"].replace(" ", "")) else: - tag = next(iter(node['leaves'] - faketags)) + tag = next(iter(node["leaves"] - faketags)) enc_width = len(encs[tag]) - determining_bits = ['_'] * enc_width - for (parent, child) in zip(path[:-1], path[1:]): - lsb = parent['separator_lsb'] - width = parent['separator_width'] - value = parent['children'].index(child) - determining_bits[lsb:lsb+width] = \ - list(reversed('{:0{}b}'.format(value, width))) + determining_bits = ["_"] * enc_width + for parent, child in zip(path[:-1], path[1:]): + lsb = parent["separator_lsb"] + width = parent["separator_width"] + value = parent["children"].index(child) + determining_bits[lsb : lsb + width] = list( + reversed("{:0{}b}".format(value, width)) + ) if tag in subinsn_groupings: - name = 'DECODE_ROOT_EE' + name = "DECODE_ROOT_EE" else: - enc_class = iset.iset[tag]['enc_class'] + enc_class = iset.iset[tag]["enc_class"] if enc_class in ext_enc_classes: - name = 'DECODE_EXT_{}'.format(enc_class) + name = "DECODE_EXT_{}".format(enc_class) elif enc_class in subinsn_enc_classes: - name = 'DECODE_SUBINSN_{}'.format(enc_class) + name = "DECODE_SUBINSN_{}".format(enc_class) else: - name = 'DECODE_ROOT_{}'.format(enc_width) + name = "DECODE_ROOT_{}".format(enc_width) if node != root: - name += '_' + ''.join(reversed(determining_bits)) + name += "_" + "".join(reversed(determining_bits)) return name + def print_node(f, node, parents): - if len(node['leaves']) <= 1: + if len(node["leaves"]) <= 1: return name = table_name(parents, node) - lsb = node['separator_lsb'] - width = node['separator_width'] - print('DECODE_NEW_TABLE({},{},DECODE_SEPARATOR_BITS({},{}))'.\ - format(name, 2 ** width, lsb, width), file=f) - for child in node['children']: - if len(child['leaves']) == 0: - print('INVALID()', file=f) - elif len(child['leaves']) == 1: - (tag,) = child['leaves'] + lsb = node["separator_lsb"] + width = node["separator_width"] + print( + "DECODE_NEW_TABLE({},{},DECODE_SEPARATOR_BITS({},{}))".format( + name, 2**width, lsb, width + ), + file=f, + ) + for child in node["children"]: + if len(child["leaves"]) == 0: + print("INVALID()", file=f) + elif len(child["leaves"]) == 1: + (tag,) = child["leaves"] if tag in subinsn_groupings: - class_a = subinsn_groupings[tag]['class_a'] - class_b = subinsn_groupings[tag]['class_b'] - enc = subinsn_groupings[tag]['enc'].replace(' ', '') - if 'RESERVED' in tag: - print('INVALID()', file=f) + class_a = subinsn_groupings[tag]["class_a"] + class_b = subinsn_groupings[tag]["class_b"] + enc = subinsn_groupings[tag]["enc"].replace(" ", "") + if "RESERVED" in tag: + print("INVALID()", file=f) else: - print('SUBINSNS({},{},{},"{}")'.\ - format(tag, class_a, class_b, enc), file=f) + print( + 'SUBINSNS({},{},{},"{}")'.format(tag, class_a, class_b, enc), + file=f, + ) elif tag in iset.enc_ext_spaces: - enc = iset.enc_ext_spaces[tag].replace(' ', '') + enc = iset.enc_ext_spaces[tag].replace(" ", "") print('EXTSPACE({},"{}")'.format(tag, enc), file=f) else: - enc = ''.join(reversed(encs[tag])) + enc = "".join(reversed(encs[tag])) print('TERMINAL({},"{}")'.format(tag, enc), file=f) else: - print('TABLE_LINK({})'.format(table_name(parents + [node], child)), - file=f) - print('DECODE_END_TABLE({},{},DECODE_SEPARATOR_BITS({},{}))'.\ - format(name, 2 ** width, lsb, width), file=f) + print("TABLE_LINK({})".format(table_name(parents + [node], child)), file=f) + print( + "DECODE_END_TABLE({},{},DECODE_SEPARATOR_BITS({},{}))".format( + name, 2**width, lsb, width + ), + file=f, + ) print(file=f) parents.append(node) - for child in node['children']: + for child in node["children"]: print_node(f, child, parents) parents.pop() + def print_tree(f, tree): print_node(f, tree, []) + def print_match_info(f): for tag in sorted(encs.keys(), key=iset.tags.index): - enc = ''.join(reversed(encs[tag])) - mask = int(re.sub(r'[^1]', r'0', enc.replace('0', '1')), 2) - match = int(re.sub(r'[^01]', r'0', enc), 2) - suffix = '' - print('DECODE{}_MATCH_INFO({},0x{:x}U,0x{:x}U)'.\ - format(suffix, tag, mask, match), file=f) + enc = "".join(reversed(encs[tag])) + mask = int(re.sub(r"[^1]", r"0", enc.replace("0", "1")), 2) + match = int(re.sub(r"[^01]", r"0", enc), 2) + suffix = "" + print( + "DECODE{}_MATCH_INFO({},0x{:x}U,0x{:x}U)".format(suffix, tag, mask, match), + file=f, + ) + + +regre = re.compile(r"((?<!DUP)[MNORCPQXSGVZA])([stuvwxyzdefg]+)([.]?[LlHh]?)(\d+S?)") +immre = re.compile(r"[#]([rRsSuUm])(\d+)(?:[:](\d+))?") -regre = re.compile( - r'((?<!DUP)[MNORCPQXSGVZA])([stuvwxyzdefg]+)([.]?[LlHh]?)(\d+S?)') -immre = re.compile(r'[#]([rRsSuUm])(\d+)(?:[:](\d+))?') def ordered_unique(l): return sorted(set(l), key=l.index) -implicit_registers = { - 'SP' : 29, - 'FP' : 30, - 'LR' : 31 -} -num_registers = { - 'R' : 32, - 'V' : 32 -} +implicit_registers = {"SP": 29, "FP": 30, "LR": 31} + +num_registers = {"R": 32, "V": 32} + def print_op_info(f): for tag in sorted(encs.keys(), key=iset.tags.index): enc = encs[tag] print(file=f) - print('DECODE_OPINFO({},'.format(tag), file=f) - regs = ordered_unique(regre.findall(iset.iset[tag]['syntax'])) - imms = ordered_unique(immre.findall(iset.iset[tag]['syntax'])) + print("DECODE_OPINFO({},".format(tag), file=f) + regs = ordered_unique(regre.findall(iset.iset[tag]["syntax"])) + imms = ordered_unique(immre.findall(iset.iset[tag]["syntax"])) regno = 0 for reg in regs: reg_type = reg[0] reg_letter = reg[1][0] - reg_num_choices = int(reg[3].rstrip('S')) - reg_mapping = reg[0] + ''.join(['_' for letter in reg[1]]) + reg[3] - reg_enc_fields = re.findall(reg_letter + '+', enc) + reg_num_choices = int(reg[3].rstrip("S")) + reg_mapping = reg[0] + "".join(["_" for letter in reg[1]]) + reg[3] + reg_enc_fields = re.findall(reg_letter + "+", enc) if len(reg_enc_fields) == 0: raise Exception('Tag "{}" missing register field!'.format(tag)) if len(reg_enc_fields) > 1: - raise Exception('Tag "{}" has split register field!'.\ - format(tag)) + raise Exception('Tag "{}" has split register field!'.format(tag)) reg_enc_field = reg_enc_fields[0] if 2 ** len(reg_enc_field) != reg_num_choices: - raise Exception('Tag "{}" has incorrect register field width!'.\ - format(tag)) - print(' DECODE_REG({},{},{})'.\ - format(regno, len(reg_enc_field), enc.index(reg_enc_field)), - file=f) - if reg_type in num_registers and \ - reg_num_choices != num_registers[reg_type]: - print(' DECODE_MAPPED_REG({},{})'.\ - format(regno, reg_mapping), file=f) + raise Exception( + 'Tag "{}" has incorrect register field width!'.format(tag) + ) + print( + " DECODE_REG({},{},{})".format( + regno, len(reg_enc_field), enc.index(reg_enc_field) + ), + file=f, + ) + if reg_type in num_registers and reg_num_choices != num_registers[reg_type]: + print( + " DECODE_MAPPED_REG({},{})".format(regno, reg_mapping), + file=f, + ) regno += 1 + def implicit_register_key(reg): return implicit_registers[reg] + for reg in sorted( - set([r for r in (iset.iset[tag]['rregs'].split(',') + \ - iset.iset[tag]['wregs'].split(',')) \ - if r in implicit_registers]), key=implicit_register_key): - print(' DECODE_IMPL_REG({},{})'.\ - format(regno, implicit_registers[reg]), file=f) + set( + [ + r + for r in ( + iset.iset[tag]["rregs"].split(",") + + iset.iset[tag]["wregs"].split(",") + ) + if r in implicit_registers + ] + ), + key=implicit_register_key, + ): + print( + " DECODE_IMPL_REG({},{})".format(regno, implicit_registers[reg]), + file=f, + ) regno += 1 if imms and imms[0][0].isupper(): imms = reversed(imms) @@ -311,41 +359,45 @@ def print_op_info(f): else: imm_shift = 0 if imm_type.islower(): - imm_letter = 'i' + imm_letter = "i" else: - imm_letter = 'I' + imm_letter = "I" remainder = imm_width - for m in reversed(list(re.finditer(imm_letter + '+', enc))): + for m in reversed(list(re.finditer(imm_letter + "+", enc))): remainder -= m.end() - m.start() - print(' DECODE_IMM({},{},{},{})'.\ - format(immno, m.end() - m.start(), m.start(), remainder), - file=f) + print( + " DECODE_IMM({},{},{},{})".format( + immno, m.end() - m.start(), m.start(), remainder + ), + file=f, + ) if remainder != 0: if imm[2]: - imm[2] = ':' + imm[2] - raise Exception('Tag "{}" has an incorrect number of ' + \ - 'encoding bits for immediate "{}"'.\ - format(tag, ''.join(imm))) - if imm_type.lower() in 'sr': - print(' DECODE_IMM_SXT({},{})'.\ - format(immno, imm_width), file=f) - if imm_type.lower() == 'n': - print(' DECODE_IMM_NEG({},{})'.\ - format(immno, imm_width), file=f) + imm[2] = ":" + imm[2] + raise Exception( + 'Tag "{}" has an incorrect number of ' + + 'encoding bits for immediate "{}"'.format(tag, "".join(imm)) + ) + if imm_type.lower() in "sr": + print(" DECODE_IMM_SXT({},{})".format(immno, imm_width), file=f) + if imm_type.lower() == "n": + print(" DECODE_IMM_NEG({},{})".format(immno, imm_width), file=f) if imm_shift: - print(' DECODE_IMM_SHIFT({},{})'.\ - format(immno, imm_shift), file=f) - print(')', file=f) + print( + " DECODE_IMM_SHIFT({},{})".format(immno, imm_shift), file=f + ) + print(")", file=f) + -if __name__ == '__main__': - with open(sys.argv[1], 'w') as f: +if __name__ == "__main__": + with open(sys.argv[1], "w") as f: print_tree(f, dectree_normal) print_tree(f, dectree_16bit) if subinsn_groupings: print_tree(f, dectree_subinsn_groupings) - for (name, dectree_subinsn) in sorted(dectree_subinsns.items()): + for name, dectree_subinsn in sorted(dectree_subinsns.items()): print_tree(f, dectree_subinsn) - for (name, dectree_ext) in sorted(dectree_extensions.items()): + for name, dectree_ext in sorted(dectree_extensions.items()): print_tree(f, dectree_ext) print_match_info(f) print_op_info(f) |