From f2acf58f9be2e37e09c5f4202e786004ad32d0f8 Mon Sep 17 00:00:00 2001 From: Dolu1990 Date: Tue, 4 Mar 2025 11:36:16 +0100 Subject: [PATCH] Add fetch uncached wishbone support --- src/main/scala/vexiiriscv/Param.scala | 5 ++- .../fetch/FetchCachelessBridge.scala | 39 ++++++++++++++++++- .../vexiiriscv/fetch/FetchCachelessBus.scala | 17 ++++++++ .../scala/vexiiriscv/tester/TestBench.scala | 26 ++++++++++++- 4 files changed, 83 insertions(+), 4 deletions(-) diff --git a/src/main/scala/vexiiriscv/Param.scala b/src/main/scala/vexiiriscv/Param.scala index aa4e330a..ae03d683 100644 --- a/src/main/scala/vexiiriscv/Param.scala +++ b/src/main/scala/vexiiriscv/Param.scala @@ -14,7 +14,7 @@ import vexiiriscv.execute._ import vexiiriscv.execute.cfu.{CfuBusParameter, CfuPlugin, CfuPluginEncoding} import vexiiriscv.execute.fpu.{FpuAddSharedParam, FpuMulParam} import vexiiriscv.execute.lsu._ -import vexiiriscv.fetch.{FetchCachelessAxi4Plugin, FetchCachelessPlugin, FetchL1Axi4Plugin, FetchL1Plugin, PrefetcherNextLinePlugin} +import vexiiriscv.fetch.{FetchCachelessAxi4Plugin, FetchCachelessPlugin, FetchCachelessWishbonePlugin, FetchL1Axi4Plugin, FetchL1Plugin, PrefetcherNextLinePlugin} import vexiiriscv.memory.{MmuPortParameter, MmuSpec, MmuStorageLevel, MmuStorageParameter, PmpParam, PmpPlugin, PmpPortParameter} import vexiiriscv.misc._ import vexiiriscv.prediction.{LearnCmd, LearnPlugin} @@ -137,6 +137,7 @@ class ParamSimple(){ var fetchL1RefillCount = 1 var fetchL1Prefetch = "none" var fetchAxi4 = false + var fetchWishbone = false var lsuSoftwarePrefetch = false var lsuHardwarePrefetch = "none" var lsuStoreBufferSlots = 0 @@ -565,6 +566,7 @@ class ParamSimple(){ opt[Unit]("with-fetch-l1") unbounded() action { (v, c) => fetchL1Enable = true } opt[Unit]("with-lsu-l1") action { (v, c) => lsuL1Enable = true } opt[Unit]("fetch-axi4") action { (v, c) => fetchAxi4 = true } + opt[Unit]("fetch-wishbone") action { (v, c) => fetchWishbone = true } opt[Unit]("fetch-l1") action { (v, c) => fetchL1Enable = true } opt[Unit]("lsu-l1") action { (v, c) => lsuL1Enable = true } opt[Int]("fetch-l1-sets") unbounded() action { (v, c) => fetchL1Sets = v } @@ -708,6 +710,7 @@ class ParamSimple(){ } ) if(fetchAxi4) plugins += new FetchCachelessAxi4Plugin() + if(fetchWishbone) plugins += new FetchCachelessWishbonePlugin() } if(fetchL1Enable) { diff --git a/src/main/scala/vexiiriscv/fetch/FetchCachelessBridge.scala b/src/main/scala/vexiiriscv/fetch/FetchCachelessBridge.scala index 692e458b..1e57b747 100644 --- a/src/main/scala/vexiiriscv/fetch/FetchCachelessBridge.scala +++ b/src/main/scala/vexiiriscv/fetch/FetchCachelessBridge.scala @@ -5,6 +5,7 @@ import spinal.lib._ import spinal.lib.bus.amba4.axi.{Axi4ReadOnly, Axi4Shared} import spinal.lib.bus.tilelink import spinal.lib.bus.tilelink.{DebugId, S2mSupport} +import spinal.lib.bus.wishbone.Wishbone import spinal.lib.misc.plugin.FiberPlugin // Plugin to embed a bridge in VexiiRiscv to convert the CachelessBus to Tilelink @@ -47,12 +48,12 @@ class FetchCachelessAxi4Plugin() extends FiberPlugin { val fcp = host[FetchCachelessPlugin] fcp.logic.bus.setAsDirectionLess() - val bridge = new CachelessBusToAxi4Shared(fcp.logic.bus) + val bridge = new CachelessBusToAxi4(fcp.logic.bus) master(bridge.axi) } } -class CachelessBusToAxi4Shared(up : CachelessBus) extends Area{ +class CachelessBusToAxi4(up : CachelessBus) extends Area{ assert(up.p.cmdPersistence) val axi = Axi4ReadOnly(up.p.toAxi4Config()) @@ -71,3 +72,37 @@ class CachelessBusToAxi4Shared(up : CachelessBus) extends Area{ axi.r.ready := True } + +class FetchCachelessWishbonePlugin() extends FiberPlugin { + val logic = during build new Area{ + val fcp = host[FetchCachelessPlugin] + fcp.logic.bus.setAsDirectionLess() + + val bridge = new CachelessBusToWishbone(fcp.logic.bus) + master(bridge.bus) + } +} + +class CachelessBusToWishbone(up : CachelessBus) extends Area{ + val wishboneConfig = up.p.toWishboneConfig() + val bus = Wishbone(wishboneConfig) + val cmdPipe = up.cmd.stage() + + bus.ADR := (cmdPipe.address >> log2Up(up.p.dataWidth/8)) + bus.CTI := B"000" + bus.BTE := "00" + bus.SEL.setAll() + bus.WE := False + bus.DAT_MOSI.assignDontCare() + bus.CYC := cmdPipe.valid + bus.STB := cmdPipe.valid + + cmdPipe.ready := cmdPipe.valid && (bus.ACK || bus.ERR) + up.rsp.valid := bus.CYC && (bus.ACK || bus.ERR) + up.rsp.word := bus.DAT_MISO + up.rsp.id := cmdPipe.id + up.rsp.error := bus.ERR + bus +} + + diff --git a/src/main/scala/vexiiriscv/fetch/FetchCachelessBus.scala b/src/main/scala/vexiiriscv/fetch/FetchCachelessBus.scala index d0010fef..66fe9bb1 100644 --- a/src/main/scala/vexiiriscv/fetch/FetchCachelessBus.scala +++ b/src/main/scala/vexiiriscv/fetch/FetchCachelessBus.scala @@ -9,6 +9,7 @@ import spinal.lib.misc.database.Database._ import spinal.lib.misc.pipeline._ import spinal.lib.bus.tilelink import spinal.lib.bus.tilelink.DebugId +import spinal.lib.bus.wishbone.WishboneConfig case class CachelessBusParam(addressWidth : Int, dataWidth : Int, @@ -46,6 +47,22 @@ case class CachelessBusParam(addressWidth : Int, useLen = false, useResp = true ) + + def toWishboneConfig() = WishboneConfig( + addressWidth = addressWidth - log2Up(dataWidth/8), + dataWidth = dataWidth, + selWidth = dataWidth/8, + useSTALL = false, + useLOCK = false, + useERR = true, + useRTY = false, + tgaWidth = 0, + tgcWidth = 0, + tgdWidth = 0, + useBTE = true, + useCTI = true + ) + } case class CachelessCmd(p : CachelessBusParam) extends Bundle{ diff --git a/src/main/scala/vexiiriscv/tester/TestBench.scala b/src/main/scala/vexiiriscv/tester/TestBench.scala index 5c36235a..96ab55f9 100644 --- a/src/main/scala/vexiiriscv/tester/TestBench.scala +++ b/src/main/scala/vexiiriscv/tester/TestBench.scala @@ -9,12 +9,14 @@ import spinal.lib.{CheckSocketPort, DoCmd} import spinal.lib.bus.misc.{AddressMapping, SizeMapping} import spinal.lib.bus.tilelink.{M2sTransfers, SizeRange} import spinal.lib.bus.tilelink.sim.{Checker, MemoryAgent, TransactionA} +import spinal.lib.bus.wishbone.Wishbone import spinal.lib.com.jtag.sim.{JtagRemote, JtagTcp} import spinal.lib.misc.Elf import spinal.lib.misc.plugin.Hostable import spinal.lib.misc.test.DualSimTracer import spinal.lib.sim.{FlowDriver, SparseMemory, StreamDriver, StreamMonitor, StreamReadyRandomizer} import spinal.lib.system.tag.{MemoryTransfers, PmaRegion} +import spinal.lib.wishbone.sim.{WishboneDriver, WishboneMonitor, WishboneTransaction} import vexiiriscv._ import vexiiriscv.execute.cfu.{CfuPlugin, CfuRsp} import vexiiriscv.execute.lsu.{LsuCachelessPlugin, LsuL1, LsuL1Plugin, LsuL1TlPlugin, LsuPlugin} @@ -336,11 +338,33 @@ class TestOptions{ val fetchUncachedAxi4 = dut.host.get[fetch.FetchCachelessAxi4Plugin].map { p => mapFetchAxi4(p.logic.bridge.axi) } - val fetchCachedAxi4 = dut.host.get[fetch.FetchL1Axi4Plugin].map { p => mapFetchAxi4(p.logic.axi) } + def mapFetchWishbone(bus : Wishbone): Unit = { + val addressShift = log2Up(bus.config.dataWidth/8) + cd.onSamplings{ + delayed(1) { + if (simRandom.nextFloat() < ibusReadyFactor && bus.CYC.toBoolean && bus.STB.toBoolean) { + val addr = bus.ADR.toLong << addressShift + val bytes = mem.readBytes(addr, bus.config.dataWidth / 8) + val data = BigInt(1, bytes.reverse) + bus.DAT_MISO #= data + bus.ERR #= addr < 0x20000000 + bus.ACK #= true + } else { + bus.ACK #= false + bus.ERR #= false + } + } + } + } + + val fetchUncachedWishbone = dut.host.get[fetch.FetchCachelessWishbonePlugin].map { p => + mapFetchWishbone(p.logic.bridge.bus) + } + val fclp = dut.host.get[fetch.FetchCachelessPlugin].filter(!_.logic.bus.cmd.valid.isDirectionLess).map { p => val bus = p.logic.bus val cmdReady = StreamReadyRandomizer(bus.cmd, cd)