Source code for uatg.instruction_generator

from os.path import join, dirname
from re import search
from string import ascii_letters, digits
from random import sample, choice, choices, seed, randint
from typing import Union, List

from uatg import __file__
from uatg.utils import load_yaml

seed(101)


[docs]class instruction_generator: """ This class reads the isem.yaml file and based upon the ISA specification , it generates random/specific instructions with random/specific range of replacements. Presently supports RV[32|64]IMAFDCB extensions. It does not generate Branch/Jump/Load/Store instructions to avoid unpredictable control flow. :Usage: .. code-block:: Python import uatg.instruction_generator generator = instruction_generator('uatg/isem.yaml', 'RV64IMAFDC') random_i_instructions = generator.generate_i_inst( instructions='random', modifiers={'xrs1': {'x0'}, 'xrs2': {'x0'}, 'xrd': {'x0'}, }, no_of_insts=10) """
[docs] def __init__(self, isa='RV64I'): """ Constructor of the class. :param isa: string containing the ISA for which instructions should be generated. """ assert (search(r'RV\d+I', isa) is not None) instruction_file = join(dirname(__file__), 'isem.yaml') integer_reg_file = {'x' + str(num) for num in range(32)} float_reg_file = {'f' + str(num) for num in range(32)} compressed_reg_file = {'x' + str(num) for num in range(8, 15)} self.isa = isa self.xlen = search(r'\d+', isa).group(0) self.imm_fields = { '$imm11': {str(num) for num in range(-1024, 1024)}, '$imm12': {str(num) for num in range(-2048, 2048)}, '$uimm20': {str(num) for num in range(0, 2**20)}, '$imm6': {str(num) for num in range(-32, 32)}, '$imm8': {str(num) for num in range(-128, 128)}, '$nzimm6': {str(num) for num in range(-2**5, 2**5, 16) if num != 0}, '$nzuimm6': {str(num) for num in range(1, 2**6)}, '$uimm6': {str(num) for num in range(0, 2**6)}, '$uimm8': {str(num) for num in range(0, 256)}, '$nzuimm8': {str(num) for num in range(0, 2**8, 16) if num != 0}, '$pred': {'r', 'rw', 'w'}, '$succ': {'r', 'rw', 'w'}, } self.prog_labels = [] self.default_modifiers = dict.fromkeys( ['xrs1', 'xrs2', 'xrs3', 'xrd', 'rm'], integer_reg_file) self.default_modifiers.update({ 'shamt5': {str(num) for num in range(1, 2**5)}, 'shamt6': {str(num) for num in range(1, 2**6)} }) self.default_modifiers.update(self.imm_fields) self.instructions = load_yaml(instruction_file) self.i_insts = { k: self.instructions['i_extension'][k]['asm_syntax'] for k in self.instructions['i_extension'].keys() if self.xlen in str(self.instructions['i_extension'][k]['xlen']) } self.m_insts, self.a_insts, self.f_insts = {}, {}, {} self.d_insts, self.b_insts, self.c_insts = {}, {}, {} if search(r'RV\d+IM', isa) is not None: self.m_insts = { k: self.instructions['m_extension'][k]['asm_syntax'] for k in self.instructions['m_extension'].keys() if self.xlen in str(self.instructions['m_extension'][k]['xlen']) } if search(r'RV\d+I\w+A', isa) is not None: self.a_insts = { k: self.instructions['a_extension'][k]['asm_syntax'] for k in self.instructions['a_extension'].keys() if self.xlen in str(self.instructions['a_extension'][k]['xlen']) } if search(r'RV\d+I\w+F', isa) is not None: self.default_modifiers.update( dict.fromkeys(['frs1', 'frs2', 'frs3'], float_reg_file)) self.f_insts = { k: self.instructions['f_extension'][k]['asm_syntax'] for k in self.instructions['f_extension'].keys() if self.xlen in str(self.instructions['f_extension'][k]['xlen']) } if search(r'RV\d+I\w+FD', isa) is not None: self.d_insts = { k: self.instructions['f_extension'][k]['asm_syntax'] for k in self.instructions['f_extension'].keys() if self.xlen in str(self.instructions['f_extension'][k]['xlen']) } if search(r'RV\d+I\w+B', isa) is not None: self.b_insts = { k: self.instructions['b_extension'][k]['asm_syntax'] for k in self.instructions['b_extension'].keys() if self.xlen in str(self.instructions['b_extension'][k]['xlen']) } if search(r'RV\d+I\w+C', isa) is not None: self.default_modifiers.update( dict.fromkeys(['c.rs1', 'c.rs2', 'c.rd'], compressed_reg_file)) self.c_insts = { k: self.instructions['c_extension'][k]['asm_syntax'] for k in self.instructions['c_extension'].keys() if self.xlen in str(self.instructions['c_extension'][k]['xlen']) } if search(r'RV\d+I\w+F', isa) is None: self.c_insts.pop('c.flw') self.c_insts.pop('c.fsw') if '32' in isa: self.c_insts.pop('c.flwsp') self.c_insts.pop('c.fswsp') if search(r'RV\d+I\w+FD', isa) is None: self.c_insts.pop('c.fld') self.c_insts.pop('c.fldsp') self.c_insts.pop('c.fsd') self.c_insts.pop('c.fsdsp')
def __replace_fields(self, instruction: str, modifiers: dict) -> str: """ Private function to replace the variable fields in a given instruction :param instruction: str containing the asm-syntax of an instruction :return: str with the variable fields are replaced with random choice of registers/values """ r_inst = instruction if '$c.r' in r_inst: # modifiers for compressed instruction registers r_inst = r_inst.replace('$c.rd', sample(modifiers['c.rd'], 1)[0]) \ if '$c.rd' in r_inst else r_inst r_inst = r_inst.replace('$c.rs1', sample(modifiers['c.rs1'], 1)[0]) \ if '$c.rs1' in r_inst else r_inst r_inst = r_inst.replace('$c.rs2', sample(modifiers['c.rs2'], 1)[0]) \ if '$c.rs2' in r_inst else r_inst if '$xr' in r_inst: # modifiers for integer file registers r_inst = r_inst.replace('$xrd', sample(modifiers['xrd'], 1)[0]) \ if '$xrd' in r_inst else r_inst r_inst = r_inst.replace('$xrs1', sample(modifiers['xrs1'], 1)[0]) \ if '$xrs1' in r_inst else r_inst r_inst = r_inst.replace('$xrs2', sample(modifiers['xrs2'], 1)[0]) \ if '$xrs2' in r_inst else r_inst if '$fr' in r_inst: # modifiers for floating registers r_inst = r_inst.replace('$frd', sample(modifiers['frd'], 1)[0]) \ if '$frd' in r_inst else r_inst r_inst = r_inst.replace('$frs1', sample(modifiers['frs1'], 1)[0]) \ if '$frs1' in r_inst else r_inst r_inst = r_inst.replace('$frs2', sample(modifiers['frs2'], 1)[0]) \ if '$frs2' in r_inst else r_inst if '$pred' in instruction or '$succ' in instruction: r_inst = r_inst.replace('$pred', sample(modifiers['$pred'], 1)[0]) \ if '$pred' in r_inst else r_inst r_inst = r_inst.replace('$succ', sample(modifiers['$succ'], 1)[0]) \ if '$succ' in r_inst else r_inst r_inst = r_inst.replace('$rm', sample(modifiers['rm'], 1)[0]) \ if '$rm' in r_inst else r_inst shamt = None if '$shamt' in r_inst: for i in ('slli', 'srli', 'srai'): if i in r_inst and '32' in self.isa: shamt = modifiers['shamt5'] elif i in r_inst and '64' in self.isa: shamt = modifiers['shamt6'] for i in ('slliw', 'srliw', 'sraiw'): if i in r_inst and '64' in self.isa: shamt = modifiers['shamt5'] for i in ('c.slli', 'c.srli', 'c.srai'): if i in r_inst and '64' in self.isa: shamt = modifiers['shamt6'] r_inst = r_inst.replace('$shamt', sample(shamt, 1)[0]) if 'imm' in r_inst: # modifiers for immediate fields for imm in self.imm_fields.keys(): r_inst = r_inst.replace( imm, sample(modifiers[imm], 1)[0]) if imm in r_inst else r_inst return r_inst def __modifier_update(self, modifiers: Union[dict, None]) -> dict: """ An private utility function to clean/update the modifiers from user-input :param modifiers: input modifiers from generate_x_inst function :return: sanitized modifiers containing default entries for unmentioned fields """ if modifiers is None: return self.default_modifiers else: for key, val in self.default_modifiers.items(): if key not in modifiers: modifiers[key] = val return modifiers def __generate_labels(self, prefix='', no_of_chars=15): label = f'label_{prefix}_' + ''.join( choices(ascii_letters, k=no_of_chars)) if label not in self.prog_labels: self.prog_labels.append(label) else: while label in self.prog_labels: label = 'label_' + ''.join( choices(ascii_letters + digits, k=no_of_chars)) self.prog_labels.append(label) return label def __handle_branch_load_store(self, inst): rt = 'nop' _lab = self.__generate_labels(prefix=inst) if inst in ('beq', 'bne', 'blt', 'bge', 'bltu', 'bgeu'): rt = f'{inst} x0, x0, {_lab}\n' \ f'{_lab}:\n\tnop\n' elif inst in ('c.beqz', 'c.bnez'): rt = f'{inst} x8, {_lab}\n' \ f'{_lab}:\n\tc.nop\n' elif inst == 'jal': rt = f'jal x0, {_lab}\n{_lab}:\n\tnop\n' elif inst in ('c.jal', 'c.j'): rt = f'{inst} {_lab}\n{_lab}:\n\tnop\n' elif inst in ('c.jr', 'c.jalr'): rt = f'\nla x1, {_lab}\n{inst} x1\n{_lab}:\n\tc.nop\n' elif inst == 'jalr': rt = f'\nla x1, {_lab}\njalr x0, 0(x1)\n' \ f'{_lab}:\n\tnop\n' elif inst in ('lb', 'lh', 'lw', 'ld', 'lbu', 'lhu', 'lwu'): if inst in ('lb', 'lbu'): rt = f'\n{_lab}:\n\tnop\nla x8, {_lab}\n{inst} x9, 0(x8)\n' elif inst in ('lh', 'lhu'): rt = f'\n.align 1\n{_lab}:\n\tnop\n' \ f'la x8, {_lab}\n{inst} x9, 0(x8)\n' elif inst in ('lw', 'lwu'): rt = f'\n.align 2\n{_lab}:\n\tnop\n' \ f'la x8, {_lab}\n{inst} x9, 0(x8)\n' else: rt = f'\n.align 3\n{_lab}:\n\tnop\n' \ f'la x8, {_lab}\n{inst} x9, 0(x8)\n' elif inst in ('c.ld', 'c.lw', 'c.fld', 'c.flw', 'c.lwsp', 'c.ldsp'): if inst == 'c.lw': rt = f'\n.align 2\n{_lab}:\n\tnop\nla x8, {_lab}\n{inst} ' \ f'x9, 0(x8)\n' elif inst == 'c.ld': rt = f'\n.align 3\n{_lab}:\n\tnop\nnop\nla x8, {_lab}' \ f'\n{inst} x9, 0(x8)\n' elif inst == 'c.flw': rt = f'\n.align 2\n{_lab}:\n\tnop\nla x8, {_lab}' \ f'\n{inst} f8, 0(x8)\n' elif inst == 'c.fld': rt = f'\n.align 3\n{_lab}:\n\tnop\nnop\nla x8, {_lab}' \ f'\n{inst} f8, 0(x8)\n' elif inst in ('c.lwsp', 'c.ldsp'): _align = 2 if 'lwsp' in inst else 3 _nop = '\n\tnop' * (_align - 1) rt = f'\n.align {_align}\n{_lab}:{_nop}\nla sp, {_lab}' \ f'\n{inst} x8, 0(sp)\n' elif inst in ( 'sw', 'sd', 'sb', 'sh', 'c.swsp', 'c.sdsp', ): if inst == 'sb': rt = f'\n{_lab}:\n\tnop\nla x1, {_lab}\n' \ f'li x2, {0x13}\n{inst} x2, 0(x1)\n' elif inst == 'sh': rt = f'\n.align 1\n{_lab}:\n\tnop\nla x1, {_lab}\n' \ f'li x2, {0x0013}\n{inst} x2, 0(x1)\n' elif inst == 'sw': rt = f'\n.align 2\n{_lab}:\n\tnop\nla x1, {_lab}\n' \ f'li x2, {0x00000013}\n{inst} x2, 0(x1)\n' elif inst == 'sd': # assuming we fetch/write 4 byte words # (over) writing the two nops under the label rt = f'\n.align 3\n{_lab}:\n\tnop\n\tnop\nla x1, {_lab}\n' \ f'li x2, {0x00000013_00000013}\n{inst} x2, 0(x1)\n' # Handling Compressed jumps: 'c.j', 'c.jal', 'c.jalr', 'c.jr' elif inst in ('c.sw', 'c.sd', 'c.fsd', 'c.fsw'): # TODO: add fsd and fsw if inst == 'c.sw': rt = f'\n.align 2\n{_lab}:\n\tnop\nla x8, {_lab}\n' \ f'li x9, {0x00000013}\n{inst} x9, 0(x8)\n' elif inst == 'c.sd': # assuming we fetch/write 4 byte words # (over) writing the two nops under the label rt = f'\n.align 3\n{_lab}:\n\tnop\n\tnop\nla x8, {_lab}\n' \ f'li x9, {0x00000013_00000013}\n{inst} x9, 0(x8)\n' elif inst in ('c.swsp', 'c.sdsp'): _align = 2 if 'swsp' in inst else 3 _nop = '\n\tnop' * (_align - 1) _val = 0x00000013_00000013 if 'sdsp' in inst else 0x13 rt = f'\n.align {_align}\n{_lab}:{_nop}\nla sp, {_lab}\n' \ f'\nli x8, {_val}\n{inst} x8, 0(sp)\n' return rt
[docs] def generate_i_inst(self, instructions: Union[str, list] = 'random', modifiers: Union[None, dict] = None, no_of_insts: int = 5) -> List[str]: """ Function to generate I-instructions. Does not generate branch/jump/load/store instructions. Can generate both random selection of instructions or a specified list of instructions. The modifiers can be used to specify specific value/range of values for variable fields :param instructions: 'random' or a list of instructions for which you wish to generate instructions :param modifiers: None or dictionary containing custom replacement options. :param no_of_insts: number of instructions to be generated :return: a list containing generated asm instructions """ modifiers = self.__modifier_update(modifiers) ret_list = [] if instructions == 'random': random_insts = choices(list(self.i_insts.keys()), k=no_of_insts) for key in random_insts: if key in ('beq', 'bne', 'blt', 'bge', 'bltu', 'bgeu', 'jal', 'jalr', 'lb', 'lh', 'lw', 'ld', 'lbu', 'lhu', 'lwu', 'sb', 'sh', 'sw', 'sd'): ret_list.append(self.__handle_branch_load_store(key)) else: asm_syntax = self.i_insts[key] r_inst = self.__replace_fields(asm_syntax, modifiers) ret_list.append(r_inst) elif type(instructions) == list: for i in instructions: assert (i in self.i_insts.keys()) for _ in range(no_of_insts): if len(instructions) <= 0: ret_list.append('nop') else: inst = choice(instructions) if inst in ('beq', 'bne', 'blt', 'bge', 'bltu', 'bgeu', 'jal', 'jalr', 'lb', 'lh', 'lw', 'ld', 'lbu', 'lhu', 'lwu', 'sb', 'sh', 'sw', 'sd'): ret_list.append(self.__handle_branch_load_store(inst)) else: asm_syntax = self.i_insts[inst] r_inst = self.__replace_fields(asm_syntax, modifiers=modifiers) ret_list.append(r_inst) return ret_list
def generate_all_i_inst(self, modifiers: Union[None, dict] = None): ret_list = [] for i_inst in self.i_insts.keys(): ret_list.append( self.generate_i_inst([i_inst], modifiers=modifiers, no_of_insts=1)[0]) return ret_list
[docs] def generate_m_inst(self, instructions: Union[str, list] = 'random', modifiers: Union[None, dict] = None, no_of_insts: int = 5) -> List[str]: """ Function to generate M-instructions. Generates all Mul/Div instructions. Can generate both random selection of instructions or a specified list of instructions. The modifiers can be used to specify specific value/range of values for variable fields :param instructions: 'random' or a list of instructions for which you wish to generate instructions :param modifiers: None or dictionary containing custom replacement options. :param no_of_insts: number of instructions to be generated :return: a list containing generated asm instructions. """ modifiers = self.__modifier_update(modifiers) ret_list = [] if instructions == 'random': random_insts = choices(list(self.m_insts.keys()), k=no_of_insts) for key in random_insts: asm_syntax = self.m_insts[key] r_inst = self.__replace_fields(asm_syntax, modifiers=modifiers) ret_list.append(r_inst) elif type(instructions) == list: for _ in range(no_of_insts): inst = choice(instructions) asm_syntax = self.m_insts[inst] r_inst = self.__replace_fields(asm_syntax, modifiers=modifiers) ret_list.append(r_inst) return ret_list
def generate_all_m_inst(self, modifiers: Union[None, dict] = None): ret_list = [] for m_inst in self.m_insts.keys(): ret_list.append( self.generate_m_inst([m_inst], modifiers=modifiers, no_of_insts=1)[0]) return ret_list
[docs] def generate_a_inst(self, instructions: Union[str, list] = 'random', modifiers: Union[None, dict] = None, no_of_insts: int = 5) -> List[str]: """ Function to generate A-instructions. Can generate both random selection of instructions or a specified list of instructions. The modifiers can be used to specify specific value/range of values for variable fields. :param instructions: 'random' or a list of instructions for which you wish to generate instructions :param modifiers: None or dictionary containing custom replacement options. :param no_of_insts: number of instructions to be generated :return: a list containing generated asm instructions """ modifiers = self.__modifier_update(modifiers) ret_list = [] if instructions == 'random': instructions = choices(list(self.a_insts.keys()), k=no_of_insts) for _ in range(no_of_insts): inst = choice(instructions) asm_syntax = self.a_insts[inst] rt = 'nop' _align = 3 if '.d' in inst else 2 _lab = self.__generate_labels(prefix=inst) _nop = '\tnop\n\tnop' if _align == 3 else '\tnop' _s_nop = 0x1300000013 if self.xlen == 64 else 0x13 ([xrs1, temp], xrs2, xrd) = (sample(modifiers['xrs1'], 2), sample(modifiers['xrs2'], 1)[0], sample(modifiers['xrd'], 1)[0]) _ = 0 while len({xrs1, temp, xrs2, xrd}) != 4 \ or xrs2 == 'x0' or xrs1 == 'x0': # making sure that register dependencies are met ([xrs1, temp], xrs2, xrd) = (sample(modifiers['xrs1'], 2), sample(modifiers['xrs2'], 1)[0], sample(modifiers['xrd'], 1)[0]) _ += 1 if _ == 100: raise Exception('Cant Solve Register Dependency Constraint') asm_syntax = asm_syntax.replace('$xrd', xrd) asm_syntax = asm_syntax.replace('$xrs1', xrs1) asm_syntax = asm_syntax.replace('$xrs2', xrs2) if 'lr' in inst: rt = f'\n.align {_align}\n{_lab}:\n{_nop}\n' \ f'la {xrs1}, {_lab}\n{asm_syntax}\n' if '.w' in inst: rt += f'li {temp}, {_s_nop}\nsw {temp}, 0({xrs1})\n' else: rt += f'li {temp}, {_s_nop}\nsw {temp}, 0({xrs1})\n' elif 'sc' in inst: rt = f'\n.align {_align}\n{_lab}:\n{_nop}\n' \ f'la {xrs1}, {_lab}\nli {xrs2}, {_s_nop}\n' \ f'{asm_syntax}\n' elif 'amoswap' in inst: rt = f'\n.align {_align}\n{_lab}:\n{_nop}\n' \ f'la {xrs1}, {_lab}\nli {xrs2}, {_s_nop}\n' \ f'{asm_syntax}\n' elif inst in ('amoadd.w', 'amoadd.d', 'amoxor.w', 'amoxor.d', 'amoor.w', 'amoor.d', 'amomax.w', 'amomax.d', 'amomaxu.w', 'amomaxu.d'): rt = f'\n.align {_align}\n{_lab}:\n{_nop}\n' \ f'la {xrs1}, {_lab}\nli {xrs2}, 0x0\n' \ f'{asm_syntax}\n' elif inst in ('amoand.w', 'amoand.d', 'amomin.w', 'amomin.d', 'amominu.w', 'amominu.d'): rt = f'\n.align {_align}\n{_lab}:\n{_nop}\n' \ f'la {xrs1}, {_lab}\n' \ f'li {xrs2}, {hex(2 ** int(self.xlen) - 1)}\n' \ f'{asm_syntax}\n' ret_list.append(rt) return ret_list
def generate_all_a_inst(self, modifiers: Union[None, dict] = None): ret_list = [] for a_inst in self.a_insts.keys(): ret_list.append( self.generate_a_inst([a_inst], modifiers=modifiers, no_of_insts=1)[0]) return ret_list
[docs] def generate_f_inst(self, instructions: Union[str, list] = 'random', modifiers: Union[None, dict] = None, no_of_insts: int = 5) -> List[str]: """ Function to generate F-instructions. Does not generate float branch/jump/load/store instructions. Can generate both random selection of instructions or a specified list of instructions. The modifiers can be used to specify specific value/range of values for variable fields :param instructions: 'random' or a list of instructions for which you wish to generate instructions :param modifiers: None or dictionary containing custom replacement options. :param no_of_insts: number of instructions to be generated :return: a list containing generated asm instructions """ modifiers = self.__modifier_update(modifiers) ret_list = [] if instructions == 'random': random_insts = choices(list(self.f_insts.keys()), k=no_of_insts) for key in random_insts: asm_syntax = self.f_insts[key] r_inst = self.__replace_fields(asm_syntax, modifiers=modifiers) ret_list.append(r_inst) elif type(instructions) == list: for _ in range(no_of_insts): inst = choice(instructions) asm_syntax = self.f_insts[inst] r_inst = self.__replace_fields(asm_syntax, modifiers=modifiers) ret_list.append(r_inst) return ret_list
def generate_all_f_inst(self, modifiers: Union[None, dict] = None): ret_list = [] for f_inst in self.f_insts.keys(): ret_list.append( self.generate_i_inst([f_inst], modifiers=modifiers, no_of_insts=1)[0]) return ret_list
[docs] def generate_d_inst(self, instructions: Union[str, list] = 'random', modifiers: Union[None, dict] = None, no_of_insts: int = 5) -> List[str]: """ Function to generate D-instructions. Does not generate float branch/jump/load/store instructions. Can generate both random selection of instructions or a specified list of instructions. The modifiers can be used to specify specific value/range of values for variable fields :param instructions: 'random' or a list of instructions for which you wish to generate instructions :param modifiers: None or dictionary containing custom replacement options. :param no_of_insts: number of instructions to be generated :return: a list containing generated asm instructions """ modifiers = self.__modifier_update(modifiers) ret_list = [] if instructions == 'random': random_insts = choices(list(self.d_insts.keys()), k=no_of_insts) for key in random_insts: asm_syntax = self.d_insts[key] r_inst = self.__replace_fields(asm_syntax, modifiers=modifiers) ret_list.append(r_inst) elif type(instructions) == list: for _ in range(no_of_insts): inst = choice(instructions) asm_syntax = self.d_insts[inst] r_inst = self.__replace_fields(asm_syntax, modifiers=modifiers) ret_list.append(r_inst) return ret_list
def generate_all_d_inst(self, modifiers: Union[None, dict] = None): ret_list = [] for d_inst in self.d_insts.keys(): ret_list.append( self.generate_i_inst([d_inst], modifiers=modifiers, no_of_insts=1)[0]) return ret_list
[docs] def generate_c_inst(self, instructions: Union[str, list] = 'random', modifiers: Union[None, dict] = None, no_of_insts: int = 5) -> List[str]: """ Function to generate C-instructions. Does not generate compressed branch/jump/load/store instructions. Can generate both random selection of instructions or a specified list of instructions. The modifiers can be used to specify specific value/range of values for variable fields :param instructions: 'random' or a list of instructions for which you wish to generate instructions :param modifiers: None or dictionary containing custom replacement options. :param no_of_insts: number of instructions to be generated :return: a list containing generated asm instructions """ modifiers = self.__modifier_update(modifiers) ret_list = [] if instructions == 'random': random_insts = choices(list(self.c_insts.keys()), k=no_of_insts) for key in random_insts: if key in ( 'c.beqz', 'c.bnez', 'c.j', 'c.jal', 'c.jalr', 'c.jr', 'c.ld', 'c.sd', 'c.lw', 'c.sw' 'c.fld', 'c.flw', 'c.fsd', 'c.fsw', 'c.fldsp', 'c.fsdsp', 'c.lwsp', 'c.ldsp', 'c.swsp', 'c.sdsp', ): ret_list.append(self.__handle_branch_load_store(key)) elif key == 'c.lui': r = randint(1, 32) ret_list.append(f'{key} x8, {r}') elif key == 'c.ebreak': ret_list.append('c.nop') else: asm_syntax = self.c_insts[key] r_inst = self.__replace_fields(asm_syntax, modifiers) ret_list.append(r_inst) elif type(instructions) == list: for _ in range(no_of_insts): if len(instructions) <= 0: ret_list.append('nop') else: inst = choice(instructions) if inst in ( 'c.beqz', 'c.bnez', 'c.j', 'c.jal', 'c.jalr', 'c.jr', 'c.ld', 'c.sd', 'c.lw', 'c.sw', 'c.fld', 'c.flw', 'c.fsd', 'c.fsw', 'c.fldsp', 'c.fsdsp', 'c.lwsp', 'c.ldsp', 'c.swsp', 'c.sdsp', ): ret_list.append(self.__handle_branch_load_store(inst)) elif inst == 'c.lui': r = randint(1, 32) ret_list.append(f'{inst} x8, {r}') elif inst == 'c.ebreak': ret_list.append('c.nop') else: asm_syntax = self.c_insts[inst] r_inst = self.__replace_fields(asm_syntax, modifiers=modifiers) ret_list.append(r_inst) return ret_list
def generate_all_c_inst(self, modifiers: Union[None, dict] = None): ret_list = [] for c_inst in self.c_insts.keys(): ret_list.append( self.generate_c_inst([c_inst], modifiers=modifiers, no_of_insts=1)[0]) return ret_list
[docs] def generate_b_inst(self, instructions: Union[str, list] = 'random', modifiers: Union[None, dict] = None, no_of_insts: int = 5) -> List[str]: """ Function to generate B-instructions. Can generate both random selection of instructions or a specified list of instructions. The modifiers can be used to specify specific value/range of values for variable fields :param instructions: 'random' or a list of instructions for which you wish to generate instructions :param modifiers: None or dictionary containing custom replacement options. :param no_of_insts: number of instructions to be generated :return: a list containing generated asm instructions """ modifiers = self.__modifier_update(modifiers) ret_list = [] if instructions == 'random': random_insts = choices(list(self.b_insts.keys()), k=no_of_insts) for key in random_insts: asm_syntax = self.b_insts[key] r_inst = self.__replace_fields(asm_syntax, modifiers=modifiers) ret_list.append(r_inst) elif type(instructions) == list: for _ in range(no_of_insts): inst = choice(instructions) asm_syntax = self.b_insts[inst] r_inst = self.__replace_fields(asm_syntax, modifiers=modifiers) ret_list.append(r_inst) return ret_list
def generate_all_b_inst(self, modifiers: Union[None, dict] = None): ret_list = [] for m_inst in self.m_insts.keys(): ret_list.append( self.generate_i_inst([m_inst], modifiers=modifiers, no_of_insts=1)[0]) return ret_list