Add Static/Dynamic branch prediction
This commit is contained in:
parent
d569242124
commit
ecf853f491
|
@ -10,7 +10,7 @@ object DISABLE extends BranchPrediction
|
|||
object STATIC extends BranchPrediction
|
||||
object DYNAMIC extends BranchPrediction
|
||||
|
||||
class NoPredictionBranchPlugin(earlyBranch : Boolean,prediction : BranchPrediction) extends Plugin[VexRiscv]{
|
||||
class BranchPlugin(earlyBranch : Boolean,prediction : BranchPrediction,historyRamSizeLog2 : Int = 10,historyWidth : Int = 2) extends Plugin[VexRiscv]{
|
||||
object BranchCtrlEnum extends SpinalEnum(binarySequential){
|
||||
val INC,B,JAL,JALR = newElement()
|
||||
}
|
||||
|
@ -18,6 +18,7 @@ class NoPredictionBranchPlugin(earlyBranch : Boolean,prediction : BranchPredicti
|
|||
object BRANCH_CTRL extends Stageable(BranchCtrlEnum())
|
||||
object BRANCH_CALC extends Stageable(UInt(32 bits))
|
||||
object BRANCH_DO extends Stageable(Bool)
|
||||
object BRANCH_COND_RESULT extends Stageable(Bool)
|
||||
|
||||
var jumpInterface : Flow[UInt] = null
|
||||
var predictionJumpInterface : Flow[UInt] = null
|
||||
|
@ -61,6 +62,7 @@ class NoPredictionBranchPlugin(earlyBranch : Boolean,prediction : BranchPredicti
|
|||
jumpInterface = pcManagerService.createJumpInterface(pipeline.execute)
|
||||
if(prediction != DISABLE) predictionJumpInterface = pcManagerService.createJumpInterface(pipeline.decode)
|
||||
}
|
||||
|
||||
override def build(pipeline: VexRiscv): Unit = prediction match {
|
||||
case `DISABLE` => buildWithoutPrediction(pipeline)
|
||||
case `STATIC` => buildWithPrediction(pipeline)
|
||||
|
@ -106,7 +108,6 @@ class NoPredictionBranchPlugin(earlyBranch : Boolean,prediction : BranchPredicti
|
|||
jumpInterface.payload := input(BRANCH_CALC)
|
||||
|
||||
when(jumpInterface.valid) {
|
||||
//prefetch.arbitration.removeIt := True
|
||||
fetch.arbitration.removeIt := True
|
||||
decode.arbitration.removeIt := True
|
||||
if(!earlyBranch) execute.arbitration.removeIt := True
|
||||
|
@ -114,23 +115,41 @@ class NoPredictionBranchPlugin(earlyBranch : Boolean,prediction : BranchPredicti
|
|||
}
|
||||
}
|
||||
|
||||
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 = {
|
||||
import pipeline._
|
||||
import pipeline.config._
|
||||
|
||||
val historyCache = Mem(BranchPredictorLine(), 1 << historyRamSizeLog2) setName("branchCache")
|
||||
val historyCacheWrite = historyCache.writePort
|
||||
|
||||
//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
|
||||
val writePortReg = RegNext(historyCacheWrite)
|
||||
when(writePortReg.valid && writePortReg.address === readAddress){
|
||||
fetch.insert(HISTORY_LINE) := writePortReg.data
|
||||
}
|
||||
}
|
||||
|
||||
decode plug new Area{
|
||||
import decode._
|
||||
val imm = IMM(input(INSTRUCTION))
|
||||
|
||||
// branch prediction
|
||||
val staticBranchPrediction = (imm.b_sext.msb && input(BRANCH_CTRL) === BranchCtrlEnum.B) || input(BRANCH_CTRL) === BranchCtrlEnum.JAL
|
||||
insert(PREDICTION_HAD_BRANCHED) := (prediction match {
|
||||
case `STATIC` =>
|
||||
staticBranchPrediction
|
||||
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
|
||||
|
@ -145,7 +164,7 @@ class NoPredictionBranchPlugin(earlyBranch : Boolean,prediction : BranchPredicti
|
|||
val less = input(SRC_LESS)
|
||||
val eq = input(SRC1) === input(SRC2)
|
||||
|
||||
insert(BRANCH_DO) := input(PREDICTION_HAD_BRANCHED) =/= input(BRANCH_CTRL).mux(
|
||||
insert(BRANCH_COND_RESULT) := input(BRANCH_CTRL).mux(
|
||||
BranchCtrlEnum.INC -> False,
|
||||
BranchCtrlEnum.JAL -> True,
|
||||
BranchCtrlEnum.JALR -> True,
|
||||
|
@ -157,6 +176,9 @@ class NoPredictionBranchPlugin(earlyBranch : Boolean,prediction : BranchPredicti
|
|||
)
|
||||
)
|
||||
|
||||
insert(BRANCH_DO) := input(PREDICTION_HAD_BRANCHED) =/= insert(BRANCH_COND_RESULT)
|
||||
|
||||
//Calculation of the branch target / correction
|
||||
val imm = IMM(input(INSTRUCTION))
|
||||
val branch_src1,branch_src2 = UInt(32 bits)
|
||||
switch(input(BRANCH_CTRL)){
|
||||
|
@ -173,6 +195,8 @@ class NoPredictionBranchPlugin(earlyBranch : Boolean,prediction : BranchPredicti
|
|||
}
|
||||
|
||||
val branchStage = if(earlyBranch) execute else memory
|
||||
|
||||
// Apply branch corrections
|
||||
branchStage plug new Area {
|
||||
import branchStage._
|
||||
jumpInterface.valid := input(BRANCH_DO) && arbitration.isFiring
|
||||
|
@ -184,5 +208,16 @@ class NoPredictionBranchPlugin(earlyBranch : Boolean,prediction : BranchPredicti
|
|||
if(!earlyBranch) execute.arbitration.removeIt := True
|
||||
}
|
||||
}
|
||||
|
||||
//Update historyCache
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
|
@ -45,7 +45,7 @@ object TopLevel {
|
|||
// new HazardSimplePlugin(false, false, false, false),
|
||||
new MulPlugin,
|
||||
new DivPlugin,
|
||||
new NoPredictionBranchPlugin(true, STATIC)
|
||||
new BranchPlugin(false, DYNAMIC)
|
||||
)
|
||||
|
||||
val toplevel = new VexRiscv(config)
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
[*]
|
||||
[*] GTKWave Analyzer v3.3.58 (w)1999-2014 BSI
|
||||
[*] Mon Mar 20 10:40:36 2017
|
||||
[*]
|
||||
[dumpfile] "/home/spinalvm/Spinal/VexRiscv/src/test/cpp/testA/dhrystoneO3M.vcd"
|
||||
[dumpfile_mtime] "Mon Mar 20 10:40:36 2017"
|
||||
[dumpfile_size] 1149914709
|
||||
[savefile] "/home/spinalvm/Spinal/VexRiscv/src/test/cpp/testA/branch.gtkw"
|
||||
[timestart] 68
|
||||
[size] 1776 953
|
||||
[pos] -775 -1
|
||||
*-4.000000 87 -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] 432
|
||||
[signals_width] 520
|
||||
[sst_expanded] 1
|
||||
[sst_vpaned_height] 279
|
||||
@28
|
||||
TOP.VexRiscv.execute_input_HISTORY_LINE_history[1:0]
|
||||
TOP.VexRiscv.fetch_HISTORY_LINE_history[1:0]
|
||||
TOP.VexRiscv.memory_input_HISTORY_LINE_history[1:0]
|
||||
TOP.VexRiscv.decode_arbitration_isValid
|
||||
TOP.VexRiscv.decode_arbitration_isFiring
|
||||
@22
|
||||
TOP.VexRiscv.decode_input_PC[31:0]
|
||||
@28
|
||||
TOP.VexRiscv.decode_input_HISTORY_LINE_history[1:0]
|
||||
@29
|
||||
TOP.VexRiscv.prefetch_PcManagerSimplePlugin_jump_pcLoad_valid
|
||||
[pattern_trace] 1
|
||||
[pattern_trace] 0
|
|
@ -12,6 +12,7 @@
|
|||
#include <fstream>
|
||||
|
||||
//#define REF
|
||||
//#define TRACE
|
||||
|
||||
class Memory{
|
||||
public:
|
||||
|
@ -137,6 +138,9 @@ public:
|
|||
VVexRiscv* top;
|
||||
int i;
|
||||
uint32_t iStall = 1,dStall = 1;
|
||||
#ifdef TRACE
|
||||
VerilatedVcdC* tfp;
|
||||
#endif
|
||||
|
||||
void setIStall(bool enable) { iStall = enable; }
|
||||
void setDStall(bool enable) { dStall = enable; }
|
||||
|
@ -157,6 +161,9 @@ public:
|
|||
|
||||
virtual ~Workspace(){
|
||||
delete top;
|
||||
#ifdef TRACE
|
||||
delete tfp;
|
||||
#endif
|
||||
}
|
||||
|
||||
Workspace* loadHex(string path){
|
||||
|
@ -168,7 +175,7 @@ public:
|
|||
virtual void checks(){}
|
||||
virtual void pass(){ throw success();}
|
||||
virtual void fail(){ throw std::exception();}
|
||||
void dump(long i){
|
||||
void dump(int i){
|
||||
#ifdef TRACE
|
||||
tfp->dump(i);
|
||||
#endif
|
||||
|
@ -179,7 +186,7 @@ public:
|
|||
// init trace dump
|
||||
Verilated::traceEverOn(true);
|
||||
#ifdef TRACE
|
||||
VerilatedVcdC* tfp = new VerilatedVcdC;
|
||||
tfp = new VerilatedVcdC;
|
||||
top->trace(tfp, 99);
|
||||
tfp->open((string(name)+ ".vcd").c_str());
|
||||
#endif
|
||||
|
@ -508,6 +515,8 @@ int main(int argc, char **argv, char **env) {
|
|||
Dhrystone("dhrystoneO3",true,true).run(1e6);
|
||||
Dhrystone("dhrystoneO3M",true,true).run(0.8e6);
|
||||
Dhrystone("dhrystoneO3M",false,false).run(0.8e6);
|
||||
// Dhrystone("dhrystoneO3ML",false,false).run(8e6);
|
||||
// Dhrystone("dhrystoneO3MLL",false,false).run(80e6);
|
||||
}
|
||||
|
||||
uint64_t duration = timer_end(startedAt);
|
||||
|
|
|
@ -2,14 +2,14 @@ TRACE=no
|
|||
|
||||
ifeq ($(TRACE),yes)
|
||||
VERILATOR_ARGS += --trace
|
||||
ADDCFLAGS += -DTRACE
|
||||
ADDCFLAGS += -CFLAGS -DTRACE
|
||||
endif
|
||||
|
||||
run: compile
|
||||
./obj_dir/VVexRiscv
|
||||
|
||||
verilate:
|
||||
verilator -cc ../../../../VexRiscv.v -O3 -CFLAGS -std=c++11 ${ADDCFLAGS} --gdbbt ${VERILATOR_ARGS} -Wno-WIDTH --x-assign unique --exe main.cpp
|
||||
verilator -cc ../../../../VexRiscv.v -O3 -CFLAGS -std=c++11 ${ADDCFLAGS} --gdbbt ${VERILATOR_ARGS} -Wno-WIDTH --x-assign unique --exe main.cpp
|
||||
|
||||
compile: verilate
|
||||
make -j -C obj_dir/ -f VVexRiscv.mk VVexRiscv
|
||||
|
|
|
@ -17,13 +17,15 @@
|
|||
:10010000032A0105832A4105032B8105832BC105A1
|
||||
:10011000032C0106832C4106032D8106832DC10685
|
||||
:10012000032E0107832E4107032F8107832FC10769
|
||||
:10013000130101081300000017110000130181864C
|
||||
:1001400017E50040130505849705014093850508D0
|
||||
:100150006308B50023200500130545006FF05FFF1D
|
||||
:1001600017D50040130585F41301C1FF97D5004052
|
||||
:100170009385C5F3630EB50083260500130545007E
|
||||
:100180002320A100E7800600032501006FF01FFE79
|
||||
:100190001301410097120040E78082A66F00000023
|
||||
:1001300013010108130000001711000013010188CA
|
||||
:10014000130540011300000013000000130000001D
|
||||
:100150001305F5FFE31805FE17E50040130585823A
|
||||
:1001600097050140938585066308B50023200500A7
|
||||
:10017000130545006FF05FFF17D50040130505F329
|
||||
:100180001301C1FF97D50040938545F2630EB5007A
|
||||
:1001900083260500130545002320A100E780060003
|
||||
:1001A000032501006FF01FFE13014100971200406C
|
||||
:0801B000E78002A56F000000CA
|
||||
:020000044000BA
|
||||
:10000000B7E7004003C79799930710046304F7000C
|
||||
:10001000678000008327050037E700400327079A21
|
||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue