From 89d129614a6b7e0cf6a8ccffb825fb0b6a2af9f7 Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Wed, 1 May 2024 01:28:58 -0700 Subject: [PATCH] Correctly detect overlapping encodings A regression introduced a few years ago prevented detecting partially overlapping encodings; instead, we only detected exact matches. Now, we detect the partial cases. We now need to maintain two allowlists (overlapping_extensions and overlapping_instructions) for the cases that extensions and/or instructions overlap by design. --- constants.py | 14 ++++++++++++++ parse.py | 45 ++++++++++++++++++++++++++++++++++----------- 2 files changed, 48 insertions(+), 11 deletions(-) diff --git a/constants.py b/constants.py index dc76ba38..cb3e689d 100644 --- a/constants.py +++ b/constants.py @@ -2,6 +2,20 @@ import csv +overlapping_extensions = { + 'rv_zcmt': {'rv_c_d'}, + 'rv_zcmp': {'rv_c_d'}, + 'rv_c': {'rv_zcmop'}, +} + +overlapping_instructions = { + 'c_addi': {'c_nop'}, + 'c_lui': {'c_addi16sp'}, + 'c_mv': {'c_jr'}, + 'c_jalr': {'c_ebreak'}, + 'c_add': {'c_ebreak', 'c_jalr'}, +} + isa_regex = \ re.compile("^RV(32|64|128)[IE]+[ABCDEFGHJKLMNPQSTUVX]*(Zicsr|Zifencei|Zihintpause|Zam|Ztso|Zkne|Zknd|Zknh|Zkse|Zksh|Zkg|Zkb|Zkr|Zks|Zkn|Zba|Zbc|Zbb|Zbp|Zbr|Zbm|Zbs|Zbe|Zbf|Zbt|Zmmul|Zbpbo|Zca|Zcf|Zcd|Zcb|Zcmp|Zcmt){,1}(_Zicsr){,1}(_Zifencei){,1}(_Zihintpause){,1}(_Zmmul){,1}(_Zam){,1}(_Zba){,1}(_Zbb){,1}(_Zbc){,1}(_Zbe){,1}(_Zbf){,1}(_Zbm){,1}(_Zbp){,1}(_Zbpbo){,1}(_Zbr){,1}(_Zbs){,1}(_Zbt){,1}(_Zkb){,1}(_Zkg){,1}(_Zkr){,1}(_Zks){,1}(_Zkn){,1}(_Zknd){,1}(_Zkne){,1}(_Zknh){,1}(_Zkse){,1}(_Zksh){,1}(_Ztso){,1}(_Zca){,1}(_Zcf){,1}(_Zcd){,1}(_Zcb){,1}(_Zcmp){,1}(_Zcmt){,1}$") diff --git a/parse.py b/parse.py index 98e06a6e..48507d96 100755 --- a/parse.py +++ b/parse.py @@ -133,7 +133,7 @@ def process_enc_line(line, ext): return (name, single_dict) -def same_base_ext (ext_name, ext_name_list): +def same_base_isa(ext_name, ext_name_list): type1 = ext_name.split("_")[0] for ext_name1 in ext_name_list: type2 = ext_name1.split("_")[0] @@ -144,6 +144,26 @@ def same_base_ext (ext_name, ext_name_list): return True return False +def overlaps(x, y): + x = x.rjust(len(y), '-') + y = y.rjust(len(x), '-') + + for i in range(0, len(x)): + if not (x[i] == '-' or y[i] == '-' or x[i] == y[i]): + return False + + return True + +def overlap_allowed(a, x, y): + return x in a and y in a[x] or \ + y in a and x in a[y] + +def extension_overlap_allowed(x, y): + return overlap_allowed(overlapping_extensions, x, y) + +def instruction_overlap_allowed(x, y): + return overlap_allowed(overlapping_instructions, x, y) + def create_inst_dict(file_filter, include_pseudo=False, include_pseudo_ops=[]): ''' This function return a dictionary containing all instructions associated @@ -222,29 +242,32 @@ def create_inst_dict(file_filter, include_pseudo=False, include_pseudo_ops=[]): # instruction is already imported and raise SystemExit if name in instr_dict: var = instr_dict[name]["extension"] - if same_base_ext(ext_name, var): - # disable same names on the same base extensions + if same_base_isa(ext_name, var): + # disable same names on the same base ISA err_msg = f'instruction : {name} from ' err_msg += f'{ext_name} is already ' - err_msg += f'added from {var} in same base extensions' + err_msg += f'added from {var} in same base ISA' logging.error(err_msg) raise SystemExit(1) elif instr_dict[name]['encoding'] != single_dict['encoding']: - # disable same names with different encodings on different base extensions + # disable same names with different encodings on different base ISAs err_msg = f'instruction : {name} from ' err_msg += f'{ext_name} is already ' - err_msg += f'added from {var} but each have different encodings in different base extensions' + err_msg += f'added from {var} but each have different encodings in different base ISAs' logging.error(err_msg) raise SystemExit(1) instr_dict[name]['extension'].extend(single_dict['extension']) else: for key in instr_dict: item = instr_dict[key] - if item["encoding"] == single_dict['encoding'] and same_base_ext(ext_name, item["extension"]): - # disable different names with same encodings on the same base extensions - err_msg = f'instruction : {name} from ' - err_msg += f'{ext_name} has the same encoding with instruction {key} ' - err_msg += f'added from {item["extension"]} in same base extensions' + if overlaps(item['encoding'], single_dict['encoding']) and \ + not extension_overlap_allowed(ext_name, item['extension'][0]) and \ + not instruction_overlap_allowed(name, key) and \ + same_base_isa(ext_name, item['extension']): + # disable different names with overlapping encodings on the same base ISA + err_msg = f'instruction : {name} in extension ' + err_msg += f'{ext_name} overlaps instruction {key} ' + err_msg += f'in extension {item["extension"]}' logging.error(err_msg) raise SystemExit(1)