Merge remote-tracking branch 'upstream/master' into pr
authorLas Safin <me@las.rs>
Sat, 25 Sep 2021 16:01:22 +0000 (16:01 +0000)
committerLas Safin <me@las.rs>
Sat, 25 Sep 2021 16:01:22 +0000 (16:01 +0000)
15 files changed:
.gitlab-ci.yml
src/soc/experiment/compldst_multi.py
src/soc/experiment/test/test_compldst_multi_mmu.py [new file with mode: 0644]
src/soc/fu/compunits/compunits.py
src/soc/fu/compunits/formal/test_compunit.py
src/soc/fu/compunits/test/test_compunit.py
src/soc/fu/compunits/test/test_div_compunit.py
src/soc/fu/mul/test/helper.py
src/soc/simple/issuer.py
src/soc/simple/test/test_core.py
src/soc/simple/test/test_issuer.py
src/soc/simple/test/test_issuer_mmu.py
src/soc/simple/test/test_microwatt.py
src/soc/simple/test/test_runner.py
src/soc/simple/test/teststate.py [new file with mode: 0644]

index f453e172739dcdee534ed7bd84cec1064417cba3..867411fa4ddce7beef88c6b704c9f3f8df997219 100644 (file)
@@ -5,6 +5,7 @@ cache:
         - ccache
         - .cache/pip
         - apt-cache
+    when: 'always'
 
 variables:
     PIP_CACHE_DIR: "$CI_PROJECT_DIR/.cache/pip"
@@ -111,7 +112,7 @@ build:
         - pip install dist/sfpy*.whl
         - popd
 
-        - cargo install maturin
+        - python3 -m pip install 'maturin>=0.11,<0.12'
         - git clone --depth 1 https://git.libre-soc.org/git/power-instruction-analyzer.git pia
         - pushd pia
         - maturin build --cargo-extra-args=--features=python-extension
index d95dfa52610c708657d65e352448eba2b756c4e2..06f8184f5cea32a92e1e3fbe9b8ac2d7911fce07 100644 (file)
@@ -20,6 +20,11 @@ Loads are activated when Go_Write[0] is enabled.  The EA is computed,
 and (as long as there was no exception) the data comes out (at any
 time from the PortInterface), and is captured by the LDCompSTUnit.
 
+TODO: dcbz, yes, that's going to be complicated, has to be done
+ with great care, to detect the case when dcbz is set
+ and *not* expect to read any data, just the address.
+ so, wait for RA but not RB.
+
 Both LD and ST may request that the address be computed from summing
 operand1 (src[0]) with operand2 (src[1]) *or* by summing operand1 with
 the immediate (from the opcode).
@@ -275,6 +280,7 @@ class LDSTCompUnit(RegSpecAPI, Elaboratable):
         # opcode decode
         op_is_ld = Signal(reset_less=True)
         op_is_st = Signal(reset_less=True)
+        op_is_dcbz = Signal(reset_less=True)
 
         # ALU/LD data output control
         alu_valid = Signal(reset_less=True)  # ALU operands are valid
@@ -321,10 +327,12 @@ class LDSTCompUnit(RegSpecAPI, Elaboratable):
 
         # decode bits of operand (latched)
         oper_r = CompLDSTOpSubset(name="oper_r")  # Dest register
-        comb += op_is_st.eq(oper_r.insn_type == MicrOp.OP_STORE)  # ST
-        comb += op_is_ld.eq(oper_r.insn_type == MicrOp.OP_LOAD)  # LD
-        comb += Display("compldst_multi: op_is_dcbz = %i",
-                        (oper_r.insn_type == MicrOp.OP_DCBZ))
+        comb += op_is_st.eq(oper_r.insn_type == MicrOp.OP_STORE)   # ST
+        comb += op_is_ld.eq(oper_r.insn_type == MicrOp.OP_LOAD)    # LD
+        comb += op_is_dcbz.eq(oper_r.insn_type == MicrOp.OP_DCBZ)  # DCBZ
+        #uncomment if needed
+        #comb += Display("compldst_multi: op_is_dcbz = %i",
+        #                (oper_r.insn_type == MicrOp.OP_DCBZ))
         op_is_update = oper_r.ldst_mode == LDSTMode.update           # UPDATE
         op_is_cix = oper_r.ldst_mode == LDSTMode.cix           # cache-inhibit
         comb += self.load_mem_o.eq(op_is_ld & self.go_ad_i)
diff --git a/src/soc/experiment/test/test_compldst_multi_mmu.py b/src/soc/experiment/test/test_compldst_multi_mmu.py
new file mode 100644 (file)
index 0000000..a62bd58
--- /dev/null
@@ -0,0 +1,178 @@
+# test case for LOAD / STORE Computation Unit using MMU
+
+from nmigen.compat.sim import run_simulation
+from nmigen.cli import verilog, rtlil
+from nmigen import Module, Signal, Mux, Cat, Elaboratable, Array, Repl
+from nmigen.hdl.rec import Record, Layout
+
+from nmutil.latch import SRLatch, latchregister
+from nmutil.byterev import byte_reverse
+from nmutil.extend import exts
+from soc.fu.regspec import RegSpecAPI
+
+from openpower.decoder.power_enums import MicrOp, Function, LDSTMode
+from soc.fu.ldst.ldst_input_record import CompLDSTOpSubset
+from openpower.decoder.power_decoder2 import Data
+from openpower.consts import MSR
+
+from soc.experiment.compalu_multi import go_record, CompUnitRecord
+from soc.experiment.l0_cache import PortInterface
+from soc.experiment.pimem import LDSTException
+from soc.experiment.compldst_multi import LDSTCompUnit
+from soc.config.test.test_loadstore import TestMemPspec
+
+from soc.experiment.mmu import MMU
+
+########################################
+
+def dcbz(dut, src1, src2, src3, imm, imm_ok=True, update=False,
+          byterev=True):
+    print("DCBZ", src1, src2, src3, imm, imm_ok, update)
+    yield dut.oper_i.insn_type.eq(MicrOp.OP_DCBZ)
+    yield dut.oper_i.data_len.eq(2)  # half-word
+    yield dut.oper_i.byte_reverse.eq(byterev)
+    yield dut.src1_i.eq(src1)
+    yield dut.src2_i.eq(src2)
+    yield dut.src3_i.eq(src3)
+    yield dut.oper_i.imm_data.data.eq(imm)
+    yield dut.oper_i.imm_data.ok.eq(imm_ok)
+    #FIXME: -- yield dut.oper_i.update.eq(update)
+    yield dut.issue_i.eq(1)
+    yield
+    yield dut.issue_i.eq(0)
+
+    if imm_ok:
+        active_rel = 0b101
+    else:
+        active_rel = 0b111
+     # wait for all active rel signals to come up
+    # guess: bug is here
+    #while True:
+    #    rel = yield dut.rd.rel_o
+    #    if rel == active_rel:
+    #        break
+    #    yield
+    #yield dut.rd.go_i.eq(active_rel)
+    #yield
+    #yield dut.rd.go_i.eq(0)
+
+    #yield from wait_for(dut.adr_rel_o, False, test1st=True)
+    # yield from wait_for(dut.adr_rel_o)
+    # yield dut.ad.go.eq(1)
+    # yield
+    # yield dut.ad.go.eq(0)
+
+    #if update:
+    #    yield from wait_for(dut.wr.rel_o[1])
+    #    yield dut.wr.go.eq(0b10)
+    #    yield
+    #    addr = yield dut.addr_o
+    #    print("addr", addr)
+    #    yield dut.wr.go.eq(0)
+    #else:
+    #    addr = None
+
+    # commented out for debugging
+    #yield from wait_for(dut.sto_rel_o)
+    #yield dut.go_st_i.eq(1)
+    #yield
+    #yield dut.go_st_i.eq(0)
+    #yield from wait_for(dut.busy_o, False)
+    # wait_for(dut.stwd_mem_o)
+    #yield
+    #return addr
+
+
+def ldst_sim(dut):
+    yield from dcbz(dut, 4, 0, 3, 2) # FIXME
+    yield
+
+########################################
+
+
+class TestLDSTCompUnitMMU(LDSTCompUnit):
+
+    def __init__(self, rwid, pspec):
+        from soc.experiment.l0_cache import TstL0CacheBuffer
+        self.l0 = l0 = TstL0CacheBuffer(pspec)
+        pi = l0.l0.dports[0]
+        LDSTCompUnit.__init__(self, pi, rwid, 4)
+
+    def elaborate(self, platform):
+        m = LDSTCompUnit.elaborate(self, platform)
+        m.submodules.l0 = self.l0
+        # link addr-go direct to rel
+        m.d.comb += self.ad.go_i.eq(self.ad.rel_o)
+        return m
+
+
+def test_scoreboard_mmu():
+
+    units = {}
+    pspec = TestMemPspec(ldst_ifacetype='mmu_cache_wb',
+                         imem_ifacetype='bare_wb',
+                         addr_wid=48,
+                         mask_wid=8,
+                         reg_wid=64,
+                         units=units)
+
+    dut = TestLDSTCompUnitMMU(16,pspec)
+    vl = rtlil.convert(dut, ports=dut.ports())
+    with open("test_ldst_comp_mmu1.il", "w") as f:
+        f.write(vl)
+
+    run_simulation(dut, ldst_sim(dut), vcd_name='test_ldst_comp.vcd')
+
+########################################
+class TestLDSTCompUnitRegSpecMMU(LDSTCompUnit):
+
+    def __init__(self, pspec):
+        from soc.experiment.l0_cache import TstL0CacheBuffer
+        from soc.fu.ldst.pipe_data import LDSTPipeSpec
+        regspec = LDSTPipeSpec.regspec
+        self.l0 = l0 = TstL0CacheBuffer(pspec)
+        self.mmu = MMU()
+        pi = l0.l0.dports[0]
+        LDSTCompUnit.__init__(self, pi, regspec, 4)
+
+    def elaborate(self, platform):
+        m = LDSTCompUnit.elaborate(self, platform)
+        m.submodules.l0 = self.l0
+        m.submodules.mmu = self.mmu
+        # link addr-go direct to rel
+        m.d.comb += self.ad.go_i.eq(self.ad.rel_o)
+
+        # link mmu and dcache together
+        dcache = self.l0.pimem.dcache
+        mmu = self.mmu
+        m.d.comb += dcache.m_in.eq(mmu.d_out) # MMUToDCacheType
+        m.d.comb += mmu.d_in.eq(dcache.m_out) # DCacheToMMUType
+
+
+        return m
+
+
+def test_scoreboard_regspec_mmu():
+
+    units = {}
+    pspec = TestMemPspec(ldst_ifacetype='mmu_cache_wb',
+                         imem_ifacetype='bare_wb',
+                         addr_wid=48,
+                         mask_wid=8,
+                         reg_wid=64,
+                         units=units)
+
+    dut = TestLDSTCompUnitRegSpecMMU(pspec)
+
+    # TODO: setup pagetables for MMU
+
+    vl = rtlil.convert(dut, ports=dut.ports())
+    with open("test_ldst_comp_mmu2.il", "w") as f:
+        f.write(vl)
+
+    run_simulation(dut, ldst_sim(dut), vcd_name='test_ldst_regspec.vcd')
+
+
+if __name__ == '__main__':
+    test_scoreboard_regspec_mmu()
+    #only one test for now -- test_scoreboard_mmu()
index bdb0847dd832be7d026a6140ef7e113759090a9d..ecac38e0dd7bd6dc7498af55abf4f46395c206f7 100644 (file)
@@ -293,7 +293,7 @@ class AllFunctionUnits(Elaboratable):
                 self.excs[name] = alu.exc_o
 
     def get_exc(self, name):
-        return self.excs.get(name, default=None)
+        return self.excs.get(name)
 
     def get_fu(self, name):
         return self.fus.get(name)
index 350a611ca9e6fb0cdeda4c1f3603dfc552793a48..133508b704ed89e508a3194ec33ceac9cf5f84f9 100644 (file)
@@ -28,12 +28,12 @@ class MaskGenTestCase(FHDLTestCase):
             yield
             while True:
                 yield
-                rd_rel = yield dut.rd.rel
+                rd_rel = yield dut.rd.rel_o
                 if rd_rel != 0:
                     break
-            yield dut.rd.go.eq(0xfff)
+            yield dut.rd.go_i.eq(0xfff)
             yield
-            yield dut.rd.go.eq(0)
+            yield dut.rd.go_i.eq(0)
             for i in range(10):
                 yield
                 
index 9882a47ee1306cc59cbe382a2c77e44e054d71f1..7885b9f74daea6bbb464ddec6e130f45edcbb225 100644 (file)
@@ -11,6 +11,7 @@ from openpower.decoder.power_decoder import create_pdecode
 from openpower.decoder.power_decoder2 import PowerDecode2, get_rdflags
 from openpower.decoder.power_enums import Function
 from openpower.decoder.isa.all import ISA
+from openpower.decoder.isa.mem import Mem
 
 from soc.experiment.compalu_multi import find_ok  # hack
 from soc.config.test.test_loadstore import TestMemPspec
@@ -137,15 +138,17 @@ def get_l0_mem(l0):  # BLECH! this is awful! hunting around through structures
     return mem.mem
 
 
-def setup_tst_memory(l0, sim):
+def setup_tst_memory(l0, test_mem):
+    # create independent Sim Mem from test values
+    sim_mem = Mem(initial_mem=test_mem)
     mem = get_l0_mem(l0)
     print("before, init mem", mem.depth, mem.width, mem)
     for i in range(mem.depth):
-        data = sim.mem.ld(i*8, 8, False)
+        data = sim_mem.ld(i*8, 8, False)
         print("init ", i, hex(data))
         yield mem._array[i].eq(data)
     yield Settle()
-    for k, v in sim.mem.mem.items():
+    for k, v in sim_mem.mem.items():
         print("    %6x %016x" % (k, v))
     print("before, nmigen mem dump")
     for i in range(mem.depth):
@@ -199,7 +202,7 @@ class TestRunner(FHDLTestCase):
 
         # initialise memory
         if self.funit == Function.LDST:
-            yield from setup_tst_memory(l0, sim)
+            yield from setup_tst_memory(l0, test.mem)
 
         pc = sim.pc.CIA.value
         index = pc//4
index ab6da5a0dc7d140f4a3cc5e4c0af12ba28776c3a..3b4d968c96df1664bd98666b69d3b7f0def8653c 100644 (file)
@@ -1,7 +1,7 @@
 import unittest
 from openpower.decoder.power_enums import (XER_bits, Function)
 
-from soc.fu.div.test.test_pipe_caller import get_cu_inputs
+from soc.fu.div.test.helper import get_cu_inputs
 from soc.fu.div.test.test_pipe_caller import DivTestCases  # creates the tests
 
 from openpower.test.common import ALUHelpers
index ec56e1fe3e63f03c21b4f6ccb9ac342754b40957..bb9d8d8490235901a78cb1dd3fee08fda5c66ed3 100644 (file)
@@ -59,8 +59,14 @@ def set_alu_inputs(alu, dec2, sim, has_third_input):
         overflow = pia.OverflowFlags(so=bool(so),
                                      ov=False,
                                      ov32=False)
+    immediate_ok = yield dec2.e.do.imm_data.ok
+    if immediate_ok:
+        immediate = yield dec2.e.do.imm_data.data
+    else:
+        immediate = None
     rc = inp["rc"] if has_third_input else None
     return pia.InstructionInput(ra=inp.get("ra"), rb=inp.get("rb"),
+                                immediate=immediate,
                                 rc=rc, overflow=overflow)
 
 
@@ -103,15 +109,7 @@ class MulTestHelper(unittest.TestCase):
             opname = code.split(' ')[0]
             fnname = opname.replace(".", "_")
             print(f"{fnname}({pia_inputs})")
-            pia_res = None
-            try:
-                pia_res = getattr(pia, fnname)(pia_inputs)
-            except AttributeError:
-                EXPECTED_FAILURES = ["mulli"]
-                if fnname not in EXPECTED_FAILURES:
-                    raise
-                else:
-                    print("not implemented, as expected.")
+            pia_res = getattr(pia, fnname)(pia_inputs)
             print(f"-> {pia_res}")
 
             yield from isa_sim.call(opname)
index dad804d4e2fbd7471821805690d999c54f9726a9..b13b5ebeaa4a9a09934c6e02a0017c7cc0bfbdd5 100644 (file)
@@ -753,6 +753,9 @@ class TestIssuerInternal(Elaboratable):
                     # and svp64 bit-rev'd ldst mode
                     ldst_dec = pdecode2.use_svp64_ldst_dec
                     sync += core.use_svp64_ldst_dec.eq(ldst_dec)
+                # after decoding, reset any previous exception condition,
+                # allowing it to be set again during the next execution
+                sync += pdecode2.ldst_exc.eq(0)
 
                 m.next = "INSN_EXECUTE"  # move to "execute"
 
@@ -768,11 +771,8 @@ class TestIssuerInternal(Elaboratable):
                 with m.If(~dbg.core_stop_o & ~core_rst):
                     comb += exec_pc_i_ready.eq(1)
                     # see https://bugs.libre-soc.org/show_bug.cgi?id=636
-                    #with m.If(exec_pc_o_valid & exc_happened):
-                    #    probably something like this:
-                    #    sync += pdecode2.ldst_exc.eq(core.fus.get_exc("ldst0")
-                    # TODO: the exception info needs to be blatted
-                    # into pdecode.ldst_exc, and the instruction "re-run".
+                    # the exception info needs to be blatted into
+                    # pdecode.ldst_exc, and the instruction "re-run".
                     # when ldst_exc.happened is set, the PowerDecoder2
                     # reacts very differently: it re-writes the instruction
                     # with a "trap" (calls PowerDecoder2.trap()) which
@@ -780,18 +780,25 @@ class TestIssuerInternal(Elaboratable):
                     # PC to the exception address, as well as alter MSR.
                     # nothing else needs to be done other than to note
                     # the change of PC and MSR (and, later, SVSTATE)
-                    #with m.Elif(exec_pc_o_valid):
-                    with m.If(exec_pc_o_valid): # replace with Elif (above)
+                    with m.If(exc_happened):
+                        sync += pdecode2.ldst_exc.eq(core.fus.get_exc("ldst0"))
+
+                    with m.If(exec_pc_o_valid):
 
                         # was this the last loop iteration?
                         is_last = Signal()
                         cur_vl = cur_state.svstate.vl
                         comb += is_last.eq(next_srcstep == cur_vl)
 
+                        # return directly to Decode if Execute generated an
+                        # exception.
+                        with m.If(pdecode2.ldst_exc.happened):
+                            m.next = "DECODE_SV"
+
                         # if either PC or SVSTATE were changed by the previous
                         # instruction, go directly back to Fetch, without
                         # updating either PC or SVSTATE
-                        with m.If(pc_changed | sv_changed):
+                        with m.Elif(pc_changed | sv_changed):
                             m.next = "ISSUE_START"
 
                         # also return to Fetch, when no output was a vector
@@ -888,7 +895,18 @@ class TestIssuerInternal(Elaboratable):
                 with m.If(~core_busy_o): # instruction done!
                     comb += exec_pc_o_valid.eq(1)
                     with m.If(exec_pc_i_ready):
-                        comb += self.insn_done.eq(1)
+                        # when finished, indicate "done".
+                        # however, if there was an exception, the instruction
+                        # is *not* yet done.  this is an implementation
+                        # detail: we choose to implement exceptions by
+                        # taking the exception information from the LDST
+                        # unit, putting that *back* into the PowerDecoder2,
+                        # and *re-running the entire instruction*.
+                        # if we erroneously indicate "done" here, it is as if
+                        # there were *TWO* instructions:
+                        # 1) the failed LDST 2) a TRAP.
+                        with m.If(~pdecode2.ldst_exc.happened):
+                            comb += self.insn_done.eq(1)
                         m.next = "INSN_START"  # back to fetch
 
     def setup_peripherals(self, m):
index a35545024e23ba05a8ad71ac96e2500e0c5b4612..c15732d1b5582e2439ed19d4260c25d0c6d22562 100644 (file)
@@ -3,12 +3,17 @@
 related bugs:
 
  * https://bugs.libre-soc.org/show_bug.cgi?id=363
+ * https://bugs.libre-soc.org/show_bug.cgi?id=686
 """
+
 from nmigen import Module, Signal, Cat
 from nmigen.back.pysim import Simulator, Delay, Settle
 from nmutil.formaltest import FHDLTestCase
 from nmigen.cli import rtlil
 import unittest
+from openpower.test.state import (SimState, teststate_check_regs,
+                                  teststate_check_mem)
+from soc.simple.test.teststate import HDLState
 from openpower.decoder.isa.caller import special_sprs
 from openpower.decoder.power_decoder import create_pdecode
 from openpower.decoder.power_decoder2 import PowerDecode2
@@ -40,14 +45,16 @@ from openpower.util import spr_to_fast_reg
 # list of SPRs that are controlled and managed by the MMU
 mmu_sprs = ["PRTBL", "DSISR", "DAR", "PIDR"]
 
-def set_mmu_spr(name, i, val, core): #important keep pep8 formatting
-        fsm = core.fus.get_fu("mmu0").alu
-        yield fsm.mmu.l_in.mtspr.eq(1)
-        yield fsm.mmu.l_in.sprn.eq(i)
-        yield fsm.mmu.l_in.rs.eq(val)
-        yield
-        yield fsm.mmu.l_in.mtspr.eq(0)
-        print("mmu_spr was updated")
+
+def set_mmu_spr(name, i, val, core):  # important keep pep8 formatting
+    fsm = core.fus.get_fu("mmu0").alu
+    yield fsm.mmu.l_in.mtspr.eq(1)
+    yield fsm.mmu.l_in.sprn.eq(i)
+    yield fsm.mmu.l_in.rs.eq(val)
+    yield
+    yield fsm.mmu.l_in.mtspr.eq(0)
+    print("mmu_spr was updated")
+
 
 def setup_regs(pdecode2, core, test):
 
@@ -67,7 +74,7 @@ def setup_regs(pdecode2, core, test):
     print("setup cr reg", hex(cr))
     for i in range(8):
         #j = 7-i
-        cri = (cr >> (i*4)) & 0xf
+        cri = (cr >> (i * 4)) & 0xf
         #cri = int('{:04b}'.format(cri)[::-1], 2)
         print("setup cr reg", hex(cri), i,
               crregs.regs[i].reg.shape())
@@ -117,7 +124,7 @@ def setup_regs(pdecode2, core, test):
                 if sprname == x.name:
                     print("setting slow SPR %d (%s) to %x" %
                           (i, sprname, val))
-                    if not sprname in mmu_sprs:
+                    if sprname not in mmu_sprs:
                         yield sregs.memory._array[i].eq(val)
                     else:
                         yield from set_mmu_spr(sprname, i, val, core)
@@ -145,61 +152,15 @@ def setup_regs(pdecode2, core, test):
 
 
 def check_regs(dut, sim, core, test, code):
-    # int regs
-    intregs = []
-    for i in range(32):
-        if core.regs.int.unary:
-            rval = yield core.regs.int.regs[i].reg
-        else:
-            rval = yield core.regs.int.memory._array[i]
-        intregs.append(rval)
-    print("int regs", list(map(hex, intregs)))
-    for i in range(32):
-        simregval = sim.gpr[i].asint()
-        dut.assertEqual(simregval, intregs[i],
-                        "int reg %d not equal %s. got %x expected %x" % \
-                            (i, repr(code), simregval, intregs[i]))
-
-    # CRs
-    crregs = []
-    for i in range(8):
-        rval = yield core.regs.cr.regs[i].reg
-        crregs.append(rval)
-    print("cr regs", list(map(hex, crregs)))
-    for i in range(8):
-        rval = crregs[i]
-        cri = sim.crl[7-i].get_range().value
-        print("cr reg", i, hex(cri), i, hex(rval))
-        # XXX https://bugs.libre-soc.org/show_bug.cgi?id=363
-        dut.assertEqual(cri, rval,
-                        "cr reg %d not equal %s" % (i, repr(code)))
-
-    # XER
-    xregs = core.regs.xer
-    so = yield xregs.regs[xregs.SO].reg
-    ov = yield xregs.regs[xregs.OV].reg
-    ca = yield xregs.regs[xregs.CA].reg
-
-    print("sim SO", sim.spr['XER'][XER_bits['SO']])
-    e_so = sim.spr['XER'][XER_bits['SO']].value
-    e_ov = sim.spr['XER'][XER_bits['OV']].value
-    e_ov32 = sim.spr['XER'][XER_bits['OV32']].value
-    e_ca = sim.spr['XER'][XER_bits['CA']].value
-    e_ca32 = sim.spr['XER'][XER_bits['CA32']].value
-
-    e_ov = e_ov | (e_ov32 << 1)
-    e_ca = e_ca | (e_ca32 << 1)
+    # create the two states and compare
+    testdic = {'sim': sim, 'hdl': core}
+    yield from teststate_check_regs(dut, testdic, test, code)
 
-    print("after: so/ov-32/ca-32", so, bin(ov), bin(ca))
-    dut.assertEqual(e_so, so, "so mismatch %s" % (repr(code)))
-    dut.assertEqual(e_ov, ov, "ov mismatch %s" % (repr(code)))
-    dut.assertEqual(e_ca, ca, "ca mismatch %s" % (repr(code)))
 
-    # Check the PC as well
-    state = core.regs.state
-    pc = yield state.r_ports['cia'].o_data
-    e_pc = sim.pc.CIA.value
-    dut.assertEqual(e_pc, pc)
+def check_mem(dut, sim, core, test, code):
+    # create the two states and compare mem
+    testdic = {'sim': sim, 'hdl': core}
+    yield from teststate_check_mem(dut, testdic, test, code)
 
 
 def wait_for_busy_hi(cu):
@@ -271,51 +232,52 @@ class TestRunner(FHDLTestCase):
             for test in self.test_data:
                 print(test.name)
                 program = test.program
-                self.subTest(test.name)
-                sim = ISA(pdecode2, test.regs, test.sprs, test.cr, test.mem,
-                          test.msr,
-                          bigendian=bigendian)
-                gen = program.generate_instructions()
-                instructions = list(zip(gen, program.assembly.splitlines()))
-
-                yield from setup_tst_memory(l0, sim)
-                yield from setup_regs(core, test)
-
-                index = sim.pc.CIA.value//4
-                while index < len(instructions):
-                    ins, code = instructions[index]
-
-                    print("instruction: 0x{:X}".format(ins & 0xffffffff))
-                    print(code)
-
-                    # ask the decoder to decode this binary data (endian'd)
-                    yield core.bigendian_i.eq(bigendian)  # little / big?
-                    yield instruction.eq(ins)          # raw binary instr.
-                    yield ivalid_i.eq(1)
-                    yield Settle()
-                    # fn_unit = yield pdecode2.e.fn_unit
-                    #fuval = self.funit.value
-                    #self.assertEqual(fn_unit & fuval, fuval)
-
-                    # set operand and get inputs
-                    yield from set_issue(core, pdecode2, sim)
-                    yield Settle()
-
-                    yield from wait_for_busy_clear(core)
-                    yield ivalid_i.eq(0)
-                    yield
-
-                    print("sim", code)
-                    # call simulated operation
-                    opname = code.split(' ')[0]
-                    yield from sim.call(opname)
-                    index = sim.pc.CIA.value//4
-
-                    # register check
-                    yield from check_regs(self, sim, core, test, code)
-
-                    # Memory check
-                    yield from check_sim_memory(self, l0, sim, code)
+                with self.subTest(test.name):
+                    sim = ISA(pdecode2, test.regs, test.sprs, test.cr,
+                              test.mem,
+                              test.msr,
+                              bigendian=bigendian)
+                    gen = program.generate_instructions()
+                    instructions = list(zip(gen, program.assembly.splitlines()))
+
+                    yield from setup_tst_memory(l0, test.mem)
+                    yield from setup_regs(core, test)
+
+                    index = sim.pc.CIA.value // 4
+                    while index < len(instructions):
+                        ins, code = instructions[index]
+
+                        print("instruction: 0x{:X}".format(ins & 0xffffffff))
+                        print(code)
+
+                        # ask the decoder to decode this binary data (endian'd)
+                        yield core.bigendian_i.eq(bigendian)  # little / big?
+                        yield instruction.eq(ins)          # raw binary instr.
+                        yield ivalid_i.eq(1)
+                        yield Settle()
+                        # fn_unit = yield pdecode2.e.fn_unit
+                        #fuval = self.funit.value
+                        #self.assertEqual(fn_unit & fuval, fuval)
+
+                        # set operand and get inputs
+                        yield from set_issue(core, pdecode2, sim)
+                        yield Settle()
+
+                        yield from wait_for_busy_clear(core)
+                        yield ivalid_i.eq(0)
+                        yield
+
+                        print("sim", code)
+                        # call simulated operation
+                        opname = code.split(' ')[0]
+                        yield from sim.call(opname)
+                        index = sim.pc.CIA.value // 4
+
+                        # register check
+                        yield from check_regs(self, sim, core, test, code)
+
+                        # Memory check
+                        yield from check_mem(self, sim, core, test, code)
 
         sim.add_sync_process(process)
         with sim.write_vcd("core_simulator.vcd", "core_simulator.gtkw",
index ebc529fcada9f0a3b60d2fee463890f477955f21..c01e8c68c5c68e4c107c18337f66fcdacf041194 100644 (file)
@@ -23,12 +23,13 @@ from openpower.test.alu.alu_cases import ALUTestCase
 from openpower.test.div.div_cases import DivTestCases
 from openpower.test.logical.logical_cases import LogicalTestCase
 from openpower.test.shift_rot.shift_rot_cases import ShiftRotTestCase
+from openpower.test.shift_rot.shift_rot_cases2 import ShiftRotTestCase2
 from openpower.test.cr.cr_cases import CRTestCase
 from openpower.test.branch.branch_cases import BranchTestCase
-from soc.fu.spr.test.test_pipe_caller import SPRTestCase
+from soc.fu.spr.test.test_pipe_caller import SPRTestCase
 from openpower.test.ldst.ldst_cases import LDSTTestCase
 from openpower.simulator.test_sim import (GeneralTestCases, AttnTestCase)
-from openpower.simulator.test_helloworld_sim import HelloTestCases
+from openpower.simulator.test_helloworld_sim import HelloTestCases
 
 
 if __name__ == "__main__":
@@ -38,21 +39,39 @@ if __name__ == "__main__":
             svp64 = False
         sys.argv.pop()
 
-    print ("SVP64 test mode enabled", svp64)
+    # allow list of testing to be selected by command-line
+    testing = sys.argv[1:]
+    sys.argv = sys.argv[:1]
+
+    if not testing:
+        testing = ['general', 'ldst', 'cr', 'shiftrot', 'shiftrot2',
+                   'logical', 'alu',
+                   'branch', 'div']
+
+    print ("SVP64 test mode enabled", svp64, testing)
 
     unittest.main(exit=False)
     suite = unittest.TestSuite()
-    # suite.addTest(TestRunner(HelloTestCases.test_data, svp64=svp64))
-    suite.addTest(TestRunner(DivTestCases().test_data, svp64=svp64))
-    # suite.addTest(TestRunner(AttnTestCase.test_data, svp64=svp64))
-    suite.addTest(TestRunner(GeneralTestCases.test_data, svp64=svp64))
-    suite.addTest(TestRunner(LDSTTestCase().test_data, svp64=svp64))
-    suite.addTest(TestRunner(CRTestCase().test_data, svp64=svp64))
-    suite.addTest(TestRunner(ShiftRotTestCase().test_data, svp64=svp64))
-    suite.addTest(TestRunner(LogicalTestCase().test_data, svp64=svp64))
-    suite.addTest(TestRunner(ALUTestCase().test_data, svp64=svp64))
-    suite.addTest(TestRunner(BranchTestCase().test_data, svp64=svp64))
-    # suite.addTest(TestRunner(SPRTestCase.test_data, svp64=svp64))
+
+    # dictionary  of data for tests
+    tests = {'hello': HelloTestCases.test_data,
+             'div': DivTestCases().test_data,
+             'attn': AttnTestCase.test_data,
+             'general': GeneralTestCases.test_data,
+             'ldst': LDSTTestCase().test_data,
+             'cr': CRTestCase().test_data,
+             'shiftrot': ShiftRotTestCase().test_data,
+             'shiftrot2': ShiftRotTestCase2().test_data,
+             'logical': LogicalTestCase().test_data,
+             'alu': ALUTestCase().test_data,
+             'branch': BranchTestCase().test_data,
+             'spr': SPRTestCase().test_data
+            }
+
+    # walk through all tests, those requested get added
+    for tname, data in tests.items():
+        if tname in testing:
+            suite.addTest(TestRunner(data, svp64=svp64))
 
     runner = unittest.TextTestRunner()
     runner.run(suite)
index a45071f858517e3f9d4781e51cac7029f1209e7d..688de4b16490c79be9422879e23f669c68cacbf5 100644 (file)
@@ -50,8 +50,6 @@ if __name__ == "__main__":
                               microwatt_mmu=True))
 
     # LD/ST exception cases
-    # TODO: Depends on TestIssuer passing the exception condition to
-    #       PowerDecoder2
     suite.addTest(TestRunner(LDSTExceptionTestCase().test_data, svp64=svp64,
                               microwatt_mmu=True))
 
index 7e5013652907ef0509f759dac0c98630bf32a059..1dd89c533d19d5f9f28c9d190fb48ce30000bf29 100644 (file)
@@ -15,8 +15,7 @@ from soc.config.test.test_loadstore import TestMemPspec
 from soc.simple.test.test_core import (setup_regs, check_regs,
                                        wait_for_busy_clear,
                                        wait_for_busy_hi)
-from soc.fu.compunits.test.test_compunit import (setup_tst_memory,
-                                                 check_sim_memory,
+from soc.fu.compunits.test.test_compunit import (check_sim_memory,
                                                  get_l0_mem)
 
 from soc.simple.test.test_runner import setup_i_memory
@@ -112,7 +111,6 @@ class TestRunner(FHDLTestCase):
                 # blech!  put the same listing into the data memory
                 data_mem = get_l0_mem(l0)
                 yield from setup_i_memory(data_mem, pc, instructions)
-                # yield from setup_tst_memory(l0, sim)
                 yield from setup_regs(core, test)
 
                 yield pc_i.eq(pc)
index 1d792fe51b6094a4172deb35e05c8b39f3b599f9..a8898bf5caaefdae9b03fbd891e6c8b4de6c4519 100644 (file)
@@ -3,9 +3,11 @@
 related bugs:
 
  * https://bugs.libre-soc.org/show_bug.cgi?id=363
+ * https://bugs.libre-soc.org/show_bug.cgi?id=686#c51
 """
 from nmigen import Module, Signal, Cat, ClockSignal
 from nmigen.hdl.xfrm import ResetInserter
+from copy import copy
 
 # NOTE: to use cxxsim, export NMIGEN_SIM_MODE=cxxsim from the shell
 # Also, check out the cxxsim nmigen branch, and latest yosys from git
@@ -25,7 +27,7 @@ from soc.regfile.regfiles import StateRegs
 from soc.simple.issuer import TestIssuerInternal
 
 from soc.config.test.test_loadstore import TestMemPspec
-from soc.simple.test.test_core import (setup_regs, check_regs,
+from soc.simple.test.test_core import (setup_regs, check_regs, check_mem,
                                        wait_for_busy_clear,
                                        wait_for_busy_hi)
 from soc.fu.compunits.test.test_compunit import (setup_tst_memory,
@@ -33,6 +35,7 @@ from soc.fu.compunits.test.test_compunit import (setup_tst_memory,
 from soc.debug.dmi import DBGCore, DBGCtrl, DBGStat
 from nmutil.util import wrap
 from soc.experiment.test.test_mmu_dcache import wb_get
+from openpower.test.state import TestState, StateRunner
 
 
 def setup_i_memory(imem, startaddr, instructions):
@@ -121,21 +124,170 @@ def get_dmi(dmi, addr):
     return data
 
 
+def run_hdl_state(dut, test, issuer, pc_i, svstate_i, instructions):
+    """run_hdl_state - runs a TestIssuer nmigen HDL simulation
+    """
+
+    imem = issuer.imem._get_memory()
+    core = issuer.core
+    dmi = issuer.dbg.dmi
+    pdecode2 = issuer.pdecode2
+    l0 = core.l0
+    hdl_states = []
+
+    # establish the TestIssuer context (mem, regs etc)
+
+    pc = 0  # start address
+    counter = 0  # test to pause/start
+
+    yield from setup_i_memory(imem, pc, instructions)
+    yield from setup_tst_memory(l0, test.mem)
+    yield from setup_regs(pdecode2, core, test)
+
+    # set PC and SVSTATE
+    yield pc_i.eq(pc)
+    yield issuer.pc_i.ok.eq(1)
+
+    # copy initial SVSTATE
+    initial_svstate = copy(test.svstate)
+    if isinstance(initial_svstate, int):
+        initial_svstate = SVP64State(initial_svstate)
+    yield svstate_i.eq(initial_svstate.value)
+    yield issuer.svstate_i.ok.eq(1)
+    yield
+
+    print("instructions", instructions)
+
+    # run the loop of the instructions on the current test
+    index = (yield issuer.cur_state.pc) // 4
+    while index < len(instructions):
+        ins, code = instructions[index]
+
+        print("hdl instr: 0x{:X}".format(ins & 0xffffffff))
+        print(index, code)
+
+        if counter == 0:
+            # start the core
+            yield
+            yield from set_dmi(dmi, DBGCore.CTRL,
+                               1<<DBGCtrl.START)
+            yield issuer.pc_i.ok.eq(0) # no change PC after this
+            yield issuer.svstate_i.ok.eq(0) # ditto
+            yield
+            yield
+
+        counter = counter + 1
+
+        # wait until executed
+        while not (yield issuer.insn_done):
+            yield
+
+        yield Settle()
+
+        index = (yield issuer.cur_state.pc) // 4
+
+        terminated = yield issuer.dbg.terminated_o
+        print("terminated", terminated)
+
+        if index < len(instructions):
+            # Get HDL mem and state
+            state = yield from TestState("hdl", core, dut,
+                                         code)
+            hdl_states.append(state)
+
+        if index >= len(instructions):
+            print ("index over, send dmi stop")
+            # stop at end
+            yield from set_dmi(dmi, DBGCore.CTRL,
+                               1<<DBGCtrl.STOP)
+            yield
+            yield
+
+        terminated = yield issuer.dbg.terminated_o
+        print("terminated(2)", terminated)
+        if terminated:
+            break
+
+    return hdl_states
+
+
+def run_sim_state(dut, test, simdec2, instructions, gen, insncode):
+    """run_sim_state - runs an ISACaller simulation
+    """
+
+    sim_states = []
+
+    # set up the Simulator (which must track TestIssuer exactly)
+    sim = ISA(simdec2, test.regs, test.sprs, test.cr, test.mem,
+              test.msr,
+              initial_insns=gen, respect_pc=True,
+              disassembly=insncode,
+              bigendian=bigendian,
+              initial_svstate=test.svstate)
+
+    # run the loop of the instructions on the current test
+    index = sim.pc.CIA.value//4
+    while index < len(instructions):
+        ins, code = instructions[index]
+
+        print("sim instr: 0x{:X}".format(ins & 0xffffffff))
+        print(index, code)
+
+        # set up simulated instruction (in simdec2)
+        try:
+            yield from sim.setup_one()
+        except KeyError:  # instruction not in imem: stop
+            break
+        yield Settle()
+
+        # call simulated operation
+        print("sim", code)
+        yield from sim.execute_one()
+        yield Settle()
+        index = sim.pc.CIA.value//4
+
+        # get sim register and memory TestState, add to list
+        state = yield from TestState("sim", sim, dut, code)
+        sim_states.append(state)
+
+    return sim_states
+
+
+class SimRunner(StateRunner):
+    def __init__(self, dut, m, pspec):
+        self.dut = dut
+
+        regreduce_en = pspec.regreduce_en == True
+        self.simdec2 = simdec2 = PowerDecode2(None, regreduce_en=regreduce_en)
+        m.submodules.simdec2 = simdec2  # pain in the neck
+
+
+class HDLRunner(StateRunner):
+    def __init__(self, dut, m, pspec):
+        self.dut = dut
+        #hard_reset = Signal(reset_less=True)
+        self.issuer = TestIssuerInternal(pspec)
+        # use DMI RESET command instead, this does actually work though
+        #issuer = ResetInserter({'coresync': hard_reset,
+        #                        'sync': hard_reset})(issuer)
+        m.submodules.issuer = self.issuer
+        self.dmi = self.issuer.dbg.dmi
+
+
 class TestRunner(FHDLTestCase):
     def __init__(self, tst_data, microwatt_mmu=False, rom=None,
-                        svp64=True):
+                        svp64=True, run_hdl=True, run_sim=True):
         super().__init__("run_all")
         self.test_data = tst_data
         self.microwatt_mmu = microwatt_mmu
         self.rom = rom
         self.svp64 = svp64
+        self.run_hdl = run_hdl
+        self.run_sim = run_sim
 
     def run_all(self):
         m = Module()
         comb = m.d.comb
-        pc_i = Signal(32)
-        svstate_i = Signal(64)
-
         if self.microwatt_mmu:
             ldst_ifacetype = 'test_mmu_cache_wb'
         else:
@@ -156,56 +308,64 @@ class TestRunner(FHDLTestCase):
                              svp64=self.svp64,
                              mmu=self.microwatt_mmu,
                              reg_wid=64)
-        #hard_reset = Signal(reset_less=True)
-        issuer = TestIssuerInternal(pspec)
-        # use DMI RESET command instead, this does actually work though
-        #issuer = ResetInserter({'coresync': hard_reset,
-        #                        'sync': hard_reset})(issuer)
-        m.submodules.issuer = issuer
-        imem = issuer.imem._get_memory()
-        core = issuer.core
-        dmi = issuer.dbg.dmi
-        pdecode2 = issuer.pdecode2
-        l0 = core.l0
-        regreduce_en = pspec.regreduce_en == True
 
-        #simdec = create_pdecode()
-        simdec2 = PowerDecode2(None, regreduce_en=regreduce_en)
-        m.submodules.simdec2 = simdec2  # pain in the neck
+        ###### SETUP PHASE #######
+        # StateRunner.setup_for_test()
+
+        if self.run_hdl:
+            hdlrun = HDLRunner(self, m, pspec)
+
+        if self.run_sim:
+            simrun = SimRunner(self, m, pspec)
 
         # run core clock at same rate as test clock
         intclk = ClockSignal("coresync")
         comb += intclk.eq(ClockSignal())
 
-        comb += issuer.pc_i.data.eq(pc_i)
-        comb += issuer.svstate_i.data.eq(svstate_i)
+        if self.run_hdl:
 
-        # nmigen Simulation
+            pc_i = Signal(32)
+            svstate_i = Signal(64)
+
+            comb += hdlrun.issuer.pc_i.data.eq(pc_i)
+            comb += hdlrun.issuer.svstate_i.data.eq(svstate_i)
+
+        # nmigen Simulation - everything runs around this, so it
+        # still has to be created.
         sim = Simulator(m)
         sim.add_clock(1e-6)
 
         def process():
 
-            # start in stopped
-            yield from set_dmi(dmi, DBGCore.CTRL, 1<<DBGCtrl.STOP)
-            yield
+            ###### PREPARATION PHASE AT START OF RUNNING #######
+            # StateRunner.setup_during_test()
+
+            if self.run_hdl:
+                # start in stopped
+                yield from set_dmi(hdlrun.dmi, DBGCore.CTRL, 1<<DBGCtrl.STOP)
+                yield
 
             # get each test, completely reset the core, and run it
 
             for test in self.test_data:
 
-                # set up bigendian (TODO: don't do this, use MSR)
-                yield issuer.core_bigendian_i.eq(bigendian)
-                yield Settle()
+                with self.subTest(test.name):
 
-                yield
-                yield
-                yield
-                yield
+                    ###### PREPARATION PHASE AT START OF TEST #######
+                    # StateRunner.prepare_for_test()
 
-                print(test.name)
-                program = test.program
-                with self.subTest(test.name):
+                    if self.run_hdl:
+                        # set up bigendian (TODO: don't do this, use MSR)
+                        yield hdlrun.issuer.core_bigendian_i.eq(bigendian)
+                        yield Settle()
+
+                        yield
+                        yield
+                        yield
+                        yield
+
+                    print(test.name)
+                    program = test.program
                     print("regs", test.regs)
                     print("sprs", test.sprs)
                     print("cr", test.cr)
@@ -216,119 +376,114 @@ class TestRunner(FHDLTestCase):
                     insncode = program.assembly.splitlines()
                     instructions = list(zip(gen, insncode))
 
-                    # set up the Simulator (which must track TestIssuer exactly)
-                    sim = ISA(simdec2, test.regs, test.sprs, test.cr, test.mem,
-                              test.msr,
-                              initial_insns=gen, respect_pc=True,
-                              disassembly=insncode,
-                              bigendian=bigendian,
-                              initial_svstate=test.svstate)
-
-                    # establish the TestIssuer context (mem, regs etc)
-
-                    pc = 0  # start address
-                    counter = 0  # test to pause/start
-
-                    yield from setup_i_memory(imem, pc, instructions)
-                    yield from setup_tst_memory(l0, sim)
-                    yield from setup_regs(pdecode2, core, test)
-
-                    # set PC and SVSTATE
-                    yield pc_i.eq(pc)
-                    yield issuer.pc_i.ok.eq(1)
-
-                    initial_svstate = test.svstate
-                    if isinstance(initial_svstate, int):
-                        initial_svstate = SVP64State(initial_svstate)
-                    yield svstate_i.eq(initial_svstate.value)
-                    yield issuer.svstate_i.ok.eq(1)
+                    ###### RUNNING OF EACH TEST #######
+                    # StateRunner.step_test()
+
+                    # Run two tests (TODO, move these to functions)
+                    # * first the Simulator, collate a batch of results
+                    # * then the HDL, likewise
+                    #   (actually, the other way round because running
+                    #    Simulator somehow modifies the test state!)
+                    # * finally, compare all the results
+
+                    ##########
+                    # 1. HDL
+                    ##########
+                    if self.run_hdl:
+                        hdl_states = yield from run_hdl_state(self, test,
+                                                              hdlrun.issuer,
+                                                              pc_i, svstate_i,
+                                                              instructions)
+
+                    ##########
+                    # 2. Simulator
+                    ##########
+
+                    if self.run_sim:
+                        sim_states = yield from run_sim_state(self, test,
+                                                          simrun.simdec2,
+                                                          instructions, gen,
+                                                          insncode)
+
+                    ###### COMPARING THE TESTS #######
+
+                    ###############
+                    # 3. Compare
+                    ###############
+
+                    if self.run_sim:
+                        last_sim = copy(sim_states[-1])
+                    elif self.run_hdl:
+                        last_sim = copy(hdl_states[-1])
+                    else:
+                        last_sim = None # err what are you doing??
+
+                    if self.run_hdl and self.run_sim:
+                        for simstate, hdlstate in zip(sim_states, hdl_states):
+                            simstate.compare(hdlstate)     # register check
+                            simstate.compare_mem(hdlstate) # memory check
+
+                    if self.run_hdl:
+                        print ("hdl_states")
+                        for state in hdl_states:
+                            print (state)
+
+                    if self.run_sim:
+                        print ("sim_states")
+                        for state in sim_states:
+                            print (state)
+
+                    # compare against expected results
+                    if test.expected is not None:
+                        # have to put these in manually
+                        test.expected.to_test = test.expected
+                        test.expected.dut = self
+                        test.expected.state_type = "expected"
+                        test.expected.code = 0
+                        # do actual comparison, against last item
+                        last_sim.compare(test.expected)
+
+                    if self.run_hdl and self.run_sim:
+                        self.assertTrue(len(hdl_states) == len(sim_states),
+                                    "number of instructions run not the same")
+
+                ###### END OF A TEST #######
+                # StateRunner.end_test()
+
+                if self.run_hdl:
+                    # stop at end
+                    yield from set_dmi(hdlrun.dmi, DBGCore.CTRL, 1<<DBGCtrl.STOP)
+                    yield
                     yield
 
-                    print("instructions", instructions)
-
-                    # run the loop of the instructions on the current test
-                    index = sim.pc.CIA.value//4
-                    while index < len(instructions):
-                        ins, code = instructions[index]
-
-                        print("instruction: 0x{:X}".format(ins & 0xffffffff))
-                        print(index, code)
-
-                        if counter == 0:
-                            # start the core
-                            yield
-                            yield from set_dmi(dmi, DBGCore.CTRL,
-                                               1<<DBGCtrl.START)
-                            yield issuer.pc_i.ok.eq(0) # no change PC after this
-                            yield issuer.svstate_i.ok.eq(0) # ditto
-                            yield
-                            yield
-
-                        counter = counter + 1
-
-                        # wait until executed
-                        while not (yield issuer.insn_done):
-                            yield
-
-                        # set up simulated instruction (in simdec2)
-                        try:
-                            yield from sim.setup_one()
-                        except KeyError:  # instruction not in imem: stop
-                            break
-                        yield Settle()
-
-                        # call simulated operation
-                        print("sim", code)
-                        yield from sim.execute_one()
-                        yield Settle()
-                        index = sim.pc.CIA.value//4
-
-                        terminated = yield issuer.dbg.terminated_o
-                        print("terminated", terminated)
-
-                        if index >= len(instructions):
-                            print ("index over, send dmi stop")
-                            # stop at end
-                            yield from set_dmi(dmi, DBGCore.CTRL,
-                                               1<<DBGCtrl.STOP)
-                            yield
-                            yield
-
-                        # register check
-                        yield from check_regs(self, sim, core, test, code)
-
-                        # Memory check
-                        yield from check_sim_memory(self, l0, sim, code)
-
-                        terminated = yield issuer.dbg.terminated_o
-                        print("terminated(2)", terminated)
-                        if terminated:
-                            break
+                    # TODO, here is where the static (expected) results
+                    # can be checked: register check (TODO, memory check)
+                    # see https://bugs.libre-soc.org/show_bug.cgi?id=686#c51
+                    # yield from check_regs(self, sim, core, test, code,
+                    #                       >>>expected_data<<<)
 
-                # stop at end
-                yield from set_dmi(dmi, DBGCore.CTRL, 1<<DBGCtrl.STOP)
-                yield
-                yield
+                    # get CR
+                    cr = yield from get_dmi(hdlrun.dmi, DBGCore.CR)
+                    print("after test %s cr value %x" % (test.name, cr))
 
-                # get CR
-                cr = yield from get_dmi(dmi, DBGCore.CR)
-                print("after test %s cr value %x" % (test.name, cr))
+                    # get XER
+                    xer = yield from get_dmi(hdlrun.dmi, DBGCore.XER)
+                    print("after test %s XER value %x" % (test.name, xer))
 
-                # get XER
-                xer = yield from get_dmi(dmi, DBGCore.XER)
-                print("after test %s XER value %x" % (test.name, xer))
+                    # test of dmi reg get
+                    for int_reg in range(32):
+                        yield from set_dmi(hdlrun.dmi, DBGCore.GSPR_IDX, int_reg)
+                        value = yield from get_dmi(hdlrun.dmi, DBGCore.GSPR_DATA)
 
-                # test of dmi reg get
-                for int_reg in range(32):
-                    yield from set_dmi(dmi, DBGCore.GSPR_IDX, int_reg)
-                    value = yield from get_dmi(dmi, DBGCore.GSPR_DATA)
+                        print("after test %s reg %2d value %x" %
+                              (test.name, int_reg, value))
 
-                    print("after test %s reg %2d value %x" %
-                          (test.name, int_reg, value))
+                    # pull a reset
+                    yield from set_dmi(hdlrun.dmi, DBGCore.CTRL, 1<<DBGCtrl.RESET)
+                    yield
 
-                # pull a reset
-                yield from set_dmi(dmi, DBGCore.CTRL, 1<<DBGCtrl.RESET)
-                yield
+        ###### END OF EVERYTHING (but none needs doing, still call fn) #######
+        # StateRunner.cleanup()
 
         styles = {
             'dec': {'base': 'dec'},
@@ -356,7 +511,7 @@ class TestRunner(FHDLTestCase):
                 'cia[63:0]', 'nia[63:0]', 'pc[63:0]',
                 'cur_pc[63:0]', 'core_core_cia[63:0]']),
             'raw_insn_i[31:0]',
-            'raw_opcode_in[31:0]', 'insn_type',
+            'raw_opcode_in[31:0]', 'insn_type', 'dec2.dec2_exc_happened',
             ('svp64 decoding', 'closed', [
                 'svp64_rm[23:0]', ('dec2.extra[8:0]', 'bin'),
                 'dec2.sv_rm_dec.mode', 'dec2.sv_rm_dec.predmode',
diff --git a/src/soc/simple/test/teststate.py b/src/soc/simple/test/teststate.py
new file mode 100644 (file)
index 0000000..3a65c9d
--- /dev/null
@@ -0,0 +1,62 @@
+""" Power ISA test API
+
+This module implements the creation, inspection and comparison
+of test states for TestIssuer HDL
+
+"""
+
+from openpower.decoder.power_enums import XER_bits
+from openpower.util import log
+from openpower.test.state import (State, state_add, state_factory,
+                                  TestState,)
+from soc.fu.compunits.test.test_compunit import get_l0_mem
+
+class HDLState(State):
+    def __init__(self, core):
+        super().__init__()
+        self.core = core
+
+    def get_intregs(self):
+        self.intregs = []
+        for i in range(32):
+            if self.core.regs.int.unary:
+                rval = yield self.core.regs.int.regs[i].reg
+            else:
+                rval = yield self.core.regs.int.memory._array[i]
+            self.intregs.append(rval)
+        log("class hdl int regs", list(map(hex, self.intregs)))
+
+    def get_crregs(self):
+        self.crregs = []
+        for i in range(8):
+            rval = yield self.core.regs.cr.regs[i].reg
+            self.crregs.append(rval)
+        log("class hdl cr regs", list(map(hex, self.crregs)))
+
+    def get_xregs(self):
+        self.xregs = []
+        self.xr = self.core.regs.xer
+        self.so = yield self.xr.regs[self.xr.SO].reg
+        self.ov = yield self.xr.regs[self.xr.OV].reg
+        self.ca = yield self.xr.regs[self.xr.CA].reg
+        self.xregs.extend((self.so, self.ov, self.ca))
+        log("class hdl xregs", list(map(hex, self.xregs)))
+
+    def get_pc(self):
+        self.pcl = []
+        self.state = self.core.regs.state
+        self.pc = yield self.state.r_ports['cia'].o_data
+        self.pcl.append(self.pc)
+        log("class hdl pc", hex(self.pc))
+
+    def get_mem(self):
+        # get the underlying HDL-simulated memory from the L0CacheBuffer
+        hdlmem = get_l0_mem(self.core.l0)
+        self.mem = {}
+        for i in range(hdlmem.depth):
+            value = yield hdlmem._array[i] # should not really do this
+            self.mem[i*8] = value
+
+
+# add to State Factory
+state_add('hdl', HDLState)