From fb94a6341673b852110eff23535457d35f929ea5 Mon Sep 17 00:00:00 2001 From: Luke Kenneth Casson Leighton Date: Fri, 21 May 2021 12:58:25 +0100 Subject: [PATCH] add first command-line version of ISACaller --- .gitignore | 2 + src/openpower/decoder/isa/pypowersim.py | 156 ++++++++++++++++++++++++ 2 files changed, 158 insertions(+) create mode 100644 src/openpower/decoder/isa/pypowersim.py diff --git a/.gitignore b/.gitignore index b4bd847f..dfab3e4f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,4 @@ .*.sw? __pycache__ +build +dist diff --git a/src/openpower/decoder/isa/pypowersim.py b/src/openpower/decoder/isa/pypowersim.py new file mode 100644 index 00000000..ab03138b --- /dev/null +++ b/src/openpower/decoder/isa/pypowersim.py @@ -0,0 +1,156 @@ +from nmigen import Module, Signal +from nmigen.back.pysim import Simulator, Delay, Settle +import string +import sys +import getopt +from openpower.decoder.power_decoder import create_pdecode +from openpower.decoder.power_decoder2 import (PowerDecode2) +from openpower.simulator.program import Program +from openpower.decoder.selectable_int import SelectableInt +from openpower.decoder.orderedset import OrderedSet +from openpower.decoder.isa.all import ISA + + +def convert_to_num(num): + # detect number types + if num.isdigit(): + return int(reg) + if num.startswith("0b"): + return int(value[2], 2) + if value.startswith("0x"): + return int(value[2], 16) + return num + + +def read_entries(fname, listqty=None): + """read_entries: reads values from a file of the format "x: y", per line + can be used for memory, or regfiles (GPR, SPR, FP). regs and entries may + start with "0x" or "0b" for hex or binary + """ + regs = {} + with open(fname) as f: + for line in f.readlines(): + # split line "x : y" into ["x", "y"], remove spaces + line = map(string.strip, line.strip().split(":")) + assert len(line) == 2, "regfile line must be formatted 'x : y'" + reg, val = line + reg = convert_to_num(reg) + val = convert_to_num(val) + assert reg not in regs, "duplicate entry %s" % (repr(reg)) + regs[reg] = val + + # post-process into a list. + if listqty is None: + return regs + result = [0] * listqty + for reg, value in regs.items(): + assert isinstance(reg, int), "list must be int, %s found" % reg + assert reg < listqty, "entry %s too large for list %s" % (reg, listqty) + result[reg] = value + + return result + + +def run_tst(args, generator, initial_regs, + initial_sprs=None, svstate=0, mmu=False, + initial_cr=0, mem=None, + initial_fprs=None): + if initial_regs is None: + initial_regs = [0] * 32 + if initial_sprs is None: + initial_sprs = {} + + m = Module() + comb = m.d.comb + instruction = Signal(32) + + pdecode = create_pdecode(include_fp=initial_fprs is not None) + + gen = list(generator.generate_instructions()) + insncode = generator.assembly.splitlines() + instructions = list(zip(gen, insncode)) + + m.submodules.pdecode2 = pdecode2 = PowerDecode2(pdecode) + simulator = ISA(pdecode2, initial_regs, initial_sprs, initial_cr, + initial_insns=gen, respect_pc=True, + initial_svstate=svstate, + initial_mem=mem, + fpregfile=initial_fprs, + disassembly=insncode, + bigendian=0, + mmu=mmu) + comb += pdecode2.dec.raw_opcode_in.eq(instruction) + sim = Simulator(m) + + def process(): + + yield pdecode2.dec.bigendian.eq(0) # little / big? + pc = simulator.pc.CIA.value + index = pc//4 + while index < len(instructions): + print("instr pc", pc) + try: + yield from simulator.setup_one() + except KeyError: # indicates instruction not in imem: stop + break + yield Settle() + + ins, code = instructions[index] + print(" 0x{:X}".format(ins & 0xffffffff)) + opname = code.split(' ')[0] + print(code, opname) + + # ask the decoder to decode this binary data (endian'd) + yield from simulator.execute_one() + pc = simulator.pc.CIA.value + index = pc//4 + + sim.add_process(process) + sim.run() + + return simulator + + +if __name__ == "__main__": + + binaryname = None + initial_regs = None + lst = None + + try: + opts, args = getopt.getopt(sys.argv[1:], "i:l:g:f:", + ["binary", "listing", + "intregs"]) + + except: + sys.stderr.write("Command-line Error\n") + exit(-1) + + for opt, arg in opts: + if opt in ['-i', '--binary']: + binaryname = arg + elif opt in ['-l', '--listing']: + lst = arg + elif opt in ['g', '--intregs']: + initial_regs = read_entries(arg, 32) + + if binaryname is None and lst is None: + sys.stderr.write("Must give binary or listing\n") + exit(-1) + + if lst: + with open(lst, "r") as f: + lst = list(f.readlines()) + + if binaryname: + with open(binaryname, "rb") as f: + lst = f.read() + + with Program(lst, bigendian=False) as prog: + simulator = run_tst(None, prog, + initial_regs, + initial_sprs=None, svstate=0, mmu=False, + initial_cr=0, mem=None, + initial_fprs=None) + simulator.gpr.dump() + simulator.fpr.dump() -- 2.30.2