From 0d318ab6b9fab60f60fe7f213afa3bb2289b0c5a Mon Sep 17 00:00:00 2001 From: Dolu1990 Date: Mon, 29 Jan 2018 13:17:11 +0100 Subject: [PATCH] Add DYNAMIC_TARGET branch prediction (1.41 DMIPS/Mhz) Add longer timeouts in the regressions tests --- src/main/scala/vexriscv/TestsWorkspace.scala | 11 +- .../scala/vexriscv/plugin/BranchPlugin.scala | 153 ++++++++++++++++-- src/test/cpp/regression/main.cpp | 12 +- 3 files changed, 155 insertions(+), 21 deletions(-) diff --git a/src/main/scala/vexriscv/TestsWorkspace.scala b/src/main/scala/vexriscv/TestsWorkspace.scala index 9ebb46a..f188023 100644 --- a/src/main/scala/vexriscv/TestsWorkspace.scala +++ b/src/main/scala/vexriscv/TestsWorkspace.scala @@ -41,7 +41,7 @@ object TestsWorkspace { // ), new IBusCachedPlugin( config = InstructionCacheConfig( - cacheSize = 4096, + cacheSize = 4096*4, bytePerLine =32, wayCount = 1, wrappedMemAccess = true, @@ -66,7 +66,7 @@ object TestsWorkspace { // ), new DBusCachedPlugin( config = new DataCacheConfig( - cacheSize = 4096, + cacheSize = 4096*4, bytePerLine = 32, wayCount = 1, addressWidth = 32, @@ -102,7 +102,7 @@ object TestsWorkspace { new SrcPlugin( separatedAddSub = false ), - new FullBarrielShifterPlugin(earlyInjection = false), + new FullBarrielShifterPlugin(earlyInjection = true), // new LightShifterPlugin, new HazardSimplePlugin( bypassExecute = true, @@ -120,9 +120,10 @@ object TestsWorkspace { new CsrPlugin(CsrPluginConfig.all), new DebugPlugin(ClockDomain.current.clone(reset = Bool().setName("debugReset"))), new BranchPlugin( - earlyBranch = false, + earlyBranch = true, catchAddressMisaligned = true, - prediction = DYNAMIC + prediction = DYNAMIC_TARGET, + historyRamSizeLog2 = 12 ), new YamlPlugin("cpu0.yaml") ) diff --git a/src/main/scala/vexriscv/plugin/BranchPlugin.scala b/src/main/scala/vexriscv/plugin/BranchPlugin.scala index c56f7a6..521a8fd 100644 --- a/src/main/scala/vexriscv/plugin/BranchPlugin.scala +++ b/src/main/scala/vexriscv/plugin/BranchPlugin.scala @@ -9,6 +9,7 @@ trait BranchPrediction object NONE extends BranchPrediction object STATIC extends BranchPrediction object DYNAMIC extends BranchPrediction +object DYNAMIC_TARGET extends BranchPrediction class BranchPlugin(earlyBranch : Boolean, catchAddressMisaligned : Boolean, @@ -66,14 +67,20 @@ class BranchPlugin(earlyBranch : Boolean, val pcManagerService = pipeline.service(classOf[JumpService]) jumpInterface = pcManagerService.createJumpInterface(if(earlyBranch) pipeline.execute else pipeline.memory) - if (prediction != NONE) - predictionJumpInterface = pcManagerService.createJumpInterface(pipeline.decode) + + prediction match { + case NONE => + case STATIC | DYNAMIC => predictionJumpInterface = pcManagerService.createJumpInterface(pipeline.decode) + case DYNAMIC_TARGET => predictionJumpInterface = pcManagerService.createJumpInterface(pipeline.fetch) + } if (catchAddressMisaligned) { val exceptionService = pipeline.service(classOf[ExceptionService]) branchExceptionPort = exceptionService.newExceptionPort(if (earlyBranch) pipeline.execute else pipeline.memory) - if (prediction != NONE) { - predictionExceptionPort = exceptionService.newExceptionPort(pipeline.decode) + prediction match { + case NONE => + case STATIC | DYNAMIC => predictionExceptionPort = exceptionService.newExceptionPort(pipeline.decode) + case DYNAMIC_TARGET => } } } @@ -82,6 +89,7 @@ class BranchPlugin(earlyBranch : Boolean, case `NONE` => buildWithoutPrediction(pipeline) case `STATIC` => buildWithPrediction(pipeline) case `DYNAMIC` => buildWithPrediction(pipeline) + case `DYNAMIC_TARGET` => buildDynamicTargetPrediction(pipeline) } def buildWithoutPrediction(pipeline: VexRiscv): Unit = { @@ -138,14 +146,15 @@ class BranchPlugin(earlyBranch : Boolean, } } - case class BranchPredictorLine() extends Bundle{ - val history = SInt(historyWidth bits) - } - - object PREDICTION_HAD_BRANCHED extends Stageable(Bool) - object HISTORY_LINE extends Stageable(BranchPredictorLine()) def buildWithPrediction(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._ @@ -256,4 +265,128 @@ class BranchPlugin(earlyBranch : Boolean, historyCacheWrite.data.history := newHistory.resized } } + + + + + + def buildDynamicTargetPrediction(pipeline: VexRiscv): Unit = { + import pipeline._ + import pipeline.config._ + + case class BranchPredictorLine() extends Bundle{ + val enable = Bool + val target = UInt(32 bits) + } + + object PREDICTION_HAD_HAZARD extends Stageable(Bool) + object PREDICTION extends Stageable(Flow(UInt(32 bits))) + + val history = Mem(BranchPredictorLine(), 1 << historyRamSizeLog2) + val historyWrite = history.writePort + + + fetch plug new Area{ + import fetch._ +// val line = predictorLines.readSync(prefetch.output(PC), prefetch.arbitration.isFiring) + val line = history.readAsync((fetch.output(PC) >> 2).resized) + predictionJumpInterface.valid := line.enable && arbitration.isFiring + predictionJumpInterface.payload := line.target + + //Avoid write to read hazard + val historyWriteLast = RegNext(historyWrite) + insert(PREDICTION_HAD_HAZARD) := historyWriteLast.valid && historyWriteLast.address === (fetch.output(PC) >> 2).resized + predictionJumpInterface.valid clearWhen(input(PREDICTION_HAD_HAZARD)) + + fetch.insert(PREDICTION) := predictionJumpInterface + } + + + + //Do branch calculations (conditions + target PC) + execute plug new Area { + import execute._ + + val less = input(SRC_LESS) + val eq = input(SRC1) === input(SRC2) + + insert(BRANCH_DO) := input(BRANCH_CTRL).mux( + BranchCtrlEnum.INC -> False, + BranchCtrlEnum.JAL -> True, + BranchCtrlEnum.JALR -> True, + BranchCtrlEnum.B -> input(INSTRUCTION)(14 downto 12).mux( + B"000" -> eq , + B"001" -> !eq , + M"1-1" -> !less, + default -> less + ) + ) + + val imm = IMM(input(INSTRUCTION)) + val branch_src1 = (input(BRANCH_CTRL) === BranchCtrlEnum.JALR) ? input(RS1).asUInt | input(PC) + val branch_src2 = input(BRANCH_CTRL).mux( + BranchCtrlEnum.JAL -> imm.j_sext, + BranchCtrlEnum.JALR -> imm.i_sext, + default -> imm.b_sext + ).asUInt + + val branchAdder = branch_src1 + branch_src2 + insert(BRANCH_CALC) := branchAdder(31 downto 1) @@ ((input(BRANCH_CTRL) === BranchCtrlEnum.JALR) ? False | branchAdder(0)) + } + + //Apply branchs (JAL,JALR, Bxx) + val branchStage = if(earlyBranch) execute else memory + branchStage plug new Area { + import branchStage._ + + historyWrite.valid := False + historyWrite.address := (branchStage.output(PC) >> 2).resized + historyWrite.data.enable := input(BRANCH_DO) + historyWrite.data.target := input(BRANCH_CALC) + + jumpInterface.valid := False + jumpInterface.payload := input(BRANCH_CALC) + + + when(!input(BRANCH_DO)){ + when(input(PREDICTION).valid) { + jumpInterface.valid := arbitration.isFiring + jumpInterface.payload := input(PC) + 4 + historyWrite.valid := arbitration.isFiring + } + } otherwise{ + when (!input(PREDICTION).valid || input(PREDICTION).payload =/= input(BRANCH_CALC)) { + jumpInterface.valid := arbitration.isFiring + historyWrite.valid := arbitration.isFiring + } + } + + //Prevent rewriting an history which already had hazard + historyWrite.valid clearWhen(input(PREDICTION_HAD_HAZARD)) + + + + when(jumpInterface.valid) { + stages(indexOf(branchStage) - 1).arbitration.flushAll := True + } + + if(catchAddressMisaligned) { + branchExceptionPort.valid := arbitration.isValid && input(BRANCH_DO) && jumpInterface.payload(1 downto 0) =/= 0 + branchExceptionPort.code := 0 + branchExceptionPort.badAddr := jumpInterface.payload + } + } + + //Init History + val historyInit = pipeline plug new Area{ + val counter = Reg(UInt(historyRamSizeLog2 + 1 bits)) init(0) + when(!counter.msb){ + prefetch.arbitration.haltByOther := True + historyWrite.valid := True + historyWrite.address := counter.resized + historyWrite.data.enable := False + counter := counter + 1 + } + } + } } \ No newline at end of file diff --git a/src/test/cpp/regression/main.cpp b/src/test/cpp/regression/main.cpp index 879cb33..06345f2 100644 --- a/src/test/cpp/regression/main.cpp +++ b/src/test/cpp/regression/main.cpp @@ -1706,14 +1706,14 @@ int main(int argc, char **argv, char **env) { #ifdef CSR 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 }; - redo(REDO,TestX28("machineCsr",machineCsrRef, sizeof(machineCsrRef)/4).noInstructionReadCheck()->run(4e3);) + redo(REDO,TestX28("machineCsr",machineCsrRef, sizeof(machineCsrRef)/4).noInstructionReadCheck()->run(4e4);) #endif #ifdef MMU uint32_t mmuRef[] = {1,2,3, 0x11111111, 0x11111111, 0x11111111, 0x22222222, 0x22222222, 0x22222222, 4, 0x11111111, 0x33333333, 0x33333333, 5, 13, 0xC4000000,0x33333333, 6,7, 1,2,3, 0x11111111, 0x11111111, 0x11111111, 0x22222222, 0x22222222, 0x22222222, 4, 0x11111111, 0x33333333, 0x33333333, 5, 13, 0xC4000000,0x33333333, 6,7}; - redo(REDO,TestX28("mmu",mmuRef, sizeof(mmuRef)/4).noInstructionReadCheck()->run(4e3);) + redo(REDO,TestX28("mmu",mmuRef, sizeof(mmuRef)/4).noInstructionReadCheck()->run(4e4);) #endif #ifdef DEBUG_PLUGIN @@ -1731,13 +1731,13 @@ int main(int argc, char **argv, char **env) { #endif #ifdef DHRYSTONE - Dhrystone("dhrystoneO3_Stall","dhrystoneO3",true,true).run(1.1e6); + Dhrystone("dhrystoneO3_Stall","dhrystoneO3",true,true).run(1.5e6); #if defined(MUL) && defined(DIV) - Dhrystone("dhrystoneO3M_Stall","dhrystoneO3M",true,true).run(1.5e6); + Dhrystone("dhrystoneO3M_Stall","dhrystoneO3M",true,true).run(1.9e6); #endif - Dhrystone("dhrystoneO3","dhrystoneO3",false,false).run(1.5e6); + Dhrystone("dhrystoneO3","dhrystoneO3",false,false).run(1.9e6); #if defined(MUL) && defined(DIV) - Dhrystone("dhrystoneO3M","dhrystoneO3M",false,false).run(1.2e6); + Dhrystone("dhrystoneO3M","dhrystoneO3M",false,false).run(1.9e6); #endif #endif