Allow the formal engine to perform a same-cycle result in the ALU
[soc.git] / src / soc / experiment / test / test_compldst_multi_mmu.py
index e81799603709846a6d80d420fc19d8f140c75952..f3a3421bcbe76a1a018fe313612b3a9a5f04932f 100644 (file)
@@ -1,7 +1,6 @@
 # test case for LOAD / STORE Computation Unit using MMU
 
-#from nmigen.compat.sim import run_simulation
-from nmigen.sim import Simulator, Delay, Settle
+from nmigen.sim import Simulator, Delay, Settle, Tick
 from nmigen.cli import verilog, rtlil
 from nmigen import Module, Signal, Mux, Cat, Elaboratable, Array, Repl
 from nmigen.hdl.rec import Record, Layout
@@ -27,64 +26,81 @@ from soc.experiment.mmu import MMU
 from nmutil.util import Display
 
 from soc.config.loadstore import ConfigMemoryPortInterface
+from soc.experiment.test import pagetables
+from openpower.test.wb_get import wb_get
+from openpower.test import wb_get as wbget
 
-def b(x): # byte-reverse function
-    return int.from_bytes(x.to_bytes(8, byteorder='little'),
-                          byteorder='big', signed=False)
-#FIXME: move to common module
 
-def wait_for_debug(sig, event, wait=True, test1st=False):
+########################################
+
+def wait_for_debug(sig, reason, wait=True, test1st=False):
     v = (yield sig)
-    print("wait for", sig, v, wait, test1st)
+    cnt = 0
+    print("wait for", reason, sig, v, wait, test1st)
     if test1st and bool(v) == wait:
         return
     while True:
+        cnt = cnt + 1
+        if cnt > 15:
+            raise(Exception(reason))
+            break
         yield
         v = (yield sig)
-        yield Display("waiting for "+event)
+        #print("...wait for", sig, v)
         if bool(v) == wait:
             break
 
-def load_debug(dut, src1, src2, imm, imm_ok=True, update=False, zero_a=False,
-         byterev=True):
-    print("LD", src1, src2, imm, imm_ok, update)
-    yield dut.oper_i.insn_type.eq(MicrOp.OP_LOAD)
+def store_debug(dut, src1, src2, src3, imm, imm_ok=True, update=False,
+          byterev=True,dcbz=False):
+    print("cut here ======================================")
+    print("ST", src1, src2, src3, imm, imm_ok, update)
+    if dcbz:
+        yield dut.oper_i.insn_type.eq(MicrOp.OP_DCBZ)
+    else:
+        yield dut.oper_i.insn_type.eq(MicrOp.OP_STORE)
     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.oper_i.zero_a.eq(zero_a)
+    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)
+    #guess: this one was removed -- 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
+    if dcbz:
+        active_rel = 0b001 # may be wrong, verify
+
+    # wait for all active rel signals to come up
+    cnt = 0
+    while True:
+        rel = yield dut.rd.rel_o # guess: wrong in dcbz case
+        cnt = cnt + 1
+        print("waitActiveRel",cnt)
+        if cnt > 10:
+            raise(Exception("Error1"))
+        print("rel EQ active_rel ?",rel,active_rel)
+        if rel == active_rel:
+            break
+        yield
+    yield dut.rd.go_i.eq(active_rel)
     yield
+    yield dut.rd.go_i.eq(0)
 
-    # set up read-operand flags
-    rd = 0b00
-    if not imm_ok:  # no immediate means RB register needs to be read
-        rd |= 0b10
-    if not zero_a:  # no zero-a means RA needs to be read
-        rd |= 0b01
-
-    # wait for the operands (RA, RB, or both)
-    if rd:
-        yield dut.rd.go_i.eq(rd)
-        yield from wait_for_debug(dut.rd.rel_o,"operands")
-        yield dut.rd.go_i.eq(0)
-
-    yield from wait_for_debug(dut.adr_rel_o, "adr_rel_o" ,False, test1st=True)
-    yield Display("load_debug: done")
+    yield from wait_for_debug(dut.adr_rel_o, "addr valid",False, test1st=True)
+    # yield from wait_for(dut.adr_rel_o)
     # yield dut.ad.go.eq(1)
     # yield
     # yield dut.ad.go.eq(0)
 
-    """
-    guess: hangs here
-
     if update:
-        yield from wait_for(dut.wr.rel_o[1])
+        yield from wait_for_debug(dut.wr.rel_o[1],"update")
         yield dut.wr.go.eq(0b10)
         yield
         addr = yield dut.addr_o
@@ -92,60 +108,78 @@ def load_debug(dut, src1, src2, imm, imm_ok=True, update=False, zero_a=False,
         yield dut.wr.go.eq(0)
     else:
         addr = None
+        print("not update ===============")
 
-    yield from wait_for(dut.wr.rel_o[0], test1st=True)
-    yield dut.wr.go.eq(1)
+    yield from wait_for_debug(dut.sto_rel_o,"sto_rel_o")
+    yield dut.go_st_i.eq(1)
     yield
-    data = yield dut.o_data
-    print(data)
-    yield dut.wr.go.eq(0)
-    yield from wait_for(dut.busy_o)
+    yield dut.go_st_i.eq(0)
+    yield from wait_for_debug(dut.busy_o,"not_busy" ,False)
+    ###wait_for(dut.stwd_mem_o)
     yield
-    # wait_for(dut.stwd_mem_o)
-    return data, addr
-    """
-
-# removed
+    return addr
 
 # same thing as soc/src/soc/experiment/test/test_dcbz_pi.py
 def ldst_sim(dut):
     yield dut.mmu.rin.prtbl.eq(0x1000000) # set process table
-    ###yield from dcbz(dut, 4, 0, 3) # EA=7
     addr = 0x100e0
-    data = 0xf553b658ba7e1f51
+    data = 0xFF #just a single byte for this test
+    #data = 0xf553b658ba7e1f51
 
     yield from store(dut, addr, 0, data, 0)
     yield
-    yield from load_debug(dut, 4, 0, 2) #FIXME
-    """
-    ld_data = yield from pi_ld(pi, addr, 8, msr_pr=0)
-    assert ld_data == 0xf553b658ba7e1f51
-    ld_data = yield from pi_ld(pi, addr, 8, msr_pr=0)
-    assert ld_data == 0xf553b658ba7e1f51
-    """
+    ld_data, data_ok, ld_addr = yield from load(dut, addr, 0, 0)
+    print(data,data_ok,ld_addr)
+    assert(ld_data==data)
     yield
 
-########################################
+    data = 0
+
+    print("doing dcbz/store with data 0 .....")
+    yield from store_debug(dut, addr, 0, data, 0, dcbz=True) #hangs
 
+    ld_data, data_ok, ld_addr = yield from load(dut, addr, 0, 0)
+    print(data,data_ok,ld_addr)
+    print("ld_data is")
+    print(ld_data)
+    assert(ld_data==data)
+    print("dzbz test passed")
 
+    wbget.stop = True # stop simulation
+
+########################################
 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)
+        # use a LoadStore1 here
+        cmpi = ConfigMemoryPortInterface(pspec)
+        self.cmpi = cmpi
+        ldst = cmpi.pi
+        self.l0 = ldst
+
+        self.mmu = MMU()
+        LDSTCompUnit.__init__(self, ldst.pi, rwid, 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.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_mmu():
 
+    m = Module()
+
     units = {}
     pspec = TestMemPspec(ldst_ifacetype='mmu_cache_wb',
                          imem_ifacetype='bare_wb',
@@ -155,24 +189,28 @@ def test_scoreboard_mmu():
                          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')
-    #TODO add wb runner here
+    m.submodules.dut = dut
+
+    sim = Simulator(m)
+    sim.add_clock(1e-6)
 
+    dut.mem = pagetables.test1
+    wbget.stop = False
+
+    sim.add_sync_process(wrap(ldst_sim(dut)))
+    sim.add_sync_process(wrap(wb_get(dut.cmpi.wb_bus(), dut.mem)))
+    with sim.write_vcd('test_scoreboard_mmu.vcd'):
+        sim.run()
 
 ########################################
 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
 
         # use a LoadStore1 here
-
         cmpi = ConfigMemoryPortInterface(pspec)
         self.cmpi = cmpi
         ldst = cmpi.pi
@@ -196,56 +234,8 @@ class TestLDSTCompUnitRegSpecMMU(LDSTCompUnit):
 
         return m
 
-# FIXME: this is redundant code
-def wb_get(wb, mem):
-    """simulator process for getting memory load requests
-    """
-
-    global stop
-    assert(stop==False)
-
-    while not stop:
-        while True: # wait for dc_valid
-            if stop:
-                return
-            cyc = yield (wb.cyc)
-            stb = yield (wb.stb)
-            if cyc and stb:
-                break
-            yield
-        addr = (yield wb.adr) << 3
-        stop = True # hack for testing
-        if addr not in mem:
-            print ("    WB LOOKUP NO entry @ %x, returning zero" % (addr))
-
-        # read or write?
-        we = (yield wb.we)
-        if we:
-            store = (yield wb.dat_w)
-            sel = (yield wb.sel)
-            data = mem.get(addr, 0)
-            # note we assume 8-bit sel, here
-            res = 0
-            for i in range(8):
-                mask = 0xff << (i*8)
-                if sel & (1<<i):
-                    res |= store & mask
-                else:
-                    res |= data & mask
-            mem[addr] = res
-            print ("    DCACHE set %x mask %x data %x" % (addr, sel, res))
-        else:
-            data = mem.get(addr, 0)
-            yield wb.dat_r.eq(data)
-            print ("    DCACHE get %x data %x" % (addr, data))
-
-        yield wb.ack.eq(1)
-        yield
-        yield wb.ack.eq(0)
-        yield
-
 def test_scoreboard_regspec_mmu():
-    
+
     m = Module()
 
     units = {}
@@ -263,39 +253,14 @@ def test_scoreboard_regspec_mmu():
     sim = Simulator(m)
     sim.add_clock(1e-6)
 
-    sim.add_sync_process(wrap(ldst_sim(dut)))
-
-    # FIXME: this is redundant code
-    mem = {
-           0x10000:    # PARTITION_TABLE_2
-                       # PATB_GR=1 PRTB=0x1000 PRTS=0xb
-           b(0x800000000100000b),
-
-           0x30000:     # RADIX_ROOT_PTE
-                        # V = 1 L = 0 NLB = 0x400 NLS = 9
-           b(0x8000000000040009),
+    dut.mem = pagetables.test1
+    wbget.stop = False
 
-           0x40000:     # RADIX_SECOND_LEVEL
-                        # V = 1 L = 1 SW = 0 RPN = 0
-                        # R = 1 C = 1 ATT = 0 EAA 0x7
-           b(0xc000000000000183),
-
-           0x1000000:   # PROCESS_TABLE_3
-                        # RTS1 = 0x2 RPDB = 0x300 RTS2 = 0x5 RPDS = 13
-           b(0x40000000000300ad),
-
-           0x10004: 0
-
-    }
-
-    sim.add_sync_process(wrap(wb_get(dut.cmpi.wb_bus(), mem)))
-    with sim.write_vcd('test_dcbz_addr_zero.vcd'):
+    sim.add_sync_process(wrap(ldst_sim(dut)))
+    sim.add_sync_process(wrap(wb_get(dut.cmpi.wb_bus(), dut.mem)))
+    with sim.write_vcd('test_scoreboard_regspec_mmu.vcd'):
         sim.run()
 
-
 if __name__ == '__main__':
-    #FIXME: avoid using global variables
-    global stop
-    stop = False
     test_scoreboard_regspec_mmu()
-    #only one test for now -- test_scoreboard_mmu()
+    test_scoreboard_mmu()