Add Static/Dynamic branch prediction

This commit is contained in:
Charles Papon 2017-03-20 12:37:20 +01:00
parent d569242124
commit ecf853f491
8 changed files with 7123 additions and 21 deletions

View File

@ -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
}
}
}

View File

@ -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)

View File

@ -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

View File

@ -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);

View File

@ -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

View File

@ -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