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(
|
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")
|
||||||
)
|
)
|
||||||
|
|
|
@ -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,6 +146,8 @@ class BranchPlugin(earlyBranch : Boolean,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def buildWithPrediction(pipeline: VexRiscv): Unit = {
|
||||||
case class BranchPredictorLine() extends Bundle{
|
case class BranchPredictorLine() extends Bundle{
|
||||||
val history = SInt(historyWidth bits)
|
val history = SInt(historyWidth bits)
|
||||||
}
|
}
|
||||||
|
@ -145,7 +155,6 @@ class BranchPlugin(earlyBranch : Boolean,
|
||||||
object PREDICTION_HAD_BRANCHED extends Stageable(Bool)
|
object PREDICTION_HAD_BRANCHED extends Stageable(Bool)
|
||||||
object HISTORY_LINE extends Stageable(BranchPredictorLine())
|
object HISTORY_LINE extends Stageable(BranchPredictorLine())
|
||||||
|
|
||||||
def buildWithPrediction(pipeline: VexRiscv): Unit = {
|
|
||||||
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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -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
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue