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)
}
def flush = fetcherflushIt || stages.map(_.arbitration.flushNext).orR
fetcherflushIt setWhen(stages.map(_.arbitration.flushNext).orR)
class PcFetch extends Area{
val preOutput = Stream(UInt(32 bits))
@ -225,12 +225,12 @@ abstract class IBusFetcherImpl(val resetVector : BigInt,
}
for((s,sNext) <- (stages, stages.tail).zipped) {
if(s == stages.head && pcRegReusedForSecondStage) {
sNext.input.arbitrationFrom(s.output.toEvent().m2sPipeWithFlush(flush, s != stages.head, collapsBubble = false))
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(fetcherflushIt, s != stages.head, collapsBubble = false))
sNext.input.payload := fetchPc.pcReg
fetchPc.propagatePc setWhen(sNext.input.fire)
} 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 := !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(() => {
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
}
})
@ -284,7 +284,7 @@ abstract class IBusFetcherImpl(val resetVector : BigInt,
bufferValid := !(!isRvc && !input.pc(1) && !bufferValid) && !(isRvc && input.pc(1) && output.ready)
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
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
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) {
iBusRsp.readyForError.clearWhen(inputBeforeStage.valid) //Can't emit error if there is a instruction pending in the s2mPipe
incomingInstruction setWhen (inputBeforeStage.valid)
}
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)
iBusRsp.readyForError.clearWhen(decodeInput.valid) //Can't emit error when there is a instruction pending in the injector stage buffer
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] = {
stucks.scanLeft(input)((i, stuck) => {
val reg = RegInit(False)
if(!relaxedInput) when(flush) {
if(!relaxedInput) when(fetcherflushIt) {
reg := False
}
when(!stuck) {
reg := i
}
if(relaxedInput || i != input) when(flush) {
if(relaxedInput || i != input) when(fetcherflushIt) {
reg := False
}
reg
@ -335,7 +335,7 @@ abstract class IBusFetcherImpl(val resetVector : BigInt,
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
decode.arbitration.isValid := decodeInput.valid && !decodeRemoved
@ -461,7 +461,7 @@ abstract class IBusFetcherImpl(val resetVector : BigInt,
}
val fetchContext = DynamicContext()
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())
decode.insert(PREDICTION_CONTEXT) := stage1ToInjectorPipe(fetchContext)._2
@ -500,17 +500,13 @@ abstract class IBusFetcherImpl(val resetVector : BigInt,
}
//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
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
// }
}
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")
@ -525,7 +521,7 @@ abstract class IBusFetcherImpl(val resetVector : BigInt,
val history = Mem(BranchPredictorLine(), 1 << historyRamSizeLog2)
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)
//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 hazard = historyWriteLast.valid && historyWriteLast.address === (iBusRsp.stages(1).input.payload >> 2).resized
//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
case class PredictionResult() extends Bundle{
@ -605,7 +601,7 @@ abstract class IBusFetcherImpl(val resetVector : BigInt,
when(decompressor.input.fire){
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)

View File

@ -151,7 +151,7 @@ class IBusCachedPlugin(resetVector : BigInt = 0x80000000l,
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.virtualAddress := cmdForkStage.input.payload
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"
@ -311,7 +311,7 @@ class IBusSimplePlugin(resetVector : BigInt,
//Manage flush for iBus transactions in flight
val discardCounter = Reg(UInt(log2Up(pendingMax + 1) bits)) init (0)
discardCounter := discardCounter - (iBus.rsp.fire && discardCounter =/= 0).asUInt
when(flush) {
when(fetcherflushIt) {
if(secondStagePersistence)
discardCounter := pendingCmd + cmd.valid.asUInt - iBus.rsp.fire.asUInt
else
@ -323,7 +323,7 @@ class IBusSimplePlugin(resetVector : BigInt,
val rspBuffer = if(!rspHoldValue) new Area{
val c = StreamFifoLowLatency(IBusSimpleRsp(), busLatencyMin + (if(cmdForkOnSecondStage && cmdForkPersistence) 1 else 0))
c.io.push << iBus.rsp.throwWhen(discardCounter =/= 0).toStream
c.io.flush := flush
c.io.flush := fetcherflushIt
rspBufferOutput << c.io.pop
} else new Area{
val rspStream = iBus.rsp.throwWhen(discardCounter =/= 0).toStream