aboutsummaryrefslogtreecommitdiff
path: root/parse.py
diff options
context:
space:
mode:
Diffstat (limited to 'parse.py')
-rwxr-xr-xparse.py84
1 files changed, 69 insertions, 15 deletions
diff --git a/parse.py b/parse.py
index 4553e06..fb0c2e7 100755
--- a/parse.py
+++ b/parse.py
@@ -1,6 +1,7 @@
#!/usr/bin/env python3
from constants import *
+import copy
import re
import glob
import os
@@ -112,22 +113,31 @@ def process_enc_line(line, ext):
encoding_args = encoding.copy()
for a in args:
if a not in arg_lut:
- logging.error(f' Found variable {a} in instruction {name} whose mapping in arg_lut does not exist')
- raise SystemExit(1)
- else:
- (msb, lsb) = arg_lut[a]
- for ind in range(lsb, msb + 1):
- # overlapping bits
- if encoding_args[31 - ind] != '-':
- logging.error(f' Found variable {a} in instruction {name} overlapping {encoding_args[31 - ind]} variable in bit {ind}')
+ if len(parts := a.split('=')) == 2:
+ existing_arg, new_arg = parts
+ if existing_arg in arg_lut:
+ arg_lut[a] = arg_lut[existing_arg]
+
+ else:
+ logging.error(f' Found field {existing_arg} in variable {a} in instruction {name} whose mapping in arg_lut does not exist')
raise SystemExit(1)
- encoding_args[31 - ind] = a
+ else:
+ logging.error(f' Found variable {a} in instruction {name} whose mapping in arg_lut does not exist')
+ raise SystemExit(1)
+ (msb, lsb) = arg_lut[a]
+ for ind in range(lsb, msb + 1):
+ # overlapping bits
+ if encoding_args[31 - ind] != '-':
+ logging.error(f' Found variable {a} in instruction {name} overlapping {encoding_args[31 - ind]} variable in bit {ind}')
+ raise SystemExit(1)
+ encoding_args[31 - ind] = a
+
# update the fields of the instruction as a dict and return back along with
# the name of the instruction
single_dict['encoding'] = "".join(encoding)
single_dict['variable_fields'] = args
- single_dict['extension'] = [ext.split('/')[-1]]
+ single_dict['extension'] = [os.path.basename(ext)]
single_dict['match']=hex(int(match,2))
single_dict['mask']=hex(int(mask,2))
@@ -164,6 +174,37 @@ def extension_overlap_allowed(x, y):
def instruction_overlap_allowed(x, y):
return overlap_allowed(overlapping_instructions, x, y)
+def add_segmented_vls_insn(instr_dict):
+ updated_dict = {}
+ for k, v in instr_dict.items():
+ if "nf" in v['variable_fields']:
+ for new_key, new_value in expand_nf_field(k,v):
+ updated_dict[new_key] = new_value
+ else:
+ updated_dict[k] = v
+ return updated_dict
+
+def expand_nf_field(name, single_dict):
+ if "nf" not in single_dict['variable_fields']:
+ logging.error(f"Cannot expand nf field for instruction {name}")
+ raise SystemExit(1)
+
+ # nf no longer a variable field
+ single_dict['variable_fields'].remove("nf")
+ # include nf in mask
+ single_dict['mask'] = hex(int(single_dict['mask'],16) | 0b111 << 29)
+
+ name_expand_index = name.find('e')
+ expanded_instructions = []
+ for nf in range(0,8):
+ new_single_dict = copy.deepcopy(single_dict)
+ new_single_dict['match'] = hex(int(single_dict['match'],16) | nf << 29)
+ new_single_dict['encoding'] = format(nf, '03b') + single_dict['encoding'][3:]
+ new_name = name if nf == 0 else name[:name_expand_index] + "seg" + str(nf+1) + name[name_expand_index:]
+ expanded_instructions.append((new_name, new_single_dict))
+ return expanded_instructions
+
+
def create_inst_dict(file_filter, include_pseudo=False, include_pseudo_ops=[]):
'''
This function return a dictionary containing all instructions associated
@@ -235,7 +276,7 @@ def create_inst_dict(file_filter, include_pseudo=False, include_pseudo_ops=[]):
# call process_enc_line to get the data about the current
# instruction
(name, single_dict) = process_enc_line(line, f)
- ext_name = f.split("/")[-1]
+ ext_name = os.path.basename(f)
# if an instruction has already been added to the filtered
# instruction dictionary throw an error saying the given
@@ -315,7 +356,7 @@ def create_inst_dict(file_filter, include_pseudo=False, include_pseudo_ops=[]):
# extension. Else throw error.
found = False
for oline in open(ext_file):
- if not re.findall(f'^\s*{orig_inst}\s+',oline):
+ if not re.findall(f'^\\s*{orig_inst}\\s+',oline):
continue
else:
found = True
@@ -336,6 +377,18 @@ def create_inst_dict(file_filter, include_pseudo=False, include_pseudo_ops=[]):
if name not in instr_dict:
instr_dict[name] = single_dict
logging.debug(f' including pseudo_ops:{name}')
+ else:
+ if(single_dict['match'] != instr_dict[name]['match']):
+ instr_dict[name + '_pseudo'] = single_dict
+
+ # if a pseudo instruction has already been added to the filtered
+ # instruction dictionary but the extension is not in the current
+ # list, add it
+ else:
+ ext_name = single_dict['extension']
+
+ if (ext_name not in instr_dict[name]['extension']) & (name + '_pseudo' not in instr_dict):
+ instr_dict[name]['extension'].extend(ext_name)
else:
logging.debug(f' Skipping pseudo_op {pseudo_inst} since original instruction {orig_inst} already selected in list')
@@ -382,7 +435,7 @@ def create_inst_dict(file_filter, include_pseudo=False, include_pseudo_ops=[]):
# extension. Else throw error.
found = False
for oline in open(ext_file):
- if not re.findall(f'^\s*{reg_instr}\s+',oline):
+ if not re.findall(f'^\\s*{reg_instr}\\s+',oline):
continue
else:
found = True
@@ -403,7 +456,7 @@ def create_inst_dict(file_filter, include_pseudo=False, include_pseudo_ops=[]):
var = instr_dict[name]["extension"]
if instr_dict[name]['encoding'] != single_dict['encoding']:
err_msg = f'imported instruction : {name} in '
- err_msg += f'{f.split("/")[-1]} is already '
+ err_msg += f'{os.path.basename(f)} is already '
err_msg += f'added from {var} but each have different encodings for the same instruction'
logging.error(err_msg)
raise SystemExit(1)
@@ -1001,8 +1054,9 @@ if __name__ == "__main__":
include_pseudo = True
instr_dict = create_inst_dict(extensions, include_pseudo)
+
with open('instr_dict.yaml', 'w') as outfile:
- yaml.dump(instr_dict, outfile, default_flow_style=False)
+ yaml.dump(add_segmented_vls_insn(instr_dict), outfile, default_flow_style=False)
instr_dict = collections.OrderedDict(sorted(instr_dict.items()))
if '-c' in sys.argv[1:]: