Add DYNAMIC_TARGET branch prediction (1.41 DMIPS/Mhz)

Add longer timeouts in the regressions tests
This commit is contained in:
Dolu1990 2018-01-29 13:17:11 +01:00
parent 307c0b6bfa
commit 0d318ab6b9
3 changed files with 155 additions and 21 deletions

View File

@ -41,7 +41,7 @@ object TestsWorkspace {
// ), // ),
new IBusCachedPlugin( new IBusCachedPlugin(
config = InstructionCacheConfig( config = InstructionCacheConfig(
cacheSize = 4096, cacheSize = 4096*4,
bytePerLine =32, bytePerLine =32,
wayCount = 1, wayCount = 1,
wrappedMemAccess = true, wrappedMemAccess = true,
@ -66,7 +66,7 @@ object TestsWorkspace {
// ), // ),
new DBusCachedPlugin( new DBusCachedPlugin(
config = new DataCacheConfig( config = new DataCacheConfig(
cacheSize = 4096, cacheSize = 4096*4,
bytePerLine = 32, bytePerLine = 32,
wayCount = 1, wayCount = 1,
addressWidth = 32, addressWidth = 32,
@ -102,7 +102,7 @@ object TestsWorkspace {
new SrcPlugin( new SrcPlugin(
separatedAddSub = false separatedAddSub = false
), ),
new FullBarrielShifterPlugin(earlyInjection = false), new FullBarrielShifterPlugin(earlyInjection = true),
// new LightShifterPlugin, // new LightShifterPlugin,
new HazardSimplePlugin( new HazardSimplePlugin(
bypassExecute = true, bypassExecute = true,
@ -120,9 +120,10 @@ object TestsWorkspace {
new CsrPlugin(CsrPluginConfig.all), new CsrPlugin(CsrPluginConfig.all),
new DebugPlugin(ClockDomain.current.clone(reset = Bool().setName("debugReset"))), new DebugPlugin(ClockDomain.current.clone(reset = Bool().setName("debugReset"))),
new BranchPlugin( new BranchPlugin(
earlyBranch = false, earlyBranch = true,
catchAddressMisaligned = true, catchAddressMisaligned = true,
prediction = DYNAMIC prediction = DYNAMIC_TARGET,
historyRamSizeLog2 = 12
), ),
new YamlPlugin("cpu0.yaml") new YamlPlugin("cpu0.yaml")
) )

View File

@ -9,6 +9,7 @@ trait BranchPrediction
object NONE extends BranchPrediction object NONE extends BranchPrediction
object STATIC extends BranchPrediction object STATIC extends BranchPrediction
object DYNAMIC extends BranchPrediction object DYNAMIC extends BranchPrediction
object DYNAMIC_TARGET extends BranchPrediction
class BranchPlugin(earlyBranch : Boolean, class BranchPlugin(earlyBranch : Boolean,
catchAddressMisaligned : Boolean, catchAddressMisaligned : Boolean,
@ -66,14 +67,20 @@ class BranchPlugin(earlyBranch : Boolean,
val pcManagerService = pipeline.service(classOf[JumpService]) val pcManagerService = pipeline.service(classOf[JumpService])
jumpInterface = pcManagerService.createJumpInterface(if(earlyBranch) pipeline.execute else pipeline.memory) 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) { if (catchAddressMisaligned) {
val exceptionService = pipeline.service(classOf[ExceptionService]) val exceptionService = pipeline.service(classOf[ExceptionService])
branchExceptionPort = exceptionService.newExceptionPort(if (earlyBranch) pipeline.execute else pipeline.memory) branchExceptionPort = exceptionService.newExceptionPort(if (earlyBranch) pipeline.execute else pipeline.memory)
if (prediction != NONE) { prediction match {
predictionExceptionPort = exceptionService.newExceptionPort(pipeline.decode) 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 `NONE` => buildWithoutPrediction(pipeline)
case `STATIC` => buildWithPrediction(pipeline) case `STATIC` => buildWithPrediction(pipeline)
case `DYNAMIC` => buildWithPrediction(pipeline) case `DYNAMIC` => buildWithPrediction(pipeline)
case `DYNAMIC_TARGET` => buildDynamicTargetPrediction(pipeline)
} }
def buildWithoutPrediction(pipeline: VexRiscv): Unit = { 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 = { 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._
import pipeline.config._ import pipeline.config._
@ -256,4 +265,128 @@ class BranchPlugin(earlyBranch : Boolean,
historyCacheWrite.data.history := newHistory.resized 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
}
}
}
} }

View File

@ -1706,14 +1706,14 @@ int main(int argc, char **argv, char **env) {
#ifdef CSR #ifdef CSR
uint32_t machineCsrRef[] = {1,11, 2,0x80000003u, 3,0x80000007u, 4,0x8000000bu, 5,6,7,0x80000007u , 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,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 #endif
#ifdef MMU #ifdef MMU
uint32_t mmuRef[] = {1,2,3, 0x11111111, 0x11111111, 0x11111111, 0x22222222, 0x22222222, 0x22222222, 4, 0x11111111, 0x33333333, 0x33333333, 5, uint32_t mmuRef[] = {1,2,3, 0x11111111, 0x11111111, 0x11111111, 0x22222222, 0x22222222, 0x22222222, 4, 0x11111111, 0x33333333, 0x33333333, 5,
13, 0xC4000000,0x33333333, 6,7, 13, 0xC4000000,0x33333333, 6,7,
1,2,3, 0x11111111, 0x11111111, 0x11111111, 0x22222222, 0x22222222, 0x22222222, 4, 0x11111111, 0x33333333, 0x33333333, 5, 1,2,3, 0x11111111, 0x11111111, 0x11111111, 0x22222222, 0x22222222, 0x22222222, 4, 0x11111111, 0x33333333, 0x33333333, 5,
13, 0xC4000000,0x33333333, 6,7}; 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 #endif
#ifdef DEBUG_PLUGIN #ifdef DEBUG_PLUGIN
@ -1731,13 +1731,13 @@ int main(int argc, char **argv, char **env) {
#endif #endif
#ifdef DHRYSTONE #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) #if defined(MUL) && defined(DIV)
Dhrystone("dhrystoneO3M_Stall","dhrystoneO3M",true,true).run(1.5e6); Dhrystone("dhrystoneO3M_Stall","dhrystoneO3M",true,true).run(1.9e6);
#endif #endif
Dhrystone("dhrystoneO3","dhrystoneO3",false,false).run(1.5e6); Dhrystone("dhrystoneO3","dhrystoneO3",false,false).run(1.9e6);
#if defined(MUL) && defined(DIV) #if defined(MUL) && defined(DIV)
Dhrystone("dhrystoneO3M","dhrystoneO3M",false,false).run(1.2e6); Dhrystone("dhrystoneO3M","dhrystoneO3M",false,false).run(1.9e6);
#endif #endif
#endif #endif