From af0755d8cf1807a190bd6153444140ab2c9b67a5 Mon Sep 17 00:00:00 2001 From: Charles Papon Date: Sun, 9 Jun 2019 15:44:05 +0200 Subject: [PATCH] rework flush with flushNext and flushIt static branch prediction jump do not depend on stage fireing anymore --- src/main/scala/vexriscv/Pipeline.scala | 4 +++- src/main/scala/vexriscv/Stage.scala | 3 ++- src/main/scala/vexriscv/VexRiscv.scala | 2 +- .../scala/vexriscv/plugin/BranchPlugin.scala | 18 +++++++++--------- src/main/scala/vexriscv/plugin/CsrPlugin.scala | 6 +++--- .../vexriscv/plugin/DBusCachedPlugin.scala | 3 ++- .../vexriscv/plugin/DBusSimplePlugin.scala | 3 ++- .../scala/vexriscv/plugin/DebugPlugin.scala | 3 ++- src/main/scala/vexriscv/plugin/Fetcher.scala | 9 +++++++-- .../vexriscv/plugin/IBusCachedPlugin.scala | 3 +++ .../vexriscv/plugin/IBusSimplePlugin.scala | 4 +++- 11 files changed, 37 insertions(+), 21 deletions(-) diff --git a/src/main/scala/vexriscv/Pipeline.scala b/src/main/scala/vexriscv/Pipeline.scala index 14fe071..2a04ef2 100644 --- a/src/main/scala/vexriscv/Pipeline.scala +++ b/src/main/scala/vexriscv/Pipeline.scala @@ -17,6 +17,8 @@ trait Pipeline { val things = mutable.HashMap[PipelineThing[_], Any]() // val services = ArrayBuffer[Any]() + def stageBefore(stage : Stage) = stages(indexOf(stage)-1) + def indexOf(stage : Stage) = stages.indexOf(stage) def service[T](clazz : Class[T]) = { @@ -127,7 +129,7 @@ trait Pipeline { //Arbitration for(stageIndex <- 0 until stages.length; stage = stages(stageIndex)) { - stage.arbitration.isFlushed := stages.drop(stageIndex).map(_.arbitration.flushAll).orR + stage.arbitration.isFlushed := stages.drop(stageIndex+1).map(_.arbitration.flushNext).orR || stages.drop(stageIndex).map(_.arbitration.flushIt).orR if(!unremovableStages.contains(stage)) stage.arbitration.removeIt setWhen stage.arbitration.isFlushed else diff --git a/src/main/scala/vexriscv/Stage.scala b/src/main/scala/vexriscv/Stage.scala index f036dfb..d86c256 100644 --- a/src/main/scala/vexriscv/Stage.scala +++ b/src/main/scala/vexriscv/Stage.scala @@ -49,7 +49,8 @@ class Stage() extends Area{ val haltItself = False //user settable, stuck the instruction, should only be set by the instruction itself val haltByOther = False //When settable, stuck the instruction, should only be set by something else than the stucked instruction val removeIt = False //When settable, unschedule the instruction as if it was never executed (no side effect) - val flushAll = False //When settable, unschedule instructions in the current stage and all prior ones + val flushIt = False //When settable, unschedule the current instruction + val flushNext = False //When settable, unschedule instruction above in the pipeline val isValid = Bool //Inform if a instruction is in the current stage val isStuck = Bool //Inform if the instruction is stuck (haltItself || haltByOther) val isStuckByOthers = Bool //Inform if the instruction is stuck by sombody else diff --git a/src/main/scala/vexriscv/VexRiscv.scala b/src/main/scala/vexriscv/VexRiscv.scala index 26d9489..1e38791 100644 --- a/src/main/scala/vexriscv/VexRiscv.scala +++ b/src/main/scala/vexriscv/VexRiscv.scala @@ -109,7 +109,7 @@ class VexRiscv(val config : VexRiscvConfig) extends Component with Pipeline{ if(withMemoryStage){ memory.arbitration.removeIt.noBackendCombMerge } - execute.arbitration.flushAll.noBackendCombMerge + execute.arbitration.flushNext.noBackendCombMerge this(RVC_GEN) = false } diff --git a/src/main/scala/vexriscv/plugin/BranchPlugin.scala b/src/main/scala/vexriscv/plugin/BranchPlugin.scala index 6885f2a..30341d3 100644 --- a/src/main/scala/vexriscv/plugin/BranchPlugin.scala +++ b/src/main/scala/vexriscv/plugin/BranchPlugin.scala @@ -200,11 +200,11 @@ class BranchPlugin(earlyBranch : Boolean, //Apply branchs (JAL,JALR, Bxx) branchStage plug new Area { import branchStage._ - jumpInterface.valid := arbitration.isValid && !arbitration.isStuckByOthers && input(BRANCH_DO) + jumpInterface.valid := arbitration.isValid && input(BRANCH_DO) jumpInterface.payload := input(BRANCH_CALC) - when(jumpInterface.valid) { - stages(indexOf(branchStage) - 1).arbitration.flushAll := True + when(jumpInterface.valid && !arbitration.isStuckByOthers) { + arbitration.flushNext := True } if(catchAddressMisalignedForReal) { @@ -282,11 +282,11 @@ class BranchPlugin(earlyBranch : Boolean, val branchStage = if(earlyBranch) execute else memory branchStage plug new Area { import branchStage._ - jumpInterface.valid := arbitration.isValid && !arbitration.isStuckByOthers && input(BRANCH_DO) + jumpInterface.valid := arbitration.isValid && input(BRANCH_DO) jumpInterface.payload := input(BRANCH_CALC) - when(jumpInterface.valid) { - stages(indexOf(branchStage) - 1).arbitration.flushAll := True + when(jumpInterface.valid && !arbitration.isStuckByOthers) { + arbitration.flushNext := True } if(catchAddressMisalignedForReal) { @@ -361,12 +361,12 @@ class BranchPlugin(earlyBranch : Boolean, input(PC) } - jumpInterface.valid := arbitration.isValid && !arbitration.isStuckByOthers && predictionMissmatch //Probably just isValid instead of isFiring is better + jumpInterface.valid := arbitration.isValid && predictionMissmatch //Probably just isValid instead of isFiring is better jumpInterface.payload := (input(BRANCH_DO) ? input(BRANCH_CALC) | input(NEXT_PC)) - when(jumpInterface.valid) { - stages(indexOf(branchStage) - 1).arbitration.flushAll := True + when(jumpInterface.valid && !arbitration.isStuckByOthers) { + arbitration.flushNext := True } if(catchAddressMisalignedForReal) { diff --git a/src/main/scala/vexriscv/plugin/CsrPlugin.scala b/src/main/scala/vexriscv/plugin/CsrPlugin.scala index 4030ab7..756156c 100644 --- a/src/main/scala/vexriscv/plugin/CsrPlugin.scala +++ b/src/main/scala/vexriscv/plugin/CsrPlugin.scala @@ -694,7 +694,7 @@ class CsrPlugin(val config: CsrPluginConfig) extends Plugin[VexRiscv] with Excep exceptionValids := exceptionValidsRegs for(portInfo <- sortedByStage; port = portInfo.port ; stage = portInfo.stage; stageId = indexOf(portInfo.stage)) { when(port.valid) { - if(indexOf(stage) != 0) stages(indexOf(stage) - 1).arbitration.flushAll := True + stage.arbitration.flushNext := True stage.arbitration.removeIt := True exceptionValids(stageId) := True exceptionContext := port.payload @@ -806,7 +806,7 @@ class CsrPlugin(val config: CsrPluginConfig) extends Plugin[VexRiscv] with Excep jumpInterface.valid := True jumpInterface.payload := (if(!xtvecModeGen) xtvec.base @@ "00" else (xtvec.mode === 0 || hadException) ? (xtvec.base @@ "00") | ((xtvec.base + trapCause) @@ "00") ) - beforeLastStage.arbitration.flushAll := True + lastStage.arbitration.flushNext := True if(privilegeGen) privilegeReg := targetPrivilege @@ -845,7 +845,7 @@ class CsrPlugin(val config: CsrPluginConfig) extends Plugin[VexRiscv] with Excep when(arbitration.isValid && input(ENV_CTRL) === EnvCtrlEnum.XRET) { fetcher.haltIt() jumpInterface.valid := True - beforeLastStage.arbitration.flushAll := True + lastStage.arbitration.flushNext := True switch(input(INSTRUCTION)(29 downto 28)){ is(3){ mstatus.MPP := U"00" diff --git a/src/main/scala/vexriscv/plugin/DBusCachedPlugin.scala b/src/main/scala/vexriscv/plugin/DBusCachedPlugin.scala index 8584a8c..a8aa740 100644 --- a/src/main/scala/vexriscv/plugin/DBusCachedPlugin.scala +++ b/src/main/scala/vexriscv/plugin/DBusCachedPlugin.scala @@ -239,7 +239,8 @@ class DBusCachedPlugin(config : DataCacheConfig, redoBranch.valid := False redoBranch.payload := input(PC) - arbitration.flushAll setWhen(redoBranch.valid) + arbitration.flushIt setWhen(redoBranch.valid) + arbitration.flushNext setWhen(redoBranch.valid) if(catchSomething) { exceptionBus.valid := False //cache.io.cpu.writeBack.mmuMiss || cache.io.cpu.writeBack.accessError || cache.io.cpu.writeBack.illegalAccess || cache.io.cpu.writeBack.unalignedAccess diff --git a/src/main/scala/vexriscv/plugin/DBusSimplePlugin.scala b/src/main/scala/vexriscv/plugin/DBusSimplePlugin.scala index 661b524..a17874c 100644 --- a/src/main/scala/vexriscv/plugin/DBusSimplePlugin.scala +++ b/src/main/scala/vexriscv/plugin/DBusSimplePlugin.scala @@ -476,7 +476,8 @@ class DBusSimplePlugin(catchAddressMisaligned : Boolean = false, memoryExceptionPort.code := (input(MEMORY_STORE) ? U(15) | U(13)).resized } - arbitration.flushAll setWhen(redoBranch.valid) + arbitration.flushIt setWhen(redoBranch.valid) + arbitration.flushNext setWhen(redoBranch.valid) } when(!(arbitration.isValid && input(MEMORY_ENABLE) && (Bool(cmdStage != rspStage) || !arbitration.isStuckByOthers))){ diff --git a/src/main/scala/vexriscv/plugin/DebugPlugin.scala b/src/main/scala/vexriscv/plugin/DebugPlugin.scala index 454d352..4088cec 100644 --- a/src/main/scala/vexriscv/plugin/DebugPlugin.scala +++ b/src/main/scala/vexriscv/plugin/DebugPlugin.scala @@ -203,7 +203,8 @@ class DebugPlugin(val debugClockDomain : ClockDomain, hardwareBreakpointCount : when(stagesFromExecute.tail.map(_.arbitration.isValid).orR === False){ iBusFetcher.flushIt() iBusFetcher.haltIt() - execute.arbitration.flushAll := True + execute.arbitration.flushIt := True + execute.arbitration.flushNext := True haltIt := True haltedByBreak := True } diff --git a/src/main/scala/vexriscv/plugin/Fetcher.scala b/src/main/scala/vexriscv/plugin/Fetcher.scala index 62d4aa7..aa1daae 100644 --- a/src/main/scala/vexriscv/plugin/Fetcher.scala +++ b/src/main/scala/vexriscv/plugin/Fetcher.scala @@ -103,7 +103,7 @@ abstract class IBusFetcherImpl(val resetVector : BigInt, pcLoad.payload := MuxOH(OHMasking.first(valids.asBits), pcs) } - def flush = jump.pcLoad.valid || fetcherflushIt + def flush = fetcherflushIt || stages.map(_.arbitration.flushNext).orR class PcFetch extends Area{ val preOutput = Stream(UInt(32 bits)) @@ -499,10 +499,15 @@ abstract class IBusFetcherImpl(val resetVector : BigInt, decodePrediction.cmd.hadBranch clearWhen(missaligned) } - predictionJumpInterface.valid := decodePrediction.cmd.hadBranch && decode.arbitration.isFiring //TODO OH Doublon de priorité + //TODO no more fireing depedancies + predictionJumpInterface.valid := decodePrediction.cmd.hadBranch && decode.arbitration.isValid //TODO OH Doublon de priorité predictionJumpInterface.payload := decode.input(PC) + ((decode.input(BRANCH_CTRL) === BranchCtrlEnum.JAL) ? imm.j_sext | imm.b_sext).asUInt if(relaxPredictorAddress) KeepAttribute(predictionJumpInterface.payload) + when(predictionJumpInterface.valid && decode.arbitration.isFiring){ + flushIt() + } + // when(predictionJumpInterface.payload((if(pipeline(RVC_GEN)) 0 else 1) downto 0) =/= 0){ // decodePrediction.cmd.hadBranch := False // } diff --git a/src/main/scala/vexriscv/plugin/IBusCachedPlugin.scala b/src/main/scala/vexriscv/plugin/IBusCachedPlugin.scala index 92722e9..65c210a 100644 --- a/src/main/scala/vexriscv/plugin/IBusCachedPlugin.scala +++ b/src/main/scala/vexriscv/plugin/IBusCachedPlugin.scala @@ -237,6 +237,9 @@ class IBusCachedPlugin(resetVector : BigInt = 0x80000000l, redoBranch.valid := redoFetch redoBranch.payload := (if (decodePcGen) decode.input(PC) else cacheRsp.pc) + when(redoBranch.valid) { + decode.arbitration.flushNext := True + } cacheRspArbitration.halt setWhen (issueDetected || iBusRspOutputHalt) iBusRsp.output.valid := cacheRspArbitration.output.valid diff --git a/src/main/scala/vexriscv/plugin/IBusSimplePlugin.scala b/src/main/scala/vexriscv/plugin/IBusSimplePlugin.scala index 67dc786..e00e122 100644 --- a/src/main/scala/vexriscv/plugin/IBusSimplePlugin.scala +++ b/src/main/scala/vexriscv/plugin/IBusSimplePlugin.scala @@ -351,7 +351,9 @@ class IBusSimplePlugin(resetVector : BigInt, redoRequired setWhen( stages.last.input.valid && mmu.joinCtx.refilling) redoBranch.valid := redoRequired && iBusRsp.readyForError redoBranch.payload := decode.input(PC) - decode.arbitration.flushAll setWhen(redoBranch.valid) + + decode.arbitration.flushIt setWhen(redoBranch.valid) + decode.arbitration.flushNext setWhen(redoBranch.valid) }