From 1ee68fde2194bd0a9bfc91e38f2067f2dbe0b70f Mon Sep 17 00:00:00 2001 From: Luke Kenneth Casson Leighton Date: Sat, 11 Dec 2021 14:36:58 +0000 Subject: [PATCH] connect up I-Cache to FetchUnitInterface FetchUnitInterface may in turn need redesigning, but that is another story --- src/soc/config/ifetch.py | 2 + src/soc/experiment/icache.py | 93 +++++++++++++++++++++++++++--------- src/soc/fu/ldst/loadstore.py | 2 +- src/soc/simple/core.py | 3 +- 4 files changed, 75 insertions(+), 25 deletions(-) diff --git a/src/soc/config/ifetch.py b/src/soc/config/ifetch.py index fd9d9d16..e86e4727 100644 --- a/src/soc/config/ifetch.py +++ b/src/soc/config/ifetch.py @@ -20,6 +20,8 @@ class ConfigFetchUnit: } if self.pspec.imem_ifacetype in ['mmu_cache_wb', 'test_mmu_cache_wb']: self.fu = self.lsmem.lsi.icache # ICache already FetchUnitInterface + # tell I-Cache to connect up to its FetchUnitInterface + self.fu.use_fetch_interface() return fukls = fudict[pspec.imem_ifacetype] diff --git a/src/soc/experiment/icache.py b/src/soc/experiment/icache.py index 4cb6b038..99da2861 100644 --- a/src/soc/experiment/icache.py +++ b/src/soc/experiment/icache.py @@ -49,6 +49,8 @@ from soc.experiment.wb_types import (WB_ADDR_BITS, WB_DATA_BITS, ) from nmigen_soc.wishbone.bus import Interface +from soc.minerva.units.fetch import FetchUnitInterface + # for test from soc.bus.sram import SRAM @@ -305,9 +307,10 @@ class RegInternal(RecordObject): self.fetch_failed = Signal() -class ICache(Elaboratable): +class ICache(FetchUnitInterface, Elaboratable): """64 bit direct mapped icache. All instructions are 4B aligned.""" - def __init__(self): + def __init__(self, pspec): + FetchUnitInterface.__init__(self, pspec) self.i_in = Fetch1ToICacheType(name="i_in") self.i_out = ICacheToDecode1Type(name="i_out") @@ -328,6 +331,11 @@ class ICache(Elaboratable): self.log_out = Signal(54) + # use FetchUnitInterface, helps keep some unit tests running + self.use_fetch_iface = False + + def use_fetch_interface(self): + self.use_fetch_iface = True # Generate a cache RAM for each way def rams(self, m, r, cache_out_row, use_previous, @@ -852,6 +860,37 @@ class ICache(Elaboratable): #self.icache_log(m, log_out, req_hit_way, ra_valid, access_ok, # req_is_miss, req_is_hit, lway, wstate, r) + # don't connect up to FetchUnitInterface so that some unit tests + # can continue to operate + if not self.use_fetch_iface: + return m + + # connect to FetchUnitInterface. FetchUnitInterface is undocumented + # so needs checking and iterative revising + i_in, bus, i_out = self.i_in, self.bus, self.i_out + comb += i_in.req.eq(self.a_i_valid) + comb += i_in.nia.eq(self.a_pc_i) + comb += self.stall_in.eq(self.a_stall_i) + comb += self.f_fetch_err_o.eq(i_out.fetch_failed) + comb += self.f_badaddr_o.eq(i_out.nia) + comb += self.f_instr_o.eq(i_out.insn) + comb += self.f_busy_o.eq(i_out.valid) # probably + + # TODO, connect dcache wb_in/wb_out to "standard" nmigen Wishbone bus + ibus = self.ibus + comb += ibus.adr.eq(self.bus.adr) + comb += ibus.dat_w.eq(self.bus.dat_w) + comb += ibus.sel.eq(self.bus.sel) + comb += ibus.cyc.eq(self.bus.cyc) + comb += ibus.stb.eq(self.bus.stb) + comb += ibus.we.eq(self.bus.we) + + comb += self.bus.dat_r.eq(ibus.dat_r) + comb += self.bus.ack.eq(ibus.ack) + if hasattr(ibus, "stall"): + comb += self.bus.stall.eq(ibus.stall) + + return m @@ -942,37 +981,47 @@ def icache_sim(dut): def test_icache(mem): - dut = ICache() + from soc.config.test.test_loadstore import TestMemPspec + pspec = TestMemPspec(addr_wid=32, + mask_wid=8, + reg_wid=64, + ) + dut = ICache(pspec) - memory = Memory(width=64, depth=512, init=mem) - sram = SRAM(memory=memory, granularity=8) + memory = Memory(width=64, depth=512, init=mem) + sram = SRAM(memory=memory, granularity=8) - m = Module() + m = Module() - m.submodules.icache = dut - m.submodules.sram = sram + m.submodules.icache = dut + m.submodules.sram = sram - m.d.comb += sram.bus.cyc.eq(dut.bus.cyc) - m.d.comb += sram.bus.stb.eq(dut.bus.stb) - m.d.comb += sram.bus.we.eq(dut.bus.we) - m.d.comb += sram.bus.sel.eq(dut.bus.sel) - m.d.comb += sram.bus.adr.eq(dut.bus.adr) - m.d.comb += sram.bus.dat_w.eq(dut.bus.dat_w) + m.d.comb += sram.bus.cyc.eq(dut.bus.cyc) + m.d.comb += sram.bus.stb.eq(dut.bus.stb) + m.d.comb += sram.bus.we.eq(dut.bus.we) + m.d.comb += sram.bus.sel.eq(dut.bus.sel) + m.d.comb += sram.bus.adr.eq(dut.bus.adr) + m.d.comb += sram.bus.dat_w.eq(dut.bus.dat_w) - m.d.comb += dut.bus.ack.eq(sram.bus.ack) - m.d.comb += dut.bus.dat_r.eq(sram.bus.dat_r) + m.d.comb += dut.bus.ack.eq(sram.bus.ack) + m.d.comb += dut.bus.dat_r.eq(sram.bus.dat_r) - # nmigen Simulation - sim = Simulator(m) - sim.add_clock(1e-6) + # nmigen Simulation + sim = Simulator(m) + sim.add_clock(1e-6) - sim.add_sync_process(wrap(icache_sim(dut))) - with sim.write_vcd('test_icache.vcd'): + sim.add_sync_process(wrap(icache_sim(dut))) + with sim.write_vcd('test_icache.vcd'): sim.run() if __name__ == '__main__': - dut = ICache() + from soc.config.test.test_loadstore import TestMemPspec + pspec = TestMemPspec(addr_wid=64, + mask_wid=8, + reg_wid=64, + ) + dut = ICache(pspec) vl = rtlil.convert(dut, ports=[]) with open("test_icache.il", "w") as f: f.write(vl) diff --git a/src/soc/fu/ldst/loadstore.py b/src/soc/fu/ldst/loadstore.py index e84a4f99..1e086562 100644 --- a/src/soc/fu/ldst/loadstore.py +++ b/src/soc/fu/ldst/loadstore.py @@ -71,7 +71,7 @@ class LoadStore1(PortInterfaceBase): super().__init__(regwid, addrwid) self.dcache = DCache() - self.icache = ICache() + self.icache = ICache(pspec) # these names are from the perspective of here (LoadStore1) self.d_out = self.dcache.d_in # in to dcache is out for LoadStore self.d_in = self.dcache.d_out # out from dcache is in for LoadStore diff --git a/src/soc/simple/core.py b/src/soc/simple/core.py index f80ed141..1d8d3d72 100644 --- a/src/soc/simple/core.py +++ b/src/soc/simple/core.py @@ -147,7 +147,7 @@ class NonProductionCore(ControlBase): # only include mmu if enabled in pspec self.fus = AllFunctionUnits(pspec, pilist=[pi]) - # link LoadStore1 into MMU and make L1 I-Cache easy to get at + # link LoadStore1 into MMU mmu = self.fus.get_fu('mmu0') ldst0 = self.fus.get_fu('ldst0') print ("core pspec", pspec.ldst_ifacetype) @@ -156,7 +156,6 @@ class NonProductionCore(ControlBase): lsi = l0.cmpi.lsmem.lsi # a LoadStore1 Interface object print ("core lsmem.lsi", lsi) mmu.alu.set_ldst_interface(lsi) - self.icache = lsi.icache # register files (yes plural) self.regs = RegFiles(pspec, make_hazard_vecs=self.make_hazard_vecs) -- 2.30.2