Add DYNAMIC_TARGET branch prediction (1.41 DMIPS/Mhz)
Add longer timeouts in the regressions tests
This commit is contained in:
parent
307c0b6bfa
commit
0d318ab6b9
|
@ -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")
|
||||
)
|
||||
|
|
|
@ -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,6 +146,8 @@ class BranchPlugin(earlyBranch : Boolean,
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
def buildWithPrediction(pipeline: VexRiscv): Unit = {
|
||||
case class BranchPredictorLine() extends Bundle{
|
||||
val history = SInt(historyWidth bits)
|
||||
}
|
||||
|
@ -145,7 +155,6 @@ class BranchPlugin(earlyBranch : Boolean,
|
|||
object PREDICTION_HAD_BRANCHED extends Stageable(Bool)
|
||||
object HISTORY_LINE extends Stageable(BranchPredictorLine())
|
||||
|
||||
def buildWithPrediction(pipeline: VexRiscv): Unit = {
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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
|
||||
|
||||
|
|
Loading…
Reference in New Issue