diff --git a/src/main/scala/vexriscv/ip/DataCache.scala b/src/main/scala/vexriscv/ip/DataCache.scala index f692680..17c4bf6 100644 --- a/src/main/scala/vexriscv/ip/DataCache.scala +++ b/src/main/scala/vexriscv/ip/DataCache.scala @@ -24,8 +24,9 @@ case class DataCacheConfig(cacheSize : Int, earlyDataMux : Boolean = false, tagSizeShift : Int = 0, //Used to force infering ram withLrSc : Boolean = false, - withAmo : Boolean = false){ - + withAmo : Boolean = false, + mergeExecuteMemory : Boolean = false){ + assert(!(mergeExecuteMemory && (earlyDataMux || earlyWaysHits))) assert(!(earlyDataMux && !earlyWaysHits)) def burstSize = bytePerLine*8/memDataWidth val burstLength = bytePerLine/(memDataWidth/8) @@ -446,7 +447,7 @@ class DataCache(p : DataCacheConfig) extends Component{ } val stageA = new Area{ - def stagePipe[T <: Data](that : T) = RegNextWhen(that, !io.cpu.memory.isStuck) + def stagePipe[T <: Data](that : T) = if(mergeExecuteMemory) CombInit(that) else RegNextWhen(that, !io.cpu.memory.isStuck) val request = stagePipe(io.cpu.execute.args) val mask = stagePipe(stage0.mask) io.cpu.memory.mmuBus.cmd.isValid := io.cpu.memory.isValid @@ -457,16 +458,22 @@ class DataCache(p : DataCacheConfig) extends Component{ val wayHits = earlyWaysHits generate ways.map(way => (io.cpu.memory.mmuBus.rsp.physicalAddress(tagRange) === way.tagsReadRsp.address && way.tagsReadRsp.valid)) val dataMux = earlyDataMux generate MuxOH(wayHits, ways.map(_.dataReadRsp)) - val colisions = stagePipe(stage0.colisions) | collisionProcess(io.cpu.memory.address(lineRange.high downto wordRange.low), mask) //Assume the writeback stage will never be unstall memory acces while memory stage is stalled + val colisions = if(mergeExecuteMemory){ + stagePipe(stage0.colisions) + } else { + //Assume the writeback stage will never be unstall memory acces while memory stage is stalled + stagePipe(stage0.colisions) | collisionProcess(io.cpu.memory.address(lineRange.high downto wordRange.low), mask) + } } val stageB = new Area { def stagePipe[T <: Data](that : T) = RegNextWhen(that, !io.cpu.writeBack.isStuck) + def ramPipe[T <: Data](that : T) = if(mergeExecuteMemory) CombInit(that) else RegNextWhen(that, !io.cpu.writeBack.isStuck) val request = RegNextWhen(stageA.request, !io.cpu.writeBack.isStuck) val mmuRspFreeze = False val mmuRsp = RegNextWhen(io.cpu.memory.mmuBus.rsp, !io.cpu.writeBack.isStuck && !mmuRspFreeze) - val tagsReadRsp = ways.map(w => stagePipe(w.tagsReadRsp)) - val dataReadRsp = !earlyDataMux generate ways.map(w => stagePipe(w.dataReadRsp)) + val tagsReadRsp = ways.map(w => ramPipe(w.tagsReadRsp)) + val dataReadRsp = !earlyDataMux generate ways.map(w => ramPipe(w.dataReadRsp)) val waysHits = if(earlyWaysHits) stagePipe(B(stageA.wayHits)) else B(tagsReadRsp.map(tag => mmuRsp.physicalAddress(tagRange) === tag.address && tag.valid).asBits()) val waysHit = waysHits.orR val dataMux = if(earlyDataMux) stagePipe(stageA.dataMux) else MuxOH(waysHits, dataReadRsp) diff --git a/src/main/scala/vexriscv/plugin/DBusCachedPlugin.scala b/src/main/scala/vexriscv/plugin/DBusCachedPlugin.scala index 8b1ceb4..9102a72 100644 --- a/src/main/scala/vexriscv/plugin/DBusCachedPlugin.scala +++ b/src/main/scala/vexriscv/plugin/DBusCachedPlugin.scala @@ -148,7 +148,7 @@ class DBusCachedPlugin(val config : DataCacheConfig, redoBranch = pipeline.service(classOf[JumpService]).createJumpInterface(if(pipeline.writeBack != null) pipeline.writeBack else pipeline.execute) if(catchSomething) - exceptionBus = pipeline.service(classOf[ExceptionService]).newExceptionPort(pipeline.writeBack) + exceptionBus = pipeline.service(classOf[ExceptionService]).newExceptionPort(if(pipeline.writeBack == null) pipeline.memory else pipeline.writeBack) if(pipeline.serviceExist(classOf[PrivilegeService])) privilegeService = pipeline.service(classOf[PrivilegeService]) @@ -162,7 +162,9 @@ class DBusCachedPlugin(val config : DataCacheConfig, dBus = master(DataCacheMemBus(this.config)).setName("dBus") - val cache = new DataCache(this.config) + val cache = new DataCache(this.config.copy( + mergeExecuteMemory = writeBack == null + )) //Interconnect the plugin dBus with the cache dBus with some optional pipelining def optionPipe[T](cond : Boolean, on : T)(f : T => T) : T = if(cond) f(on) else on @@ -226,22 +228,22 @@ class DBusCachedPlugin(val config : DataCacheConfig, if(relaxedMemoryTranslationRegister) insert(MEMORY_VIRTUAL_ADDRESS) := cache.io.cpu.execute.address } - val flushStage = if(memory != null) memory else execute - flushStage plug new Area { - import flushStage._ + val mmuAndBufferStage = if(writeBack != null) memory else execute + mmuAndBufferStage plug new Area { + import mmuAndBufferStage._ cache.io.cpu.memory.isValid := arbitration.isValid && input(MEMORY_ENABLE) cache.io.cpu.memory.isStuck := arbitration.isStuck cache.io.cpu.memory.isRemoved := arbitration.removeIt - cache.io.cpu.memory.address := (if(relaxedMemoryTranslationRegister) input(MEMORY_VIRTUAL_ADDRESS) else U(input(REGFILE_WRITE_DATA))) + cache.io.cpu.memory.address := (if(relaxedMemoryTranslationRegister) input(MEMORY_VIRTUAL_ADDRESS) else if(mmuAndBufferStage == execute) cache.io.cpu.execute.address else U(input(REGFILE_WRITE_DATA))) cache.io.cpu.memory.mmuBus <> mmuBus cache.io.cpu.memory.mmuBus.rsp.isIoAccess setWhen(pipeline(DEBUG_BYPASS_CACHE) && !cache.io.cpu.memory.isWrite) } - val fenceStage = stages.last - fenceStage plug new Area{ - import fenceStage._ + val managementStage = stages.last + managementStage plug new Area{ + import managementStage._ cache.io.cpu.writeBack.isValid := arbitration.isValid && input(MEMORY_ENABLE) cache.io.cpu.writeBack.isStuck := arbitration.isStuck cache.io.cpu.writeBack.isUser := (if(privilegeService != null) privilegeService.isUser() else False) @@ -326,10 +328,10 @@ class DBusCachedPlugin(val config : DataCacheConfig, execute.insert(IS_DBUS_SHARING) := dBusAccess.cmd.fire - mmuBus.cmd.bypassTranslation setWhen(flushStage.input(IS_DBUS_SHARING)) - cache.io.cpu.memory.isValid setWhen(flushStage.input(IS_DBUS_SHARING)) - cache.io.cpu.writeBack.isValid setWhen(fenceStage.input(IS_DBUS_SHARING)) - dBusAccess.rsp.valid := fenceStage.input(IS_DBUS_SHARING) && !cache.io.cpu.writeBack.isWrite && (cache.io.cpu.redo || !cache.io.cpu.writeBack.haltIt) + mmuBus.cmd.bypassTranslation setWhen(mmuAndBufferStage.input(IS_DBUS_SHARING)) + if(mmuAndBufferStage != execute) (cache.io.cpu.memory.isValid setWhen(mmuAndBufferStage.input(IS_DBUS_SHARING))) + cache.io.cpu.writeBack.isValid setWhen(managementStage.input(IS_DBUS_SHARING)) + dBusAccess.rsp.valid := managementStage.input(IS_DBUS_SHARING) && !cache.io.cpu.writeBack.isWrite && (cache.io.cpu.redo || !cache.io.cpu.writeBack.haltIt) dBusAccess.rsp.data := cache.io.cpu.writeBack.data dBusAccess.rsp.error := cache.io.cpu.writeBack.unalignedAccess || cache.io.cpu.writeBack.accessError dBusAccess.rsp.redo := cache.io.cpu.redo @@ -337,10 +339,10 @@ class DBusCachedPlugin(val config : DataCacheConfig, when(forceDatapath){ execute.output(REGFILE_WRITE_DATA) := dBusAccess.cmd.address.asBits } - flushStage.input(IS_DBUS_SHARING) init(False) - fenceStage.input(IS_DBUS_SHARING) init(False) + if(mmuAndBufferStage != execute) mmuAndBufferStage.input(IS_DBUS_SHARING) init(False) + managementStage.input(IS_DBUS_SHARING) init(False) when(dBusAccess.rsp.valid){ - fenceStage.input(IS_DBUS_SHARING).getDrivingReg := False + managementStage.input(IS_DBUS_SHARING).getDrivingReg := False } } }