set up LoadStore1 in ConfigMemoryPortInterface and hook it up in MMU
authorLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Fri, 30 Apr 2021 00:22:21 +0000 (01:22 +0100)
committerLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Fri, 30 Apr 2021 00:22:21 +0000 (01:22 +0100)
src/soc/config/loadstore.py
src/soc/fu/mmu/fsm.py
src/soc/fu/mmu/test/test_pipe_caller.py
src/soc/simple/core.py
src/soc/simple/issuer.py

index f280227d57d010fccd9fe7d08c335c7c024cecbf..3e42e13478a97bbb18142de4b96d8716f109204c 100644 (file)
@@ -11,13 +11,14 @@ from soc.bus.test.test_minerva import TestSRAMBareLoadStoreUnit
 from soc.experiment.pi2ls import Pi2LSUI
 from soc.experiment.pimem import TestMemoryPortInterface
 from soc.minerva.units.loadstore import BareLoadStoreUnit
+from soc.fu.mmu.fsm import LoadStore1 # MMU and DCache
 
 class ConfigLoadStoreUnit:
     def __init__(self, pspec):
         lsidict = {'testmem': TestMemLoadStoreUnit,
                    'test_bare_wb': TestSRAMBareLoadStoreUnit,
                    'bare_wb': BareLoadStoreUnit,
-                   #'test_cache_wb': TestCacheLoadStoreUnit
+                   'mmu_cache_wb': LoadStore1
                   }
         lsikls = lsidict[pspec.ldst_ifacetype]
         self.lsi = lsikls(pspec)
@@ -31,11 +32,19 @@ class ConfigMemoryPortInterface:
                                               regwid=pspec.reg_wid) # data bus
             return
         self.lsmem = ConfigLoadStoreUnit(pspec)
+        if self.pspec.ldst_ifacetype == 'mmu_cache_wb':
+            self.pi = self.lsmem.lsi.pi # LoadStore1 already is a PortInterface
+            return
         self.pi = Pi2LSUI("mem", lsui=self.lsmem.lsi,
                           addr_wid=pspec.addr_wid, # address range
                           mask_wid=pspec.mask_wid, # cache line range
                           data_wid=pspec.reg_wid)  # data bus width
 
+    def wb_bus(self):
+        if self.pspec.ldst_ifacetype == 'mmu_cache_wb':
+            return self.lsmem.lsi.dbus
+        return self.lsmem.lsi.slavebus
+
     def ports(self):
         if self.pspec.ldst_ifacetype == 'testpi':
             return self.pi.ports()
index 6b72c8a2b7b7e20845c85365aa544e659de91e2d..34bbc32357f8d5fdf6e08d7725b37d14066430ce 100644 (file)
@@ -1,4 +1,5 @@
 from nmigen import Elaboratable, Module, Signal, Shape, unsigned, Cat, Mux
+from nmigen import Record
 from nmigen import Const
 from soc.fu.mmu.pipe_data import MMUInputData, MMUOutputData, MMUPipeSpec
 from nmutil.singlepipe import ControlBase
@@ -19,10 +20,15 @@ from soc.experiment.pimem import PortInterfaceBase
 from soc.experiment.mem_types import LoadStore1ToDCacheType, LoadStore1ToMMUType
 from soc.experiment.mem_types import DCacheToLoadStore1Type, MMUToLoadStore1Type
 
+from soc.minerva.wishbone import make_wb_layout
+
 
 # glue logic for microwatt mmu and dcache
 class LoadStore1(PortInterfaceBase):
-    def __init__(self, regwid=64, addrwid=4):
+    def __init__(self, pspec):
+        regwid = pspec.reg_wid
+        addrwid = pspec.addr_wid
+
         super().__init__(regwid, addrwid)
         self.dcache = DCache()
         self.d_in  = self.dcache.d_in
@@ -37,7 +43,7 @@ class LoadStore1(PortInterfaceBase):
         self.derror = Signal()
 
         # TODO, convert dcache wb_in/wb_out to "standard" nmigen Wishbone bus
-        # self.bus = Interface(...)
+        self.dbus = Record(make_wb_layout(pspec))
 
     def set_wr_addr(self, m, addr, mask):
         #m.d.comb += self.d_in.valid.eq(1)
@@ -95,11 +101,11 @@ class LoadStore1(PortInterfaceBase):
     def elaborate(self, platform):
         m = super().elaborate(platform)
 
-        d_out = self.d_out
-        l_out = self.l_out
-
         # create dcache module
-        m.submodules.dcache = self.dcache
+        m.submodules.dcache = dcache = self.dcache
+
+        # temp vars
+        d_out, l_out, dbus = self.d_out, self.l_out, self.dbus
 
         with m.If(d_out.error):
             with m.If(d_out.cache_paradox):
@@ -136,6 +142,8 @@ class LoadStore1(PortInterfaceBase):
 
         # TODO some exceptions set SPRs
 
+        # TODO, connect dcache wb_in/wb_out to "standard" nmigen Wishbone bus
+        # comb += dcache.wb_in.blahblah.eq(dbus.blahblah)
         return m
 
     def ports(self):
@@ -144,6 +152,11 @@ class LoadStore1(PortInterfaceBase):
 
 
 class FSMMMUStage(ControlBase):
+    """FSM MMU
+
+    FSM-based MMU: must call set_ldst_interface and pass in an instance
+    of a LoadStore1.  this to comply with the ConfigMemoryPortInterface API
+    """
     def __init__(self, pspec):
         super().__init__()
         self.pspec = pspec
@@ -152,11 +165,6 @@ class FSMMMUStage(ControlBase):
         self.p.data_i = MMUInputData(pspec)
         self.n.data_o = MMUOutputData(pspec)
 
-        # incoming PortInterface
-        self.ldst = LoadStore1()       # TODO make this depend on pspec
-        self.dcache = self.ldst.dcache
-        self.pi = self.ldst.pi
-
         # this Function Unit is extremely unusual in that it actually stores a
         # "thing" rather than "processes inputs and produces outputs".  hence
         # why it has to be a FSM.  linking up LD/ST however is going to have
@@ -183,7 +191,18 @@ class FSMMMUStage(ControlBase):
         self.fields = DecodeFields(SignalBitRange, [i.ctx.op.insn])
         self.fields.create_specs()
 
+    def set_ldst_interface(self, ldst):
+        """must be called back in Core, after FUs have been set up.
+        one of those will be the MMU (us!) but the LoadStore1 instance
+        must be set up in ConfigMemoryPortInterface. sigh.
+        """
+        # incoming PortInterface
+        self.ldst = ldst
+        self.dcache = self.ldst.dcache
+        self.pi = self.ldst.pi
+
     def elaborate(self, platform):
+        assert hasattr(self, "dcache"), "remember to call set_ldst_interface"
         m = super().elaborate(platform)
         comb = m.d.comb
         dcache = self.dcache
index 446dd22703895dab5914fb9ee0c95f7b8f37c3f9..1c05e8810d26efa1fb66a8444fa17226536b9f1c 100644 (file)
@@ -17,9 +17,10 @@ from openpower.consts import MSR
 from openpower.test.mmu.mmu_cases import MMUTestCase
 
 from openpower.test.common import (TestAccumulatorBase, skip_case, ALUHelpers)
+from soc.config.test.test_loadstore import TestMemPspec
 #from soc.fu.spr.pipeline import SPRBasePipe
 #from soc.fu.spr.pipe_data import SPRPipeSpec
-from soc.fu.mmu.fsm import FSMMMUStage
+from soc.fu.mmu.fsm import FSMMMUStage, LoadStore1
 from soc.fu.mmu.pipe_data import MMUPipeSpec
 import random
 
@@ -203,12 +204,20 @@ class TestRunner(unittest.TestCase):
         comb = m.d.comb
         instruction = Signal(32)
 
+        pspec = TestMemPspec(addr_wid=48,
+                             mask_wid=8,
+                             reg_wid=64,
+                             )
+
         pdecode = create_pdecode()
 
         m.submodules.pdecode2 = pdecode2 = PowerDecode2(pdecode)
 
-        pspec = MMUPipeSpec(id_wid=2)
-        m.submodules.fsm = fsm = FSMMMUStage(pspec)
+        pipe_spec = MMUPipeSpec(id_wid=2)
+        ldst = LoadStore1(pspec)
+        fsm = FSMMMUStage(pipe_spec)
+        fsm.set_ldst_interface(ldst)
+        m.submodules.fsm = fsm
 
         #FIXME connect fsm inputs
 
index f4cf959de60f9605e1f3175b1ba3a29e20c262d8..5c1dc13f48a82940bc04d2d07c323473c0e47043 100644 (file)
@@ -79,13 +79,17 @@ class NonProductionCore(Elaboratable):
                              (pspec.regreduce == True))
 
         # single LD/ST funnel for memory access
-        self.l0 = TstL0CacheBuffer(pspec, n_units=1)
-        pi = self.l0.l0.dports[0]
+        self.l0 = l0 = TstL0CacheBuffer(pspec, n_units=1)
+        pi = l0.l0.dports[0]
 
         # function units (only one each)
         # only include mmu if enabled in pspec
         self.fus = AllFunctionUnits(pspec, pilist=[pi])
 
+        # link LoadStore1 into MMU
+        if hasattr(self.fus, 'mmu') and hasattr(l0.cmpi, "ldst"):
+            self.fus.mmu.set_ldst_interface(l0.cmpi.ldst)
+
         # register files (yes plural)
         self.regs = RegFiles(pspec)
 
index 9d50a075179e2ec77a2a77bd42862dee0b60f02b..a78eb0744d280815047cbcada42793cc9615a90b 100644 (file)
@@ -1170,7 +1170,7 @@ class TestIssuerInternal(Elaboratable):
             ports += list(self.dbg.dmi.ports())
 
         ports += list(self.imem.ibus.fields.values())
-        ports += list(self.core.l0.cmpi.lsmem.lsi.slavebus.fields.values())
+        ports += list(self.core.l0.cmpi.wb_bus().fields.values())
 
         if self.sram4x4k:
             for sram in self.sram4k: