Fix branch plugin decode prediction exception by using the instruction decoder

This commit is contained in:
Dolu1990 2018-05-24 12:52:00 +02:00
parent a53f8fdc35
commit 2f8ccc55b6
7 changed files with 71 additions and 102 deletions

View File

@ -62,14 +62,14 @@ object Riscv{
def LR = M"00010--00000-----010-----0101111" def LR = M"00010--00000-----010-----0101111"
def SC = M"00011------------010-----0101111" def SC = M"00011------------010-----0101111"
def BEQ = M"-----------------000-----1100011" def BEQ (rvc : Boolean) = if(rvc) M"-----------------000-----1100011" else M"-----------------000---0-1100011"
def BNE = M"-----------------001-----1100011" def BNE (rvc : Boolean) = if(rvc) M"-----------------001-----1100011" else M"-----------------001---0-1100011"
def BLT = M"-----------------100-----1100011" def BLT (rvc : Boolean) = if(rvc) M"-----------------100-----1100011" else M"-----------------100---0-1100011"
def BGE = M"-----------------101-----1100011" def BGE (rvc : Boolean) = if(rvc) M"-----------------101-----1100011" else M"-----------------101---0-1100011"
def BLTU = M"-----------------110-----1100011" def BLTU(rvc : Boolean) = if(rvc) M"-----------------110-----1100011" else M"-----------------110---0-1100011"
def BGEU = M"-----------------111-----1100011" def BGEU(rvc : Boolean) = if(rvc) M"-----------------111-----1100011" else M"-----------------111---0-1100011"
def JALR = M"-----------------000-----1100111" def JALR = M"-----------------000-----1100111"
def JAL = M"-------------------------1101111" def JAL(rvc : Boolean) = if(rvc) M"-------------------------1101111" else M"----------0--------------1101111"
def LUI = M"-------------------------0110111" def LUI = M"-------------------------0110111"
def AUIPC = M"-------------------------0010111" def AUIPC = M"-------------------------0010111"

View File

@ -34,10 +34,10 @@ object TestsWorkspace {
new IBusSimplePlugin( new IBusSimplePlugin(
resetVector = 0x80000000l, resetVector = 0x80000000l,
relaxedPcCalculation = false, relaxedPcCalculation = false,
prediction = NONE, prediction = DYNAMIC,
historyRamSizeLog2 = 8, historyRamSizeLog2 = 8,
catchAccessFault = true, catchAccessFault = true,
compressedGen = true compressedGen = false
), ),
// new IBusCachedPlugin( // new IBusCachedPlugin(
// resetVector = 0x80000000l, // resetVector = 0x80000000l,
@ -104,7 +104,7 @@ object TestsWorkspace {
new SrcPlugin( new SrcPlugin(
separatedAddSub = false separatedAddSub = false
), ),
new FullBarrielShifterPlugin(earlyInjection = true), new FullBarrielShifterPlugin(earlyInjection = false),
// new LightShifterPlugin, // new LightShifterPlugin,
new HazardSimplePlugin( new HazardSimplePlugin(
bypassExecute = true, bypassExecute = true,
@ -117,9 +117,9 @@ object TestsWorkspace {
), ),
// new HazardSimplePlugin(false, true, false, true), // new HazardSimplePlugin(false, true, false, true),
// new HazardSimplePlugin(false, false, false, false), // new HazardSimplePlugin(false, false, false, false),
// new MulPlugin, new MulPlugin,
new MulDivIterativePlugin( new MulDivIterativePlugin(
genMul = true, genMul = false,
genDiv = true, genDiv = true,
mulUnroolFactor = 32, mulUnroolFactor = 32,
divUnroolFactor = 1 divUnroolFactor = 1
@ -128,7 +128,7 @@ object TestsWorkspace {
new CsrPlugin(CsrPluginConfig.all(0x80000020l).copy(deterministicInteruptionEntry = false)), new CsrPlugin(CsrPluginConfig.all(0x80000020l).copy(deterministicInteruptionEntry = false)),
new DebugPlugin(ClockDomain.current.clone(reset = Bool().setName("debugReset"))), new DebugPlugin(ClockDomain.current.clone(reset = Bool().setName("debugReset"))),
new BranchPlugin( new BranchPlugin(
earlyBranch = true, earlyBranch = false,
catchAddressMisaligned = true catchAddressMisaligned = true
), ),
new YamlPlugin("cpu0.yaml") new YamlPlugin("cpu0.yaml")

View File

@ -103,15 +103,16 @@ class BranchPlugin(earlyBranch : Boolean,
import IntAluPlugin._ import IntAluPlugin._
decoderService.addDefault(BRANCH_CTRL, BranchCtrlEnum.INC) decoderService.addDefault(BRANCH_CTRL, BranchCtrlEnum.INC)
val rvc = pipeline(RVC_GEN)
decoderService.add(List( decoderService.add(List(
JAL -> (jActions ++ List(BRANCH_CTRL -> BranchCtrlEnum.JAL, ALU_CTRL -> AluCtrlEnum.ADD_SUB)), JAL(rvc) -> (jActions ++ List(BRANCH_CTRL -> BranchCtrlEnum.JAL, ALU_CTRL -> AluCtrlEnum.ADD_SUB)),
JALR -> (jActions ++ List(BRANCH_CTRL -> BranchCtrlEnum.JALR, ALU_CTRL -> AluCtrlEnum.ADD_SUB, RS1_USE -> True)), JALR -> (jActions ++ List(BRANCH_CTRL -> BranchCtrlEnum.JALR, ALU_CTRL -> AluCtrlEnum.ADD_SUB, RS1_USE -> True)),
BEQ -> (bActions ++ List(BRANCH_CTRL -> BranchCtrlEnum.B)), BEQ(rvc) -> (bActions ++ List(BRANCH_CTRL -> BranchCtrlEnum.B)),
BNE -> (bActions ++ List(BRANCH_CTRL -> BranchCtrlEnum.B)), BNE(rvc) -> (bActions ++ List(BRANCH_CTRL -> BranchCtrlEnum.B)),
BLT -> (bActions ++ List(BRANCH_CTRL -> BranchCtrlEnum.B, SRC_LESS_UNSIGNED -> False)), BLT(rvc) -> (bActions ++ List(BRANCH_CTRL -> BranchCtrlEnum.B, SRC_LESS_UNSIGNED -> False)),
BGE -> (bActions ++ List(BRANCH_CTRL -> BranchCtrlEnum.B, SRC_LESS_UNSIGNED -> False)), BGE(rvc) -> (bActions ++ List(BRANCH_CTRL -> BranchCtrlEnum.B, SRC_LESS_UNSIGNED -> False)),
BLTU -> (bActions ++ List(BRANCH_CTRL -> BranchCtrlEnum.B, SRC_LESS_UNSIGNED -> True)), BLTU(rvc) -> (bActions ++ List(BRANCH_CTRL -> BranchCtrlEnum.B, SRC_LESS_UNSIGNED -> True)),
BGEU -> (bActions ++ List(BRANCH_CTRL -> BranchCtrlEnum.B, SRC_LESS_UNSIGNED -> True)) BGEU(rvc) -> (bActions ++ List(BRANCH_CTRL -> BranchCtrlEnum.B, SRC_LESS_UNSIGNED -> True))
)) ))
val pcManagerService = pipeline.service(classOf[JumpService]) val pcManagerService = pipeline.service(classOf[JumpService])
@ -187,54 +188,11 @@ class BranchPlugin(earlyBranch : Boolean,
def buildDecodePrediction(pipeline: VexRiscv): Unit = { def buildDecodePrediction(pipeline: VexRiscv): Unit = {
// case class BranchPredictorLine() extends Bundle{
// val history = SInt(historyWidth bits)
// }
object PREDICTION_HAD_BRANCHED extends Stageable(Bool) object PREDICTION_HAD_BRANCHED extends Stageable(Bool)
// object HISTORY_LINE extends Stageable(BranchPredictorLine())
import pipeline._ import pipeline._
import pipeline.config._ import pipeline.config._
// val historyCache = if(prediction == DYNAMIC) Mem(BranchPredictorLine(), 1 << historyRamSizeLog2) setName("branchCache") else null
// val historyCacheWrite = if(prediction == DYNAMIC) historyCache.writePort else null
//Read historyCache
// if(prediction == DYNAMIC) fetch plug new Area{
// val readAddress = prefetch.output(PC)(2, historyRamSizeLog2 bits)
// fetch.insert(HISTORY_LINE) := historyCache.readSync(readAddress,!prefetch.arbitration.isStuckByOthers)
//
// //WriteFirst bypass TODO long combinatorial path
//// val writePortReg = RegNext(historyCacheWrite)
//// when(writePortReg.valid && writePortReg.address === readAddress){
//// fetch.insert(HISTORY_LINE) := writePortReg.data
//// }
// }
//Branch JAL, predict Bxx and branch it
// decode plug new Area{
// import decode._
// val imm = IMM(input(INSTRUCTION))
//
// val conditionalBranchPrediction = (prediction match {
// case `STATIC` => imm.b_sext.msb
// case `DYNAMIC` => input(HISTORY_LINE).history.msb
// })
// insert(PREDICTION_HAD_BRANCHED) := input(BRANCH_CTRL) === BranchCtrlEnum.JAL || (input(BRANCH_CTRL) === BranchCtrlEnum.B && conditionalBranchPrediction)
//
// predictionJumpInterface.valid := input(PREDICTION_HAD_BRANCHED) && arbitration.isFiring //TODO OH Doublon de priorité
// predictionJumpInterface.payload := input(PC) + ((input(BRANCH_CTRL) === BranchCtrlEnum.JAL) ? imm.j_sext | imm.b_sext).asUInt
// when(predictionJumpInterface.valid) {
// fetch.arbitration.flushAll := True
// }
//
// if(catchAddressMisaligned) {
// predictionExceptionPort.valid := input(INSTRUCTION_READY) && input(PREDICTION_HAD_BRANCHED) && arbitration.isValid && predictionJumpInterface.payload(1 downto 0) =/= 0
// predictionExceptionPort.code := 0
// predictionExceptionPort.badAddr := predictionJumpInterface.payload
// }
// }
decode plug new Area { decode plug new Area {
import decode._ import decode._
@ -292,23 +250,14 @@ class BranchPlugin(earlyBranch : Boolean,
} }
if(catchAddressMisaligned) { if(catchAddressMisaligned) {
branchExceptionPort.valid := arbitration.isValid && input(BRANCH_DO) && (if(pipeline(RVC_GEN)) input(BRANCH_CALC)(0 downto 0) =/= 0 else input(BRANCH_CALC)(1 downto 0) =/= 0) val unalignedJump = input(BRANCH_DO) && (if(pipeline(RVC_GEN)) input(BRANCH_CALC)(0 downto 0) =/= 0 else input(BRANCH_CALC)(1 downto 0) =/= 0)
branchExceptionPort.valid := arbitration.isValid && unalignedJump
branchExceptionPort.code := 0 branchExceptionPort.code := 0
branchExceptionPort.badAddr := input(BRANCH_CALC) branchExceptionPort.badAddr := input(BRANCH_CALC) //pipeline.stages(pipeline.indexOf(branchStage)-1).input
} }
} }
//Update historyCache
decodePrediction.rsp.wasWrong := jumpInterface.valid decodePrediction.rsp.wasWrong := jumpInterface.valid
// if(prediction == DYNAMIC) branchStage plug new Area {
// import branchStage._
// val newHistory = input(HISTORY_LINE).history.resize(historyWidth + 1) + Mux(input(BRANCH_COND_RESULT),S(-1),S(1))
// val noOverflow = newHistory(newHistory.high downto newHistory.high - 1) =/= S"10" && newHistory(newHistory.high downto newHistory.high - 1) =/= S"01"
//
// historyCacheWrite.valid := arbitration.isFiring && input(BRANCH_CTRL) === BranchCtrlEnum.B && noOverflow
// historyCacheWrite.address := input(PC)(2, historyRamSizeLog2 bits)
// historyCacheWrite.data.history := newHistory.resized
// }
} }
@ -321,6 +270,7 @@ class BranchPlugin(earlyBranch : Boolean,
//Do branch calculations (conditions + target PC) //Do branch calculations (conditions + target PC)
object NEXT_PC extends Stageable(UInt(32 bits))
execute plug new Area { execute plug new Area {
import execute._ import execute._
@ -349,6 +299,7 @@ class BranchPlugin(earlyBranch : Boolean,
val branchAdder = branch_src1 + branch_src2 val branchAdder = branch_src1 + branch_src2
insert(BRANCH_CALC) := branchAdder(31 downto 1) @@ ((input(BRANCH_CTRL) === BranchCtrlEnum.JALR) ? False | branchAdder(0)) insert(BRANCH_CALC) := branchAdder(31 downto 1) @@ ((input(BRANCH_CTRL) === BranchCtrlEnum.JALR) ? False | branchAdder(0))
insert(NEXT_PC) := input(PC) + (if(pipeline(RVC_GEN)) ((input(IS_RVC)) ? U(2) | U(4)) else 4)
} }
//Apply branchs (JAL,JALR, Bxx) //Apply branchs (JAL,JALR, Bxx)
@ -361,7 +312,7 @@ class BranchPlugin(earlyBranch : Boolean,
fetchPrediction.rsp.finalPc := input(BRANCH_CALC) fetchPrediction.rsp.finalPc := input(BRANCH_CALC)
jumpInterface.valid := arbitration.isFiring && predictionMissmatch //Probably just isValid instead of isFiring is better jumpInterface.valid := arbitration.isFiring && predictionMissmatch //Probably just isValid instead of isFiring is better
jumpInterface.payload := (input(BRANCH_DO) ? input(BRANCH_CALC) | input(PC) + (if(pipeline(RVC_GEN)) ((input(IS_RVC)) ? U(2) | U(4)) else 4)) jumpInterface.payload := (input(BRANCH_DO) ? input(BRANCH_CALC) | input(NEXT_PC))
when(jumpInterface.valid) { when(jumpInterface.valid) {

View File

@ -16,16 +16,12 @@ abstract class IBusFetcherImpl(val catchAccessFault : Boolean,
val cmdToRspStageCount : Int, val cmdToRspStageCount : Int,
val injectorReadyCutGen : Boolean, val injectorReadyCutGen : Boolean,
val relaxedPcCalculation : Boolean, val relaxedPcCalculation : Boolean,
val prediction_ : BranchPrediction, val prediction : BranchPrediction,
val historyRamSizeLog2 : Int, val historyRamSizeLog2 : Int,
val injectorStage : Boolean) extends Plugin[VexRiscv] with JumpService with IBusFetcher{ val injectorStage : Boolean) extends Plugin[VexRiscv] with JumpService with IBusFetcher{
var prefetchExceptionPort : Flow[ExceptionCause] = null var prefetchExceptionPort : Flow[ExceptionCause] = null
var decodePrediction : DecodePredictionBus = null var decodePrediction : DecodePredictionBus = null
var fetchPrediction : FetchPredictionBus = null var fetchPrediction : FetchPredictionBus = null
val prediction = prediction_ match{
case DYNAMIC => STATIC
case x => x
}
assert(cmdToRspStageCount >= 1) assert(cmdToRspStageCount >= 1)
assert(!(cmdToRspStageCount == 1 && !injectorStage)) assert(!(cmdToRspStageCount == 1 && !injectorStage))
assert(!(compressedGen && !decodePcGen)) assert(!(compressedGen && !decodePcGen))
@ -397,31 +393,54 @@ abstract class IBusFetcherImpl(val catchAccessFault : Boolean,
case NONE => case NONE =>
case STATIC | DYNAMIC => { case STATIC | DYNAMIC => {
def historyWidth = 2 def historyWidth = 2
// if(prediction == DYNAMIC) { val dynamic = ifGen(prediction == DYNAMIC) (new Area {
// case class BranchPredictorLine() extends Bundle{ case class BranchPredictorLine() extends Bundle{
// val history = SInt(historyWidth bits) val history = SInt(historyWidth bits)
// } }
//
// val historyCache = if(prediction == DYNAMIC) Mem(BranchPredictorLine(), 1 << historyRamSizeLog2) setName("branchCache") else null val historyCache = Mem(BranchPredictorLine(), 1 << historyRamSizeLog2)
// val historyCacheWrite = if(prediction == DYNAMIC) historyCache.writePort else null val historyWrite = historyCache.writePort
// val historyWriteLast = RegNextWhen(historyWrite, iBusRsp.inputPipeline(0).ready)
// val hazard = historyWriteLast.valid && historyWriteLast.address === (iBusRsp.inputPipeline(0).payload >> 2).resized
// val readAddress = (2, historyRamSizeLog2 bits)
// fetch.insert(HISTORY_LINE) := historyCache.readSync(readAddress,!prefetch.arbitration.isStuckByOthers) case class DynamicContext() extends Bundle{
// val hazard = Bool
// } val line = BranchPredictorLine()
}
val fetchContext = DynamicContext()
fetchContext.hazard := hazard
fetchContext.line := historyCache.readSync((fetchPc.output.payload >> 2).resized, iBusRsp.inputPipeline(0).ready)
val iBusRspContext = iBusRsp.inputPipeline.tail.foldLeft(fetchContext)((data,stream) => RegNextWhen(data, stream.ready))
val injectorContext = Delay(iBusRspContext,cycleCount=if(injectorStage) 1 else 0, when=injector.decodeInput.ready)
object PREDICTION_CONTEXT extends Stageable(DynamicContext())
decode.insert(PREDICTION_CONTEXT) := injectorContext
val branchStage = decodePrediction.stage
val branchContext = branchStage.input(PREDICTION_CONTEXT)
val moreJump = decodePrediction.rsp.wasWrong ^ branchContext.line.history.msb
historyWrite.address := branchStage.input(PC)(2, historyRamSizeLog2 bits)
historyWrite.data.history := branchContext.line.history + (moreJump ? S(-1) | S(1))
val sat = (branchContext.line.history === (moreJump ? S(branchContext.line.history.minValue) | S(branchContext.line.history.maxValue)))
historyWrite.valid := !branchContext.hazard && branchStage.arbitration.isFiring && branchStage.input(BRANCH_CTRL) === BranchCtrlEnum.B && !sat
})
val imm = IMM(decode.input(INSTRUCTION)) val imm = IMM(decode.input(INSTRUCTION))
val conditionalBranchPrediction = (prediction match { val conditionalBranchPrediction = prediction match {
case STATIC => imm.b_sext.msb case STATIC => imm.b_sext.msb
// case DYNAMIC => decodeHistory.history.msb case DYNAMIC => dynamic.injectorContext.line.history.msb
}) }
decodePrediction.cmd.hadBranch := decode.input(BRANCH_CTRL) === BranchCtrlEnum.JAL || (decode.input(BRANCH_CTRL) === BranchCtrlEnum.B && conditionalBranchPrediction) decodePrediction.cmd.hadBranch := decode.input(BRANCH_CTRL) === BranchCtrlEnum.JAL || (decode.input(BRANCH_CTRL) === BranchCtrlEnum.B && conditionalBranchPrediction)
predictionJumpInterface.valid := decodePrediction.cmd.hadBranch && decode.arbitration.isFiring //TODO OH Doublon de priorité predictionJumpInterface.valid := decodePrediction.cmd.hadBranch && decode.arbitration.isFiring //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
// 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{
val historyRamSizeLog2 : Int = 10 val historyRamSizeLog2 : Int = 10

View File

@ -25,7 +25,7 @@ class IBusCachedPlugin(resetVector : BigInt = 0x80000000l,
cmdToRspStageCount = (if(config.twoCycleCache) 2 else 1), cmdToRspStageCount = (if(config.twoCycleCache) 2 else 1),
injectorReadyCutGen = false, injectorReadyCutGen = false,
relaxedPcCalculation = relaxedPcCalculation, relaxedPcCalculation = relaxedPcCalculation,
prediction_ = prediction, prediction = prediction,
historyRamSizeLog2 = historyRamSizeLog2, historyRamSizeLog2 = historyRamSizeLog2,
injectorStage = !config.twoCycleCache){ injectorStage = !config.twoCycleCache){
import config._ import config._

View File

@ -123,7 +123,7 @@ class IBusSimplePlugin(resetVector : BigInt,
cmdToRspStageCount = busLatencyMin, cmdToRspStageCount = busLatencyMin,
injectorReadyCutGen = false, injectorReadyCutGen = false,
relaxedPcCalculation = relaxedPcCalculation, relaxedPcCalculation = relaxedPcCalculation,
prediction_ = prediction, prediction = prediction,
historyRamSizeLog2 = historyRamSizeLog2, historyRamSizeLog2 = historyRamSizeLog2,
injectorStage = injectorStage){ injectorStage = injectorStage){
var iBus : IBusSimpleBus = null var iBus : IBusSimpleBus = null
@ -184,7 +184,6 @@ class IBusSimplePlugin(resetVector : BigInt,
} }
// val rsp = recursive[Stream[IBusSimpleRsp]](rspUnbuffered, cmdToRspStageCount, x => x.s2mPipe(flush))
val rspBuffer = StreamFifoLowLatency(IBusSimpleRsp(), cmdToRspStageCount + (if(relaxedBusCmdValid) 1 else 0)) val rspBuffer = StreamFifoLowLatency(IBusSimpleRsp(), cmdToRspStageCount + (if(relaxedBusCmdValid) 1 else 0))
rspBuffer.io.push << iBus.rsp.throwWhen(discardCounter =/= 0).toStream rspBuffer.io.push << iBus.rsp.throwWhen(discardCounter =/= 0).toStream
rspBuffer.io.flush := flush rspBuffer.io.flush := flush

View File

@ -1761,7 +1761,7 @@ int main(int argc, char **argv, char **env) {
#ifdef CSR #ifdef CSR
#ifndef COMPRESSED #ifndef COMPRESSED
uint32_t machineCsrRef[] = {1,11, 2,0x80000003u, 3,0x80000007u, 4,0x8000000bu, 5,6,7,0x80000007u , uint32_t machineCsrRef[] = {1,11, 2,0x80000003u, 3,0x80000007u, 4,0x8000000bu, 5,6,7,0x80000007u ,
8,6,9,6,10,4,11,4, 12,13,0, 14,2, 15,5,16,17,1 }; 8,6,9,6,10,4,11,4, 12,13,2, 14,2, 15,5,16,17,1 };
redo(REDO,TestX28("machineCsr",machineCsrRef, sizeof(machineCsrRef)/4).noInstructionReadCheck()->run(10e4);) redo(REDO,TestX28("machineCsr",machineCsrRef, sizeof(machineCsrRef)/4).noInstructionReadCheck()->run(10e4);)
#else #else
uint32_t machineCsrRef[] = {1,11, 2,0x80000003u, 3,0x80000007u, 4,0x8000000bu, 5,6,7,0x80000007u , uint32_t machineCsrRef[] = {1,11, 2,0x80000003u, 3,0x80000007u, 4,0x8000000bu, 5,6,7,0x80000007u ,