rework flush with flushNext and flushIt
static branch prediction jump do not depend on stage fireing anymore
This commit is contained in:
parent
0e2d40c37f
commit
af0755d8cf
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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))){
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
// }
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue