diff options
Diffstat (limited to 'parse.py')
-rwxr-xr-x | parse.py | 84 |
1 files changed, 69 insertions, 15 deletions
@@ -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:]: |