diff --git a/src/main/scala/vexriscv/TestsWorkspace.scala b/src/main/scala/vexriscv/TestsWorkspace.scala index f188023..38e57c4 100644 --- a/src/main/scala/vexriscv/TestsWorkspace.scala +++ b/src/main/scala/vexriscv/TestsWorkspace.scala @@ -123,7 +123,7 @@ object TestsWorkspace { earlyBranch = true, catchAddressMisaligned = true, prediction = DYNAMIC_TARGET, - historyRamSizeLog2 = 12 + historyRamSizeLog2 = 8 ), new YamlPlugin("cpu0.yaml") ) diff --git a/src/main/scala/vexriscv/demo/DhrystoneBench.scala b/src/main/scala/vexriscv/demo/DhrystoneBench.scala index d190199..9cebd0e 100644 --- a/src/main/scala/vexriscv/demo/DhrystoneBench.scala +++ b/src/main/scala/vexriscv/demo/DhrystoneBench.scala @@ -32,14 +32,14 @@ object DhrystoneBench extends App{ getDmips( name = "GenSmallest", gen = GenSmallest.main(null), - test = "make clean run REDO=0 IBUS=SIMPLE DBUS=SIMPLE MMU=no DEBUG_PLUGIN=no MUL=no DIV=no" + test = "make clean run REDO=0 IBUS=SIMPLE DBUS=SIMPLE CSR=no MMU=no DEBUG_PLUGIN=no MUL=no DIV=no" ) getDmips( name = "GenSmallAndProductive", gen = GenSmallAndProductive.main(null), - test = "make clean run REDO=0 IBUS=SIMPLE DBUS=SIMPLE MMU=no DEBUG_PLUGIN=no MUL=no DIV=no" + test = "make clean run REDO=0 IBUS=SIMPLE DBUS=SIMPLE CSR=no MMU=no DEBUG_PLUGIN=no MUL=no DIV=no" ) diff --git a/src/main/scala/vexriscv/demo/GenFullNoMmuMaxPerf.scala b/src/main/scala/vexriscv/demo/GenFullNoMmuMaxPerf.scala index 17a6317..40c7f51 100644 --- a/src/main/scala/vexriscv/demo/GenFullNoMmuMaxPerf.scala +++ b/src/main/scala/vexriscv/demo/GenFullNoMmuMaxPerf.scala @@ -78,7 +78,8 @@ object GenFullNoMmuMaxPerf extends App{ new BranchPlugin( earlyBranch = true, catchAddressMisaligned = true, - prediction = DYNAMIC + prediction = DYNAMIC_TARGET, + historyRamSizeLog2 = 8 ), new YamlPlugin("cpu0.yaml") ) diff --git a/src/main/scala/vexriscv/plugin/BranchPlugin.scala b/src/main/scala/vexriscv/plugin/BranchPlugin.scala index 521a8fd..1a16504 100644 --- a/src/main/scala/vexriscv/plugin/BranchPlugin.scala +++ b/src/main/scala/vexriscv/plugin/BranchPlugin.scala @@ -275,12 +275,14 @@ class BranchPlugin(earlyBranch : Boolean, import pipeline.config._ case class BranchPredictorLine() extends Bundle{ - val enable = Bool + val source = Bits(31 - historyRamSizeLog2 bits) + val confidence = UInt(2 bits) val target = UInt(32 bits) } - object PREDICTION_HAD_HAZARD extends Stageable(Bool) - object PREDICTION extends Stageable(Flow(UInt(32 bits))) + object PREDICTION_WRITE_HAZARD extends Stageable(Bool) + object PREDICTION extends Stageable(BranchPredictorLine()) + object PREDICTION_HIT extends Stageable(Bool) val history = Mem(BranchPredictorLine(), 1 << historyRamSizeLog2) val historyWrite = history.writePort @@ -288,17 +290,20 @@ class BranchPlugin(earlyBranch : Boolean, 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 + val line = history.readSync((prefetch.output(PC) >> 2).resized, prefetch.arbitration.isFiring) +// val line = history.readAsync((fetch.output(PC) >> 2).resized) + val hit = line.source === (input(PC).asBits >> 1 + historyRamSizeLog2) //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)) + val hazard = historyWriteLast.valid && historyWriteLast.address === (output(PC) >> 2).resized + insert(PREDICTION_WRITE_HAZARD) := hazard - fetch.insert(PREDICTION) := predictionJumpInterface + predictionJumpInterface.valid := line.confidence.msb && hit && arbitration.isFiring && !hazard + predictionJumpInterface.payload := line.target + + insert(PREDICTION) := line + insert(PREDICTION_HIT) := hit } @@ -339,9 +344,11 @@ class BranchPlugin(earlyBranch : Boolean, branchStage plug new Area { import branchStage._ + val predictionMissmatch = input(PREDICTION).confidence.msb =/= input(BRANCH_DO) || (input(BRANCH_DO) && input(PREDICTION).target =/= input(BRANCH_CALC)) + historyWrite.valid := False historyWrite.address := (branchStage.output(PC) >> 2).resized - historyWrite.data.enable := input(BRANCH_DO) + historyWrite.data.source := input(PC).asBits >> 1 + historyRamSizeLog2 historyWrite.data.target := input(BRANCH_CALC) jumpInterface.valid := False @@ -349,20 +356,29 @@ class BranchPlugin(earlyBranch : Boolean, when(!input(BRANCH_DO)){ - when(input(PREDICTION).valid) { - jumpInterface.valid := arbitration.isFiring - jumpInterface.payload := input(PC) + 4 - historyWrite.valid := arbitration.isFiring - } + historyWrite.valid := arbitration.isFiring && input(PREDICTION_HIT) + historyWrite.data.confidence := input(PREDICTION).confidence - (input(PREDICTION).confidence =/= 0).asUInt + historyWrite.data.target := input(BRANCH_CALC) + + + jumpInterface.valid := input(PREDICTION_HIT) && input(PREDICTION).confidence.msb && !input(PREDICTION_WRITE_HAZARD) && arbitration.isFiring + jumpInterface.payload := input(PC) + 4 } otherwise{ - when (!input(PREDICTION).valid || input(PREDICTION).payload =/= input(BRANCH_CALC)) { + when(!input(PREDICTION_HIT) || input(PREDICTION_WRITE_HAZARD)){ jumpInterface.valid := arbitration.isFiring historyWrite.valid := arbitration.isFiring + historyWrite.data.confidence := "10" + } otherwise { + historyWrite.valid := arbitration.isFiring + historyWrite.data.confidence := input(PREDICTION).confidence + (input(PREDICTION).confidence =/= 3).asUInt + when(!input(PREDICTION).confidence.msb || input(PREDICTION).target =/= input(BRANCH_CALC)){ + jumpInterface.valid := arbitration.isFiring + } } } //Prevent rewriting an history which already had hazard - historyWrite.valid clearWhen(input(PREDICTION_HAD_HAZARD)) + historyWrite.valid clearWhen(input(PREDICTION_WRITE_HAZARD)) @@ -384,7 +400,7 @@ class BranchPlugin(earlyBranch : Boolean, prefetch.arbitration.haltByOther := True historyWrite.valid := True historyWrite.address := counter.resized - historyWrite.data.enable := False + historyWrite.data.confidence := 0 counter := counter + 1 } } diff --git a/src/test/cpp/regression/prediction.gtkw b/src/test/cpp/regression/prediction.gtkw new file mode 100644 index 0000000..8abfdd9 --- /dev/null +++ b/src/test/cpp/regression/prediction.gtkw @@ -0,0 +1,43 @@ +[*] +[*] GTKWave Analyzer v3.3.58 (w)1999-2014 BSI +[*] Mon Jan 29 13:38:19 2018 +[*] +[dumpfile] "/home/spinalvm/hdl/VexRiscv/src/test/cpp/regression/dhrystoneO3M.vcd" +[dumpfile_mtime] "Mon Jan 29 13:37:19 2018" +[dumpfile_size] 1215443558 +[savefile] "/home/spinalvm/hdl/VexRiscv/src/test/cpp/regression/prediction.gtkw" +[timestart] 127017 +[size] 1784 950 +[pos] -383 -155 +*-3.000000 127032 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 +[treeopen] TOP. +[sst_width] 400 +[signals_width] 583 +[sst_expanded] 1 +[sst_vpaned_height] 492 +@28 +TOP.VexRiscv.iBus_cmd_valid +TOP.VexRiscv.decode_arbitration_flushAll +TOP.VexRiscv.execute_arbitration_flushAll +TOP.VexRiscv.fetch_arbitration_flushAll +TOP.VexRiscv.memory_arbitration_flushAll +TOP.VexRiscv.prefetch_arbitration_flushAll +TOP.VexRiscv.writeBack_arbitration_flushAll +TOP.VexRiscv.execute_BranchPlugin_predictionMissmatch +TOP.VexRiscv.execute_PREDICTION2_confidence[1:0] +@22 +TOP.VexRiscv.execute_PREDICTION2_source[18:0] +TOP.VexRiscv.execute_PREDICTION2_target[31:0] +@28 +TOP.VexRiscv.execute_PREDICTION_HIT2 +TOP.VexRiscv.execute_PREDICTION_WRITE_HAZARD2 +@23 +TOP.VexRiscv.execute_PC[31:0] +@28 +TOP.VexRiscv.prefetch_PcManagerSimplePlugin_jump_pcLoad_valid +@22 +TOP.VexRiscv.prefetch_PcManagerSimplePlugin_jump_pcLoad_payload[31:0] +@29 +TOP.VexRiscv.execute_arbitration_isFiring +[pattern_trace] 1 +[pattern_trace] 0