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 things = mutable.HashMap[PipelineThing[_], Any]()
|
||||||
// val services = ArrayBuffer[Any]()
|
// val services = ArrayBuffer[Any]()
|
||||||
|
|
||||||
|
def stageBefore(stage : Stage) = stages(indexOf(stage)-1)
|
||||||
|
|
||||||
def indexOf(stage : Stage) = stages.indexOf(stage)
|
def indexOf(stage : Stage) = stages.indexOf(stage)
|
||||||
|
|
||||||
def service[T](clazz : Class[T]) = {
|
def service[T](clazz : Class[T]) = {
|
||||||
|
@ -127,7 +129,7 @@ trait Pipeline {
|
||||||
|
|
||||||
//Arbitration
|
//Arbitration
|
||||||
for(stageIndex <- 0 until stages.length; stage = stages(stageIndex)) {
|
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))
|
if(!unremovableStages.contains(stage))
|
||||||
stage.arbitration.removeIt setWhen stage.arbitration.isFlushed
|
stage.arbitration.removeIt setWhen stage.arbitration.isFlushed
|
||||||
else
|
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 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 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 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 isValid = Bool //Inform if a instruction is in the current stage
|
||||||
val isStuck = Bool //Inform if the instruction is stuck (haltItself || haltByOther)
|
val isStuck = Bool //Inform if the instruction is stuck (haltItself || haltByOther)
|
||||||
val isStuckByOthers = Bool //Inform if the instruction is stuck by sombody else
|
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){
|
if(withMemoryStage){
|
||||||
memory.arbitration.removeIt.noBackendCombMerge
|
memory.arbitration.removeIt.noBackendCombMerge
|
||||||
}
|
}
|
||||||
execute.arbitration.flushAll.noBackendCombMerge
|
execute.arbitration.flushNext.noBackendCombMerge
|
||||||
|
|
||||||
this(RVC_GEN) = false
|
this(RVC_GEN) = false
|
||||||
}
|
}
|
||||||
|
|
|
@ -200,11 +200,11 @@ class BranchPlugin(earlyBranch : Boolean,
|
||||||
//Apply branchs (JAL,JALR, Bxx)
|
//Apply branchs (JAL,JALR, Bxx)
|
||||||
branchStage plug new Area {
|
branchStage plug new Area {
|
||||||
import branchStage._
|
import branchStage._
|
||||||
jumpInterface.valid := arbitration.isValid && !arbitration.isStuckByOthers && input(BRANCH_DO)
|
jumpInterface.valid := arbitration.isValid && input(BRANCH_DO)
|
||||||
jumpInterface.payload := input(BRANCH_CALC)
|
jumpInterface.payload := input(BRANCH_CALC)
|
||||||
|
|
||||||
when(jumpInterface.valid) {
|
when(jumpInterface.valid && !arbitration.isStuckByOthers) {
|
||||||
stages(indexOf(branchStage) - 1).arbitration.flushAll := True
|
arbitration.flushNext := True
|
||||||
}
|
}
|
||||||
|
|
||||||
if(catchAddressMisalignedForReal) {
|
if(catchAddressMisalignedForReal) {
|
||||||
|
@ -282,11 +282,11 @@ class BranchPlugin(earlyBranch : Boolean,
|
||||||
val branchStage = if(earlyBranch) execute else memory
|
val branchStage = if(earlyBranch) execute else memory
|
||||||
branchStage plug new Area {
|
branchStage plug new Area {
|
||||||
import branchStage._
|
import branchStage._
|
||||||
jumpInterface.valid := arbitration.isValid && !arbitration.isStuckByOthers && input(BRANCH_DO)
|
jumpInterface.valid := arbitration.isValid && input(BRANCH_DO)
|
||||||
jumpInterface.payload := input(BRANCH_CALC)
|
jumpInterface.payload := input(BRANCH_CALC)
|
||||||
|
|
||||||
when(jumpInterface.valid) {
|
when(jumpInterface.valid && !arbitration.isStuckByOthers) {
|
||||||
stages(indexOf(branchStage) - 1).arbitration.flushAll := True
|
arbitration.flushNext := True
|
||||||
}
|
}
|
||||||
|
|
||||||
if(catchAddressMisalignedForReal) {
|
if(catchAddressMisalignedForReal) {
|
||||||
|
@ -361,12 +361,12 @@ class BranchPlugin(earlyBranch : Boolean,
|
||||||
input(PC)
|
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))
|
jumpInterface.payload := (input(BRANCH_DO) ? input(BRANCH_CALC) | input(NEXT_PC))
|
||||||
|
|
||||||
|
|
||||||
when(jumpInterface.valid) {
|
when(jumpInterface.valid && !arbitration.isStuckByOthers) {
|
||||||
stages(indexOf(branchStage) - 1).arbitration.flushAll := True
|
arbitration.flushNext := True
|
||||||
}
|
}
|
||||||
|
|
||||||
if(catchAddressMisalignedForReal) {
|
if(catchAddressMisalignedForReal) {
|
||||||
|
|
|
@ -694,7 +694,7 @@ class CsrPlugin(val config: CsrPluginConfig) extends Plugin[VexRiscv] with Excep
|
||||||
exceptionValids := exceptionValidsRegs
|
exceptionValids := exceptionValidsRegs
|
||||||
for(portInfo <- sortedByStage; port = portInfo.port ; stage = portInfo.stage; stageId = indexOf(portInfo.stage)) {
|
for(portInfo <- sortedByStage; port = portInfo.port ; stage = portInfo.stage; stageId = indexOf(portInfo.stage)) {
|
||||||
when(port.valid) {
|
when(port.valid) {
|
||||||
if(indexOf(stage) != 0) stages(indexOf(stage) - 1).arbitration.flushAll := True
|
stage.arbitration.flushNext := True
|
||||||
stage.arbitration.removeIt := True
|
stage.arbitration.removeIt := True
|
||||||
exceptionValids(stageId) := True
|
exceptionValids(stageId) := True
|
||||||
exceptionContext := port.payload
|
exceptionContext := port.payload
|
||||||
|
@ -806,7 +806,7 @@ class CsrPlugin(val config: CsrPluginConfig) extends Plugin[VexRiscv] with Excep
|
||||||
|
|
||||||
jumpInterface.valid := True
|
jumpInterface.valid := True
|
||||||
jumpInterface.payload := (if(!xtvecModeGen) xtvec.base @@ "00" else (xtvec.mode === 0 || hadException) ? (xtvec.base @@ "00") | ((xtvec.base + trapCause) @@ "00") )
|
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
|
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) {
|
when(arbitration.isValid && input(ENV_CTRL) === EnvCtrlEnum.XRET) {
|
||||||
fetcher.haltIt()
|
fetcher.haltIt()
|
||||||
jumpInterface.valid := True
|
jumpInterface.valid := True
|
||||||
beforeLastStage.arbitration.flushAll := True
|
lastStage.arbitration.flushNext := True
|
||||||
switch(input(INSTRUCTION)(29 downto 28)){
|
switch(input(INSTRUCTION)(29 downto 28)){
|
||||||
is(3){
|
is(3){
|
||||||
mstatus.MPP := U"00"
|
mstatus.MPP := U"00"
|
||||||
|
|
|
@ -239,7 +239,8 @@ class DBusCachedPlugin(config : DataCacheConfig,
|
||||||
|
|
||||||
redoBranch.valid := False
|
redoBranch.valid := False
|
||||||
redoBranch.payload := input(PC)
|
redoBranch.payload := input(PC)
|
||||||
arbitration.flushAll setWhen(redoBranch.valid)
|
arbitration.flushIt setWhen(redoBranch.valid)
|
||||||
|
arbitration.flushNext setWhen(redoBranch.valid)
|
||||||
|
|
||||||
if(catchSomething) {
|
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
|
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
|
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))){
|
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){
|
when(stagesFromExecute.tail.map(_.arbitration.isValid).orR === False){
|
||||||
iBusFetcher.flushIt()
|
iBusFetcher.flushIt()
|
||||||
iBusFetcher.haltIt()
|
iBusFetcher.haltIt()
|
||||||
execute.arbitration.flushAll := True
|
execute.arbitration.flushIt := True
|
||||||
|
execute.arbitration.flushNext := True
|
||||||
haltIt := True
|
haltIt := True
|
||||||
haltedByBreak := True
|
haltedByBreak := True
|
||||||
}
|
}
|
||||||
|
|
|
@ -103,7 +103,7 @@ abstract class IBusFetcherImpl(val resetVector : BigInt,
|
||||||
pcLoad.payload := MuxOH(OHMasking.first(valids.asBits), pcs)
|
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{
|
class PcFetch extends Area{
|
||||||
val preOutput = Stream(UInt(32 bits))
|
val preOutput = Stream(UInt(32 bits))
|
||||||
|
@ -499,10 +499,15 @@ abstract class IBusFetcherImpl(val resetVector : BigInt,
|
||||||
decodePrediction.cmd.hadBranch clearWhen(missaligned)
|
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
|
predictionJumpInterface.payload := decode.input(PC) + ((decode.input(BRANCH_CTRL) === BranchCtrlEnum.JAL) ? imm.j_sext | imm.b_sext).asUInt
|
||||||
if(relaxPredictorAddress) KeepAttribute(predictionJumpInterface.payload)
|
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){
|
// when(predictionJumpInterface.payload((if(pipeline(RVC_GEN)) 0 else 1) downto 0) =/= 0){
|
||||||
// decodePrediction.cmd.hadBranch := False
|
// decodePrediction.cmd.hadBranch := False
|
||||||
// }
|
// }
|
||||||
|
|
|
@ -237,6 +237,9 @@ class IBusCachedPlugin(resetVector : BigInt = 0x80000000l,
|
||||||
|
|
||||||
redoBranch.valid := redoFetch
|
redoBranch.valid := redoFetch
|
||||||
redoBranch.payload := (if (decodePcGen) decode.input(PC) else cacheRsp.pc)
|
redoBranch.payload := (if (decodePcGen) decode.input(PC) else cacheRsp.pc)
|
||||||
|
when(redoBranch.valid) {
|
||||||
|
decode.arbitration.flushNext := True
|
||||||
|
}
|
||||||
|
|
||||||
cacheRspArbitration.halt setWhen (issueDetected || iBusRspOutputHalt)
|
cacheRspArbitration.halt setWhen (issueDetected || iBusRspOutputHalt)
|
||||||
iBusRsp.output.valid := cacheRspArbitration.output.valid
|
iBusRsp.output.valid := cacheRspArbitration.output.valid
|
||||||
|
|
|
@ -351,7 +351,9 @@ class IBusSimplePlugin(resetVector : BigInt,
|
||||||
redoRequired setWhen( stages.last.input.valid && mmu.joinCtx.refilling)
|
redoRequired setWhen( stages.last.input.valid && mmu.joinCtx.refilling)
|
||||||
redoBranch.valid := redoRequired && iBusRsp.readyForError
|
redoBranch.valid := redoRequired && iBusRsp.readyForError
|
||||||
redoBranch.payload := decode.input(PC)
|
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