def on_configure(sim: OTBNSim, args: List[str]) -> Optional[OTBNSim]: check_arg_count('configure', 1, args) enable = read_word('secure_wipe_en', args[0], 1) != 0 sim.configure(enable) return None
def main() -> int: parser = argparse.ArgumentParser() parser.add_argument('elf') parser.add_argument('-v', '--verbose', action='store_true') parser.add_argument('--dmem-dump') args = parser.parse_args() sim = OTBNSim() load_elf(sim, args.elf) sim.state.pc = 0 sim.state.start() sim.run(verbose=args.verbose) if args.dmem_dump is not None: try: with open(args.dmem_dump, 'wb') as dmem_file: dmem_file.write(sim.dump_data()) except OSError as err: sys.stderr.write('Failed to write DMEM to {!r}: {}.' .format(args.dmem_dump, err)) return 1 return 0
def _run_sim_for_stats(sim: OTBNSim) -> ExecutionStats: sim.run(verbose=False, collect_stats=True) # Ensure that the execution was successful. assert sim.state.ext_regs.read('ERR_BITS', False) == 0 assert sim.stats return sim.stats
def on_load_i(sim: OTBNSim, args: List[str]) -> None: '''Load contents of insn memory from file at path given by only argument''' if len(args) != 1: raise ValueError( 'load_i expects exactly 1 argument. Got {}.'.format(args)) path = args[0] print('LOAD_I {!r}'.format(path)) sim.load_program(decode_file(0, path))
def on_start(sim: OTBNSim, args: List[str]) -> Optional[OTBNSim]: '''Jump to an address given as the (only) argument and start running''' check_arg_count('start', 0, args) print('START') sim.state.ext_regs.commit() sim.start(collect_stats=False) return None
def on_start(sim: OTBNSim, args: List[str]) -> Optional[OTBNSim]: '''Jump to an address given as the (only) argument and start running''' if len(args) != 0: raise ValueError('start expects zero arguments. Got {}.'.format(args)) print('START') sim.state.ext_regs.commit() sim.start(collect_stats=False) return None
def on_load_i(sim: OTBNSim, args: List[str]) -> Optional[OTBNSim]: '''Load contents of insn memory from file at path given by only argument''' check_arg_count('load_i', 1, args) path = args[0] print('LOAD_I {!r}'.format(path)) sim.load_program(decode_file(0, path)) return None
def on_load_d(sim: OTBNSim, args: List[str]) -> None: '''Load contents of data memory from file at path given by only argument''' if len(args) != 1: raise ValueError( 'load_d expects exactly 1 argument. Got {}.'.format(args)) path = args[0] print('LOAD_D {!r}'.format(path)) with open(path, 'rb') as handle: sim.load_data(handle.read())
def on_load_d(sim: OTBNSim, args: List[str]) -> Optional[OTBNSim]: '''Load contents of data memory from file at path given by only argument''' check_arg_count('load_d', 1, args) path = args[0] print('LOAD_D {!r}'.format(path)) with open(path, 'rb') as handle: sim.load_data(handle.read(), has_validity=True) return None
def _run_sim_for_stats(asm_file: str, tmpdir: str) -> ExecutionStats: """ Run the OTBN simulator, collect statistics, and return them. """ assert os.path.exists(asm_file) elf_file = testutil.asm_and_link_one_file(asm_file, tmpdir) sim = OTBNSim() load_elf(sim, elf_file) sim.state.start(0) sim.run(verbose=False, collect_stats=True) return sim.stats
def main() -> int: parser = argparse.ArgumentParser() parser.add_argument("imem_words", type=int) parser.add_argument("imem_file") parser.add_argument("dmem_words", type=int) parser.add_argument("dmem_file") parser.add_argument("cycles_file") parser.add_argument("trace_file") parser.add_argument("start_addr", type=int) args = parser.parse_args() sim = OTBNSim(OTBNModel(verbose=args.trace_file)) sim.load_program(decode_file(args.imem_file)) with open(args.dmem_file, "rb") as f: sim.load_data(f.read()) cycles = sim.run(start_addr=args.start_addr) with open(args.dmem_file, "wb") as f: f.write(sim.dump_data()) with open(args.cycles_file, "wb") as f: f.write(struct.pack("<L", cycles)) return 0
def on_start(sim: OTBNSim, args: List[str]) -> None: '''Jump to an address given as the (only) argument and start running''' if len(args) != 1: raise ValueError('start expects exactly 1 argument. Got {}.' .format(args)) addr = read_word('addr', args[0], 32) if addr & 3: raise ValueError('start address must be word-aligned. Got {:#08x}.' .format(addr)) print('START {:#08x}'.format(addr)) sim.state.ext_regs.write('START_ADDR', addr, False) sim.state.ext_regs.commit() sim.start()
def on_clear_loop_warps(sim: OTBNSim, args: List[str]) -> Optional[OTBNSim]: '''Run until ecall or error''' check_arg_count('clear_loop_warps', 0, args) sim.loop_warps = {} return None
def on_run(sim: OTBNSim, args: List[str]) -> None: '''Run until ecall or error''' if len(args): raise ValueError('run expects zero arguments. Got {}.'.format(args)) num_cycles = sim.run(verbose=False) print(' ran for {} cycles'.format(num_cycles))
def main() -> int: parser = argparse.ArgumentParser() parser.add_argument('elf') parser.add_argument('-v', '--verbose', action='store_true') parser.add_argument( '--dump-dmem', metavar="FILE", type=argparse.FileType('wb'), help=("after execution, write the data memory contents to this file. " "Use '-' to write to STDOUT.")) parser.add_argument( '--dump-regs', metavar="FILE", type=argparse.FileType('w'), help=("after execution, write the GPR and WDR contents to this file. " "Use '-' to write to STDOUT.")) parser.add_argument( '--dump-stats', metavar="FILE", type=argparse.FileType('w'), help=("after execution, write execution statistics to this file. " "Use '-' to write to STDOUT.")) args = parser.parse_args() collect_stats = args.dump_stats is not None sim = OTBNSim() load_elf(sim, args.elf) sim.state.start(0) sim.run(verbose=args.verbose, collect_stats=collect_stats) if args.dump_dmem is not None: args.dump_dmem.write(sim.dump_data()) if args.dump_regs is not None: for idx, value in enumerate(sim.state.gprs.peek_unsigned_values()): args.dump_regs.write(' x{:<2} = 0x{:08x}\n'.format(idx, value)) for idx, value in enumerate(sim.state.wdrs.peek_unsigned_values()): args.dump_regs.write(' w{:<2} = 0x{:064x}\n'.format(idx, value)) if collect_stats: stat_analyzer = ExecutionStatAnalyzer(sim.stats, args.elf) args.dump_stats.write(stat_analyzer.dump()) return 0
def main() -> int: sim = OTBNSim() try: for line in sys.stdin: on_input(sim, line) except KeyboardInterrupt: print("Received shutdown request, ending OTBN simulation.") return 0 return 0
def on_clear_loop_warps(sim: OTBNSim, args: List[str]) -> Optional[OTBNSim]: '''Run until ecall or error''' if len(args): raise ValueError( 'clear_loop_warps expects zero arguments. Got {}.'.format(args)) sim.loop_warps = {} return None
def prepare_sim_for_asm_file(asm_file: str, tmpdir: py.path.local, start_addr: int = 0) -> OTBNSim: '''Set up the simulation of a single assembly file. The returned simulation is ready to be run through the run() method. ''' assert os.path.exists(asm_file) elf_file = asm_and_link_one_file(asm_file, tmpdir) sim = OTBNSim() load_elf(sim, elf_file) sim.state.ext_regs.write('START_ADDR', start_addr, False) sim.state.ext_regs.commit() sim.start() return sim
def main() -> int: parser = argparse.ArgumentParser() parser.add_argument('elf') parser.add_argument('-v', '--verbose', action='store_true') parser.add_argument( '--dump-dmem', metavar="FILE", type=argparse.FileType('wb'), help=("after execution, write the data memory contents to this file. " "Use '-' to write to STDOUT.")) parser.add_argument( '--dump-regs', metavar="FILE", type=argparse.FileType('w'), help=("after execution, write the GPR and WDR contents to this file. " "Use '-' to write to STDOUT.")) parser.add_argument( '--dump-stats', metavar="FILE", type=argparse.FileType('w'), help=("after execution, write execution statistics to this file. " "Use '-' to write to STDOUT.")) args = parser.parse_args() collect_stats = args.dump_stats is not None sim = OTBNSim() exp_end_addr = load_elf(sim, args.elf) sim.state.ext_regs.write('START_ADDR', 0, False) sim.state.ext_regs.commit() sim.start() sim.run(verbose=args.verbose, collect_stats=collect_stats) if exp_end_addr is not None: if sim.state.pc != exp_end_addr: print('Run stopped at PC {:#x}, but _expected_end_addr was {:#x}.'. format(sim.state.pc, exp_end_addr), file=sys.stderr) return 1 if args.dump_dmem is not None: args.dump_dmem.write(sim.dump_data()) if args.dump_regs is not None: for idx, value in enumerate(sim.state.gprs.peek_unsigned_values()): args.dump_regs.write(' x{:<2} = 0x{:08x}\n'.format(idx, value)) for idx, value in enumerate(sim.state.wdrs.peek_unsigned_values()): args.dump_regs.write(' w{:<2} = 0x{:064x}\n'.format(idx, value)) if collect_stats: assert sim.stats is not None stat_analyzer = ExecutionStatAnalyzer(sim.stats, args.elf) args.dump_stats.write(stat_analyzer.dump()) return 0
def on_step(sim: OTBNSim, args: List[str]) -> None: '''Step one instruction''' if len(args): raise ValueError('step expects zero arguments. Got {}.'.format(args)) pc = int(sim.model.state.pc) assert 0 == pc & 3 print('EXEC {:#08x}'.format(pc)) done, changes = sim.step() for trace in changes: print(' {}'.format(trace))
def on_step(sim: OTBNSim, args: List[str]) -> None: '''Step one instruction''' if len(args): raise ValueError('step expects zero arguments. Got {}.'.format(args)) pc = int(sim.state.pc) assert 0 == pc & 3 insn, changes = sim.step(verbose=False) disasm = '(not running)' if insn is None else insn.disassemble(pc) print('EXEC {:#08x}: {}'.format(pc, disasm)) for trace in changes: print(' {}'.format(trace))
def on_add_loop_warp(sim: OTBNSim, args: List[str]) -> Optional[OTBNSim]: '''Add a loop warp to the simulation''' check_arg_count('add_loop_warp', 3, args) try: addr = int(args[0], 0) if addr < 0: raise ValueError('addr is negative') from_cnt = int(args[1], 0) if from_cnt < 0: raise ValueError('from_cnt is negative') to_cnt = int(args[2], 0) if to_cnt < 0: raise ValueError('to_cnt is negative') except ValueError as err: raise ValueError( 'Bad argument to add_loop_warp: {}'.format(err)) from None print('ADD_LOOP_WARP {:#x} {} {}'.format(addr, from_cnt, to_cnt)) sim.add_loop_warp(addr, from_cnt, to_cnt) return None
def main() -> int: parser = argparse.ArgumentParser() parser.add_argument('elf') parser.add_argument('-v', '--verbose', action='store_true') parser.add_argument( '--dump-dmem', metavar="FILE", type=argparse.FileType('wb'), help="after execution, write the data memory contents to this file") parser.add_argument( '--dump-regs', metavar="FILE", type=argparse.FileType('w'), default=sys.stdout, help= "after execution, write the GPR and WDR contents to this file (default: STDOUT)" ) args = parser.parse_args() sim = OTBNSim() load_elf(sim, args.elf) sim.state.pc = 0 sim.state.start() sim.run(verbose=args.verbose) if args.dump_dmem is not None: args.dump_dmem.write(sim.dump_data()) if args.dump_regs is not None: for idx, value in enumerate(sim.state.gprs.peek_unsigned_values()): args.dump_regs.write(' x{:<2} = 0x{:08x}\n'.format(idx, value)) for idx, value in enumerate(sim.state.wdrs.peek_unsigned_values()): args.dump_regs.write(' w{:<2} = 0x{:064x}\n'.format(idx, value)) return 0
def on_step(sim: OTBNSim, args: List[str]) -> Optional[OTBNSim]: '''Step one instruction''' check_arg_count('step', 0, args) pc = sim.state.pc assert 0 == pc & 3 insn, changes = sim.step(verbose=False) print('STALL' if insn is None else insn.rtl_trace(pc)) for change in changes: entry = change.rtl_trace() if entry is not None: print(entry) return None
def on_step(sim: OTBNSim, args: List[str]) -> Optional[OTBNSim]: '''Step one instruction''' if len(args): raise ValueError('step expects zero arguments. Got {}.'.format(args)) pc = sim.state.pc assert 0 == pc & 3 insn, changes = sim.step(verbose=False) print('STALL' if insn is None else insn.rtl_trace(pc)) for change in changes: entry = change.rtl_trace() if entry is not None: print(entry) return None
def on_step(sim: OTBNSim, args: List[str]) -> Optional[OTBNSim]: '''Step one instruction''' check_arg_count('step', 0, args) pc = sim.state.pc assert 0 == pc & 3 was_wiping = sim.state.wiping() and sim.state.secure_wipe_enabled insn, changes = sim.step(verbose=False) if insn is not None: hdr = insn.rtl_trace(pc) # type: Optional[str] elif was_wiping: # The trailing space is a bit naff but matches the behaviour in the RTL # tracer, where it's rather difficult to change. hdr = 'U ' if sim.state.wiping() else 'V ' elif (sim.state.executing() or (changes and not sim.state.secure_wipe_enabled)): hdr = 'STALL' else: hdr = None rtl_changes = [] for c in changes: rt = c.rtl_trace() if rt is not None: rtl_changes.append(rt) # This is a bit of a hack. Very occasionally, we'll see traced changes when # there's not actually an instruction in flight. For example, this happens # if there's a RND request still pending when an operation stops. In this # case, we might see a change where we drop the REQ signal after the secure # wipe has finished. Rather than define a special "do-nothing" trace entry # format for this situation, we cheat and use STALL. if hdr is None and rtl_changes: hdr = 'STALL' if hdr is not None: print(hdr) for rt in rtl_changes: print(rt) return None
def on_step(sim: OTBNSim, args: List[str]) -> None: '''Step one instruction''' if len(args): raise ValueError('step expects zero arguments. Got {}.'.format(args)) pc = sim.state.pc assert 0 == pc & 3 insn, changes = sim.step(verbose=False) if insn is None: hdr = 'STALL' else: hdr = 'E PC: {:#010x}, insn: {:#010x}'.format(pc, insn.raw) print(hdr) for change in changes: entry = change.rtl_trace() if entry is not None: print(entry)
def on_step(sim: OTBNSim, args: List[str]) -> None: '''Step one instruction''' if len(args): raise ValueError('step expects zero arguments. Got {}.' .format(args)) pc = sim.state.pc assert 0 == pc & 3 insn, changes = sim.step(verbose=False, collect_stats=False) if insn is None: print('STALL') else: print(f'E PC: {pc:#010x}, insn: {insn.raw:#010x}') print(f'# @{pc:#010x}: {insn.insn.mnemonic}') for change in changes: entry = change.rtl_trace() if entry is not None: print(entry)
def on_step(sim: OTBNSim, args: List[str]) -> Optional[OTBNSim]: '''Step one instruction''' check_arg_count('step', 0, args) pc = sim.state.pc assert 0 == pc & 3 was_wiping = sim.state.wiping() and sim.state.secure_wipe_enabled insn, changes = sim.step(verbose=False) if insn is not None: hdr = insn.rtl_trace(pc) # type: Optional[str] elif was_wiping: # The trailing space is a bit naff but matches the behaviour in the RTL # tracer, where it's rather difficult to change. hdr = 'U ' if sim.state.wiping() else 'V ' elif (sim.state.running() or (changes and not sim.state.secure_wipe_enabled)): hdr = 'STALL' else: hdr = None rtl_changes = [] for c in changes: rt = c.rtl_trace() if rt is not None: rtl_changes.append(rt) if hdr is None: assert not rtl_changes else: print(hdr) for rt in rtl_changes: print(rt) return None
def on_reset(sim: OTBNSim, args: List[str]) -> Optional[OTBNSim]: if args: raise ValueError('reset expects zero arguments. Got {}.'.format(args)) return OTBNSim()