fix qemu trap test
authorLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Sun, 5 Jul 2020 10:34:16 +0000 (11:34 +0100)
committerLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Sun, 5 Jul 2020 10:34:16 +0000 (11:34 +0100)
src/soc/decoder/isa/caller.py
src/soc/decoder/power_decoder2.py
src/soc/simulator/qemu.py
src/soc/simulator/test_sim.py

index 273ffd17b9814047517559a0174c6c1c8bf9cb23..d25fa6282c069c227c1373607275e14b44ae7314 100644 (file)
@@ -244,7 +244,8 @@ class ISACaller:
     def __init__(self, decoder2, regfile, initial_sprs=None, initial_cr=0,
                        initial_mem=None, initial_msr=0,
                        initial_insns=None, respect_pc=False,
-                       disassembly=None):
+                       disassembly=None,
+                       initial_pc=0):
 
         self.respect_pc = respect_pc
         if initial_sprs is None:
@@ -262,12 +263,15 @@ class ISACaller:
         if not respect_pc:
             if isinstance(initial_mem, tuple):
                 self.fake_pc = initial_mem[0]
+                disasm_start = self.fake_pc
+        else:
+            disasm_start = initial_pc
 
         # disassembly: we need this for now (not given from the decoder)
         self.disassembly = {}
         if disassembly:
             for i, code in enumerate(disassembly):
-                self.disassembly[i*4 + self.fake_pc] = code
+                self.disassembly[i*4 + disasm_start] = code
 
         # set up registers, instruction memory, data memory, PC, SPRs, MSR
         self.gpr = GPR(decoder2, regfile)
@@ -312,6 +316,8 @@ class ISACaller:
                           'SO': XER_bits['SO']
                           })
 
+        # update pc to requested start point
+        self.set_pc(initial_pc)
 
         # field-selectable versions of Condition Register TODO check bitranges?
         self.crl = []
@@ -325,12 +331,12 @@ class ISACaller:
         self.dec2 = decoder2
 
     def TRAP(self, trap_addr=0x700):
-        print ("TRAP: TODO")
+        print ("TRAP:", hex(trap_addr))
         # store CIA(+4?) in SRR0, set NIA to 0x700
         # store MSR in SRR1, set MSR to um errr something, have to check spec
         self.spr['SRR0'] = self.pc.CIA
         self.spr['SRR1'] = self.namespace['MSR']
-        self.set_pc(trap_addr)
+        self.trap_nia = SelectableInt(trap_addr, 64)
         self.namespace['MSR'][63-PI.TRAP] = 1 # bit 45, "this is a trap"
 
     def memassign(self, ea, sz, val):
@@ -460,7 +466,7 @@ class ISACaller:
         if ins is None:
             raise KeyError("no instruction at 0x%x" % pc)
         print("setup: 0x%x 0x%x %s" % (pc, ins & 0xffffffff, bin(ins)))
-        print ("NIA, CIA", self.pc.CIA.value, self.pc.NIA.value)
+        print ("CIA NIA", self.respect_pc, self.pc.CIA.value, self.pc.NIA.value)
 
         yield self.dec2.dec.raw_opcode_in.eq(ins & 0xffffffff)
         yield self.dec2.dec.bigendian.eq(0)  # little / big?
@@ -476,7 +482,7 @@ class ISACaller:
 
         if not self.respect_pc:
             self.fake_pc += 4
-        print ("NIA, CIA", self.pc.CIA.value, self.pc.NIA.value)
+        print ("execute one, CIA NIA", self.pc.CIA.value, self.pc.NIA.value)
 
     def get_assembly_name(self):
         # TODO, asmregs is from the spec, e.g. add RT,RA,RB
@@ -546,10 +552,20 @@ class ISACaller:
             else:
                 inputs.append(self.namespace[special])
 
+        # clear trap (trap) NIA
+        self.trap_nia = None
+
         print(inputs)
         results = info.func(self, *inputs)
         print(results)
 
+        # "inject" decorator takes namespace from function locals: we need to
+        # overwrite NIA being overwritten (sigh)
+        if self.trap_nia is not None:
+            self.namespace['NIA'] = self.trap_nia
+
+        print ("after func", self.namespace['CIA'], self.namespace['NIA'])
+
         # detect if CA/CA32 already in outputs (sra*, basically)
         already_done = 0
         if info.write_regs:
@@ -610,7 +626,8 @@ class ISACaller:
                         output = SelectableInt(output.value, 64)
                     self.gpr[regnum] = output
 
-        # update program counter
+        print ("end of call", self.namespace['CIA'], self.namespace['NIA'])
+        # UPDATE program counter
         self.pc.update(self.namespace)
 
 
@@ -638,6 +655,9 @@ def inject():
             saved_values = func_globals.copy()  # Shallow copy of dict.
             func_globals.update(context)
             result = func(*args, **kwargs)
+            print ("globals after", func_globals['CIA'], func_globals['NIA'])
+            print ("args[0]", args[0].namespace['CIA'],
+                              args[0].namespace['NIA'])
             args[0].namespace = func_globals
             #exec (func.__code__, func_globals)
 
index 84e1c789897d52218f50cc6dcbf24a7dfa125b3f..812bf72e812f2491bb5c5adbc38eb9c1b700a512 100644 (file)
@@ -627,6 +627,8 @@ class PowerDecode2(Elaboratable):
 
         # illegal instruction must redirect to trap. this is done by
         # *overwriting* the decoded instruction and starting again.
+        # (note: the same goes for interrupts and for privileged operations,
+        # just with different trapaddr and traptype)
         with m.If(op.internal_op == InternalOp.OP_ILLEGAL):
             comb += e.eq(0) # reset eeeeeverything
             # start again
@@ -649,8 +651,12 @@ class PowerDecode2(Elaboratable):
 
         # TODO: get msr, then can do privileged instruction
         with m.If(instr_is_priv(m, op.internal_op, e.insn) & msr[MSR_PR]):
+            comb += e.eq(0) # reset eeeeeverything
+            # start again
+            comb += e.insn.eq(self.dec.opcode_in)
+            comb += e.insn_type.eq(InternalOp.OP_TRAP)
+            comb += e.fn_unit.eq(Function.TRAP)
             # privileged instruction trap
-            comb += op.insn_type.eq(InternalOp.OP_TRAP)
             comb += e.traptype.eq(TT_PRIV) # request privileged instruction
             comb += e.trapaddr.eq(0x70)    # addr=0x700 (strip first nibble)
         return m
index c265a77ffa2b16ec30487a04b86cd1fc3b26457b..b39ada05d07d1bb4879ec3f93bbdba9b400e1c79 100644 (file)
@@ -112,6 +112,8 @@ def run_program(program, initial_mem=None):
     q.delete_breakpoint()
     # run to completion
     q.break_address(0x20000000 + program.size())
+    # or to trap
+    q.break_address(0x700)
     q.gdb_continue()
     return q
 
index de4193bc5f3bacd7311a984682e728c52484b6a4..a619ba1bd39c533bebfad9b6d7512db5a2be8b3c 100644 (file)
@@ -209,7 +209,7 @@ class GeneralTestCases(FHDLTestCase):
 
 class DecoderBase:
 
-    def run_tst(self, generator, initial_mem=None):
+    def run_tst(self, generator, initial_mem=None, initial_pc=0):
         m = Module()
         comb = m.d.comb
 
@@ -220,9 +220,13 @@ class DecoderBase:
         pdecode = create_pdecode()
         m.submodules.pdecode2 = pdecode2 = PowerDecode2(pdecode)
 
+        # place program at requested address
+        gen = (initial_pc, gen)
+
         simulator = ISA(pdecode2, [0] * 32, {}, 0, initial_mem, 0,
                         initial_insns=gen, respect_pc=True,
-                        disassembly=insn_code)
+                        disassembly=insn_code,
+                        initial_pc=initial_pc)
 
         sim = Simulator(m)
 
@@ -246,7 +250,8 @@ class DecoderBase:
 
     def run_tst_program(self, prog, reglist, initial_mem=None):
         import sys
-        simulator = self.run_tst(prog, initial_mem=initial_mem)
+        simulator = self.run_tst(prog, initial_mem=initial_mem,
+                                 initial_pc=0x20000000)
         prog.reset()
         with run_program(prog, initial_mem) as q:
             self.qemu_register_compare(simulator, q, reglist)
@@ -280,10 +285,12 @@ class DecoderBase:
         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(qcr, sim_cr)
+        self.assertEqual(qpc, sim_pc)
         for reg in regs:
             qemu_val = qemu.get_register(reg)
             sim_val = sim.gpr(reg).value