from openpower.decoder.orderedset import OrderedSet
from openpower.decoder.isa.all import ISA
from openpower.util import log
+from openpower.simulator.qemu import run_program
def read_data(fname, offset=0):
return result
-
-def run_tst(args, generator, initial_regs,
+def qemu_register_compare(sim, qemu, regs):
+ qpc, qxer, qcr = qemu.get_pc(), qemu.get_xer(), qemu.get_cr()
+ sim_cr = sim.cr.value
+ sim_pc = sim.pc.CIA.value
+ sim_xer = sim.spr['XER'].value
+ print("qemu pc", hex(qpc))
+ print("qemu cr", hex(qcr))
+ 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))
+ #self.assertEqual(qpc, sim_pc)
+ for reg in regs:
+ qemu_val = qemu.get_register(reg)
+ sim_val = sim.gpr(reg).value
+ log("expect %x got %x" % (qemu_val, sim_val))
+ #self.assertEqual(qemu_val, sim_val,
+ # "expect %x got %x" % (qemu_val, sim_val))
+ #self.assertEqual(qcr, sim_cr)
+
+
+def run_tst(args, generator, qemu,
+ initial_regs,
initial_sprs=None, svstate=0, mmu=False,
initial_cr=0, mem=None,
- initial_fprs=None):
+ initial_fprs=None,
+ initial_pc=0):
if initial_regs is None:
initial_regs = [0] * 32
if initial_sprs is None:
initial_sprs = {}
+ if qemu:
+ log("qemu program", generator.binfile.name)
+ qemu = run_program(generator, initial_mem=mem,
+ bigendian=False, start_addr=initial_pc,
+ continuous_run=False)
+
m = Module()
comb = m.d.comb
instruction = Signal(32)
m.submodules.pdecode2 = pdecode2 = PowerDecode2(pdecode)
simulator = ISA(pdecode2, initial_regs, initial_sprs, initial_cr,
- initial_insns=gen, respect_pc=True,
+ initial_insns=(initial_pc, gen), respect_pc=True,
initial_svstate=svstate,
initial_mem=mem,
+ initial_pc=initial_pc,
fpregfile=initial_fprs,
disassembly=insncode,
bigendian=0,
yield pdecode2.dec.bigendian.eq(0) # little / big?
pc = simulator.pc.CIA.value
index = pc//4
- while index < len(instructions) and not simulator.halted:
+ while not simulator.halted:
log("instr pc", pc)
try:
yield from simulator.setup_one()
break
yield Settle()
- ins = instructions[index]
- if isinstance(ins, list):
- ins, code = ins
- log(" 0x{:X}".format(ins & 0xffffffff))
- opname = code.split(' ')[0]
- log(code, opname)
- else:
- log(" 0x{:X}".format(ins & 0xffffffff))
+ if False:
+ ins = instructions[index]
+ if isinstance(ins, list):
+ ins, code = ins
+ log(" 0x{:X}".format(ins & 0xffffffff))
+ opname = code.split(' ')[0]
+ log(code, opname)
+ else:
+ log(" 0x{:X}".format(ins & 0xffffffff))
# ask the decoder to decode this binary data (endian'd)
yield from simulator.execute_one()
- pc = simulator.pc.CIA.value
- index = pc//4
+ #pc = simulator.pc.CIA.value
+ #index = pc//4
+
+ if not qemu:
+ continue
+
+ # check qemu co-sim: run one instruction
+ qemu.step()
+ qemu_register_compare(simulator, qemu, range(32))
+
+ # cleanup
+ if qemu:
+ qemu.exit()
sim.add_process(process)
sim.run()
print ("-s --spregs= colon-separated file with SPR values")
print ("-l --load= filename:address to load binary into memory")
print ("-d --dump= filename:address:len to binary save from memory")
+ print ("-q --qemu= run qemu co-simulation")
+ print ("-p --pc= set initial program counter")
print ("-h --help prints this message")
print ("notes:")
print ("load and dump may be given multiple times")
initial_fprs = [0]*32
initial_sprs = None
initial_mem = {}
+ initial_pc = 0x0
lst = None
+ qemu_cosim = False
write_to = []
try:
- opts, args = getopt.getopt(sys.argv[1:], "hi:a:g:f:s:l:d:",
- ["help",
+ opts, args = getopt.getopt(sys.argv[1:], "qhi:a:g:f:s:l:d:p:",
+ ["qemu", "help", "pc=",
"binary=", "listing=",
"intregs=", "fpregs=", "sprs=",
"load=", "dump="])
for opt, arg in opts:
if opt in ['-h', '--help']:
help()
+ elif opt in ['-q', '--qemu']:
+ qemu_cosim = True
elif opt in ['-i', '--binary']:
binaryname = arg
+ elif opt in ['-p', '--pc']:
+ initial_pc = convert_to_num(arg)
elif opt in ['-a', '--listing']:
lst = arg
elif opt in ['-g', '--intregs']:
with open(binaryname, "rb") as f:
lst = f.read()
- with Program(lst, bigendian=False) as prog:
- simulator = run_tst(None, prog,
+ with Program(lst, bigendian=False, orig_filename=binaryname) as prog:
+ simulator = run_tst(None, prog, qemu_cosim,
initial_regs,
initial_sprs=initial_sprs,
svstate=0, mmu=False,
initial_cr=0, mem=initial_mem,
- initial_fprs=initial_fprs)
+ initial_fprs=initial_fprs,
+ initial_pc=initial_pc)
print ("GPRs")
simulator.gpr.dump()
print ("FPRs")
return self._get_register('x {}'.format(num))
def step(self):
- return self.gdb.write('-exec-next-instruction')
+ return self.gdb.write('-exec-step-instruction')
def gdb_continue(self):
return self.gdb.write('-exec-continue')
self.qemu_popen.stdout.close()
self.qemu_popen.stdin.close()
+ def upload_mem(self, initial_mem):
+ for addr, (v, wid) in initial_mem.items():
+ for i in range(wid):
+ # sigh byte-level loads, veery slow
+ self.set_byte(addr+i, (v >> i*8) & 0xff)
+
def run_program(program, initial_mem=None, extra_break_addr=None,
- bigendian=False):
+ bigendian=False, start_addr=0x20000000, init_endian=True,
+ continuous_run=True):
q = QemuController(program.binfile.name, bigendian)
q.connect()
- q.set_endian(True) # easier to set variables this way
-
- # Run to the start of the program
+ q.set_endian(init_endian) # easier to set variables this way
if initial_mem:
- for addr, (v, wid) in initial_mem.items():
- for i in range(wid):
- q.set_byte(addr+i, (v >> i*8) & 0xff)
+ q.upload_mem(initial_mem)
- # set breakpoint at start
- q.break_address(0x20000000)
+ # Run to the start of the program
+ q.gdb_eval('$pc=%d' % start_addr)
+ pc = q.get_pc()
+ print("pc", bigendian, hex(pc))
+ q.break_address(start_addr) # set breakpoint at start
q.gdb_continue()
+
# set the MSR bit 63, to set bigendian/littleendian mode
msr = q.get_msr()
print("msr", bigendian, hex(msr))
q.gdb_eval('$cr=0')
# delete the previous breakpoint so loops don't screw things up
q.delete_breakpoint()
- # run to completion
- q.break_address(0x20000000 + program.size())
- # or to trap
+ # allow run to end
+ q.break_address(start_addr + program.size())
+ # or to trap (not ideal)
q.break_address(0x700)
# or to alternative (absolute) address)
- if extra_break_addr:
+ if extra_break_addr is not None:
q.break_address(extra_break_addr)
- q.gdb_continue()
+ if continuous_run:
+ q.gdb_continue()
+ else:
+ q.step()
q.set_endian(bigendian)
return q