Merge branch 'master' of ssh://git.libre-riscv.org:922/soc
[soc.git] / src / soc / experiment / pimem.py
index 279e8971f44a9b626ed28114332ad457b2581577..f8a05992b2b49ae29fdcbf7b704d179a9224c6db 100644 (file)
@@ -22,11 +22,14 @@ from nmutil.iocontrol import RecordObject
 from nmigen.utils import log2_int
 
 from nmutil.latch import SRLatch, latchregister
+from nmutil.util import rising_edge
 from soc.decoder.power_decoder2 import Data
 from soc.scoreboard.addr_match import LenExpand
+from soc.experiment.mem_types import LDSTException
 
 # for testing purposes
 from soc.experiment.testmem import TestMemory
+#from soc.scoreboard.addr_split import LDSTSplitter
 
 import unittest
 
@@ -56,13 +59,13 @@ class PortInterface(RecordObject):
       for the L0 Cache/Buffer to have an additional address latch
       (because the LDSTCompUnit already has it)
 
-    * addr_ok_o (or addr_exc_o) must be waited for.  these will
+    * addr_ok_o (or exception.happened) must be waited for.  these will
       be asserted *only* for one cycle and one cycle only.
 
-    * addr_exc_o will be asserted if there is no chance that the
+    * exception.happened will be asserted if there is no chance that the
       memory request may be fulfilled.
 
-      busy_o is deasserted on the same cycle as addr_exc_o is asserted.
+      busy_o is deasserted on the same cycle as exception.happened is asserted.
 
     * conversely: addr_ok_o must *ONLY* be asserted if there is a
       HUNDRED PERCENT guarantee that the memory request will be
@@ -104,12 +107,26 @@ class PortInterface(RecordObject):
         self.addr = Data(addrwid, "addr_i")            # addr/addr-ok
         # addr is valid (TLB, L1 etc.)
         self.addr_ok_o = Signal(reset_less=True)
-        self.addr_exc_o = Signal(reset_less=True)  # TODO, "type" of exception
+        self.exception_o = LDSTException("exc")
 
         # LD/ST
         self.ld = Data(regwid, "ld_data_o")  # ok to be set by L0 Cache/Buf
         self.st = Data(regwid, "st_data_i")  # ok to be set by CompUnit
 
+        # additional "modes"
+        self.dcbz          = Signal()  # data cache block zero request
+        self.nc            = Signal()  # no cacheing
+        self.virt_mode     = Signal()  # virtual mode
+        self.priv_mode     = Signal()  # privileged mode
+
+        # mmu
+        self.mmu_done          = Signal() # keep for now
+       
+        # dcache
+        self.ldst_error        = Signal()
+        ## Signalling ld/st error - NC cache hit, TLB miss, prot/RC failure
+        self.cache_paradox     = Signal()
+
     def connect_port(self, inport):
         print("connect_port", self, inport)
         return [self.is_ld_i.eq(inport.is_ld_i),
@@ -122,7 +139,10 @@ class PortInterface(RecordObject):
                 inport.ld.eq(self.ld),
                 inport.busy_o.eq(self.busy_o),
                 inport.addr_ok_o.eq(self.addr_ok_o),
-                inport.addr_exc_o.eq(self.addr_exc_o),
+                inport.exception_o.eq(self.exception_o),
+                inport.mmu_done.eq(self.mmu_done),
+                inport.ldst_error.eq(self.ldst_error),
+                inport.cache_paradox.eq(self.cache_paradox)
                 ]
 
 
@@ -166,7 +186,10 @@ class PortInterfaceBase(Elaboratable):
         m.submodules.adrok_l = adrok_l = SRLatch(False, name="addr_acked")
         m.submodules.busy_l = busy_l = SRLatch(False, name="busy")
         m.submodules.cyc_l = cyc_l = SRLatch(True, name="cyc")
-        comb += st_done.s.eq(0)
+
+        self.busy_l = busy_l
+
+        sync += st_done.s.eq(0)
         comb += st_done.r.eq(0)
         comb += st_active.r.eq(0)
         comb += ld_active.r.eq(0)
@@ -193,8 +216,8 @@ class PortInterfaceBase(Elaboratable):
         comb += busy_edge.eq(pi.busy_o & ~busy_delay)
 
         # activate mode: only on "edge"
-        comb += ld_active.s.eq(lds & busy_edge)  # activate LD mode
-        comb += st_active.s.eq(sts & busy_edge)  # activate ST mode
+        comb += ld_active.s.eq(rising_edge(m, lds))  # activate LD mode
+        comb += st_active.s.eq(rising_edge(m, sts))  # activate ST mode
 
         # LD/ST requested activates "busy" (only if not already busy)
         with m.If(self.pi.is_ld_i | self.pi.is_st_i):
@@ -249,7 +272,7 @@ class PortInterfaceBase(Elaboratable):
             # TODO: replace with link to LoadStoreUnitInterface.x_store_data
             # and also handle the ready/stall/busy protocol
             stok = self.set_wr_data(m, stdata, lenexp.lexp_o)
-            comb += st_done.s.eq(1)     # store done trigger
+            sync += st_done.s.eq(1)     # store done trigger
         with m.If(st_done.q):
             comb += reset_l.s.eq(stok)   # reset mode after 1 cycle
 
@@ -268,7 +291,7 @@ class PortInterfaceBase(Elaboratable):
             comb += st_done.r.eq(1)     # store done reset
 
         # monitor for an exception or the completion of LD.
-        with m.If(self.pi.addr_exc_o):
+        with m.If(self.pi.exception_o.happened):
             comb += busy_l.r.eq(1)
 
         # however ST needs one cycle before busy is reset