from nmigen import Module, Signal
-from nmigen.back.pysim import Simulator, Delay, Settle
+from nmigen.sim import Simulator, Delay, Settle
import sys
import getopt
import struct
val = mem.ld(addr, 8)
f.write(struct.pack('>Q', val)) # unsigned long
+def sim_check_data(simulator, qemu, check_addr, msg):
+ addr = check_addr & ~0x7 # align
+ sim_data = simulator.mem.ld(addr, 8, swap=False)
+ qdata = qemu.get_mem(addr, 8)[0]
+ log ("last", msg, hex(check_addr), hex(sim_data), hex(qdata))
+ if sim_data != qdata:
+ log("expect mem %x, %x got %x" % (addr, qdata, sim_data))
+ exit(0)
def convert_to_num(num):
# detect number types
return result
-def qemu_register_compare(sim, qemu, regs):
- qpc, qxer, qcr = qemu.get_pc(), qemu.get_xer(), qemu.get_cr()
+
+def qemu_register_compare(sim, q, regs, fprs):
+ qpc, qxer, qcr, qlr = q.get_pc(), q.get_xer(), q.get_cr(), q.get_lr()
sim_cr = sim.cr.value
sim_pc = sim.pc.CIA.value
sim_xer = sim.spr['XER'].value
+ sim_lr = sim.spr['LR'].value
print("qemu pc", hex(qpc))
print("qemu cr", hex(qcr))
+ print("qemu lr", hex(qlr))
print("qemu xer", bin(qxer))
print("sim nia", hex(sim.pc.NIA.value))
print("sim pc", hex(sim.pc.CIA.value))
print("sim cr", hex(sim_cr))
print("sim xer", hex(sim_xer))
+ print("sim lr", hex(sim_lr))
#self.assertEqual(qpc, sim_pc)
for reg in regs:
- qemu_val = qemu.get_register(reg)
+ qemu_val = q.get_gpr(reg)
sim_val = sim.gpr(reg).value
- log("expect %x got %x" % (qemu_val, sim_val))
+ if qemu_val != sim_val:
+ log("expect gpr %d %x got %x" % (reg, qemu_val, sim_val))
+ #self.assertEqual(qemu_val, sim_val,
+ # "expect %x got %x" % (qemu_val, sim_val))
+ for fpr in fprs:
+ qemu_val = q.get_fpr(fpr)
+ sim_val = sim.fpr(fpr).value
+ if qemu_val != sim_val:
+ log("expect fpr %d %x got %x" % (fpr, qemu_val, sim_val))
#self.assertEqual(qemu_val, sim_val,
# "expect %x got %x" % (qemu_val, sim_val))
#self.assertEqual(qcr, sim_cr)
log("qemu program", generator.binfile.name)
qemu = run_program(generator, initial_mem=mem,
bigendian=False, start_addr=initial_pc,
- continuous_run=False)
+ continuous_run=False, initial_sprs=initial_sprs,
+ initial_regs=initial_regs, initial_fprs=initial_fprs)
+ for reg, val in qemu._get_registers().items():
+ log ("qemu reg", reg, hex(val))
+ if True:
+ offs, length = 0x200000, 0x200
+ qmem = qemu.get_mem(offs, length)
+ log("qemu mem pre-dump", hex(offs), length)
+ for i, data in enumerate(qmem):
+ log(hex(offs+i*8), hex(data))
m = Module()
comb = m.d.comb
yield pdecode2.dec.bigendian.eq(0) # little / big?
pc = simulator.pc.CIA.value
index = pc//4
+
+ # rather awkward: qemu will go wonky if stepped over the
+ # last instruction. use ISACaller to check if this is
+ # the last instruction, and leave qemu pointing at it
+ # rather than trigger an exception in the remote-qemu program
+ try:
+ _pc, _ins = simulator.get_next_insn()
+ except KeyError: # indicates instruction not in imem: stop
+ return
+
while not simulator.halted:
log("instr pc", pc)
- try:
- yield from simulator.setup_one()
- except KeyError: # indicates instruction not in imem: stop
- break
+ yield from simulator.setup_next_insn(_pc, _ins)
yield Settle()
if False:
#index = pc//4
if not qemu:
+ try:
+ _pc, _ins = simulator.get_next_insn()
+ except KeyError: # indicates instruction not in imem: stop
+ return
continue
- # check qemu co-sim: run one instruction
+ # check qemu co-sim: run one instruction, but first check
+ # in ISACaller if there *is* a next instruction. if there
+ # is, "recover" qemu by switching bigendian back
+ try:
+ _pc, _ins = simulator.get_next_insn()
+ except KeyError: # indicates instruction not in imem: stop
+ _pc, _insn = (None, None)
qemu.step()
- qemu_register_compare(simulator, qemu, range(32))
-
- # cleanup
- if qemu:
- qemu.exit()
+ if not _pc or simulator.halted:
+ qemu.set_endian(False)
+ qemu_register_compare(simulator, qemu, range(32), range(32))
+ # check last store address
+ check_addr = None
+ if simulator.last_st_addr is not None:
+ check_addr = simulator.last_st_addr
+ msg = "st"
+ if simulator.last_ld_addr is not None:
+ check_addr = simulator.last_ld_addr
+ msg = "ld"
+ if check_addr is not None:
+ sim_check_data(simulator, qemu, check_addr, msg)
+ sim_check_data(simulator, qemu, 0x600800, "dbgld")
+ if _pc is None:
+ break
sim.add_process(process)
sim.run()
- return simulator
+ return simulator, qemu
def help():
def run_simulation():
binaryname = None
- initial_regs = [0]*32
- initial_fprs = [0]*32
+ initial_regs = [0]*128
+ initial_fprs = [0]*128
initial_sprs = None
initial_mem = {}
initial_pc = 0x0
elif opt in ['-a', '--listing']:
lst = arg
elif opt in ['-g', '--intregs']:
- initial_regs = read_entries(arg, 32)
+ initial_regs = read_entries(arg, 128)
elif opt in ['-f', '--fpregs']:
- initial_fprs = read_entries(arg, 32)
+ initial_fprs = read_entries(arg, 128)
elif opt in ['-s', '--sprs']:
initial_sprs = read_entries(arg, 32)
elif opt in ['-l', '--load']:
else:
fname, offs = arg
offs = convert_to_num(offs)
- log ("offs load", fname, offs)
+ log ("offs load", fname, hex(offs))
mem = read_data(fname, offs)
initial_mem.update(mem)
elif opt in ['-d', '--dump']:
lst = f.read()
with Program(lst, bigendian=False, orig_filename=binaryname) as prog:
- simulator = run_tst(None, prog, qemu_cosim,
+ simulator, qemu = run_tst(None, prog, qemu_cosim,
initial_regs,
initial_sprs=initial_sprs,
svstate=0, mmu=False,
for fname, offs, length in write_to:
write_data(simulator.mem, fname, offs, length)
+ if qemu:
+ qmem = qemu.get_mem(offs, length)
+ log("qemu mem", hex(offs), length)
+ for i, mem in enumerate(qmem):
+ log(hex(offs+i*8), hex(mem))
+ if qemu:
+ log("final complete qemu reg dump")
+ for reg, val in qemu._get_registers().items():
+ log ("qemu reg", reg, hex(val))
+ # cleanup
+ if qemu:
+ qemu.exit()
if __name__ == "__main__":
run_simulation()