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)
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()
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
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
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)
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):
# 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):
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
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
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
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
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
(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)