DYNAMIC_TARGET prediction datapath/control path are now splited

This commit is contained in:
Charles Papon 2019-06-10 22:20:32 +02:00
parent 0e95154869
commit 5b53440d27
3 changed files with 20 additions and 24 deletions

View File

@ -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 = fetcherflushIt || stages.map(_.arbitration.flushNext).orR fetcherflushIt setWhen(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))
@ -225,12 +225,12 @@ abstract class IBusFetcherImpl(val resetVector : BigInt,
} }
for((s,sNext) <- (stages, stages.tail).zipped) { for((s,sNext) <- (stages, stages.tail).zipped) {
if(s == stages.head && pcRegReusedForSecondStage) { if(s == stages.head && pcRegReusedForSecondStage && prediction != DYNAMIC_TARGET) { //DYNAMIC_TARGET realy need PC state for both stage(0) and stage(1)
sNext.input.arbitrationFrom(s.output.toEvent().m2sPipeWithFlush(flush, s != stages.head, collapsBubble = false)) sNext.input.arbitrationFrom(s.output.toEvent().m2sPipeWithFlush(fetcherflushIt, s != stages.head, collapsBubble = false))
sNext.input.payload := fetchPc.pcReg sNext.input.payload := fetchPc.pcReg
fetchPc.propagatePc setWhen(sNext.input.fire) fetchPc.propagatePc setWhen(sNext.input.fire)
} else { } else {
sNext.input << s.output.m2sPipeWithFlush(flush, s != stages.head, collapsBubble = false) sNext.input << s.output.m2sPipeWithFlush(fetcherflushIt, s != stages.head, collapsBubble = false)
} }
} }
@ -273,7 +273,7 @@ abstract class IBusFetcherImpl(val resetVector : BigInt,
// input.ready := (bufferValid ? (!isRvc && output.ready) | (input.pc(1) || output.ready)) // input.ready := (bufferValid ? (!isRvc && output.ready) | (input.pc(1) || output.ready))
input.ready := !output.valid || !(!output.ready || (isRvc && !input.pc(1) && input.rsp.inst(16, 2 bits) =/= 3) || (!isRvc && bufferValid && input.rsp.inst(16, 2 bits) =/= 3)) input.ready := !output.valid || !(!output.ready || (isRvc && !input.pc(1) && input.rsp.inst(16, 2 bits) =/= 3) || (!isRvc && bufferValid && input.rsp.inst(16, 2 bits) =/= 3))
addPrePopTask(() => { addPrePopTask(() => {
when(!input.ready && output.fire && !flush /* && ((isRvc && !bufferValid && !input.pc(1)) || (!isRvc && bufferValid && input.rsp.inst(16, 2 bits) =/= 3))*/) { when(!input.ready && output.fire && !fetcherflushIt /* && ((isRvc && !bufferValid && !input.pc(1)) || (!isRvc && bufferValid && input.rsp.inst(16, 2 bits) =/= 3))*/) {
input.pc.getDrivingReg(1) := True input.pc.getDrivingReg(1) := True
} }
}) })
@ -284,7 +284,7 @@ abstract class IBusFetcherImpl(val resetVector : BigInt,
bufferValid := !(!isRvc && !input.pc(1) && !bufferValid) && !(isRvc && input.pc(1) && output.ready) bufferValid := !(!isRvc && !input.pc(1) && !bufferValid) && !(isRvc && input.pc(1) && output.ready)
bufferData := input.rsp.inst(31 downto 16) bufferData := input.rsp.inst(31 downto 16)
} }
bufferValid.clearWhen(flush) bufferValid.clearWhen(fetcherflushIt)
iBusRsp.readyForError.clearWhen(bufferValid && isRvc) //Can't emit error, as there is a earlier instruction pending iBusRsp.readyForError.clearWhen(bufferValid && isRvc) //Can't emit error, as there is a earlier instruction pending
incomingInstruction setWhen(bufferValid && bufferData(1 downto 0) =/= 3) incomingInstruction setWhen(bufferValid && bufferData(1 downto 0) =/= 3)
}) })
@ -292,13 +292,13 @@ abstract class IBusFetcherImpl(val resetVector : BigInt,
def condApply[T](that : T, cond : Boolean)(func : (T) => T) = if(cond)func(that) else that def condApply[T](that : T, cond : Boolean)(func : (T) => T) = if(cond)func(that) else that
val injector = new Area { val injector = new Area {
val inputBeforeStage = condApply(if (decodePcGen) decompressor.output else iBusRsp.output, injectorReadyCutGen)(_.s2mPipe(flush)) val inputBeforeStage = condApply(if (decodePcGen) decompressor.output else iBusRsp.output, injectorReadyCutGen)(_.s2mPipe(fetcherflushIt))
if (injectorReadyCutGen) { if (injectorReadyCutGen) {
iBusRsp.readyForError.clearWhen(inputBeforeStage.valid) //Can't emit error if there is a instruction pending in the s2mPipe iBusRsp.readyForError.clearWhen(inputBeforeStage.valid) //Can't emit error if there is a instruction pending in the s2mPipe
incomingInstruction setWhen (inputBeforeStage.valid) incomingInstruction setWhen (inputBeforeStage.valid)
} }
val decodeInput = (if (injectorStage) { val decodeInput = (if (injectorStage) {
val decodeInput = inputBeforeStage.m2sPipeWithFlush(flush, collapsBubble = false) val decodeInput = inputBeforeStage.m2sPipeWithFlush(fetcherflushIt, collapsBubble = false)
decode.insert(INSTRUCTION_ANTICIPATED) := Mux(decode.arbitration.isStuck, decode.input(INSTRUCTION), inputBeforeStage.rsp.inst) decode.insert(INSTRUCTION_ANTICIPATED) := Mux(decode.arbitration.isStuck, decode.input(INSTRUCTION), inputBeforeStage.rsp.inst)
iBusRsp.readyForError.clearWhen(decodeInput.valid) //Can't emit error when there is a instruction pending in the injector stage buffer iBusRsp.readyForError.clearWhen(decodeInput.valid) //Can't emit error when there is a instruction pending in the injector stage buffer
incomingInstruction setWhen (decodeInput.valid) incomingInstruction setWhen (decodeInput.valid)
@ -313,13 +313,13 @@ abstract class IBusFetcherImpl(val resetVector : BigInt,
def pcUpdatedGen(input : Bool, stucks : Seq[Bool], relaxedInput : Boolean) : Seq[Bool] = { def pcUpdatedGen(input : Bool, stucks : Seq[Bool], relaxedInput : Boolean) : Seq[Bool] = {
stucks.scanLeft(input)((i, stuck) => { stucks.scanLeft(input)((i, stuck) => {
val reg = RegInit(False) val reg = RegInit(False)
if(!relaxedInput) when(flush) { if(!relaxedInput) when(fetcherflushIt) {
reg := False reg := False
} }
when(!stuck) { when(!stuck) {
reg := i reg := i
} }
if(relaxedInput || i != input) when(flush) { if(relaxedInput || i != input) when(fetcherflushIt) {
reg := False reg := False
} }
reg reg
@ -335,7 +335,7 @@ abstract class IBusFetcherImpl(val resetVector : BigInt,
pcValids := Vec(valids.takeRight(stages.size)) pcValids := Vec(valids.takeRight(stages.size))
} }
val decodeRemoved = RegInit(False) setWhen(decode.arbitration.isRemoved) clearWhen(flush) //!decode.arbitration.isStuck || decode.arbitration.isFlushed val decodeRemoved = RegInit(False) setWhen(decode.arbitration.isRemoved) clearWhen(fetcherflushIt) //!decode.arbitration.isStuck || decode.arbitration.isFlushed
decodeInput.ready := !decode.arbitration.isStuck decodeInput.ready := !decode.arbitration.isStuck
decode.arbitration.isValid := decodeInput.valid && !decodeRemoved decode.arbitration.isValid := decodeInput.valid && !decodeRemoved
@ -461,7 +461,7 @@ abstract class IBusFetcherImpl(val resetVector : BigInt,
} }
val fetchContext = DynamicContext() val fetchContext = DynamicContext()
fetchContext.hazard := hazard fetchContext.hazard := hazard
fetchContext.line := historyCache.readSync((fetchPc.output.payload >> 2).resized, iBusRsp.stages(0).output.ready || flush) fetchContext.line := historyCache.readSync((fetchPc.output.payload >> 2).resized, iBusRsp.stages(0).output.ready || fetcherflushIt)
object PREDICTION_CONTEXT extends Stageable(DynamicContext()) object PREDICTION_CONTEXT extends Stageable(DynamicContext())
decode.insert(PREDICTION_CONTEXT) := stage1ToInjectorPipe(fetchContext)._2 decode.insert(PREDICTION_CONTEXT) := stage1ToInjectorPipe(fetchContext)._2
@ -500,17 +500,13 @@ abstract class IBusFetcherImpl(val resetVector : BigInt,
} }
//TODO no more fireing depedancies //TODO no more fireing depedancies
predictionJumpInterface.valid := decodePrediction.cmd.hadBranch && decode.arbitration.isValid //TODO OH Doublon de priorité predictionJumpInterface.valid := decode.arbitration.isValid && decodePrediction.cmd.hadBranch //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){ when(predictionJumpInterface.valid && decode.arbitration.isFiring){
flushIt() flushIt()
} }
// when(predictionJumpInterface.payload((if(pipeline(RVC_GEN)) 0 else 1) downto 0) =/= 0){
// decodePrediction.cmd.hadBranch := False
// }
} }
case DYNAMIC_TARGET => new Area{ case DYNAMIC_TARGET => new Area{
// assert(!compressedGen || cmdToRspStageCount == 1, "Can't combine DYNAMIC_TARGET and RVC as it could stop the instruction fetch mid-air") // assert(!compressedGen || cmdToRspStageCount == 1, "Can't combine DYNAMIC_TARGET and RVC as it could stop the instruction fetch mid-air")
@ -525,7 +521,7 @@ abstract class IBusFetcherImpl(val resetVector : BigInt,
val history = Mem(BranchPredictorLine(), 1 << historyRamSizeLog2) val history = Mem(BranchPredictorLine(), 1 << historyRamSizeLog2)
val historyWrite = history.writePort val historyWrite = history.writePort
val line = history.readSync((iBusRsp.stages(0).input.payload >> 2).resized, iBusRsp.stages(0).output.ready || flush) val line = history.readSync((iBusRsp.stages(0).input.payload >> 2).resized, iBusRsp.stages(0).output.ready || fetcherflushIt)
val hit = line.source === (iBusRsp.stages(1).input.payload.asBits >> 2 + historyRamSizeLog2) && (if(compressedGen)(!(!line.unaligned && iBusRsp.stages(1).input.payload(1))) else True) val hit = line.source === (iBusRsp.stages(1).input.payload.asBits >> 2 + historyRamSizeLog2) && (if(compressedGen)(!(!line.unaligned && iBusRsp.stages(1).input.payload(1))) else True)
//Avoid stoping instruction fetch in the middle patch //Avoid stoping instruction fetch in the middle patch
@ -537,7 +533,7 @@ abstract class IBusFetcherImpl(val resetVector : BigInt,
val historyWriteLast = RegNextWhen(historyWrite, iBusRsp.stages(0).output.ready) val historyWriteLast = RegNextWhen(historyWrite, iBusRsp.stages(0).output.ready)
val hazard = historyWriteLast.valid && historyWriteLast.address === (iBusRsp.stages(1).input.payload >> 2).resized val hazard = historyWriteLast.valid && historyWriteLast.address === (iBusRsp.stages(1).input.payload >> 2).resized
//TODO improve predictionPcLoad way of doing things //TODO improve predictionPcLoad way of doing things
fetchPc.predictionPcLoad.valid := line.branchWish.msb && hit && !hazard && iBusRsp.stages(1).output.fire //XXX && !(!line.unaligned && iBusRsp.inputPipeline(0).payload(1)) fetchPc.predictionPcLoad.valid := line.branchWish.msb && hit && !hazard && iBusRsp.stages(1).output.valid //XXX && !(!line.unaligned && iBusRsp.inputPipeline(0).payload(1))
fetchPc.predictionPcLoad.payload := line.target fetchPc.predictionPcLoad.payload := line.target
case class PredictionResult() extends Bundle{ case class PredictionResult() extends Bundle{
@ -605,7 +601,7 @@ abstract class IBusFetcherImpl(val resetVector : BigInt,
when(decompressor.input.fire){ when(decompressor.input.fire){
decompressorFailure := decompressorContext.hit && !decompressorContext.hazard && !decompressor.output.valid && decompressorContext.line.branchWish(1) decompressorFailure := decompressorContext.hit && !decompressorContext.hazard && !decompressor.output.valid && decompressorContext.line.branchWish(1)
} }
decompressorFailure clearWhen(flush || decompressor.output.fire) decompressorFailure clearWhen(fetcherflushIt || decompressor.output.fire)
val injectorFailure = Delay(decompressorFailure, cycleCount=if(injectorStage) 1 else 0, when=injector.decodeInput.ready) val injectorFailure = Delay(decompressorFailure, cycleCount=if(injectorStage) 1 else 0, when=injector.decodeInput.ready)

View File

@ -151,7 +151,7 @@ class IBusCachedPlugin(resetVector : BigInt = 0x80000000l,
stages(0).halt setWhen (cache.io.cpu.prefetch.haltIt) stages(0).halt setWhen (cache.io.cpu.prefetch.haltIt)
cache.io.cpu.fetch.isRemoved := flush cache.io.cpu.fetch.isRemoved := fetcherflushIt
} }

View File

@ -284,7 +284,7 @@ class IBusSimplePlugin(resetVector : BigInt,
mmuBus.cmd.isValid := cmdForkStage.input.valid mmuBus.cmd.isValid := cmdForkStage.input.valid
mmuBus.cmd.virtualAddress := cmdForkStage.input.payload mmuBus.cmd.virtualAddress := cmdForkStage.input.payload
mmuBus.cmd.bypassTranslation := False mmuBus.cmd.bypassTranslation := False
mmuBus.end := cmdForkStage.output.fire || flush mmuBus.end := cmdForkStage.output.fire || fetcherflushIt
cmd.pc := mmuBus.rsp.physicalAddress(31 downto 2) @@ "00" cmd.pc := mmuBus.rsp.physicalAddress(31 downto 2) @@ "00"
@ -311,7 +311,7 @@ class IBusSimplePlugin(resetVector : BigInt,
//Manage flush for iBus transactions in flight //Manage flush for iBus transactions in flight
val discardCounter = Reg(UInt(log2Up(pendingMax + 1) bits)) init (0) val discardCounter = Reg(UInt(log2Up(pendingMax + 1) bits)) init (0)
discardCounter := discardCounter - (iBus.rsp.fire && discardCounter =/= 0).asUInt discardCounter := discardCounter - (iBus.rsp.fire && discardCounter =/= 0).asUInt
when(flush) { when(fetcherflushIt) {
if(secondStagePersistence) if(secondStagePersistence)
discardCounter := pendingCmd + cmd.valid.asUInt - iBus.rsp.fire.asUInt discardCounter := pendingCmd + cmd.valid.asUInt - iBus.rsp.fire.asUInt
else else
@ -323,7 +323,7 @@ class IBusSimplePlugin(resetVector : BigInt,
val rspBuffer = if(!rspHoldValue) new Area{ val rspBuffer = if(!rspHoldValue) new Area{
val c = StreamFifoLowLatency(IBusSimpleRsp(), busLatencyMin + (if(cmdForkOnSecondStage && cmdForkPersistence) 1 else 0)) val c = StreamFifoLowLatency(IBusSimpleRsp(), busLatencyMin + (if(cmdForkOnSecondStage && cmdForkPersistence) 1 else 0))
c.io.push << iBus.rsp.throwWhen(discardCounter =/= 0).toStream c.io.push << iBus.rsp.throwWhen(discardCounter =/= 0).toStream
c.io.flush := flush c.io.flush := fetcherflushIt
rspBufferOutput << c.io.pop rspBufferOutput << c.io.pop
} else new Area{ } else new Area{
val rspStream = iBus.rsp.throwWhen(discardCounter =/= 0).toStream val rspStream = iBus.rsp.throwWhen(discardCounter =/= 0).toStream