Fix target branch prediction for RVC, all default configs pass dhrystone
This commit is contained in:
parent
a684d5e4d1
commit
59508d5b57
|
@ -247,36 +247,42 @@ abstract class IBusFetcherImpl(val resetVector : BigInt,
|
||||||
val bufferValid = RegInit(False)
|
val bufferValid = RegInit(False)
|
||||||
val bufferData = Reg(Bits(16 bits))
|
val bufferData = Reg(Bits(16 bits))
|
||||||
|
|
||||||
|
|
||||||
|
val isInputLowRvc = input.rsp.inst(1 downto 0) =/= 3
|
||||||
|
val isInputHighRvc = input.rsp.inst(17 downto 16) =/= 3
|
||||||
|
val doubleRvc = iBusRsp.stages.last.input.valid && !bufferValid && isInputLowRvc && isInputHighRvc && !input.pc(1)
|
||||||
|
val throw2BytesReg = RegInit(False)
|
||||||
|
val throw2Bytes = throw2BytesReg || input.pc(1)
|
||||||
|
val unaligned = throw2Bytes || bufferValid
|
||||||
|
def aligned = !unaligned
|
||||||
val raw = Mux(
|
val raw = Mux(
|
||||||
sel = bufferValid,
|
sel = bufferValid,
|
||||||
whenTrue = input.rsp.inst(15 downto 0) ## bufferData,
|
whenTrue = input.rsp.inst(15 downto 0) ## bufferData,
|
||||||
whenFalse = input.rsp.inst(31 downto 16) ## (input.pc(1) ? input.rsp.inst(31 downto 16) | input.rsp.inst(15 downto 0))
|
whenFalse = input.rsp.inst(31 downto 16) ## (throw2Bytes ? input.rsp.inst(31 downto 16) | input.rsp.inst(15 downto 0))
|
||||||
)
|
)
|
||||||
val isRvc = raw(1 downto 0) =/= 3
|
val isRvc = raw(1 downto 0) =/= 3
|
||||||
val isBufferRvc = bufferData(1 downto 0) =/= 3
|
|
||||||
val decompressed = RvcDecompressor(raw(15 downto 0))
|
val decompressed = RvcDecompressor(raw(15 downto 0))
|
||||||
output.valid := bufferValid ? (isBufferRvc || input.valid) | (input.valid && (!input.pc(1) || input.rsp.inst(17 downto 16) =/= 3))
|
output.valid := input.valid && !(throw2Bytes && !bufferValid && !isInputHighRvc)
|
||||||
output.pc := input.pc
|
output.pc := input.pc
|
||||||
output.isRvc := isRvc
|
output.isRvc := isRvc
|
||||||
output.rsp.inst := isRvc ? decompressed | raw
|
output.rsp.inst := isRvc ? decompressed | raw
|
||||||
input.ready := output.ready && !(bufferValid && isBufferRvc)
|
input.ready := output.ready && (!iBusRsp.stages.last.input.valid || (!(bufferValid && isInputHighRvc) && !(aligned && isInputLowRvc && isInputHighRvc)))
|
||||||
|
|
||||||
val bufferFill = False
|
when(output.fire){
|
||||||
when(output.ready && (isBufferRvc || input.valid)){
|
throw2BytesReg := (aligned && isInputLowRvc && isInputHighRvc) || (bufferValid && isInputHighRvc)
|
||||||
|
}
|
||||||
|
val bufferFill = (aligned && isInputLowRvc && !isInputHighRvc) || (bufferValid && !isInputHighRvc) || (throw2Bytes && !isRvc && !isInputHighRvc)
|
||||||
|
when(output.ready && input.valid){
|
||||||
bufferValid := False
|
bufferValid := False
|
||||||
}
|
}
|
||||||
when(output.ready && input.valid){
|
when(output.ready && input.valid){
|
||||||
bufferData := input.rsp.inst(31 downto 16)
|
bufferData := input.rsp.inst(31 downto 16)
|
||||||
when((!bufferValid && !input.pc(1) && input.rsp.inst(1 downto 0) =/= 3) || (bufferValid && !isBufferRvc) || (input.pc(1) && input.rsp.inst(17 downto 16) === 3)){
|
bufferValid setWhen(bufferFill)
|
||||||
bufferFill := True
|
|
||||||
bufferValid := True
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bufferValid.clearWhen(flush)
|
when(flush){
|
||||||
when(bufferValid && isBufferRvc){
|
throw2BytesReg := False
|
||||||
iBusRsp.readyForError := False
|
bufferValid := False
|
||||||
incomingInstruction := True
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -504,7 +510,7 @@ abstract class IBusFetcherImpl(val resetVector : BigInt,
|
||||||
val source = Bits(30 - historyRamSizeLog2 bits)
|
val source = Bits(30 - historyRamSizeLog2 bits)
|
||||||
val branchWish = UInt(2 bits)
|
val branchWish = UInt(2 bits)
|
||||||
val target = UInt(32 bits)
|
val target = UInt(32 bits)
|
||||||
val unaligned = ifGen(compressedGen)(Bool)
|
val last2Bytes = ifGen(compressedGen)(Bool)
|
||||||
}
|
}
|
||||||
|
|
||||||
val history = Mem(BranchPredictorLine(), 1 << historyRamSizeLog2)
|
val history = Mem(BranchPredictorLine(), 1 << historyRamSizeLog2)
|
||||||
|
@ -515,6 +521,7 @@ abstract class IBusFetcherImpl(val resetVector : BigInt,
|
||||||
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
|
||||||
val line = history.readSync((iBusRsp.stages(0).input.payload >> 2).resized, iBusRsp.stages(0).output.ready)
|
val line = history.readSync((iBusRsp.stages(0).input.payload >> 2).resized, iBusRsp.stages(0).output.ready)
|
||||||
val hit = line.source === (iBusRsp.stages(1).input.payload.asBits >> 2 + historyRamSizeLog2)
|
val hit = line.source === (iBusRsp.stages(1).input.payload.asBits >> 2 + historyRamSizeLog2)
|
||||||
|
if(compressedGen) hit clearWhen(!line.last2Bytes && iBusRsp.stages(1).input.payload(1))
|
||||||
|
|
||||||
fetchPc.predictionPcLoad.valid := line.branchWish.msb && hit && !hazard && iBusRsp.stages(1).input.valid
|
fetchPc.predictionPcLoad.valid := line.branchWish.msb && hit && !hazard && iBusRsp.stages(1).input.valid
|
||||||
fetchPc.predictionPcLoad.payload := line.target
|
fetchPc.predictionPcLoad.payload := line.target
|
||||||
|
@ -533,14 +540,16 @@ abstract class IBusFetcherImpl(val resetVector : BigInt,
|
||||||
val (decompressorContext, injectorContext) = stage1ToInjectorPipe(fetchContext)
|
val (decompressorContext, injectorContext) = stage1ToInjectorPipe(fetchContext)
|
||||||
if(compressedGen) {
|
if(compressedGen) {
|
||||||
//prediction hit on the right instruction into words
|
//prediction hit on the right instruction into words
|
||||||
decompressorContext.hit clearWhen(decompressorContext.line.unaligned && (decompressor.bufferValid || (decompressor.isRvc && !decompressor.input.pc(1))))
|
decompressorContext.hit clearWhen(decompressorContext.line.last2Bytes && (decompressor.bufferValid || (decompressor.isRvc && !decompressor.throw2Bytes)))
|
||||||
|
|
||||||
decodePc.predictionPcLoad.valid := injectorContext.line.branchWish.msb && injectorContext.hit && !injectorContext.hazard && injector.decodeInput.fire
|
decodePc.predictionPcLoad.valid := injectorContext.line.branchWish.msb && injectorContext.hit && !injectorContext.hazard && injector.decodeInput.fire
|
||||||
decodePc.predictionPcLoad.payload := injectorContext.line.target
|
decodePc.predictionPcLoad.payload := injectorContext.line.target
|
||||||
|
|
||||||
|
//Clean the RVC buffer when a prediction was made
|
||||||
when(decompressorContext.line.branchWish.msb && decompressorContext.hit && !decompressorContext.hazard && decompressor.output.fire){
|
when(decompressorContext.line.branchWish.msb && decompressorContext.hit && !decompressorContext.hazard && decompressor.output.fire){
|
||||||
decompressor.bufferValid := False
|
decompressor.bufferValid := False
|
||||||
decompressor.input.ready := True
|
decompressor.throw2BytesReg := False
|
||||||
|
decompressor.input.ready := True //Drop the remaining byte if any
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -557,7 +566,7 @@ abstract class IBusFetcherImpl(val resetVector : BigInt,
|
||||||
historyWrite.address := fetchPrediction.rsp.sourceLastWord(2, historyRamSizeLog2 bits)
|
historyWrite.address := fetchPrediction.rsp.sourceLastWord(2, historyRamSizeLog2 bits)
|
||||||
historyWrite.data.source := fetchPrediction.rsp.sourceLastWord.asBits >> 2 + historyRamSizeLog2
|
historyWrite.data.source := fetchPrediction.rsp.sourceLastWord.asBits >> 2 + historyRamSizeLog2
|
||||||
historyWrite.data.target := fetchPrediction.rsp.finalPc
|
historyWrite.data.target := fetchPrediction.rsp.finalPc
|
||||||
if(compressedGen) historyWrite.data.unaligned := !fetchPrediction.stage.input(PC)(1) ^ fetchPrediction.stage.input(IS_RVC)
|
if(compressedGen) historyWrite.data.last2Bytes := fetchPrediction.stage.input(PC)(1) && fetchPrediction.stage.input(IS_RVC)
|
||||||
|
|
||||||
when(fetchPrediction.rsp.wasRight) {
|
when(fetchPrediction.rsp.wasRight) {
|
||||||
historyWrite.valid := branchContext.hit
|
historyWrite.valid := branchContext.hit
|
||||||
|
@ -574,18 +583,13 @@ abstract class IBusFetcherImpl(val resetVector : BigInt,
|
||||||
|
|
||||||
historyWrite.valid clearWhen(branchContext.hazard || !branchStage.arbitration.isFiring)
|
historyWrite.valid clearWhen(branchContext.hazard || !branchStage.arbitration.isFiring)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
val predictionFailure = ifGen(compressedGen)(new Area{
|
val predictionFailure = ifGen(compressedGen)(new Area{
|
||||||
val predictionBranch = decompressorContext.hit && !decompressorContext.hazard && decompressorContext.line.branchWish(1)
|
val predictionBranch = decompressorContext.hit && !decompressorContext.hazard && decompressorContext.line.branchWish(1)
|
||||||
val unalignedWordIssue = decompressor.bufferFill && decompressor.input.rsp.inst(17 downto 16) === 3 && predictionBranch
|
val unalignedWordIssue = iBusRsp.output.valid && predictionBranch && decompressor.throw2Bytes && !decompressor.isInputHighRvc
|
||||||
val decompressorFailure = RegInit(False) setWhen(unalignedWordIssue) clearWhen(fetcherflushIt)
|
|
||||||
val injectorFailure = Delay(decompressorFailure, cycleCount=if(injectorStage) 1 else 0, when=injector.decodeInput.ready, init=False)
|
|
||||||
val bypassFailure = if(!injectorStage) False else decompressorFailure && !injector.decodeInput.valid
|
|
||||||
|
|
||||||
when(injectorFailure || bypassFailure){
|
when(unalignedWordIssue){
|
||||||
historyWrite.valid := True
|
historyWrite.valid := True
|
||||||
historyWrite.address := (decode.input(PC) >> 2).resized
|
historyWrite.address := (iBusRsp.stages(1).input.payload >> 2).resized
|
||||||
historyWrite.data.branchWish := 0
|
historyWrite.data.branchWish := 0
|
||||||
|
|
||||||
iBusRsp.redoFetch := True
|
iBusRsp.redoFetch := True
|
||||||
|
|
Loading…
Reference in New Issue