aboutsummaryrefslogtreecommitdiff
path: root/target/hexagon/dectree.py
diff options
context:
space:
mode:
Diffstat (limited to 'target/hexagon/dectree.py')
-rwxr-xr-xtarget/hexagon/dectree.py396
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)