From cf516c7b827ffae8f3df49b139af9badfb3765c4 Mon Sep 17 00:00:00 2001 From: Luke Kenneth Casson Leighton Date: Fri, 30 Apr 2021 01:22:21 +0100 Subject: [PATCH] set up LoadStore1 in ConfigMemoryPortInterface and hook it up in MMU --- src/soc/config/loadstore.py | 11 ++++++- src/soc/fu/mmu/fsm.py | 41 ++++++++++++++++++------- src/soc/fu/mmu/test/test_pipe_caller.py | 15 +++++++-- src/soc/simple/core.py | 8 +++-- src/soc/simple/issuer.py | 2 +- 5 files changed, 59 insertions(+), 18 deletions(-) diff --git a/src/soc/config/loadstore.py b/src/soc/config/loadstore.py index f280227d..3e42e134 100644 --- a/src/soc/config/loadstore.py +++ b/src/soc/config/loadstore.py @@ -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() diff --git a/src/soc/fu/mmu/fsm.py b/src/soc/fu/mmu/fsm.py index 6b72c8a2..34bbc323 100644 --- a/src/soc/fu/mmu/fsm.py +++ b/src/soc/fu/mmu/fsm.py @@ -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 diff --git a/src/soc/fu/mmu/test/test_pipe_caller.py b/src/soc/fu/mmu/test/test_pipe_caller.py index 446dd227..1c05e881 100644 --- a/src/soc/fu/mmu/test/test_pipe_caller.py +++ b/src/soc/fu/mmu/test/test_pipe_caller.py @@ -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 diff --git a/src/soc/simple/core.py b/src/soc/simple/core.py index f4cf959d..5c1dc13f 100644 --- a/src/soc/simple/core.py +++ b/src/soc/simple/core.py @@ -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) diff --git a/src/soc/simple/issuer.py b/src/soc/simple/issuer.py index 9d50a075..a78eb074 100644 --- a/src/soc/simple/issuer.py +++ b/src/soc/simple/issuer.py @@ -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: -- 2.30.2