diff --git a/src/main/scala/vexriscv/TestsWorkspace.scala b/src/main/scala/vexriscv/TestsWorkspace.scala index ccedab4..0749b2c 100644 --- a/src/main/scala/vexriscv/TestsWorkspace.scala +++ b/src/main/scala/vexriscv/TestsWorkspace.scala @@ -31,32 +31,33 @@ object TestsWorkspace { SpinalConfig(mergeAsyncProcess = false).generateVerilog { val configFull = VexRiscvConfig( plugins = List( - new IBusSimplePlugin( - resetVector = 0x80000000l, - relaxedPcCalculation = false, - prediction = NONE, - catchAccessFault = true, - catchAddressMisaligned = true, - compressedGen = true - ), -// new IBusCachedPlugin( -// config = InstructionCacheConfig( -// cacheSize = 1024*16, -// bytePerLine = 32, -// wayCount = 1, -// addressWidth = 32, -// cpuDataWidth = 32, -// memDataWidth = 32, -// catchIllegalAccess = false, -// catchAccessFault = true, -// catchMemoryTranslationMiss = false, -// asyncTagMemory = false, -// twoCycleRam = false -// )//, -//// memoryTranslatorPortConfig = MemoryTranslatorPortConfig( -//// portTlbSize = 4 -//// ) +// new IBusSimplePlugin( +// resetVector = 0x80000000l, +// relaxedPcCalculation = false, +// prediction = NONE, +// catchAccessFault = true, +// catchAddressMisaligned = false, +// compressedGen = true // ), + new IBusCachedPlugin( + config = InstructionCacheConfig( + cacheSize = 1024*16, + bytePerLine = 32, + wayCount = 1, + addressWidth = 32, + cpuDataWidth = 32, + memDataWidth = 32, + catchIllegalAccess = false, + catchAccessFault = true, + catchMemoryTranslationMiss = false, + asyncTagMemory = false, + twoCycleRam = false, + twoCycleCache = true + )//, +// memoryTranslatorPortConfig = MemoryTranslatorPortConfig( +// portTlbSize = 4 +// ) + ), // new DBusSimplePlugin( // catchAddressMisaligned = true, // catchAccessFault = true, diff --git a/src/main/scala/vexriscv/ip/InstructionCache.scala b/src/main/scala/vexriscv/ip/InstructionCache.scala index ed95756..f137e43 100644 --- a/src/main/scala/vexriscv/ip/InstructionCache.scala +++ b/src/main/scala/vexriscv/ip/InstructionCache.scala @@ -23,7 +23,6 @@ case class InstructionCacheConfig( cacheSize : Int, assert(!(twoCycleRam && !twoCycleCache)) - def dataOnDecode = twoCycleRam && wayCount > 1 def burstSize = bytePerLine*8/memDataWidth def catchSomething = catchAccessFault || catchMemoryTranslationMiss || catchIllegalAccess @@ -60,7 +59,15 @@ case class InstructionCacheCpuPrefetch(p : InstructionCacheConfig) extends Bundl } } -case class InstructionCacheCpuFetch(p : InstructionCacheConfig) extends Bundle with IMasterSlave { +trait InstructionCacheCommons{ + val isValid : Bool + val isStuck : Bool + val pc : UInt + val data : Bits + val cacheMiss, error, mmuMiss, illegalAccess,isUser : Bool +} + +case class InstructionCacheCpuFetch(p : InstructionCacheConfig) extends Bundle with IMasterSlave with InstructionCacheCommons { val isValid = Bool val isStuck = Bool val pc = UInt(p.addressWidth bits) @@ -77,11 +84,11 @@ case class InstructionCacheCpuFetch(p : InstructionCacheConfig) extends Bundle w } -case class InstructionCacheCpuDecode(p : InstructionCacheConfig) extends Bundle with IMasterSlave { +case class InstructionCacheCpuDecode(p : InstructionCacheConfig) extends Bundle with IMasterSlave with InstructionCacheCommons { val isValid = Bool val isStuck = Bool val pc = UInt(p.addressWidth bits) - val data = ifGen(p.dataOnDecode) (Bits(p.cpuDataWidth bits)) + val data = Bits(p.cpuDataWidth bits) val cacheMiss, error, mmuMiss, illegalAccess, isUser = ifGen(p.twoCycleCache)(Bool) override def asMaster(): Unit = { @@ -309,6 +316,9 @@ class InstructionCache(p : InstructionCacheConfig) extends Component{ val data = read.waysValues.map(_.data).read(id) val word = data.subdivideIn(cpuDataWidth bits).read(io.cpu.fetch.pc(memWordToCpuWordRange)) io.cpu.fetch.data := word + if(twoCycleCache){ + io.cpu.decode.data := RegNextWhen(io.cpu.fetch.data,!io.cpu.decode.isStuck) + } } else null if(twoCycleRam && wayCount == 1){ @@ -345,11 +355,9 @@ class InstructionCache(p : InstructionCacheConfig) extends Component{ val valid = Cat(hits).orR val id = OHToUInt(hits) val error = tags(id).error - if(dataOnDecode) { - val data = fetchStage.read.waysValues.map(way => stage(way.data)).read(id) - val word = data.subdivideIn(cpuDataWidth bits).read(io.cpu.decode.pc(memWordToCpuWordRange)) - io.cpu.decode.data := word - } + val data = fetchStage.read.waysValues.map(way => stage(way.data)).read(id) + val word = data.subdivideIn(cpuDataWidth bits).read(io.cpu.decode.pc(memWordToCpuWordRange)) + io.cpu.decode.data := word } io.cpu.decode.cacheMiss := !hit.valid diff --git a/src/main/scala/vexriscv/plugin/IBusCachedPlugin.scala b/src/main/scala/vexriscv/plugin/IBusCachedPlugin.scala index f3dd0ba..6212234 100644 --- a/src/main/scala/vexriscv/plugin/IBusCachedPlugin.scala +++ b/src/main/scala/vexriscv/plugin/IBusCachedPlugin.scala @@ -13,14 +13,14 @@ class IBusCachedPlugin(config : InstructionCacheConfig, memoryTranslatorPortConf catchAccessFault = config.catchAccessFault, resetVector = BigInt(0x80000000l), keepPcPlus4 = false, - decodePcGen = false, - compressedGen = false, - cmdToRspStageCount = 1, + decodePcGen = true, + compressedGen = true, + cmdToRspStageCount = (if(config.twoCycleCache) 2 else 1), injectorReadyCutGen = false, relaxedPcCalculation = false, prediction = NONE, catchAddressMisaligned = false, - injectorStage = true){ + injectorStage = !config.twoCycleCache){ import config._ var iBus : InstructionCacheMemBus = null @@ -103,6 +103,19 @@ class IBusCachedPlugin(config : InstructionCacheConfig, memoryTranslatorPortConf cache.io.cpu.fetch.isStuck := !iBusRsp.input.ready cache.io.cpu.fetch.pc := iBusRsp.inputPipeline(0).payload + + if(twoCycleCache){ + cache.io.cpu.decode.isValid := iBusRsp.inputPipeline(1).valid + cache.io.cpu.decode.isStuck := !iBusRsp.input.ready + cache.io.cpu.decode.pc := iBusRsp.inputPipeline(1).payload + cache.io.cpu.decode.isUser := (if (privilegeService != null) privilegeService.isUser(decode) else False) + + if((!twoCycleRam || wayCount == 1) && !compressedGen){ + decode.insert(INSTRUCTION_ANTICIPATED) := Mux(decode.arbitration.isStuck, decode.input(INSTRUCTION), cache.io.cpu.fetch.data) + } + } + + if (mmuBus != null) { cache.io.cpu.fetch.mmuBus <> mmuBus } else { @@ -116,40 +129,34 @@ class IBusCachedPlugin(config : InstructionCacheConfig, memoryTranslatorPortConf } // val missHalt = cache.io.cpu.fetch.isValid && cache.io.cpu.fetch.cacheMiss + val cacheRsp = if(twoCycleCache) cache.io.cpu.decode else cache.io.cpu.fetch + val cacheRspArbitration = iBusRsp.inputPipeline(if(twoCycleCache) 1 else 0) var issueDetected = False - val redoFetch = False //RegNext(False) init(False) - when(cache.io.cpu.fetch.isValid && cache.io.cpu.fetch.cacheMiss && !issueDetected){ + when(cacheRsp.isValid && cacheRsp.cacheMiss && !issueDetected){ issueDetected \= True redoFetch := iBusRsp.readyForError -// if(decodePcGen) { -// redoFetch := !flush && iBusRsp.readyForError -// } else { -// redoFetch := !flush && iBusRsp.readyForError -// } } cache.io.cpu.fill.valid := redoFetch redoBranch.valid := redoFetch assert(decodePcGen == compressedGen) - redoBranch.payload := (if(decodePcGen) decode.input(PC) else cache.io.cpu.fetch.pc) - cache.io.cpu.fill.payload := cache.io.cpu.fetch.pc + redoBranch.payload := (if(decodePcGen) decode.input(PC) else cacheRsp.pc) + cache.io.cpu.fill.payload := cacheRsp.pc if(catchSomething){ -// val missHalt = cache.io.cpu.fetch.isValid && cache.io.cpu.fetch.cacheMiss - decodeExceptionPort.valid := False decodeExceptionPort.code := 1 - decodeExceptionPort.badAddr := cache.io.cpu.fetch.pc - when(cache.io.cpu.fetch.isValid && cache.io.cpu.fetch.error && !issueDetected){ + decodeExceptionPort.badAddr := cacheRsp.pc + when(cacheRsp.isValid && cacheRsp.error && !issueDetected){ issueDetected \= True decodeExceptionPort.valid := iBusRsp.readyForError } } - iBusRsp.output.arbitrationFrom(iBusRsp.inputPipeline(0).haltWhen(issueDetected)) - iBusRsp.output.rsp.inst := cache.io.cpu.fetch.data - iBusRsp.output.pc := iBusRsp.inputPipeline(0).payload + iBusRsp.output.arbitrationFrom(cacheRspArbitration.haltWhen(issueDetected)) + iBusRsp.output.rsp.inst := cacheRsp.data + iBusRsp.output.pc := cacheRspArbitration.payload // if (dataOnDecode) {