Merge remote-tracking branch 'origin/rework_jump_flush' into dev

This commit is contained in:
Charles Papon 2019-06-15 18:09:38 +02:00
commit 60c9c094a7
17 changed files with 222 additions and 232 deletions

View File

@ -66,53 +66,53 @@ The CPU configurations used below can be found in the `src/scala/vexriscv/demo`
``` ```
VexRiscv smallest (RV32I, 0.52 DMIPS/Mhz, no datapath bypass, no interrupt) -> VexRiscv smallest (RV32I, 0.52 DMIPS/Mhz, no datapath bypass, no interrupt) ->
Artix 7 -> 366 Mhz 488 LUT 505 FF Artix 7 -> 324 Mhz 496 LUT 505 FF
Cyclone V -> 181 Mhz 350 ALMs Cyclone V -> 193 Mhz 347 ALMs
Cyclone IV -> 177 Mhz 732 LUT 494 FF Cyclone IV -> 179 Mhz 730 LUT 494 FF
iCE40 -> 85 Mhz 1131 LC iCE40 -> 92 Mhz 1130 LC
VexRiscv smallest (RV32I, 0.52 DMIPS/Mhz, no datapath bypass) -> VexRiscv smallest (RV32I, 0.52 DMIPS/Mhz, no datapath bypass) ->
Artix 7 -> 317 Mhz 539 LUT 559 FF Artix 7 -> 328 Mhz 539 LUT 562 FF
Cyclone V -> 191 Mhz 393 ALMs Cyclone V -> 189 Mhz 387 ALMs
Cyclone IV -> 171 Mhz 826 LUT 547 FF Cyclone IV -> 175 Mhz 829 LUT 550 FF
iCE40 -> 72 Mhz 1284 LC iCE40 -> 85 Mhz 1292 LC
VexRiscv small and productive (RV32I, 0.82 DMIPS/Mhz) -> VexRiscv small and productive (RV32I, 0.82 DMIPS/Mhz) ->
Artix 7 -> 338 Mhz 697 LUT 527 FF Artix 7 -> 324 Mhz 701 LUT 531 FF
Cyclone V -> 149 Mhz 495 ALMs Cyclone V -> 145 Mhz 499 ALMs
Cyclone IV -> 137 Mhz 1,103 LUT 522 FF Cyclone IV -> 150 Mhz 1,111 LUT 525 FF
iCE40 -> 65 Mhz 1593 LC iCE40 -> 63 Mhz 1596 LC
VexRiscv small and productive with I$ (RV32I, 0.70 DMIPS/Mhz, 4KB-I$) -> VexRiscv small and productive with I$ (RV32I, 0.70 DMIPS/Mhz, 4KB-I$) ->
Artix 7 -> 314 Mhz 721 LUT 562 FF Artix 7 -> 336 Mhz 764 LUT 562 FF
Cyclone V -> 152 Mhz 504 ALMs Cyclone V -> 145 Mhz 511 ALMs
Cyclone IV -> 142 Mhz 1,146 LUT 528 FF Cyclone IV -> 144 Mhz 1,145 LUT 531 FF
iCE40 -> 69 Mhz 1661 LC iCE40 -> 66 Mhz 1680 LC
VexRiscv full no cache (RV32IM, 1.21 DMIPS/Mhz 2.30 Coremark/Mhz, single cycle barrel shifter, debug module, catch exceptions, static branch) -> VexRiscv full no cache (RV32IM, 1.21 DMIPS/Mhz 2.30 Coremark/Mhz, single cycle barrel shifter, debug module, catch exceptions, static branch) ->
Artix 7 -> 325 Mhz 1448 LUT 976 FF Artix 7 -> 326 Mhz 1544 LUT 977 FF
Cyclone V -> 141 Mhz 957 ALMs Cyclone V -> 139 Mhz 958 ALMs
Cyclone IV -> 139 Mhz 2,001 LUT 966 FF Cyclone IV -> 135 Mhz 2,011 LUT 968 FF
VexRiscv full (RV32IM, 1.21 DMIPS/Mhz 2.30 Coremark/Mhz with cache trashing, 4KB-I$,4KB-D$, single cycle barrel shifter, debug module, catch exceptions, static branch) -> VexRiscv full (RV32IM, 1.21 DMIPS/Mhz 2.30 Coremark/Mhz with cache trashing, 4KB-I$,4KB-D$, single cycle barrel shifter, debug module, catch exceptions, static branch) ->
Artix 7 -> 241 Mhz 1692 LUT 1202 FF Artix 7 -> 279 Mhz 1686 LUT 1172 FF
Cyclone V -> 132 Mhz 1,127 ALMs Cyclone V -> 144 Mhz 1,128 ALMs
Cyclone IV -> 124 Mhz 2,296 LUT 1,115 FF Cyclone IV -> 133 Mhz 2,298 LUT 1,096 FF
VexRiscv full max dmips/mhz -> (RV32IM, 1.44 DMIPS/Mhz 2.70 Coremark/Mhz,, 16KB-I$,16KB-D$, single cycle barrel shifter, debug module, catch exceptions, dynamic branch prediction in the fetch stage, branch and shift operations done in the Execute stage) -> VexRiscv full max dmips/mhz -> (RV32IM, 1.44 DMIPS/Mhz 2.70 Coremark/Mhz,, 16KB-I$,16KB-D$, single cycle barrel shifter, debug module, catch exceptions, dynamic branch prediction in the fetch stage, branch and shift operations done in the Execute stage) ->
Artix 7 -> 195 Mhz 1824 LUT 1110 FF Artix 7 -> 195 Mhz 1943 LUT 1111 FF
Cyclone V -> 83 Mhz 1,067 ALMs Cyclone V -> 90 Mhz 1,089 ALMs
Cyclone IV -> 78 Mhz 2,335 LUT 1,045 FF Cyclone IV -> 80 Mhz 2,335 LUT 1,048 FF
VexRiscv full with MMU (RV32IM, 1.24 DMIPS/Mhz 2.35 Coremark/Mhz, with cache trashing, 4KB-I$, 4KB-D$, single cycle barrel shifter, debug module, catch exceptions, dynamic branch, MMU) -> VexRiscv full with MMU (RV32IM, 1.24 DMIPS/Mhz 2.35 Coremark/Mhz, with cache trashing, 4KB-I$, 4KB-D$, single cycle barrel shifter, debug module, catch exceptions, dynamic branch, MMU) ->
Artix 7 -> 218 Mhz 1966 LUT 1551 FF Artix 7 -> 239 Mhz 2029 LUT 1585 FF
Cyclone V -> 123 Mhz 1,298 ALMs Cyclone V -> 124 Mhz 1,319 ALMs
Cyclone IV -> 109 Mhz 2,703 LUT 1,498 FF Cyclone IV -> 122 Mhz 2,710 LUT 1,501 FF
VexRiscv linux balanced (RV32IMA, 1.21 DMIPS/Mhz 2.27 Coremark/Mhz, with cache trashing, 4KB-I$, 4KB-D$, single cycle barrel shifter, catch exceptions, static branch, MMU, Supervisor, Compatible with mainstream linux) -> VexRiscv linux balanced (RV32IMA, 1.21 DMIPS/Mhz 2.27 Coremark/Mhz, with cache trashing, 4KB-I$, 4KB-D$, single cycle barrel shifter, catch exceptions, static branch, MMU, Supervisor, Compatible with mainstream linux) ->
Artix 7 -> 239 Mhz 2483 LUT 2134 FF Artix 7 -> 249 Mhz 2549 LUT 2014 FF
Cyclone V -> 130 Mhz 1,636 ALMs Cyclone V -> 125 Mhz 1,618 ALMs
Cyclone IV -> 116 Mhz 3,324 LUT 2,010 FF Cyclone IV -> 116 Mhz 3,314 LUT 2,016 FF
``` ```
@ -296,9 +296,9 @@ You can find some FPGA projects which instantiate the Briey SoC here (DE1-SoC, D
Here are some measurements of Briey SoC timings and area : Here are some measurements of Briey SoC timings and area :
``` ```
Artix 7 -> 232 Mhz 3042 LUT 3281 FF Artix 7 -> 275 Mhz 3072 LUT 3291 FF
Cyclone V -> 138 Mhz 2,179 ALMs Cyclone V -> 139 Mhz 2,175 ALMs
Cyclone IV -> 120 Mhz 4,333 LUT 3,167 FF Cyclone IV -> 129 Mhz 4,337 LUT 3,170 FF
``` ```
## Murax SoC ## Murax SoC
@ -351,16 +351,16 @@ Here are some timing and area measurements of the Murax SoC:
``` ```
Murax interlocked stages (0.45 DMIPS/Mhz, 8 bits GPIO) -> Murax interlocked stages (0.45 DMIPS/Mhz, 8 bits GPIO) ->
Artix 7 - > 301 Mhz 1032 LUT 1199 FF Artix 7 -> 313 Mhz 1039 LUT 1200 FF
Cyclone V -> 183 Mhz 736 ALMs Cyclone V -> 173 Mhz 737 ALMs
Cyclone IV -> 148 Mhz 1,481 LUT 1,204 FF Cyclone IV -> 144 Mhz 1,484 LUT 1,206 FF
iCE40 -> 69 Mhz 2403 LC (nextpnr) iCE40 -> 64 Mhz 2422 LC (nextpnr)
MuraxFast bypassed stages (0.65 DMIPS/Mhz, 8 bits GPIO) -> MuraxFast bypassed stages (0.65 DMIPS/Mhz, 8 bits GPIO) ->
Artix 7 -> 321 Mhz 1198 LUT 1298 FF Artix 7 -> 323 Mhz 1241 LUT 1301 FF
Cyclone V -> 165 Mhz 873 ALMs Cyclone V -> 159 Mhz 864 ALMs
Cyclone IV -> 145 Mhz 1,691 LUT 1,239 FF Cyclone IV -> 137 Mhz 1,688 LUT 1,241 FF
iCE40 -> 61 Mhz 2778 LC (nextpnr) iCE40 -> 66 Mhz 2799 LC (nextpnr)
``` ```
Some scripts to generate the SoC and call the icestorm toolchain can be found here: `scripts/Murax/` Some scripts to generate the SoC and call the icestorm toolchain can be found here: `scripts/Murax/`

View File

@ -17,6 +17,8 @@ trait Pipeline {
val things = mutable.HashMap[PipelineThing[_], Any]() val things = mutable.HashMap[PipelineThing[_], Any]()
// val services = ArrayBuffer[Any]() // val services = ArrayBuffer[Any]()
def stageBefore(stage : Stage) = stages(indexOf(stage)-1)
def indexOf(stage : Stage) = stages.indexOf(stage) def indexOf(stage : Stage) = stages.indexOf(stage)
def service[T](clazz : Class[T]) = { def service[T](clazz : Class[T]) = {
@ -127,7 +129,7 @@ trait Pipeline {
//Arbitration //Arbitration
for(stageIndex <- 0 until stages.length; stage = stages(stageIndex)) { for(stageIndex <- 0 until stages.length; stage = stages(stageIndex)) {
stage.arbitration.isFlushed := stages.drop(stageIndex).map(_.arbitration.flushAll).orR stage.arbitration.isFlushed := stages.drop(stageIndex+1).map(_.arbitration.flushNext).orR || stages.drop(stageIndex).map(_.arbitration.flushIt).orR
if(!unremovableStages.contains(stage)) if(!unremovableStages.contains(stage))
stage.arbitration.removeIt setWhen stage.arbitration.isFlushed stage.arbitration.removeIt setWhen stage.arbitration.isFlushed
else else

View File

@ -49,7 +49,8 @@ class Stage() extends Area{
val haltItself = False //user settable, stuck the instruction, should only be set by the instruction itself val haltItself = False //user settable, stuck the instruction, should only be set by the instruction itself
val haltByOther = False //When settable, stuck the instruction, should only be set by something else than the stucked instruction val haltByOther = False //When settable, stuck the instruction, should only be set by something else than the stucked instruction
val removeIt = False //When settable, unschedule the instruction as if it was never executed (no side effect) val removeIt = False //When settable, unschedule the instruction as if it was never executed (no side effect)
val flushAll = False //When settable, unschedule instructions in the current stage and all prior ones val flushIt = False //When settable, unschedule the current instruction
val flushNext = False //When settable, unschedule instruction above in the pipeline
val isValid = Bool //Inform if a instruction is in the current stage val isValid = Bool //Inform if a instruction is in the current stage
val isStuck = Bool //Inform if the instruction is stuck (haltItself || haltByOther) val isStuck = Bool //Inform if the instruction is stuck (haltItself || haltByOther)
val isStuckByOthers = Bool //Inform if the instruction is stuck by sombody else val isStuckByOthers = Bool //Inform if the instruction is stuck by sombody else

View File

@ -109,7 +109,7 @@ class VexRiscv(val config : VexRiscvConfig) extends Component with Pipeline{
if(withMemoryStage){ if(withMemoryStage){
memory.arbitration.removeIt.noBackendCombMerge memory.arbitration.removeIt.noBackendCombMerge
} }
execute.arbitration.flushAll.noBackendCombMerge execute.arbitration.flushNext.noBackendCombMerge
this(RVC_GEN) = false this(RVC_GEN) = false
} }

View File

@ -84,6 +84,8 @@ class BranchPlugin(earlyBranch : Boolean,
decodePrediction decodePrediction
} }
def hasHazardOnBranch = if(earlyBranch) pipeline.service(classOf[HazardService]).hazardOnExecuteRS else False
override def setup(pipeline: VexRiscv): Unit = { override def setup(pipeline: VexRiscv): Unit = {
import Riscv._ import Riscv._
import pipeline.config._ import pipeline.config._
@ -200,12 +202,9 @@ class BranchPlugin(earlyBranch : Boolean,
//Apply branchs (JAL,JALR, Bxx) //Apply branchs (JAL,JALR, Bxx)
branchStage plug new Area { branchStage plug new Area {
import branchStage._ import branchStage._
jumpInterface.valid := arbitration.isValid && !arbitration.isStuckByOthers && input(BRANCH_DO) jumpInterface.valid := arbitration.isValid && input(BRANCH_DO) && !hasHazardOnBranch
jumpInterface.payload := input(BRANCH_CALC) jumpInterface.payload := input(BRANCH_CALC)
arbitration.flushNext setWhen(jumpInterface.valid)
when(jumpInterface.valid) {
stages(indexOf(branchStage) - 1).arbitration.flushAll := True
}
if(catchAddressMisalignedForReal) { if(catchAddressMisalignedForReal) {
branchExceptionPort.valid := arbitration.isValid && input(BRANCH_DO) && jumpInterface.payload(1) branchExceptionPort.valid := arbitration.isValid && input(BRANCH_DO) && jumpInterface.payload(1)
@ -282,12 +281,9 @@ class BranchPlugin(earlyBranch : Boolean,
val branchStage = if(earlyBranch) execute else memory val branchStage = if(earlyBranch) execute else memory
branchStage plug new Area { branchStage plug new Area {
import branchStage._ import branchStage._
jumpInterface.valid := arbitration.isValid && !arbitration.isStuckByOthers && input(BRANCH_DO) jumpInterface.valid := arbitration.isValid && input(BRANCH_DO) && !hasHazardOnBranch
jumpInterface.payload := input(BRANCH_CALC) jumpInterface.payload := input(BRANCH_CALC)
arbitration.flushNext setWhen(jumpInterface.valid)
when(jumpInterface.valid) {
stages(indexOf(branchStage) - 1).arbitration.flushAll := True
}
if(catchAddressMisalignedForReal) { if(catchAddressMisalignedForReal) {
val unalignedJump = input(BRANCH_DO) && input(BRANCH_CALC)(1) val unalignedJump = input(BRANCH_DO) && input(BRANCH_CALC)(1)
@ -361,14 +357,11 @@ class BranchPlugin(earlyBranch : Boolean,
input(PC) input(PC)
} }
jumpInterface.valid := arbitration.isValid && !arbitration.isStuckByOthers && predictionMissmatch //Probably just isValid instead of isFiring is better jumpInterface.valid := arbitration.isValid && predictionMissmatch && !hasHazardOnBranch
jumpInterface.payload := (input(BRANCH_DO) ? input(BRANCH_CALC) | input(NEXT_PC)) jumpInterface.payload := (input(BRANCH_DO) ? input(BRANCH_CALC) | input(NEXT_PC))
arbitration.flushNext setWhen(jumpInterface.valid)
when(jumpInterface.valid) {
stages(indexOf(branchStage) - 1).arbitration.flushAll := True
}
if(catchAddressMisalignedForReal) { if(catchAddressMisalignedForReal) {
branchExceptionPort.valid := arbitration.isValid && input(BRANCH_DO) && input(BRANCH_CALC)(1) branchExceptionPort.valid := arbitration.isValid && input(BRANCH_DO) && input(BRANCH_CALC)(1)
branchExceptionPort.code := 0 branchExceptionPort.code := 0

View File

@ -68,11 +68,13 @@ case class CsrPluginConfig(
medelegAccess : CsrAccess = CsrAccess.NONE, medelegAccess : CsrAccess = CsrAccess.NONE,
midelegAccess : CsrAccess = CsrAccess.NONE, midelegAccess : CsrAccess = CsrAccess.NONE,
pipelineCsrRead : Boolean = false, pipelineCsrRead : Boolean = false,
pipelinedInterrupt : Boolean = true,
deterministicInteruptionEntry : Boolean = false //Only used for simulatation purposes deterministicInteruptionEntry : Boolean = false //Only used for simulatation purposes
){ ){
assert(!ucycleAccess.canWrite) assert(!ucycleAccess.canWrite)
def privilegeGen = userGen || supervisorGen def privilegeGen = userGen || supervisorGen
def noException = this.copy(ecallGen = false, ebreakGen = false, catchIllegalAccess = false) def noException = this.copy(ecallGen = false, ebreakGen = false, catchIllegalAccess = false)
def noExceptionButEcall = this.copy(ecallGen = true, ebreakGen = false, catchIllegalAccess = false)
} }
object CsrPluginConfig{ object CsrPluginConfig{
@ -693,7 +695,7 @@ class CsrPlugin(val config: CsrPluginConfig) extends Plugin[VexRiscv] with Excep
exceptionValids := exceptionValidsRegs exceptionValids := exceptionValidsRegs
for(portInfo <- sortedByStage; port = portInfo.port ; stage = portInfo.stage; stageId = indexOf(portInfo.stage)) { for(portInfo <- sortedByStage; port = portInfo.port ; stage = portInfo.stage; stageId = indexOf(portInfo.stage)) {
when(port.valid) { when(port.valid) {
if(indexOf(stage) != 0) stages(indexOf(stage) - 1).arbitration.flushAll := True stage.arbitration.flushNext := True
stage.arbitration.removeIt := True stage.arbitration.removeIt := True
exceptionValids(stageId) := True exceptionValids(stageId) := True
exceptionContext := port.payload exceptionContext := port.payload
@ -715,7 +717,7 @@ class CsrPlugin(val config: CsrPluginConfig) extends Plugin[VexRiscv] with Excep
} }
} }
when(exceptionValidsRegs.orR){ when(exceptionValids.orR){
fetcher.haltIt() fetcher.haltIt()
} }
@ -729,32 +731,37 @@ class CsrPlugin(val config: CsrPluginConfig) extends Plugin[VexRiscv] with Excep
//Process interrupt request, code and privilege //Process interrupt request, code and privilege
val interrupt = False val interrupt = new Area {
val interruptCode = UInt(4 bits).assignDontCare().addTag(Verilator.public) val valid = if(pipelinedInterrupt) RegNext(False) init(False) else False
var interruptPrivilegs = if (supervisorGen) List(1, 3) else List(3) val code = if(pipelinedInterrupt) Reg(UInt(4 bits)) else UInt(4 bits).assignDontCare()
val interruptTargetPrivilege = UInt(2 bits).assignDontCare() var privilegs = if (supervisorGen) List(1, 3) else List(3)
val privilegeAllowInterrupts = mutable.HashMap[Int, Bool]() val targetPrivilege = if(pipelinedInterrupt) Reg(UInt(2 bits)) else UInt(2 bits).assignDontCare()
if(supervisorGen) privilegeAllowInterrupts += 1 -> ((sstatus.SIE && privilege === "01") || privilege < "01") val privilegeAllowInterrupts = mutable.HashMap[Int, Bool]()
privilegeAllowInterrupts += 3 -> (mstatus.MIE || privilege < "11") if (supervisorGen) privilegeAllowInterrupts += 1 -> ((sstatus.SIE && privilege === "01") || privilege < "01")
while(interruptPrivilegs.nonEmpty){ privilegeAllowInterrupts += 3 -> (mstatus.MIE || privilege < "11")
val p = interruptPrivilegs.head while (privilegs.nonEmpty) {
when(privilegeAllowInterrupts(p)){ val p = privilegs.head
for(i <- interruptSpecs when(privilegeAllowInterrupts(p)) {
if i.privilege <= p //EX : Machine timer interrupt can't go into supervisor mode for (i <- interruptSpecs
if interruptPrivilegs.tail.forall(e => i.delegators.exists(_.privilege == e))){ // EX : Supervisor timer need to have machine mode delegator if i.privilege <= p //EX : Machine timer interrupt can't go into supervisor mode
val delegUpOn = i.delegators.filter(_.privilege > p).map(_.enable).fold(True)(_ && _) if privilegs.tail.forall(e => i.delegators.exists(_.privilege == e))) { // EX : Supervisor timer need to have machine mode delegator
val delegDownOff = !i.delegators.filter(_.privilege <= p).map(_.enable).orR val delegUpOn = i.delegators.filter(_.privilege > p).map(_.enable).fold(True)(_ && _)
when(i.cond && delegUpOn && delegDownOff){ val delegDownOff = !i.delegators.filter(_.privilege <= p).map(_.enable).orR
interrupt := True when(i.cond && delegUpOn && delegDownOff) {
interruptCode := i.id valid := True
interruptTargetPrivilege := p code := i.id
targetPrivilege := p
}
} }
} }
privilegs = privilegs.tail
} }
interruptPrivilegs = interruptPrivilegs.tail
code.addTag(Verilator.public)
} }
interrupt.clearWhen(!allowInterrupts)
val exception = if(exceptionPortCtrl != null) exceptionPortCtrl.exceptionValids.last && allowException else False val exception = if(exceptionPortCtrl != null) exceptionPortCtrl.exceptionValids.last && allowException else False
val lastStageWasWfi = if(wfiGenAsWait) RegNext(lastStage.arbitration.isFiring && lastStage.input(ENV_CTRL) === EnvCtrlEnum.WFI) init(False) else False val lastStageWasWfi = if(wfiGenAsWait) RegNext(lastStage.arbitration.isFiring && lastStage.input(ENV_CTRL) === EnvCtrlEnum.WFI) init(False) else False
@ -763,7 +770,7 @@ class CsrPlugin(val config: CsrPluginConfig) extends Plugin[VexRiscv] with Excep
//Used to make the pipeline empty softly (for interrupts) //Used to make the pipeline empty softly (for interrupts)
val pipelineLiberator = new Area{ val pipelineLiberator = new Area{
when(interrupt){ when(interrupt.valid && allowInterrupts){
decode.arbitration.haltByOther := decode.arbitration.isValid decode.arbitration.haltByOther := decode.arbitration.isValid
} }
@ -773,18 +780,18 @@ class CsrPlugin(val config: CsrPluginConfig) extends Plugin[VexRiscv] with Excep
//Interrupt/Exception entry logic //Interrupt/Exception entry logic
val interruptJump = Bool.addTag(Verilator.public) val interruptJump = Bool.addTag(Verilator.public)
interruptJump := interrupt && pipelineLiberator.done interruptJump := interrupt.valid && pipelineLiberator.done && allowInterrupts
val hadException = RegNext(exception) init(False) val hadException = RegNext(exception) init(False)
pipelineLiberator.done.clearWhen(hadException) pipelineLiberator.done.clearWhen(hadException)
val targetPrivilege = CombInit(interruptTargetPrivilege) val targetPrivilege = CombInit(interrupt.targetPrivilege)
if(exceptionPortCtrl != null) when(hadException) { if(exceptionPortCtrl != null) when(hadException) {
targetPrivilege := exceptionPortCtrl.exceptionTargetPrivilege targetPrivilege := exceptionPortCtrl.exceptionTargetPrivilege
} }
val trapCause = CombInit(interruptCode) val trapCause = CombInit(interrupt.code)
if(exceptionPortCtrl != null) when( hadException){ if(exceptionPortCtrl != null) when( hadException){
trapCause := exceptionPortCtrl.exceptionContext.code trapCause := exceptionPortCtrl.exceptionContext.code
} }
@ -800,7 +807,7 @@ class CsrPlugin(val config: CsrPluginConfig) extends Plugin[VexRiscv] with Excep
jumpInterface.valid := True jumpInterface.valid := True
jumpInterface.payload := (if(!xtvecModeGen) xtvec.base @@ "00" else (xtvec.mode === 0 || hadException) ? (xtvec.base @@ "00") | ((xtvec.base + trapCause) @@ "00") ) jumpInterface.payload := (if(!xtvecModeGen) xtvec.base @@ "00" else (xtvec.mode === 0 || hadException) ? (xtvec.base @@ "00") | ((xtvec.base + trapCause) @@ "00") )
beforeLastStage.arbitration.flushAll := True lastStage.arbitration.flushNext := True
if(privilegeGen) privilegeReg := targetPrivilege if(privilegeGen) privilegeReg := targetPrivilege
@ -839,7 +846,7 @@ class CsrPlugin(val config: CsrPluginConfig) extends Plugin[VexRiscv] with Excep
when(arbitration.isValid && input(ENV_CTRL) === EnvCtrlEnum.XRET) { when(arbitration.isValid && input(ENV_CTRL) === EnvCtrlEnum.XRET) {
fetcher.haltIt() fetcher.haltIt()
jumpInterface.valid := True jumpInterface.valid := True
beforeLastStage.arbitration.flushAll := True lastStage.arbitration.flushNext := True
switch(input(INSTRUCTION)(29 downto 28)){ switch(input(INSTRUCTION)(29 downto 28)){
is(3){ is(3){
mstatus.MPP := U"00" mstatus.MPP := U"00"

View File

@ -247,7 +247,8 @@ class DBusCachedPlugin(val config : DataCacheConfig,
redoBranch.valid := False redoBranch.valid := False
redoBranch.payload := input(PC) redoBranch.payload := input(PC)
arbitration.flushAll setWhen(redoBranch.valid) arbitration.flushIt setWhen(redoBranch.valid)
arbitration.flushNext setWhen(redoBranch.valid)
if(catchSomething) { if(catchSomething) {
exceptionBus.valid := False //cache.io.cpu.writeBack.mmuMiss || cache.io.cpu.writeBack.accessError || cache.io.cpu.writeBack.illegalAccess || cache.io.cpu.writeBack.unalignedAccess exceptionBus.valid := False //cache.io.cpu.writeBack.mmuMiss || cache.io.cpu.writeBack.accessError || cache.io.cpu.writeBack.illegalAccess || cache.io.cpu.writeBack.unalignedAccess

View File

@ -516,7 +516,8 @@ class DBusSimplePlugin(catchAddressMisaligned : Boolean = false,
memoryExceptionPort.code := (input(MEMORY_STORE) ? U(15) | U(13)).resized memoryExceptionPort.code := (input(MEMORY_STORE) ? U(15) | U(13)).resized
} }
arbitration.flushAll setWhen(redoBranch.valid) arbitration.flushIt setWhen(redoBranch.valid)
arbitration.flushNext setWhen(redoBranch.valid)
} }
when(!(arbitration.isValid && input(MEMORY_ENABLE) && (Bool(cmdStage != rspStage) || !arbitration.isStuckByOthers))){ when(!(arbitration.isValid && input(MEMORY_ENABLE) && (Bool(cmdStage != rspStage) || !arbitration.isStuckByOthers))){

View File

@ -203,7 +203,8 @@ class DebugPlugin(val debugClockDomain : ClockDomain, hardwareBreakpointCount :
when(stagesFromExecute.tail.map(_.arbitration.isValid).orR === False){ when(stagesFromExecute.tail.map(_.arbitration.isValid).orR === False){
iBusFetcher.flushIt() iBusFetcher.flushIt()
iBusFetcher.haltIt() iBusFetcher.haltIt()
execute.arbitration.flushAll := True execute.arbitration.flushIt := True
execute.arbitration.flushNext := True
haltIt := True haltIt := True
haltedByBreak := True haltedByBreak := True
} }

View File

@ -28,7 +28,7 @@ case class Masked(value : BigInt,care : BigInt){
def mergeOneBitDifSmaller(x: Masked) = { def mergeOneBitDifSmaller(x: Masked) = {
val bit = value - x.value val bit = value - x.value
val ret = new Masked(value &~ bit, care & ~bit) val ret = new Masked(value &~ bit, care & ~bit)
// ret.isPrime = isPrime || x.isPrime // ret.isPrime = isPrime || x.isPrime
isPrime = false isPrime = false
x.isPrime = false x.isPrime = false
ret ret
@ -44,7 +44,10 @@ case class Masked(value : BigInt,care : BigInt){
def toString(bitCount : Int) = (0 until bitCount).map(i => if(care.testBit(i)) (if(value.testBit(i)) "1" else "0") else "-").reverseIterator.reduce(_+_) def toString(bitCount : Int) = (0 until bitCount).map(i => if(care.testBit(i)) (if(value.testBit(i)) "1" else "0") else "-").reverseIterator.reduce(_+_)
} }
class DecoderSimplePlugin(catchIllegalInstruction : Boolean = false, forceLegalInstructionComputation : Boolean = false) extends Plugin[VexRiscv] with DecoderService { class DecoderSimplePlugin(catchIllegalInstruction : Boolean = false,
throwIllegalInstruction : Boolean = false,
assertIllegalInstruction : Boolean = false,
forceLegalInstructionComputation : Boolean = false) extends Plugin[VexRiscv] with DecoderService {
override def add(encoding: Seq[(MaskedLiteral, Seq[(Stageable[_ <: BaseType], Any)])]): Unit = encoding.foreach(e => this.add(e._1,e._2)) override def add(encoding: Seq[(MaskedLiteral, Seq[(Stageable[_ <: BaseType], Any)])]): Unit = encoding.foreach(e => this.add(e._1,e._2))
override def add(key: MaskedLiteral, values: Seq[(Stageable[_ <: BaseType], Any)]): Unit = { override def add(key: MaskedLiteral, values: Seq[(Stageable[_ <: BaseType], Any)]): Unit = {
val instructionModel = encodings.getOrElseUpdate(key,ArrayBuffer[(Stageable[_ <: BaseType], BaseType)]()) val instructionModel = encodings.getOrElseUpdate(key,ArrayBuffer[(Stageable[_ <: BaseType], BaseType)]())
@ -78,6 +81,10 @@ class DecoderSimplePlugin(catchIllegalInstruction : Boolean = false, forceLegalI
} }
} }
val detectLegalInstructions = catchIllegalInstruction || throwIllegalInstruction || forceLegalInstructionComputation || assertIllegalInstruction
object ASSERT_ERROR extends Stageable(Bool)
override def build(pipeline: VexRiscv): Unit = { override def build(pipeline: VexRiscv): Unit = {
import pipeline.config._ import pipeline.config._
import pipeline.decode._ import pipeline.decode._
@ -86,7 +93,7 @@ class DecoderSimplePlugin(catchIllegalInstruction : Boolean = false, forceLegalI
val stupidDecoder = false val stupidDecoder = false
if(stupidDecoder){ if(stupidDecoder){
if (catchIllegalInstruction || forceLegalInstructionComputation) insert(LEGAL_INSTRUCTION) := False if (detectLegalInstructions) insert(LEGAL_INSTRUCTION) := False
for(stageable <- stageables){ for(stageable <- stageables){
if(defaults.contains(stageable)){ if(defaults.contains(stageable)){
insert(stageable).assignFrom(defaults(stageable)) insert(stageable).assignFrom(defaults(stageable))
@ -96,7 +103,7 @@ class DecoderSimplePlugin(catchIllegalInstruction : Boolean = false, forceLegalI
} }
for((key, tasks) <- encodings){ for((key, tasks) <- encodings){
when(input(INSTRUCTION) === key){ when(input(INSTRUCTION) === key){
if (catchIllegalInstruction || forceLegalInstructionComputation) insert(LEGAL_INSTRUCTION) := True if (detectLegalInstructions) insert(LEGAL_INSTRUCTION) := True
for((stageable, value) <- tasks){ for((stageable, value) <- tasks){
insert(stageable).assignFrom(value) insert(stageable).assignFrom(value)
} }
@ -145,8 +152,15 @@ class DecoderSimplePlugin(catchIllegalInstruction : Boolean = false, forceLegalI
// logic implementation // logic implementation
val decodedBits = Bits(stageables.foldLeft(0)(_ + _.dataType.getBitsWidth) bits) val decodedBits = Bits(stageables.foldLeft(0)(_ + _.dataType.getBitsWidth) bits)
decodedBits := Symplify(input(INSTRUCTION), spec, decodedBits.getWidth) decodedBits := Symplify(input(INSTRUCTION), spec, decodedBits.getWidth)
if (catchIllegalInstruction || forceLegalInstructionComputation) insert(LEGAL_INSTRUCTION) := Symplify.logicOf(input(INSTRUCTION), SymplifyBit.getPrimeImplicantsByTrueAndDontCare(spec.unzip._1.toSeq, Nil, 32)) if (detectLegalInstructions) insert(LEGAL_INSTRUCTION) := Symplify.logicOf(input(INSTRUCTION), SymplifyBit.getPrimeImplicantsByTrueAndDontCare(spec.unzip._1.toSeq, Nil, 32))
if (throwIllegalInstruction) {
input(LEGAL_INSTRUCTION) //Fill the request for later (prePopTask)
Component.current.addPrePopTask(() => arbitration.isValid clearWhen(!input(LEGAL_INSTRUCTION)))
}
if(assertIllegalInstruction){
val reg = RegInit(False) setWhen(arbitration.isValid) clearWhen(arbitration.isRemoved || !arbitration.isStuck)
insert(ASSERT_ERROR) := arbitration.isValid || reg
}
//Unpack decodedBits and insert fields in the pipeline //Unpack decodedBits and insert fields in the pipeline
offset = 0 offset = 0
@ -162,6 +176,10 @@ class DecoderSimplePlugin(catchIllegalInstruction : Boolean = false, forceLegalI
decodeExceptionPort.code := 2 decodeExceptionPort.code := 2
decodeExceptionPort.badAddr := input(INSTRUCTION).asUInt decodeExceptionPort.badAddr := input(INSTRUCTION).asUInt
} }
if(assertIllegalInstruction){
pipeline.stages.tail.foreach(s => s.output(ASSERT_ERROR) clearWhen(s.arbitration.isRemoved))
assert(!pipeline.stages.last.output(ASSERT_ERROR))
}
} }
def bench(toplevel : VexRiscv): Unit ={ def bench(toplevel : VexRiscv): Unit ={
@ -176,7 +194,7 @@ class DecoderSimplePlugin(catchIllegalInstruction : Boolean = false, forceLegalI
val stageables = encodings.flatMap(_._2.map(_._1)).toSet val stageables = encodings.flatMap(_._2.map(_._1)).toSet
stageables.foreach(e => out(RegNext(RegNext(toplevel.decode.insert(e)).setName(e.getName())))) stageables.foreach(e => out(RegNext(RegNext(toplevel.decode.insert(e)).setName(e.getName()))))
if(catchIllegalInstruction) out(RegNext(RegNext(toplevel.decode.insert(LEGAL_INSTRUCTION)).setName(LEGAL_INSTRUCTION.getName()))) if(catchIllegalInstruction) out(RegNext(RegNext(toplevel.decode.insert(LEGAL_INSTRUCTION)).setName(LEGAL_INSTRUCTION.getName())))
// toplevel.getAdditionalNodesRoot.clear() // toplevel.getAdditionalNodesRoot.clear()
} }
} }
} }
@ -345,14 +363,14 @@ object SymplifyBit{
def main(args: Array[String]) { def main(args: Array[String]) {
{ {
// val default = Masked(0, 0xF) // val default = Masked(0, 0xF)
// val primeImplicants = List(4, 8, 10, 11, 12, 15).map(v => Masked(v, 0xF)) // val primeImplicants = List(4, 8, 10, 11, 12, 15).map(v => Masked(v, 0xF))
// val dcImplicants = List(9, 14).map(v => Masked(v, 0xF).setPrime(false)) // val dcImplicants = List(9, 14).map(v => Masked(v, 0xF).setPrime(false))
// val reducedPrimeImplicants = getPrimeImplicantsByTrueAndDontCare(primeImplicants, dcImplicants, 4) // val reducedPrimeImplicants = getPrimeImplicantsByTrueAndDontCare(primeImplicants, dcImplicants, 4)
// println("UUT") // println("UUT")
// println(reducedPrimeImplicants.map(_.toString(4)).mkString("\n")) // println(reducedPrimeImplicants.map(_.toString(4)).mkString("\n"))
// println("REF") // println("REF")
// println("-100\n10--\n1--0\n1-1-") // println("-100\n10--\n1--0\n1-1-")
} }
{ {

View File

@ -103,64 +103,47 @@ abstract class IBusFetcherImpl(val resetVector : BigInt,
pcLoad.payload := MuxOH(OHMasking.first(valids.asBits), pcs) pcLoad.payload := MuxOH(OHMasking.first(valids.asBits), pcs)
} }
def flush = jump.pcLoad.valid || fetcherflushIt fetcherflushIt setWhen(stages.map(_.arbitration.flushNext).orR)
class PcFetch extends Area{ //The fetchPC pcReg can also be use for the second stage of the fetch
val preOutput = Stream(UInt(32 bits)) //When the fetcherHalt is set and the pipeline isn't stalled,, the pc is propagated to to the pcReg, which allow
val output = preOutput.haltWhen(fetcherHalt) //using the pc pipeline to get the next PC value for interrupts
val predictionPcLoad = ifGen(prediction == DYNAMIC_TARGET) (Flow(UInt(32 bits))) val fetchPc = new Area{
}
val fetchPc = new PcFetch{
//PC calculation without Jump //PC calculation without Jump
val output = Stream(UInt(32 bits))
val pcReg = Reg(UInt(32 bits)) init(if(resetVector != null) resetVector else externalResetVector) addAttribute(Verilator.public) val pcReg = Reg(UInt(32 bits)) init(if(resetVector != null) resetVector else externalResetVector) addAttribute(Verilator.public)
val inc = RegInit(False) val corrected = False
val propagatePc = False val pcRegPropagate = False
val booted = RegNext(True) init (False)
val inc = RegInit(False) clearWhen(corrected || pcRegPropagate) setWhen(output.fire) clearWhen(!output.valid && output.ready)
val pc = pcReg + (inc ## B"00").asUInt val pc = pcReg + (inc ## B"00").asUInt
val samplePcNext = False val predictionPcLoad = ifGen(prediction == DYNAMIC_TARGET) (Flow(UInt(32 bits)))
if(compressedGen) { if(compressedGen) when(inc) {
when(inc) { pc(1) := False
pc(1) := False
}
}
when(propagatePc){
samplePcNext := True
inc := False
} }
if(predictionPcLoad != null) { if(predictionPcLoad != null) {
when(predictionPcLoad.valid) { when(predictionPcLoad.valid) {
inc := False corrected := True
samplePcNext := True
pc := predictionPcLoad.payload pc := predictionPcLoad.payload
} }
} }
when(jump.pcLoad.valid) { when(jump.pcLoad.valid) {
inc := False corrected := True
samplePcNext := True
pc := jump.pcLoad.payload pc := jump.pcLoad.payload
} }
when(preOutput.fire){ when(booted && (output.ready || fetcherflushIt || pcRegPropagate)){
inc := True
samplePcNext := True
}
when(samplePcNext) {
pcReg := pc pcReg := pc
} }
pc(0) := False pc(0) := False
if(!pipeline(RVC_GEN)) pc(1) := False if(!pipeline(RVC_GEN)) pc(1) := False
preOutput.valid := RegNext(True) init (False) output.valid := !fetcherHalt && booted
preOutput.payload := pc output.payload := pc
} }
val decodePc = ifGen(decodePcGen)(new Area { val decodePc = ifGen(decodePcGen)(new Area {
@ -185,7 +168,7 @@ abstract class IBusFetcherImpl(val resetVector : BigInt,
} }
//application of the selected jump request //application of the selected jump request
when(jump.pcLoad.valid) { when(jump.pcLoad.valid && (!decode.arbitration.isStuck || decode.arbitration.isRemoved)) {
pcReg := jump.pcLoad.payload pcReg := jump.pcLoad.payload
} }
}) })
@ -226,11 +209,11 @@ abstract class IBusFetcherImpl(val resetVector : BigInt,
for((s,sNext) <- (stages, stages.tail).zipped) { for((s,sNext) <- (stages, stages.tail).zipped) {
if(s == stages.head && pcRegReusedForSecondStage) { if(s == stages.head && pcRegReusedForSecondStage) {
sNext.input.arbitrationFrom(s.output.toEvent().m2sPipeWithFlush(flush, s != stages.head, collapsBubble = false)) sNext.input.arbitrationFrom(s.output.toEvent().m2sPipeWithFlush(fetcherflushIt, s != stages.head, collapsBubble = false))
sNext.input.payload := fetchPc.pcReg sNext.input.payload := fetchPc.pcReg
fetchPc.propagatePc setWhen(sNext.input.fire) fetchPc.pcRegPropagate setWhen(sNext.input.ready)
} else { } else {
sNext.input << s.output.m2sPipeWithFlush(flush, s != stages.head, collapsBubble = false) sNext.input << s.output.m2sPipeWithFlush(fetcherflushIt, s != stages.head, collapsBubble = false)
} }
} }
@ -273,7 +256,7 @@ abstract class IBusFetcherImpl(val resetVector : BigInt,
// input.ready := (bufferValid ? (!isRvc && output.ready) | (input.pc(1) || output.ready)) // input.ready := (bufferValid ? (!isRvc && output.ready) | (input.pc(1) || output.ready))
input.ready := !output.valid || !(!output.ready || (isRvc && !input.pc(1) && input.rsp.inst(16, 2 bits) =/= 3) || (!isRvc && bufferValid && input.rsp.inst(16, 2 bits) =/= 3)) input.ready := !output.valid || !(!output.ready || (isRvc && !input.pc(1) && input.rsp.inst(16, 2 bits) =/= 3) || (!isRvc && bufferValid && input.rsp.inst(16, 2 bits) =/= 3))
addPrePopTask(() => { addPrePopTask(() => {
when(!input.ready && output.fire && !flush /* && ((isRvc && !bufferValid && !input.pc(1)) || (!isRvc && bufferValid && input.rsp.inst(16, 2 bits) =/= 3))*/) { when(!input.ready && output.fire && !fetcherflushIt /* && ((isRvc && !bufferValid && !input.pc(1)) || (!isRvc && bufferValid && input.rsp.inst(16, 2 bits) =/= 3))*/) {
input.pc.getDrivingReg(1) := True input.pc.getDrivingReg(1) := True
} }
}) })
@ -284,7 +267,7 @@ abstract class IBusFetcherImpl(val resetVector : BigInt,
bufferValid := !(!isRvc && !input.pc(1) && !bufferValid) && !(isRvc && input.pc(1) && output.ready) bufferValid := !(!isRvc && !input.pc(1) && !bufferValid) && !(isRvc && input.pc(1) && output.ready)
bufferData := input.rsp.inst(31 downto 16) bufferData := input.rsp.inst(31 downto 16)
} }
bufferValid.clearWhen(flush) bufferValid.clearWhen(fetcherflushIt)
iBusRsp.readyForError.clearWhen(bufferValid && isRvc) //Can't emit error, as there is a earlier instruction pending iBusRsp.readyForError.clearWhen(bufferValid && isRvc) //Can't emit error, as there is a earlier instruction pending
incomingInstruction setWhen(bufferValid && bufferData(1 downto 0) =/= 3) incomingInstruction setWhen(bufferValid && bufferData(1 downto 0) =/= 3)
}) })
@ -292,13 +275,13 @@ abstract class IBusFetcherImpl(val resetVector : BigInt,
def condApply[T](that : T, cond : Boolean)(func : (T) => T) = if(cond)func(that) else that def condApply[T](that : T, cond : Boolean)(func : (T) => T) = if(cond)func(that) else that
val injector = new Area { val injector = new Area {
val inputBeforeStage = condApply(if (decodePcGen) decompressor.output else iBusRsp.output, injectorReadyCutGen)(_.s2mPipe(flush)) val inputBeforeStage = condApply(if (decodePcGen) decompressor.output else iBusRsp.output, injectorReadyCutGen)(_.s2mPipe(fetcherflushIt))
if (injectorReadyCutGen) { if (injectorReadyCutGen) {
iBusRsp.readyForError.clearWhen(inputBeforeStage.valid) //Can't emit error if there is a instruction pending in the s2mPipe iBusRsp.readyForError.clearWhen(inputBeforeStage.valid) //Can't emit error if there is a instruction pending in the s2mPipe
incomingInstruction setWhen (inputBeforeStage.valid) incomingInstruction setWhen (inputBeforeStage.valid)
} }
val decodeInput = (if (injectorStage) { val decodeInput = (if (injectorStage) {
val decodeInput = inputBeforeStage.m2sPipeWithFlush(flush, collapsBubble = false) val decodeInput = inputBeforeStage.m2sPipeWithFlush(fetcherflushIt, collapsBubble = false)
decode.insert(INSTRUCTION_ANTICIPATED) := Mux(decode.arbitration.isStuck, decode.input(INSTRUCTION), inputBeforeStage.rsp.inst) decode.insert(INSTRUCTION_ANTICIPATED) := Mux(decode.arbitration.isStuck, decode.input(INSTRUCTION), inputBeforeStage.rsp.inst)
iBusRsp.readyForError.clearWhen(decodeInput.valid) //Can't emit error when there is a instruction pending in the injector stage buffer iBusRsp.readyForError.clearWhen(decodeInput.valid) //Can't emit error when there is a instruction pending in the injector stage buffer
incomingInstruction setWhen (decodeInput.valid) incomingInstruction setWhen (decodeInput.valid)
@ -313,13 +296,13 @@ abstract class IBusFetcherImpl(val resetVector : BigInt,
def pcUpdatedGen(input : Bool, stucks : Seq[Bool], relaxedInput : Boolean) : Seq[Bool] = { def pcUpdatedGen(input : Bool, stucks : Seq[Bool], relaxedInput : Boolean) : Seq[Bool] = {
stucks.scanLeft(input)((i, stuck) => { stucks.scanLeft(input)((i, stuck) => {
val reg = RegInit(False) val reg = RegInit(False)
if(!relaxedInput) when(flush) { if(!relaxedInput) when(fetcherflushIt) {
reg := False reg := False
} }
when(!stuck) { when(!stuck) {
reg := i reg := i
} }
if(relaxedInput || i != input) when(flush) { if(relaxedInput || i != input) when(fetcherflushIt) {
reg := False reg := False
} }
reg reg
@ -335,7 +318,7 @@ abstract class IBusFetcherImpl(val resetVector : BigInt,
pcValids := Vec(valids.takeRight(stages.size)) pcValids := Vec(valids.takeRight(stages.size))
} }
val decodeRemoved = RegInit(False) setWhen(decode.arbitration.isRemoved) clearWhen(flush) //!decode.arbitration.isStuck || decode.arbitration.isFlushed val decodeRemoved = RegInit(False) setWhen(decode.arbitration.isRemoved) clearWhen(fetcherflushIt) //!decode.arbitration.isStuck || decode.arbitration.isFlushed
decodeInput.ready := !decode.arbitration.isStuck decodeInput.ready := !decode.arbitration.isStuck
decode.arbitration.isValid := decodeInput.valid && !decodeRemoved decode.arbitration.isValid := decodeInput.valid && !decodeRemoved
@ -461,7 +444,7 @@ abstract class IBusFetcherImpl(val resetVector : BigInt,
} }
val fetchContext = DynamicContext() val fetchContext = DynamicContext()
fetchContext.hazard := hazard fetchContext.hazard := hazard
fetchContext.line := historyCache.readSync((fetchPc.output.payload >> 2).resized, iBusRsp.stages(0).output.ready || flush) fetchContext.line := historyCache.readSync((fetchPc.output.payload >> 2).resized, iBusRsp.stages(0).output.ready || fetcherflushIt)
object PREDICTION_CONTEXT extends Stageable(DynamicContext()) object PREDICTION_CONTEXT extends Stageable(DynamicContext())
decode.insert(PREDICTION_CONTEXT) := stage1ToInjectorPipe(fetchContext)._2 decode.insert(PREDICTION_CONTEXT) := stage1ToInjectorPipe(fetchContext)._2
@ -499,13 +482,14 @@ abstract class IBusFetcherImpl(val resetVector : BigInt,
decodePrediction.cmd.hadBranch clearWhen(missaligned) decodePrediction.cmd.hadBranch clearWhen(missaligned)
} }
predictionJumpInterface.valid := decodePrediction.cmd.hadBranch && decode.arbitration.isFiring //TODO OH Doublon de priorité //TODO no more fireing depedancies
predictionJumpInterface.valid := decode.arbitration.isValid && decodePrediction.cmd.hadBranch //TODO OH Doublon de priorité
predictionJumpInterface.payload := decode.input(PC) + ((decode.input(BRANCH_CTRL) === BranchCtrlEnum.JAL) ? imm.j_sext | imm.b_sext).asUInt predictionJumpInterface.payload := decode.input(PC) + ((decode.input(BRANCH_CTRL) === BranchCtrlEnum.JAL) ? imm.j_sext | imm.b_sext).asUInt
if(relaxPredictorAddress) KeepAttribute(predictionJumpInterface.payload) if(relaxPredictorAddress) KeepAttribute(predictionJumpInterface.payload)
// when(predictionJumpInterface.payload((if(pipeline(RVC_GEN)) 0 else 1) downto 0) =/= 0){ when(predictionJumpInterface.valid && decode.arbitration.isFiring){
// decodePrediction.cmd.hadBranch := False flushIt()
// } }
} }
case DYNAMIC_TARGET => new Area{ case DYNAMIC_TARGET => new Area{
// assert(!compressedGen || cmdToRspStageCount == 1, "Can't combine DYNAMIC_TARGET and RVC as it could stop the instruction fetch mid-air") // assert(!compressedGen || cmdToRspStageCount == 1, "Can't combine DYNAMIC_TARGET and RVC as it could stop the instruction fetch mid-air")
@ -520,7 +504,7 @@ abstract class IBusFetcherImpl(val resetVector : BigInt,
val history = Mem(BranchPredictorLine(), 1 << historyRamSizeLog2) val history = Mem(BranchPredictorLine(), 1 << historyRamSizeLog2)
val historyWrite = history.writePort val historyWrite = history.writePort
val line = history.readSync((iBusRsp.stages(0).input.payload >> 2).resized, iBusRsp.stages(0).output.ready || flush) val line = history.readSync((iBusRsp.stages(0).input.payload >> 2).resized, iBusRsp.stages(0).output.ready || fetcherflushIt)
val hit = line.source === (iBusRsp.stages(1).input.payload.asBits >> 2 + historyRamSizeLog2) && (if(compressedGen)(!(!line.unaligned && iBusRsp.stages(1).input.payload(1))) else True) val hit = line.source === (iBusRsp.stages(1).input.payload.asBits >> 2 + historyRamSizeLog2) && (if(compressedGen)(!(!line.unaligned && iBusRsp.stages(1).input.payload(1))) else True)
//Avoid stoping instruction fetch in the middle patch //Avoid stoping instruction fetch in the middle patch
@ -532,7 +516,7 @@ abstract class IBusFetcherImpl(val resetVector : BigInt,
val historyWriteLast = RegNextWhen(historyWrite, iBusRsp.stages(0).output.ready) val historyWriteLast = RegNextWhen(historyWrite, iBusRsp.stages(0).output.ready)
val hazard = historyWriteLast.valid && historyWriteLast.address === (iBusRsp.stages(1).input.payload >> 2).resized val hazard = historyWriteLast.valid && historyWriteLast.address === (iBusRsp.stages(1).input.payload >> 2).resized
//TODO improve predictionPcLoad way of doing things //TODO improve predictionPcLoad way of doing things
fetchPc.predictionPcLoad.valid := line.branchWish.msb && hit && !hazard && iBusRsp.stages(1).output.fire //XXX && !(!line.unaligned && iBusRsp.inputPipeline(0).payload(1)) fetchPc.predictionPcLoad.valid := line.branchWish.msb && hit && !hazard && iBusRsp.stages(1).output.valid //XXX && !(!line.unaligned && iBusRsp.inputPipeline(0).payload(1))
fetchPc.predictionPcLoad.payload := line.target fetchPc.predictionPcLoad.payload := line.target
case class PredictionResult() extends Bundle{ case class PredictionResult() extends Bundle{
@ -600,7 +584,7 @@ abstract class IBusFetcherImpl(val resetVector : BigInt,
when(decompressor.input.fire){ when(decompressor.input.fire){
decompressorFailure := decompressorContext.hit && !decompressorContext.hazard && !decompressor.output.valid && decompressorContext.line.branchWish(1) decompressorFailure := decompressorContext.hit && !decompressorContext.hazard && !decompressor.output.valid && decompressorContext.line.branchWish(1)
} }
decompressorFailure clearWhen(flush || decompressor.output.fire) decompressorFailure clearWhen(fetcherflushIt || decompressor.output.fire)
val injectorFailure = Delay(decompressorFailure, cycleCount=if(injectorStage) 1 else 0, when=injector.decodeInput.ready) val injectorFailure = Delay(decompressorFailure, cycleCount=if(injectorStage) 1 else 0, when=injector.decodeInput.ready)
@ -612,6 +596,7 @@ abstract class IBusFetcherImpl(val resetVector : BigInt,
historyWrite.data.branchWish := 0 historyWrite.data.branchWish := 0
decode.arbitration.isValid := False decode.arbitration.isValid := False
decode.arbitration.flushNext := True
dynamicTargetFailureCorrection.valid := True dynamicTargetFailureCorrection.valid := True
} }
}) })

View File

@ -19,7 +19,7 @@ class HazardSimplePlugin(bypassExecute : Boolean = false,
def hazardOnExecuteRS = { def hazardOnExecuteRS = {
if(pipeline.service(classOf[RegFileService]).readStage() == pipeline.execute) pipeline.execute.arbitration.isStuckByOthers else False if(pipeline.service(classOf[RegFileService]).readStage() == pipeline.execute) pipeline.execute.arbitration.isStuckByOthers else False //TODO not so nice
} }
override def setup(pipeline: VexRiscv): Unit = { override def setup(pipeline: VexRiscv): Unit = {

View File

@ -157,7 +157,7 @@ class IBusCachedPlugin(resetVector : BigInt = 0x80000000l,
stages(0).halt setWhen (cache.io.cpu.prefetch.haltIt) stages(0).halt setWhen (cache.io.cpu.prefetch.haltIt)
cache.io.cpu.fetch.isRemoved := flush cache.io.cpu.fetch.isRemoved := fetcherflushIt
} }
@ -237,12 +237,20 @@ class IBusCachedPlugin(resetVector : BigInt = 0x80000000l,
decodeExceptionPort.code := 1 decodeExceptionPort.code := 1
} }
redoFetch clearWhen(!iBusRsp.readyForError) when(!iBusRsp.readyForError){
cache.io.cpu.fill.valid clearWhen(!iBusRsp.readyForError) redoFetch := False
if (catchSomething) decodeExceptionPort.valid clearWhen(fetcherHalt) cache.io.cpu.fill.valid := False
}
// when(pipeline.stages.map(_.arbitration.flushIt).orR){
// cache.io.cpu.fill.valid := False
// }
redoBranch.valid := redoFetch redoBranch.valid := redoFetch
redoBranch.payload := (if (decodePcGen) decode.input(PC) else cacheRsp.pc) redoBranch.payload := (if (decodePcGen) decode.input(PC) else cacheRsp.pc)
decode.arbitration.flushNext setWhen(redoBranch.valid)
cacheRspArbitration.halt setWhen (issueDetected || iBusRspOutputHalt) cacheRspArbitration.halt setWhen (issueDetected || iBusRspOutputHalt)
iBusRsp.output.valid := cacheRspArbitration.output.valid iBusRsp.output.valid := cacheRspArbitration.output.valid

View File

@ -314,7 +314,7 @@ class IBusSimplePlugin( resetVector : BigInt,
mmuBus.cmd.isValid := cmdForkStage.input.valid mmuBus.cmd.isValid := cmdForkStage.input.valid
mmuBus.cmd.virtualAddress := cmdForkStage.input.payload mmuBus.cmd.virtualAddress := cmdForkStage.input.payload
mmuBus.cmd.bypassTranslation := False mmuBus.cmd.bypassTranslation := False
mmuBus.end := cmdForkStage.output.fire || flush mmuBus.end := cmdForkStage.output.fire || fetcherflushIt
cmd.pc := mmuBus.rsp.physicalAddress(31 downto 2) @@ "00" cmd.pc := mmuBus.rsp.physicalAddress(31 downto 2) @@ "00"
@ -341,7 +341,7 @@ class IBusSimplePlugin( resetVector : BigInt,
//Manage flush for iBus transactions in flight //Manage flush for iBus transactions in flight
val discardCounter = Reg(UInt(log2Up(pendingMax + 1) bits)) init (0) val discardCounter = Reg(UInt(log2Up(pendingMax + 1) bits)) init (0)
discardCounter := discardCounter - (iBus.rsp.fire && discardCounter =/= 0).asUInt discardCounter := discardCounter - (iBus.rsp.fire && discardCounter =/= 0).asUInt
when(flush) { when(fetcherflushIt) {
if(secondStagePersistence) if(secondStagePersistence)
discardCounter := pendingCmd + cmd.valid.asUInt - iBus.rsp.fire.asUInt discardCounter := pendingCmd + cmd.valid.asUInt - iBus.rsp.fire.asUInt
else else
@ -353,7 +353,7 @@ class IBusSimplePlugin( resetVector : BigInt,
val rspBuffer = if(!rspHoldValue) new Area{ val rspBuffer = if(!rspHoldValue) new Area{
val c = StreamFifoLowLatency(IBusSimpleRsp(), busLatencyMin + (if(cmdForkOnSecondStage && cmdForkPersistence) 1 else 0)) val c = StreamFifoLowLatency(IBusSimpleRsp(), busLatencyMin + (if(cmdForkOnSecondStage && cmdForkPersistence) 1 else 0))
c.io.push << iBus.rsp.throwWhen(discardCounter =/= 0).toStream c.io.push << iBus.rsp.throwWhen(discardCounter =/= 0).toStream
c.io.flush := flush c.io.flush := fetcherflushIt
rspBufferOutput << c.io.pop rspBufferOutput << c.io.pop
} else new Area{ } else new Area{
val rspStream = iBus.rsp.throwWhen(discardCounter =/= 0).toStream val rspStream = iBus.rsp.throwWhen(discardCounter =/= 0).toStream
@ -381,7 +381,9 @@ class IBusSimplePlugin( resetVector : BigInt,
redoRequired setWhen( stages.last.input.valid && mmu.joinCtx.refilling) redoRequired setWhen( stages.last.input.valid && mmu.joinCtx.refilling)
redoBranch.valid := redoRequired && iBusRsp.readyForError redoBranch.valid := redoRequired && iBusRsp.readyForError
redoBranch.payload := decode.input(PC) redoBranch.payload := decode.input(PC)
decode.arbitration.flushAll setWhen(redoBranch.valid)
decode.arbitration.flushIt setWhen(redoBranch.valid)
decode.arbitration.flushNext setWhen(redoBranch.valid)
} }
@ -400,7 +402,7 @@ class IBusSimplePlugin( resetVector : BigInt,
exceptionDetected := True exceptionDetected := True
} }
} }
decodeExceptionPort.valid := exceptionDetected && iBusRsp.readyForError && !fetcherHalt decodeExceptionPort.valid := exceptionDetected && iBusRsp.readyForError
} }
} }
} }

View File

@ -1550,7 +1550,7 @@ public:
riscvRef.liveness(top->VexRiscv->execute_CsrPlugin_inWfi); riscvRef.liveness(top->VexRiscv->execute_CsrPlugin_inWfi);
if(top->VexRiscv->CsrPlugin_interruptJump){ if(top->VexRiscv->CsrPlugin_interruptJump){
if(riscvRefEnable) riscvRef.trap(true, top->VexRiscv->CsrPlugin_interruptCode); if(riscvRefEnable) riscvRef.trap(true, top->VexRiscv->CsrPlugin_interrupt_code);
} }
} }
#endif #endif
@ -3443,7 +3443,7 @@ string freeRtosTests[] = {
// "test1","test1","test1","test1","test1","test1","test1","test1" // "test1","test1","test1","test1","test1","test1","test1","test1"
"AltQTest", "AltBlock", "AltPollQ", "blocktim", "countsem", "dead", "EventGroupsDemo", "flop", "integer", "QPeek", "AltQTest", "AltBlock", "AltPollQ", "blocktim", "countsem", "dead", "EventGroupsDemo", "flop", "integer", "QPeek",
"QueueSet", "recmutex", "semtest", "TaskNotify", "BlockQ", "crhook", "dynamic", "QueueSet", "recmutex", "semtest", "TaskNotify", "crhook", "dynamic",
"GenQTest", "PollQ", "QueueOverwrite", "QueueSetPolling", "sp_flop", "test1" "GenQTest", "PollQ", "QueueOverwrite", "QueueSetPolling", "sp_flop", "test1"
//"BlockQ","BlockQ","BlockQ","BlockQ","BlockQ","BlockQ","BlockQ","BlockQ" //"BlockQ","BlockQ","BlockQ","BlockQ","BlockQ","BlockQ","BlockQ","BlockQ"
// "flop" // "flop"
@ -3625,14 +3625,18 @@ static void multiThreading(queue<std::function<void()>> *lambdas, std::mutex *mu
static void multiThreadedExecute(queue<std::function<void()>> &lambdas){ static void multiThreadedExecute(queue<std::function<void()>> &lambdas){
std::mutex mutex; std::mutex mutex;
std::thread * t[THREAD_COUNT]; if(THREAD_COUNT == 1){
for(int id = 0;id < THREAD_COUNT;id++){ multiThreading(&lambdas, &mutex);
t[id] = new thread(multiThreading,&lambdas,&mutex); } else {
} std::thread * t[THREAD_COUNT];
for(int id = 0;id < THREAD_COUNT;id++){ for(int id = 0;id < THREAD_COUNT;id++){
t[id]->join(); t[id] = new thread(multiThreading,&lambdas,&mutex);
delete t[id]; }
for(int id = 0;id < THREAD_COUNT;id++){
t[id]->join();
delete t[id];
}
} }
} }
@ -3847,7 +3851,9 @@ int main(int argc, char **argv, char **env) {
#endif #endif
#ifdef DEBUG_PLUGIN #ifdef DEBUG_PLUGIN
#ifndef CONCURRENT_OS_EXECUTIONS
redo(REDO,DebugPluginTest().run(1e6);); redo(REDO,DebugPluginTest().run(1e6););
#endif
#endif #endif
#endif #endif

View File

@ -51,7 +51,9 @@ else
ADDCFLAGS += -CFLAGS -O3 -O3 ADDCFLAGS += -CFLAGS -O3 -O3
endif endif
ifeq ($(CONCURRENT_OS_EXECUTIONS),yes)
ADDCFLAGS += -CFLAGS -DCONCURRENT_OS_EXECUTIONS
endif
ifeq ($(LITEX),yes) ifeq ($(LITEX),yes)
ADDCFLAGS += -CFLAGS -DLITEX ADDCFLAGS += -CFLAGS -DLITEX

View File

@ -474,7 +474,7 @@ class CsrDimension(freertos : String, zephyr : String) extends VexRiscvDimension
if(supervisor){ if(supervisor){
new VexRiscvPosition("Supervisor") with CatchAllPosition{ new VexRiscvPosition("Supervisor") with CatchAllPosition{
override def applyOn(config: VexRiscvConfig): Unit = config.plugins += new CsrPlugin(CsrPluginConfig.linuxFull(0x80000020l)) override def applyOn(config: VexRiscvConfig): Unit = config.plugins += new CsrPlugin(CsrPluginConfig.linuxFull(0x80000020l))
override def testParam = s"FREERTOS=$freertos ZEPHYR=$zephyr LINUX_REGRESSION=yes SUPERVISOR=yes" override def testParam = s"FREERTOS=$freertos ZEPHYR=$zephyr LINUX_REGRESSION=${sys.env.getOrElse("VEXRISCV_REGRESSION_LINUX_REGRESSION", "yes")} SUPERVISOR=yes"
} }
} else if(catchAll){ } else if(catchAll){
new VexRiscvPosition("MachineOs") with CatchAllPosition{ new VexRiscvPosition("MachineOs") with CatchAllPosition{
@ -483,8 +483,8 @@ class CsrDimension(freertos : String, zephyr : String) extends VexRiscvDimension
} }
} else if(r.nextDouble() < 0.3){ } else if(r.nextDouble() < 0.3){
new VexRiscvPosition("AllNoException") with CatchAllPosition{ new VexRiscvPosition("AllNoException") with CatchAllPosition{
override def applyOn(config: VexRiscvConfig): Unit = config.plugins += new CsrPlugin(CsrPluginConfig.all(0x80000020l).noException) override def applyOn(config: VexRiscvConfig): Unit = config.plugins += new CsrPlugin(CsrPluginConfig.all(0x80000020l).noExceptionButEcall)
override def testParam = s"CSR=yes CSR_SKIP_TEST=yes FREERTOS=$freertos" override def testParam = s"CSR=yes CSR_SKIP_TEST=yes FREERTOS=$freertos ZEPHYR=$zephyr"
} }
} else { } else {
new VexRiscvPosition("None") { new VexRiscvPosition("None") {
@ -514,7 +514,8 @@ class DecoderDimension extends VexRiscvDimension("Decoder") {
val catchAll = universes.contains(VexRiscvUniverse.CATCH_ALL) val catchAll = universes.contains(VexRiscvUniverse.CATCH_ALL)
new VexRiscvPosition("") { new VexRiscvPosition("") {
override def applyOn(config: VexRiscvConfig): Unit = config.plugins += new DecoderSimplePlugin( override def applyOn(config: VexRiscvConfig): Unit = config.plugins += new DecoderSimplePlugin(
catchIllegalInstruction = catchAll catchIllegalInstruction = catchAll,
throwIllegalInstruction = false
) )
// override def isCompatibleWith(positions: Seq[ConfigPosition[VexRiscvConfig]]) = catchAll == positions.exists(_.isInstanceOf[CatchAllPosition]) // override def isCompatibleWith(positions: Seq[ConfigPosition[VexRiscvConfig]]) = catchAll == positions.exists(_.isInstanceOf[CatchAllPosition])
@ -555,23 +556,13 @@ class TestIndividualFeatures extends FunSuite {
new HazardDimension, new HazardDimension,
new RegFileDimension, new RegFileDimension,
new SrcDimension, new SrcDimension,
new CsrDimension(sys.env.getOrElse("VEXRISCV_REGRESSION_FREERTOS_COUNT", "1"), sys.env.getOrElse("VEXRISCV_REGRESSION_ZEPHYR_COUNT", "4")), new CsrDimension(/*sys.env.getOrElse("VEXRISCV_REGRESSION_FREERTOS_COUNT", "1")*/ "0", sys.env.getOrElse("VEXRISCV_REGRESSION_ZEPHYR_COUNT", "4")), //Freertos old port software is broken
new DecoderDimension, new DecoderDimension,
new DebugDimension, new DebugDimension,
new MmuDimension new MmuDimension
) )
// def genDefaultsPositions(dims : Seq[VexRiscvDimension], stack : List[VexRiscvPosition] = Nil) : Seq[List[VexRiscvPosition]] = dims match {
// case head :: tail => head.default.flatMap(p => genDefaultsPositions(tail, p :: stack))
// case Nil => List(stack)
// }
// val usedPositions = mutable.HashSet[VexRiscvPosition]();
// val positionsCount = dimensions.map(d => d.positions.length).sum
def doTest(positionsToApply : List[VexRiscvPosition], prefix : String = "", testSeed : Int, universes : mutable.HashSet[VexRiscvUniverse]): Unit ={ def doTest(positionsToApply : List[VexRiscvPosition], prefix : String = "", testSeed : Int, universes : mutable.HashSet[VexRiscvUniverse]): Unit ={
// usedPositions ++= positionsToApply
val noMemory = universes.contains(VexRiscvUniverse.NO_MEMORY) val noMemory = universes.contains(VexRiscvUniverse.NO_MEMORY)
val noWriteback = universes.contains(VexRiscvUniverse.NO_WRITEBACK) val noWriteback = universes.contains(VexRiscvUniverse.NO_WRITEBACK)
def gen = { def gen = {
@ -597,8 +588,9 @@ class TestIndividualFeatures extends FunSuite {
test(prefix + name + "_test") { test(prefix + name + "_test") {
println("START TEST " + prefix + name)
val debug = true val debug = true
val stdCmd = (s"make clean run WITH_USER_IO=no REDO=10 TRACE=${if(debug) "yes" else "no"} TRACE_START=9999924910246l FLOW_INFO=no STOP_ON_ERROR=no DHRYSTONE=yes COREMARK=yes THREAD_COUNT=${sys.env.getOrElse("VEXRISCV_REGRESSION_THREAD_COUNT", 1)} ") + s" SEED=${testSeed} " val stdCmd = (s"make clean run WITH_USER_IO=no REDO=10 TRACE=${if(debug) "yes" else "no"} TRACE_START=9999924910246l STOP_ON_ERROR=no FLOW_INFO=no STOP_ON_ERROR=no DHRYSTONE=yes COREMARK=${sys.env.getOrElse("VEXRISCV_REGRESSION_COREMARK", "yes")} THREAD_COUNT=${sys.env.getOrElse("VEXRISCV_REGRESSION_THREAD_COUNT", 1)} ") + s" SEED=${testSeed} "
val testCmd = stdCmd + (positionsToApply).map(_.testParam).mkString(" ") val testCmd = stdCmd + (positionsToApply).map(_.testParam).mkString(" ")
println(testCmd) println(testCmd)
val str = doCmd(testCmd) val str = doCmd(testCmd)
@ -606,14 +598,12 @@ class TestIndividualFeatures extends FunSuite {
} }
} }
// dimensions.foreach(d => d.positions.foreach(p => p.dimension = d))
val testId : Option[mutable.HashSet[Int]] = None val testId : Option[mutable.HashSet[Int]] = None
val seed = Random.nextLong() val seed = sys.env.getOrElse("VEXRISCV_REGRESSION_SEED", Random.nextLong().toString).toLong
// val testId = Some(mutable.HashSet(18,34,77,85,118,129,132,134,152,167,175,188,191,198,199)) //37/29 sp_flop_rv32i_O3 // val testId = Some(mutable.HashSet(3,4,9,11,13,16,18,19,20,21))
//val testId = Some(mutable.HashSet(0)) // val testId = Some(mutable.HashSet(24, 43, 49))
// val testId = Some(mutable.HashSet(4)) // val testId = Some(mutable.HashSet(11))
// val seed = -8309068850561113754l // val seed = -8309068850561113754l
@ -655,31 +645,4 @@ class TestIndividualFeatures extends FunSuite {
doTest(positions," random_" + i + "_", testSeed, universe) doTest(positions," random_" + i + "_", testSeed, universe)
Hack.dCounter += 1 Hack.dCounter += 1
} }
}
// println(s"${usedPositions.size}/$positionsCount positions")
// for (dimension <- dimensions) {
// for (position <- dimension.positions/* if position.name.contains("Cached")*/) {
// for(defaults <- genDefaultsPositions(dimensions.filter(_ != dimension))){
// doTest(position :: defaults)
// }
// }
// }
}
/*
val seed = -2412372746600605141l
129
FAIL AltQTest_rv32i_O3
FAIL AltQTest_rv32ic_O3
FAIL GenQTest_rv32i_O0
134
FAIL AltQTest_rv32i_O3
val seed = 4331444545509090137l
1 => flops i O0
*/