fix wb_get error where data was being corrupted
[soc.git] / src / soc / experiment / test / test_mmu_dcache.py
index 505fccf4b42d0cd67081076f463daf17e9ab1a51..1528d7d40db31bbaed8f821a7a90663ef087bb26 100644 (file)
@@ -20,60 +20,144 @@ from soc.experiment.mem_types import (LoadStore1ToMMUType,
 
 from soc.experiment.mmu import MMU
 from soc.experiment.dcache import DCache
+from soc.experiment.icache import ICache
+
+import random
 
 stop = False
 
+def set_stop(newval):
+    global stop
+    stop = newval
 
-def wb_get(dc):
-    """simulator process for getting memory load requests
-    """
 
-    global stop
+def b(x):
+    return int.from_bytes(x.to_bytes(8, byteorder='little'),
+                          byteorder='big', signed=False)
 
-    def b(x):
-        return int.from_bytes(x.to_bytes(8, byteorder='little'),
-                              byteorder='big', signed=False)
 
-    mem = {0x10000:    # PARTITION_TABLE_2
+default_mem = { 0x10000:    # PARTITION_TABLE_2
                        # PATB_GR=1 PRTB=0x1000 PRTS=0xb
-           b(0x800000000100000b),
+                b(0x800000000100000b),
 
-           0x30000:     # RADIX_ROOT_PTE
+                0x30000:     # RADIX_ROOT_PTE
                         # V = 1 L = 0 NLB = 0x400 NLS = 9
-           b(0x8000000000040009),
+                b(0x8000000000040009),
 
-           0x40000:     # RADIX_SECOND_LEVEL
+                0x40000:     # RADIX_SECOND_LEVEL
                         #         V = 1 L = 1 SW = 0 RPN = 0
                            # R = 1 C = 1 ATT = 0 EAA 0x7
-           b(0xc000000000000187),
+                b(0xc000000000000187),
 
-          0x1000000:   # PROCESS_TABLE_3
+                0x1000000:   # PROCESS_TABLE_3
                        # RTS1 = 0x2 RPDB = 0x300 RTS2 = 0x5 RPDS = 13
-           b(0x40000000000300ad),
-          }
+                b(0x40000000000300ad),
+            }
+
+
+def wb_get(c, mem, name):
+    """simulator process for getting memory load requests
+    """
+
+    logfile = open("/tmp/wb_get.log","w")
 
+    def log(msg):
+        logfile.write(msg+"\n")
+        print(msg)
+
+    global stop
     while not stop:
         while True: # wait for dc_valid
             if stop:
+                log("stop")
                 return
-            cyc = yield (dc.wb_out.cyc)
-            stb = yield (dc.wb_out.stb)
+            cyc = yield (c.wb_out.cyc)
+            stb = yield (c.wb_out.stb)
             if cyc and stb:
                 break
             yield
-        addr = (yield dc.wb_out.adr) << 3
+        addr = (yield c.wb_out.adr) << 3
         if addr not in mem:
-            print ("    DCACHE LOOKUP FAIL %x" % (addr))
+            log("%s LOOKUP FAIL %x" % (name, addr))
             stop = True
             return
 
         yield
         data = mem[addr]
-        yield dc.wb_in.dat.eq(data)
-        print ("    DCACHE get %x data %x" % (addr, data))
-        yield dc.wb_in.ack.eq(1)
+        yield c.wb_in.dat.eq(data)
+        log("%s get %x data %x" % (name, addr, data))
+        yield c.wb_in.ack.eq(1)
+        yield
+        yield c.wb_in.ack.eq(0)
+        yield
+
+
+def icache_sim(dut, mem):
+    i_out = dut.i_in
+    i_in  = dut.i_out
+    m_out = dut.m_in
+
+    for k,v in mem.items():
+        yield i_in.valid.eq(0)
+        yield i_out.priv_mode.eq(1)
+        yield i_out.req.eq(0)
+        yield i_out.nia.eq(0)
+        yield i_out.stop_mark.eq(0)
+        yield m_out.tlbld.eq(0)
+        yield m_out.tlbie.eq(0)
+        yield m_out.addr.eq(0)
+        yield m_out.pte.eq(0)
+        yield
+        yield
+        yield
         yield
-        yield dc.wb_in.ack.eq(0)
+        yield i_out.req.eq(1)
+        yield i_out.nia.eq(C(k, 64))
+        while True:
+            yield
+            valid = yield i_in.valid
+            if valid:
+                break
+        nia   = yield i_out.nia
+        insn  = yield i_in.insn
+        yield
+        assert insn == v, \
+            "insn @%x=%x expected %x" % (nia, insn, v)
+        yield i_out.req.eq(0)
+        yield
+
+
+def test_icache_il():
+    dut = ICache()
+    vl = rtlil.convert(dut, ports=[])
+    with open("test_icache.il", "w") as f:
+        f.write(vl)
+
+
+def test_icache():
+    # create a random set of addresses and "instructions" at those addresses
+    mem = {}
+    # fail 'AssertionError: insn @1d8=0 expected 61928a6100000000'
+    #random.seed(41)
+    # fail infinite loop 'cache read adr: 24 data: 0'
+    random.seed(43)
+    for i in range(3):
+        mem[random.randint(0, 1<<10)] = b(random.randint(0,1<<32))
+
+    # set up module for simulation
+    m = Module()
+    icache = ICache()
+    m.submodules.icache = icache
+
+    # nmigen Simulation
+    sim = Simulator(m)
+    sim.add_clock(1e-6)
+
+    # read from "memory" process and corresponding wishbone "read" process
+    sim.add_sync_process(wrap(icache_sim(icache, mem)))
+    sim.add_sync_process(wrap(wb_get(icache, mem, "ICACHE")))
+    with sim.write_vcd('test_icache.vcd'):
+        sim.run()
 
 
 def mmu_lookup(mmu, addr):
@@ -104,6 +188,7 @@ def mmu_lookup(mmu, addr):
 
     return phys_addr
 
+
 def mmu_sim(mmu):
     global stop
     yield mmu.rin.prtbl.eq(0x1000000) # set process table
@@ -117,6 +202,7 @@ def mmu_sim(mmu):
 
     stop = True
 
+
 def test_mmu():
     mmu = MMU()
     dcache = DCache()
@@ -133,9 +219,12 @@ def test_mmu():
     sim.add_clock(1e-6)
 
     sim.add_sync_process(wrap(mmu_sim(mmu)))
-    sim.add_sync_process(wrap(wb_get(dcache)))
+    sim.add_sync_process(wrap(wb_get(dcache, default_mem, "DCACHE")))
     with sim.write_vcd('test_mmu.vcd'):
         sim.run()
 
+
 if __name__ == '__main__':
     test_mmu()
+    #test_icache_il()
+    #test_icache()