From 2f8ccc55b60dc57eb1c6ee4ed3bddcf9ba316ae4 Mon Sep 17 00:00:00 2001 From: Dolu1990 Date: Thu, 24 May 2018 12:52:00 +0200 Subject: [PATCH] Fix branch plugin decode prediction exception by using the instruction decoder --- src/main/scala/vexriscv/Riscv.scala | 14 ++-- src/main/scala/vexriscv/TestsWorkspace.scala | 12 +-- .../scala/vexriscv/plugin/BranchPlugin.scala | 79 ++++--------------- src/main/scala/vexriscv/plugin/Fetcher.scala | 61 +++++++++----- .../vexriscv/plugin/IBusCachedPlugin.scala | 2 +- .../vexriscv/plugin/IBusSimplePlugin.scala | 3 +- src/test/cpp/regression/main.cpp | 2 +- 7 files changed, 71 insertions(+), 102 deletions(-) diff --git a/src/main/scala/vexriscv/Riscv.scala b/src/main/scala/vexriscv/Riscv.scala index 6a82a36..57251a4 100644 --- a/src/main/scala/vexriscv/Riscv.scala +++ b/src/main/scala/vexriscv/Riscv.scala @@ -62,14 +62,14 @@ object Riscv{ def LR = M"00010--00000-----010-----0101111" def SC = M"00011------------010-----0101111" - def BEQ = M"-----------------000-----1100011" - def BNE = M"-----------------001-----1100011" - def BLT = M"-----------------100-----1100011" - def BGE = M"-----------------101-----1100011" - def BLTU = M"-----------------110-----1100011" - def BGEU = M"-----------------111-----1100011" + def BEQ (rvc : Boolean) = if(rvc) M"-----------------000-----1100011" else M"-----------------000---0-1100011" + def BNE (rvc : Boolean) = if(rvc) M"-----------------001-----1100011" else M"-----------------001---0-1100011" + def BLT (rvc : Boolean) = if(rvc) M"-----------------100-----1100011" else M"-----------------100---0-1100011" + def BGE (rvc : Boolean) = if(rvc) M"-----------------101-----1100011" else M"-----------------101---0-1100011" + def BLTU(rvc : Boolean) = if(rvc) M"-----------------110-----1100011" else M"-----------------110---0-1100011" + def BGEU(rvc : Boolean) = if(rvc) M"-----------------111-----1100011" else M"-----------------111---0-1100011" 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 AUIPC = M"-------------------------0010111" diff --git a/src/main/scala/vexriscv/TestsWorkspace.scala b/src/main/scala/vexriscv/TestsWorkspace.scala index 9bff08f..c381b4f 100644 --- a/src/main/scala/vexriscv/TestsWorkspace.scala +++ b/src/main/scala/vexriscv/TestsWorkspace.scala @@ -34,10 +34,10 @@ object TestsWorkspace { new IBusSimplePlugin( resetVector = 0x80000000l, relaxedPcCalculation = false, - prediction = NONE, + prediction = DYNAMIC, historyRamSizeLog2 = 8, catchAccessFault = true, - compressedGen = true + compressedGen = false ), // new IBusCachedPlugin( // resetVector = 0x80000000l, @@ -104,7 +104,7 @@ object TestsWorkspace { new SrcPlugin( separatedAddSub = false ), - new FullBarrielShifterPlugin(earlyInjection = true), + new FullBarrielShifterPlugin(earlyInjection = false), // new LightShifterPlugin, new HazardSimplePlugin( bypassExecute = true, @@ -117,9 +117,9 @@ object TestsWorkspace { ), // new HazardSimplePlugin(false, true, false, true), // new HazardSimplePlugin(false, false, false, false), -// new MulPlugin, + new MulPlugin, new MulDivIterativePlugin( - genMul = true, + genMul = false, genDiv = true, mulUnroolFactor = 32, divUnroolFactor = 1 @@ -128,7 +128,7 @@ object TestsWorkspace { new CsrPlugin(CsrPluginConfig.all(0x80000020l).copy(deterministicInteruptionEntry = false)), new DebugPlugin(ClockDomain.current.clone(reset = Bool().setName("debugReset"))), new BranchPlugin( - earlyBranch = true, + earlyBranch = false, catchAddressMisaligned = true ), new YamlPlugin("cpu0.yaml") diff --git a/src/main/scala/vexriscv/plugin/BranchPlugin.scala b/src/main/scala/vexriscv/plugin/BranchPlugin.scala index 1f2bc98..cd9faaa 100644 --- a/src/main/scala/vexriscv/plugin/BranchPlugin.scala +++ b/src/main/scala/vexriscv/plugin/BranchPlugin.scala @@ -103,15 +103,16 @@ class BranchPlugin(earlyBranch : Boolean, import IntAluPlugin._ decoderService.addDefault(BRANCH_CTRL, BranchCtrlEnum.INC) + val rvc = pipeline(RVC_GEN) decoderService.add(List( - JAL -> (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)), - BEQ -> (bActions ++ List(BRANCH_CTRL -> BranchCtrlEnum.B)), - BNE -> (bActions ++ List(BRANCH_CTRL -> BranchCtrlEnum.B)), - BLT -> (bActions ++ List(BRANCH_CTRL -> BranchCtrlEnum.B, SRC_LESS_UNSIGNED -> False)), - BGE -> (bActions ++ List(BRANCH_CTRL -> BranchCtrlEnum.B, SRC_LESS_UNSIGNED -> False)), - BLTU -> (bActions ++ List(BRANCH_CTRL -> BranchCtrlEnum.B, SRC_LESS_UNSIGNED -> True)), - BGEU -> (bActions ++ List(BRANCH_CTRL -> BranchCtrlEnum.B, SRC_LESS_UNSIGNED -> True)) + 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)), + BEQ(rvc) -> (bActions ++ List(BRANCH_CTRL -> BranchCtrlEnum.B)), + BNE(rvc) -> (bActions ++ List(BRANCH_CTRL -> BranchCtrlEnum.B)), + BLT(rvc) -> (bActions ++ List(BRANCH_CTRL -> BranchCtrlEnum.B, SRC_LESS_UNSIGNED -> False)), + BGE(rvc) -> (bActions ++ List(BRANCH_CTRL -> BranchCtrlEnum.B, SRC_LESS_UNSIGNED -> False)), + BLTU(rvc) -> (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]) @@ -187,54 +188,11 @@ class BranchPlugin(earlyBranch : Boolean, def buildDecodePrediction(pipeline: VexRiscv): Unit = { -// case class BranchPredictorLine() extends Bundle{ -// val history = SInt(historyWidth bits) -// } - object PREDICTION_HAD_BRANCHED extends Stageable(Bool) -// object HISTORY_LINE extends Stageable(BranchPredictorLine()) import pipeline._ 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 { import decode._ @@ -292,23 +250,14 @@ class BranchPlugin(earlyBranch : Boolean, } 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.badAddr := input(BRANCH_CALC) + branchExceptionPort.badAddr := input(BRANCH_CALC) //pipeline.stages(pipeline.indexOf(branchStage)-1).input } } - //Update historyCache 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) + object NEXT_PC extends Stageable(UInt(32 bits)) execute plug new Area { import execute._ @@ -349,6 +299,7 @@ class BranchPlugin(earlyBranch : Boolean, val branchAdder = branch_src1 + branch_src2 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) @@ -361,7 +312,7 @@ class BranchPlugin(earlyBranch : Boolean, fetchPrediction.rsp.finalPc := input(BRANCH_CALC) 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) { diff --git a/src/main/scala/vexriscv/plugin/Fetcher.scala b/src/main/scala/vexriscv/plugin/Fetcher.scala index 3d01396..9550b9c 100644 --- a/src/main/scala/vexriscv/plugin/Fetcher.scala +++ b/src/main/scala/vexriscv/plugin/Fetcher.scala @@ -16,16 +16,12 @@ abstract class IBusFetcherImpl(val catchAccessFault : Boolean, val cmdToRspStageCount : Int, val injectorReadyCutGen : Boolean, val relaxedPcCalculation : Boolean, - val prediction_ : BranchPrediction, + val prediction : BranchPrediction, val historyRamSizeLog2 : Int, val injectorStage : Boolean) extends Plugin[VexRiscv] with JumpService with IBusFetcher{ var prefetchExceptionPort : Flow[ExceptionCause] = null var decodePrediction : DecodePredictionBus = null var fetchPrediction : FetchPredictionBus = null - val prediction = prediction_ match{ - case DYNAMIC => STATIC - case x => x - } assert(cmdToRspStageCount >= 1) assert(!(cmdToRspStageCount == 1 && !injectorStage)) assert(!(compressedGen && !decodePcGen)) @@ -397,31 +393,54 @@ abstract class IBusFetcherImpl(val catchAccessFault : Boolean, case NONE => case STATIC | DYNAMIC => { def historyWidth = 2 - // if(prediction == DYNAMIC) { - // case class BranchPredictorLine() extends Bundle{ - // val history = SInt(historyWidth bits) - // } - // - // val historyCache = if(prediction == DYNAMIC) Mem(BranchPredictorLine(), 1 << historyRamSizeLog2) setName("branchCache") else null - // val historyCacheWrite = if(prediction == DYNAMIC) historyCache.writePort else null - // - // - // val readAddress = (2, historyRamSizeLog2 bits) - // fetch.insert(HISTORY_LINE) := historyCache.readSync(readAddress,!prefetch.arbitration.isStuckByOthers) - // - // } + val dynamic = ifGen(prediction == DYNAMIC) (new Area { + case class BranchPredictorLine() extends Bundle{ + val history = SInt(historyWidth bits) + } + + val historyCache = Mem(BranchPredictorLine(), 1 << historyRamSizeLog2) + val historyWrite = historyCache.writePort + val historyWriteLast = RegNextWhen(historyWrite, iBusRsp.inputPipeline(0).ready) + val hazard = historyWriteLast.valid && historyWriteLast.address === (iBusRsp.inputPipeline(0).payload >> 2).resized + + 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 conditionalBranchPrediction = (prediction match { + val conditionalBranchPrediction = prediction match { 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) 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 + +// when(predictionJumpInterface.payload((if(pipeline(RVC_GEN)) 0 else 1) downto 0) =/= 0){ +// decodePrediction.cmd.hadBranch := False +// } } case DYNAMIC_TARGET => new Area{ val historyRamSizeLog2 : Int = 10 diff --git a/src/main/scala/vexriscv/plugin/IBusCachedPlugin.scala b/src/main/scala/vexriscv/plugin/IBusCachedPlugin.scala index 2c1cd2c..182b83d 100644 --- a/src/main/scala/vexriscv/plugin/IBusCachedPlugin.scala +++ b/src/main/scala/vexriscv/plugin/IBusCachedPlugin.scala @@ -25,7 +25,7 @@ class IBusCachedPlugin(resetVector : BigInt = 0x80000000l, cmdToRspStageCount = (if(config.twoCycleCache) 2 else 1), injectorReadyCutGen = false, relaxedPcCalculation = relaxedPcCalculation, - prediction_ = prediction, + prediction = prediction, historyRamSizeLog2 = historyRamSizeLog2, injectorStage = !config.twoCycleCache){ import config._ diff --git a/src/main/scala/vexriscv/plugin/IBusSimplePlugin.scala b/src/main/scala/vexriscv/plugin/IBusSimplePlugin.scala index aefafd2..9cef45c 100644 --- a/src/main/scala/vexriscv/plugin/IBusSimplePlugin.scala +++ b/src/main/scala/vexriscv/plugin/IBusSimplePlugin.scala @@ -123,7 +123,7 @@ class IBusSimplePlugin(resetVector : BigInt, cmdToRspStageCount = busLatencyMin, injectorReadyCutGen = false, relaxedPcCalculation = relaxedPcCalculation, - prediction_ = prediction, + prediction = prediction, historyRamSizeLog2 = historyRamSizeLog2, injectorStage = injectorStage){ 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)) rspBuffer.io.push << iBus.rsp.throwWhen(discardCounter =/= 0).toStream rspBuffer.io.flush := flush diff --git a/src/test/cpp/regression/main.cpp b/src/test/cpp/regression/main.cpp index f89393b..57e25c0 100644 --- a/src/test/cpp/regression/main.cpp +++ b/src/test/cpp/regression/main.cpp @@ -1761,7 +1761,7 @@ int main(int argc, char **argv, char **env) { #ifdef CSR #ifndef COMPRESSED 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);) #else uint32_t machineCsrRef[] = {1,11, 2,0x80000003u, 3,0x80000007u, 4,0x8000000bu, 5,6,7,0x80000007u ,