begin working on _test_loadstore1_ifetch_invalid() inner function
[soc.git] / src / soc / experiment / test / test_loadstore1.py
index fc909b7c094d7cf154de7ec42fbd72417cd714c5..0e2aa25058580d3383f0858b1394edf8c85776ca 100644 (file)
@@ -8,7 +8,8 @@ from random import randint, seed
 from nmigen.sim import Simulator, Delay, Settle
 from nmutil.util import wrap
 
-from soc.config.test.test_pi2ls import pi_ld, pi_st, pi_ldst, wait_busy
+from soc.config.test.test_pi2ls import (pi_ld, pi_st, pi_ldst, wait_busy,
+                                        get_exception_info)
 #from soc.config.test.test_pi2ls import pi_st_debug
 from soc.config.test.test_loadstore import TestMemPspec
 from soc.config.loadstore import ConfigMemoryPortInterface
@@ -191,9 +192,11 @@ def _test_loadstore1_ifetch(dut, mem):
     yield ldst.instr_fault.eq(0)
     while True:
         done = yield (ldst.done)
-        if done:
+        exc_info = yield from get_exception_info(pi.exc_o)
+        if done or exc_info.happened:
             break
         yield
+    assert exc_info.happened == 0 # assert just before doing the fault set zero
     yield ldst.instr_fault.eq(0)
     yield
     yield
@@ -385,6 +388,110 @@ def _test_loadstore1(dut, mem):
     wbget.stop = True
 
 
+def _test_loadstore1_ifetch_invalid(dut, mem):
+    mmu = dut.submodules.mmu
+    ldst = dut.submodules.ldst
+    pi = ldst.pi
+    icache = dut.submodules.ldst.icache
+    wbget.stop = False
+
+    print("=== test loadstore instruction (invalid) ===")
+
+    i_in = icache.i_in
+    i_out  = icache.i_out
+    i_m_in = icache.m_in
+
+    # first virtual memory test
+
+    print ("set process table")
+    yield mmu.rin.prtbl.eq(0x1000000) # set process table
+    yield
+
+    # set address to zero, update mem[0] to 01234
+    addr = 8
+    expected_insn = 0x1234
+    mem[addr] = expected_insn
+
+    yield i_in.priv_mode.eq(1)
+    yield i_in.req.eq(0)
+    yield i_in.nia.eq(addr)
+    yield i_in.stop_mark.eq(0)
+    yield i_m_in.tlbld.eq(0)
+    yield i_m_in.tlbie.eq(0)
+    yield i_m_in.addr.eq(0)
+    yield i_m_in.pte.eq(0)
+    yield
+    yield
+    yield
+
+    # some more cycles for gtkwave debugging
+    yield
+    yield
+    yield
+
+    wbget.stop = True
+    return
+    # TODO: implement rest
+
+    # miss, stalls for a bit
+    yield i_in.req.eq(1)
+    yield i_in.nia.eq(addr)
+    yield
+    valid = yield i_out.valid
+    while not valid:
+        yield
+        valid = yield i_out.valid
+    yield i_in.req.eq(0)
+
+    nia   = yield i_out.nia
+    insn  = yield i_out.insn
+    yield
+    yield
+
+    print ("fetched %x from addr %x" % (insn, nia))
+    assert insn == expected_insn
+
+    print("=== test loadstore instruction (virtual) ===")
+
+    # look up i-cache expecting it to fail
+
+    # set address to 0x10200, update mem[] to 5678
+    virt_addr = 0x10200
+    real_addr = virt_addr
+    expected_insn = 0x5678
+    mem[real_addr] = expected_insn
+
+    yield i_in.priv_mode.eq(1)
+    yield i_in.virt_mode.eq(1)
+    yield i_in.req.eq(0)
+    yield i_in.nia.eq(virt_addr)
+    yield i_in.stop_mark.eq(0)
+    yield i_m_in.tlbld.eq(0)
+    yield i_m_in.tlbie.eq(0)
+    yield i_m_in.addr.eq(0)
+    yield i_m_in.pte.eq(0)
+    yield
+    yield
+    yield
+
+    # miss, stalls for a bit
+    yield i_in.req.eq(1)
+    yield i_in.nia.eq(virt_addr)
+    yield
+    valid = yield i_out.valid
+    failed = yield i_out.fetch_failed
+    while not valid and not failed:
+        yield
+        valid = yield i_out.valid
+        failed = yield i_out.fetch_failed
+    yield i_in.req.eq(0)
+
+    print ("failed?", "yes" if failed else "no")
+    assert failed == 1
+    yield
+    yield
+
+
 def test_loadstore1_ifetch():
 
     m, cmpi = setup_mmu()
@@ -436,8 +543,28 @@ def test_loadstore1_invalid():
     with sim.write_vcd('test_loadstore1_invalid.vcd'):
         sim.run()
 
+def test_loadstore1_ifetch_invalid():
+    m, cmpi = setup_mmu()
+
+    mem = {}
+
+    # nmigen Simulation
+    sim = Simulator(m)
+    sim.add_clock(1e-6)
+
+    icache = m.submodules.ldst.icache
+    sim.add_sync_process(wrap(_test_loadstore1_ifetch_invalid(m, mem)))
+    # add two wb_get processes onto the *same* memory dictionary.
+    # this shouuuld work.... cross-fingers...
+    sim.add_sync_process(wrap(wb_get(cmpi.wb_bus(), mem)))
+    sim.add_sync_process(wrap(wb_get(icache.bus, mem)))
+    with sim.write_vcd('test_loadstore1_ifetch_invalid.vcd'):
+        sim.run()
+
+
 
 if __name__ == '__main__':
-    test_loadstore1()
-    test_loadstore1_invalid()
-    test_loadstore1_ifetch()
+    #test_loadstore1()
+    #test_loadstore1_invalid()
+    #test_loadstore1_ifetch()
+    test_loadstore1_ifetch_invalid()