Merge remote-tracking branch 'origin/rework_jump_flush' into dev
This commit is contained in:
commit
60c9c094a7
84
README.md
84
README.md
|
@ -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) ->
|
||||
Artix 7 -> 366 Mhz 488 LUT 505 FF
|
||||
Cyclone V -> 181 Mhz 350 ALMs
|
||||
Cyclone IV -> 177 Mhz 732 LUT 494 FF
|
||||
iCE40 -> 85 Mhz 1131 LC
|
||||
Artix 7 -> 324 Mhz 496 LUT 505 FF
|
||||
Cyclone V -> 193 Mhz 347 ALMs
|
||||
Cyclone IV -> 179 Mhz 730 LUT 494 FF
|
||||
iCE40 -> 92 Mhz 1130 LC
|
||||
|
||||
VexRiscv smallest (RV32I, 0.52 DMIPS/Mhz, no datapath bypass) ->
|
||||
Artix 7 -> 317 Mhz 539 LUT 559 FF
|
||||
Cyclone V -> 191 Mhz 393 ALMs
|
||||
Cyclone IV -> 171 Mhz 826 LUT 547 FF
|
||||
iCE40 -> 72 Mhz 1284 LC
|
||||
Artix 7 -> 328 Mhz 539 LUT 562 FF
|
||||
Cyclone V -> 189 Mhz 387 ALMs
|
||||
Cyclone IV -> 175 Mhz 829 LUT 550 FF
|
||||
iCE40 -> 85 Mhz 1292 LC
|
||||
|
||||
VexRiscv small and productive (RV32I, 0.82 DMIPS/Mhz) ->
|
||||
Artix 7 -> 338 Mhz 697 LUT 527 FF
|
||||
Cyclone V -> 149 Mhz 495 ALMs
|
||||
Cyclone IV -> 137 Mhz 1,103 LUT 522 FF
|
||||
iCE40 -> 65 Mhz 1593 LC
|
||||
Artix 7 -> 324 Mhz 701 LUT 531 FF
|
||||
Cyclone V -> 145 Mhz 499 ALMs
|
||||
Cyclone IV -> 150 Mhz 1,111 LUT 525 FF
|
||||
iCE40 -> 63 Mhz 1596 LC
|
||||
|
||||
VexRiscv small and productive with I$ (RV32I, 0.70 DMIPS/Mhz, 4KB-I$) ->
|
||||
Artix 7 -> 314 Mhz 721 LUT 562 FF
|
||||
Cyclone V -> 152 Mhz 504 ALMs
|
||||
Cyclone IV -> 142 Mhz 1,146 LUT 528 FF
|
||||
iCE40 -> 69 Mhz 1661 LC
|
||||
Artix 7 -> 336 Mhz 764 LUT 562 FF
|
||||
Cyclone V -> 145 Mhz 511 ALMs
|
||||
Cyclone IV -> 144 Mhz 1,145 LUT 531 FF
|
||||
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) ->
|
||||
Artix 7 -> 325 Mhz 1448 LUT 976 FF
|
||||
Cyclone V -> 141 Mhz 957 ALMs
|
||||
Cyclone IV -> 139 Mhz 2,001 LUT 966 FF
|
||||
Artix 7 -> 326 Mhz 1544 LUT 977 FF
|
||||
Cyclone V -> 139 Mhz 958 ALMs
|
||||
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) ->
|
||||
Artix 7 -> 241 Mhz 1692 LUT 1202 FF
|
||||
Cyclone V -> 132 Mhz 1,127 ALMs
|
||||
Cyclone IV -> 124 Mhz 2,296 LUT 1,115 FF
|
||||
Artix 7 -> 279 Mhz 1686 LUT 1172 FF
|
||||
Cyclone V -> 144 Mhz 1,128 ALMs
|
||||
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) ->
|
||||
Artix 7 -> 195 Mhz 1824 LUT 1110 FF
|
||||
Cyclone V -> 83 Mhz 1,067 ALMs
|
||||
Cyclone IV -> 78 Mhz 2,335 LUT 1,045 FF
|
||||
Artix 7 -> 195 Mhz 1943 LUT 1111 FF
|
||||
Cyclone V -> 90 Mhz 1,089 ALMs
|
||||
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) ->
|
||||
Artix 7 -> 218 Mhz 1966 LUT 1551 FF
|
||||
Cyclone V -> 123 Mhz 1,298 ALMs
|
||||
Cyclone IV -> 109 Mhz 2,703 LUT 1,498 FF
|
||||
Artix 7 -> 239 Mhz 2029 LUT 1585 FF
|
||||
Cyclone V -> 124 Mhz 1,319 ALMs
|
||||
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) ->
|
||||
Artix 7 -> 239 Mhz 2483 LUT 2134 FF
|
||||
Cyclone V -> 130 Mhz 1,636 ALMs
|
||||
Cyclone IV -> 116 Mhz 3,324 LUT 2,010 FF
|
||||
Artix 7 -> 249 Mhz 2549 LUT 2014 FF
|
||||
Cyclone V -> 125 Mhz 1,618 ALMs
|
||||
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 :
|
||||
|
||||
```
|
||||
Artix 7 -> 232 Mhz 3042 LUT 3281 FF
|
||||
Cyclone V -> 138 Mhz 2,179 ALMs
|
||||
Cyclone IV -> 120 Mhz 4,333 LUT 3,167 FF
|
||||
Artix 7 -> 275 Mhz 3072 LUT 3291 FF
|
||||
Cyclone V -> 139 Mhz 2,175 ALMs
|
||||
Cyclone IV -> 129 Mhz 4,337 LUT 3,170 FF
|
||||
```
|
||||
|
||||
## 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) ->
|
||||
Artix 7 - > 301 Mhz 1032 LUT 1199 FF
|
||||
Cyclone V -> 183 Mhz 736 ALMs
|
||||
Cyclone IV -> 148 Mhz 1,481 LUT 1,204 FF
|
||||
iCE40 -> 69 Mhz 2403 LC (nextpnr)
|
||||
Artix 7 -> 313 Mhz 1039 LUT 1200 FF
|
||||
Cyclone V -> 173 Mhz 737 ALMs
|
||||
Cyclone IV -> 144 Mhz 1,484 LUT 1,206 FF
|
||||
iCE40 -> 64 Mhz 2422 LC (nextpnr)
|
||||
|
||||
MuraxFast bypassed stages (0.65 DMIPS/Mhz, 8 bits GPIO) ->
|
||||
Artix 7 -> 321 Mhz 1198 LUT 1298 FF
|
||||
Cyclone V -> 165 Mhz 873 ALMs
|
||||
Cyclone IV -> 145 Mhz 1,691 LUT 1,239 FF
|
||||
iCE40 -> 61 Mhz 2778 LC (nextpnr)
|
||||
Artix 7 -> 323 Mhz 1241 LUT 1301 FF
|
||||
Cyclone V -> 159 Mhz 864 ALMs
|
||||
Cyclone IV -> 137 Mhz 1,688 LUT 1,241 FF
|
||||
iCE40 -> 66 Mhz 2799 LC (nextpnr)
|
||||
```
|
||||
|
||||
Some scripts to generate the SoC and call the icestorm toolchain can be found here: `scripts/Murax/`
|
||||
|
|
|
@ -17,6 +17,8 @@ trait Pipeline {
|
|||
val things = mutable.HashMap[PipelineThing[_], Any]()
|
||||
// val services = ArrayBuffer[Any]()
|
||||
|
||||
def stageBefore(stage : Stage) = stages(indexOf(stage)-1)
|
||||
|
||||
def indexOf(stage : Stage) = stages.indexOf(stage)
|
||||
|
||||
def service[T](clazz : Class[T]) = {
|
||||
|
@ -127,7 +129,7 @@ trait Pipeline {
|
|||
|
||||
//Arbitration
|
||||
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))
|
||||
stage.arbitration.removeIt setWhen stage.arbitration.isFlushed
|
||||
else
|
||||
|
|
|
@ -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 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 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 isStuck = Bool //Inform if the instruction is stuck (haltItself || haltByOther)
|
||||
val isStuckByOthers = Bool //Inform if the instruction is stuck by sombody else
|
||||
|
|
|
@ -109,7 +109,7 @@ class VexRiscv(val config : VexRiscvConfig) extends Component with Pipeline{
|
|||
if(withMemoryStage){
|
||||
memory.arbitration.removeIt.noBackendCombMerge
|
||||
}
|
||||
execute.arbitration.flushAll.noBackendCombMerge
|
||||
execute.arbitration.flushNext.noBackendCombMerge
|
||||
|
||||
this(RVC_GEN) = false
|
||||
}
|
||||
|
|
|
@ -84,6 +84,8 @@ class BranchPlugin(earlyBranch : Boolean,
|
|||
decodePrediction
|
||||
}
|
||||
|
||||
def hasHazardOnBranch = if(earlyBranch) pipeline.service(classOf[HazardService]).hazardOnExecuteRS else False
|
||||
|
||||
override def setup(pipeline: VexRiscv): Unit = {
|
||||
import Riscv._
|
||||
import pipeline.config._
|
||||
|
@ -200,12 +202,9 @@ class BranchPlugin(earlyBranch : Boolean,
|
|||
//Apply branchs (JAL,JALR, Bxx)
|
||||
branchStage plug new Area {
|
||||
import branchStage._
|
||||
jumpInterface.valid := arbitration.isValid && !arbitration.isStuckByOthers && input(BRANCH_DO)
|
||||
jumpInterface.valid := arbitration.isValid && input(BRANCH_DO) && !hasHazardOnBranch
|
||||
jumpInterface.payload := input(BRANCH_CALC)
|
||||
|
||||
when(jumpInterface.valid) {
|
||||
stages(indexOf(branchStage) - 1).arbitration.flushAll := True
|
||||
}
|
||||
arbitration.flushNext setWhen(jumpInterface.valid)
|
||||
|
||||
if(catchAddressMisalignedForReal) {
|
||||
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
|
||||
branchStage plug new Area {
|
||||
import branchStage._
|
||||
jumpInterface.valid := arbitration.isValid && !arbitration.isStuckByOthers && input(BRANCH_DO)
|
||||
jumpInterface.valid := arbitration.isValid && input(BRANCH_DO) && !hasHazardOnBranch
|
||||
jumpInterface.payload := input(BRANCH_CALC)
|
||||
|
||||
when(jumpInterface.valid) {
|
||||
stages(indexOf(branchStage) - 1).arbitration.flushAll := True
|
||||
}
|
||||
arbitration.flushNext setWhen(jumpInterface.valid)
|
||||
|
||||
if(catchAddressMisalignedForReal) {
|
||||
val unalignedJump = input(BRANCH_DO) && input(BRANCH_CALC)(1)
|
||||
|
@ -361,14 +357,11 @@ class BranchPlugin(earlyBranch : Boolean,
|
|||
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))
|
||||
arbitration.flushNext setWhen(jumpInterface.valid)
|
||||
|
||||
|
||||
when(jumpInterface.valid) {
|
||||
stages(indexOf(branchStage) - 1).arbitration.flushAll := True
|
||||
}
|
||||
|
||||
if(catchAddressMisalignedForReal) {
|
||||
branchExceptionPort.valid := arbitration.isValid && input(BRANCH_DO) && input(BRANCH_CALC)(1)
|
||||
branchExceptionPort.code := 0
|
||||
|
|
|
@ -68,11 +68,13 @@ case class CsrPluginConfig(
|
|||
medelegAccess : CsrAccess = CsrAccess.NONE,
|
||||
midelegAccess : CsrAccess = CsrAccess.NONE,
|
||||
pipelineCsrRead : Boolean = false,
|
||||
pipelinedInterrupt : Boolean = true,
|
||||
deterministicInteruptionEntry : Boolean = false //Only used for simulatation purposes
|
||||
){
|
||||
assert(!ucycleAccess.canWrite)
|
||||
def privilegeGen = userGen || supervisorGen
|
||||
def noException = this.copy(ecallGen = false, ebreakGen = false, catchIllegalAccess = false)
|
||||
def noExceptionButEcall = this.copy(ecallGen = true, ebreakGen = false, catchIllegalAccess = false)
|
||||
}
|
||||
|
||||
object CsrPluginConfig{
|
||||
|
@ -693,7 +695,7 @@ class CsrPlugin(val config: CsrPluginConfig) extends Plugin[VexRiscv] with Excep
|
|||
exceptionValids := exceptionValidsRegs
|
||||
for(portInfo <- sortedByStage; port = portInfo.port ; stage = portInfo.stage; stageId = indexOf(portInfo.stage)) {
|
||||
when(port.valid) {
|
||||
if(indexOf(stage) != 0) stages(indexOf(stage) - 1).arbitration.flushAll := True
|
||||
stage.arbitration.flushNext := True
|
||||
stage.arbitration.removeIt := True
|
||||
exceptionValids(stageId) := True
|
||||
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()
|
||||
}
|
||||
|
||||
|
@ -729,32 +731,37 @@ class CsrPlugin(val config: CsrPluginConfig) extends Plugin[VexRiscv] with Excep
|
|||
|
||||
|
||||
//Process interrupt request, code and privilege
|
||||
val interrupt = False
|
||||
val interruptCode = UInt(4 bits).assignDontCare().addTag(Verilator.public)
|
||||
var interruptPrivilegs = if (supervisorGen) List(1, 3) else List(3)
|
||||
val interruptTargetPrivilege = UInt(2 bits).assignDontCare()
|
||||
val privilegeAllowInterrupts = mutable.HashMap[Int, Bool]()
|
||||
if(supervisorGen) privilegeAllowInterrupts += 1 -> ((sstatus.SIE && privilege === "01") || privilege < "01")
|
||||
privilegeAllowInterrupts += 3 -> (mstatus.MIE || privilege < "11")
|
||||
while(interruptPrivilegs.nonEmpty){
|
||||
val p = interruptPrivilegs.head
|
||||
when(privilegeAllowInterrupts(p)){
|
||||
for(i <- interruptSpecs
|
||||
if i.privilege <= p //EX : Machine timer interrupt can't go into supervisor mode
|
||||
if interruptPrivilegs.tail.forall(e => i.delegators.exists(_.privilege == e))){ // EX : Supervisor timer need to have machine mode delegator
|
||||
val delegUpOn = i.delegators.filter(_.privilege > p).map(_.enable).fold(True)(_ && _)
|
||||
val delegDownOff = !i.delegators.filter(_.privilege <= p).map(_.enable).orR
|
||||
when(i.cond && delegUpOn && delegDownOff){
|
||||
interrupt := True
|
||||
interruptCode := i.id
|
||||
interruptTargetPrivilege := p
|
||||
val interrupt = new Area {
|
||||
val valid = if(pipelinedInterrupt) RegNext(False) init(False) else False
|
||||
val code = if(pipelinedInterrupt) Reg(UInt(4 bits)) else UInt(4 bits).assignDontCare()
|
||||
var privilegs = if (supervisorGen) List(1, 3) else List(3)
|
||||
val targetPrivilege = if(pipelinedInterrupt) Reg(UInt(2 bits)) else UInt(2 bits).assignDontCare()
|
||||
val privilegeAllowInterrupts = mutable.HashMap[Int, Bool]()
|
||||
if (supervisorGen) privilegeAllowInterrupts += 1 -> ((sstatus.SIE && privilege === "01") || privilege < "01")
|
||||
privilegeAllowInterrupts += 3 -> (mstatus.MIE || privilege < "11")
|
||||
while (privilegs.nonEmpty) {
|
||||
val p = privilegs.head
|
||||
when(privilegeAllowInterrupts(p)) {
|
||||
for (i <- interruptSpecs
|
||||
if i.privilege <= p //EX : Machine timer interrupt can't go into supervisor mode
|
||||
if privilegs.tail.forall(e => i.delegators.exists(_.privilege == e))) { // EX : Supervisor timer need to have machine mode delegator
|
||||
val delegUpOn = i.delegators.filter(_.privilege > p).map(_.enable).fold(True)(_ && _)
|
||||
val delegDownOff = !i.delegators.filter(_.privilege <= p).map(_.enable).orR
|
||||
when(i.cond && delegUpOn && delegDownOff) {
|
||||
valid := True
|
||||
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 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)
|
||||
val pipelineLiberator = new Area{
|
||||
when(interrupt){
|
||||
when(interrupt.valid && allowInterrupts){
|
||||
decode.arbitration.haltByOther := decode.arbitration.isValid
|
||||
}
|
||||
|
||||
|
@ -773,18 +780,18 @@ class CsrPlugin(val config: CsrPluginConfig) extends Plugin[VexRiscv] with Excep
|
|||
|
||||
//Interrupt/Exception entry logic
|
||||
val interruptJump = Bool.addTag(Verilator.public)
|
||||
interruptJump := interrupt && pipelineLiberator.done
|
||||
interruptJump := interrupt.valid && pipelineLiberator.done && allowInterrupts
|
||||
|
||||
val hadException = RegNext(exception) init(False)
|
||||
pipelineLiberator.done.clearWhen(hadException)
|
||||
|
||||
|
||||
val targetPrivilege = CombInit(interruptTargetPrivilege)
|
||||
val targetPrivilege = CombInit(interrupt.targetPrivilege)
|
||||
if(exceptionPortCtrl != null) when(hadException) {
|
||||
targetPrivilege := exceptionPortCtrl.exceptionTargetPrivilege
|
||||
}
|
||||
|
||||
val trapCause = CombInit(interruptCode)
|
||||
val trapCause = CombInit(interrupt.code)
|
||||
if(exceptionPortCtrl != null) when( hadException){
|
||||
trapCause := exceptionPortCtrl.exceptionContext.code
|
||||
}
|
||||
|
@ -800,7 +807,7 @@ class CsrPlugin(val config: CsrPluginConfig) extends Plugin[VexRiscv] with Excep
|
|||
|
||||
jumpInterface.valid := True
|
||||
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
|
||||
|
||||
|
@ -839,7 +846,7 @@ class CsrPlugin(val config: CsrPluginConfig) extends Plugin[VexRiscv] with Excep
|
|||
when(arbitration.isValid && input(ENV_CTRL) === EnvCtrlEnum.XRET) {
|
||||
fetcher.haltIt()
|
||||
jumpInterface.valid := True
|
||||
beforeLastStage.arbitration.flushAll := True
|
||||
lastStage.arbitration.flushNext := True
|
||||
switch(input(INSTRUCTION)(29 downto 28)){
|
||||
is(3){
|
||||
mstatus.MPP := U"00"
|
||||
|
|
|
@ -247,7 +247,8 @@ class DBusCachedPlugin(val config : DataCacheConfig,
|
|||
|
||||
redoBranch.valid := False
|
||||
redoBranch.payload := input(PC)
|
||||
arbitration.flushAll setWhen(redoBranch.valid)
|
||||
arbitration.flushIt setWhen(redoBranch.valid)
|
||||
arbitration.flushNext setWhen(redoBranch.valid)
|
||||
|
||||
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
|
||||
|
|
|
@ -516,7 +516,8 @@ class DBusSimplePlugin(catchAddressMisaligned : Boolean = false,
|
|||
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))){
|
||||
|
|
|
@ -203,7 +203,8 @@ class DebugPlugin(val debugClockDomain : ClockDomain, hardwareBreakpointCount :
|
|||
when(stagesFromExecute.tail.map(_.arbitration.isValid).orR === False){
|
||||
iBusFetcher.flushIt()
|
||||
iBusFetcher.haltIt()
|
||||
execute.arbitration.flushAll := True
|
||||
execute.arbitration.flushIt := True
|
||||
execute.arbitration.flushNext := True
|
||||
haltIt := True
|
||||
haltedByBreak := True
|
||||
}
|
||||
|
|
|
@ -28,7 +28,7 @@ case class Masked(value : BigInt,care : BigInt){
|
|||
def mergeOneBitDifSmaller(x: Masked) = {
|
||||
val bit = value - x.value
|
||||
val ret = new Masked(value &~ bit, care & ~bit)
|
||||
// ret.isPrime = isPrime || x.isPrime
|
||||
// ret.isPrime = isPrime || x.isPrime
|
||||
isPrime = false
|
||||
x.isPrime = false
|
||||
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(_+_)
|
||||
}
|
||||
|
||||
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(key: MaskedLiteral, values: Seq[(Stageable[_ <: BaseType], Any)]): Unit = {
|
||||
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 = {
|
||||
import pipeline.config._
|
||||
import pipeline.decode._
|
||||
|
@ -86,7 +93,7 @@ class DecoderSimplePlugin(catchIllegalInstruction : Boolean = false, forceLegalI
|
|||
|
||||
val stupidDecoder = false
|
||||
if(stupidDecoder){
|
||||
if (catchIllegalInstruction || forceLegalInstructionComputation) insert(LEGAL_INSTRUCTION) := False
|
||||
if (detectLegalInstructions) insert(LEGAL_INSTRUCTION) := False
|
||||
for(stageable <- stageables){
|
||||
if(defaults.contains(stageable)){
|
||||
insert(stageable).assignFrom(defaults(stageable))
|
||||
|
@ -96,7 +103,7 @@ class DecoderSimplePlugin(catchIllegalInstruction : Boolean = false, forceLegalI
|
|||
}
|
||||
for((key, tasks) <- encodings){
|
||||
when(input(INSTRUCTION) === key){
|
||||
if (catchIllegalInstruction || forceLegalInstructionComputation) insert(LEGAL_INSTRUCTION) := True
|
||||
if (detectLegalInstructions) insert(LEGAL_INSTRUCTION) := True
|
||||
for((stageable, value) <- tasks){
|
||||
insert(stageable).assignFrom(value)
|
||||
}
|
||||
|
@ -145,8 +152,15 @@ class DecoderSimplePlugin(catchIllegalInstruction : Boolean = false, forceLegalI
|
|||
// logic implementation
|
||||
val decodedBits = Bits(stageables.foldLeft(0)(_ + _.dataType.getBitsWidth) bits)
|
||||
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
|
||||
offset = 0
|
||||
|
@ -162,6 +176,10 @@ class DecoderSimplePlugin(catchIllegalInstruction : Boolean = false, forceLegalI
|
|||
decodeExceptionPort.code := 2
|
||||
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 ={
|
||||
|
@ -176,7 +194,7 @@ class DecoderSimplePlugin(catchIllegalInstruction : Boolean = false, forceLegalI
|
|||
val stageables = encodings.flatMap(_._2.map(_._1)).toSet
|
||||
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())))
|
||||
// toplevel.getAdditionalNodesRoot.clear()
|
||||
// toplevel.getAdditionalNodesRoot.clear()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -345,14 +363,14 @@ object SymplifyBit{
|
|||
|
||||
def main(args: Array[String]) {
|
||||
{
|
||||
// val default = Masked(0, 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 reducedPrimeImplicants = getPrimeImplicantsByTrueAndDontCare(primeImplicants, dcImplicants, 4)
|
||||
// println("UUT")
|
||||
// println(reducedPrimeImplicants.map(_.toString(4)).mkString("\n"))
|
||||
// println("REF")
|
||||
// println("-100\n10--\n1--0\n1-1-")
|
||||
// val default = Masked(0, 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 reducedPrimeImplicants = getPrimeImplicantsByTrueAndDontCare(primeImplicants, dcImplicants, 4)
|
||||
// println("UUT")
|
||||
// println(reducedPrimeImplicants.map(_.toString(4)).mkString("\n"))
|
||||
// println("REF")
|
||||
// println("-100\n10--\n1--0\n1-1-")
|
||||
}
|
||||
|
||||
{
|
||||
|
|
|
@ -103,64 +103,47 @@ abstract class IBusFetcherImpl(val resetVector : BigInt,
|
|||
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{
|
||||
val preOutput = Stream(UInt(32 bits))
|
||||
val output = preOutput.haltWhen(fetcherHalt)
|
||||
val predictionPcLoad = ifGen(prediction == DYNAMIC_TARGET) (Flow(UInt(32 bits)))
|
||||
}
|
||||
|
||||
val fetchPc = new PcFetch{
|
||||
//The fetchPC pcReg can also be use for the second stage of the fetch
|
||||
//When the fetcherHalt is set and the pipeline isn't stalled,, the pc is propagated to to the pcReg, which allow
|
||||
//using the pc pipeline to get the next PC value for interrupts
|
||||
val fetchPc = new Area{
|
||||
//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 inc = RegInit(False)
|
||||
val propagatePc = False
|
||||
|
||||
val corrected = 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 samplePcNext = False
|
||||
val predictionPcLoad = ifGen(prediction == DYNAMIC_TARGET) (Flow(UInt(32 bits)))
|
||||
|
||||
if(compressedGen) {
|
||||
when(inc) {
|
||||
pc(1) := False
|
||||
}
|
||||
}
|
||||
|
||||
when(propagatePc){
|
||||
samplePcNext := True
|
||||
inc := False
|
||||
if(compressedGen) when(inc) {
|
||||
pc(1) := False
|
||||
}
|
||||
|
||||
if(predictionPcLoad != null) {
|
||||
when(predictionPcLoad.valid) {
|
||||
inc := False
|
||||
samplePcNext := True
|
||||
corrected := True
|
||||
pc := predictionPcLoad.payload
|
||||
}
|
||||
}
|
||||
when(jump.pcLoad.valid) {
|
||||
inc := False
|
||||
samplePcNext := True
|
||||
corrected := True
|
||||
pc := jump.pcLoad.payload
|
||||
}
|
||||
|
||||
|
||||
when(preOutput.fire){
|
||||
inc := True
|
||||
samplePcNext := True
|
||||
}
|
||||
|
||||
|
||||
when(samplePcNext) {
|
||||
when(booted && (output.ready || fetcherflushIt || pcRegPropagate)){
|
||||
pcReg := pc
|
||||
}
|
||||
|
||||
pc(0) := False
|
||||
if(!pipeline(RVC_GEN)) pc(1) := False
|
||||
|
||||
preOutput.valid := RegNext(True) init (False)
|
||||
preOutput.payload := pc
|
||||
|
||||
output.valid := !fetcherHalt && booted
|
||||
output.payload := pc
|
||||
}
|
||||
|
||||
val decodePc = ifGen(decodePcGen)(new Area {
|
||||
|
@ -185,7 +168,7 @@ abstract class IBusFetcherImpl(val resetVector : BigInt,
|
|||
}
|
||||
|
||||
//application of the selected jump request
|
||||
when(jump.pcLoad.valid) {
|
||||
when(jump.pcLoad.valid && (!decode.arbitration.isStuck || decode.arbitration.isRemoved)) {
|
||||
pcReg := jump.pcLoad.payload
|
||||
}
|
||||
})
|
||||
|
@ -226,11 +209,11 @@ abstract class IBusFetcherImpl(val resetVector : BigInt,
|
|||
|
||||
for((s,sNext) <- (stages, stages.tail).zipped) {
|
||||
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
|
||||
fetchPc.propagatePc setWhen(sNext.input.fire)
|
||||
fetchPc.pcRegPropagate setWhen(sNext.input.ready)
|
||||
} 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 := !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(() => {
|
||||
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
|
||||
}
|
||||
})
|
||||
|
@ -284,7 +267,7 @@ abstract class IBusFetcherImpl(val resetVector : BigInt,
|
|||
bufferValid := !(!isRvc && !input.pc(1) && !bufferValid) && !(isRvc && input.pc(1) && output.ready)
|
||||
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
|
||||
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
|
||||
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) {
|
||||
iBusRsp.readyForError.clearWhen(inputBeforeStage.valid) //Can't emit error if there is a instruction pending in the s2mPipe
|
||||
incomingInstruction setWhen (inputBeforeStage.valid)
|
||||
}
|
||||
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)
|
||||
iBusRsp.readyForError.clearWhen(decodeInput.valid) //Can't emit error when there is a instruction pending in the injector stage buffer
|
||||
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] = {
|
||||
stucks.scanLeft(input)((i, stuck) => {
|
||||
val reg = RegInit(False)
|
||||
if(!relaxedInput) when(flush) {
|
||||
if(!relaxedInput) when(fetcherflushIt) {
|
||||
reg := False
|
||||
}
|
||||
when(!stuck) {
|
||||
reg := i
|
||||
}
|
||||
if(relaxedInput || i != input) when(flush) {
|
||||
if(relaxedInput || i != input) when(fetcherflushIt) {
|
||||
reg := False
|
||||
}
|
||||
reg
|
||||
|
@ -335,7 +318,7 @@ abstract class IBusFetcherImpl(val resetVector : BigInt,
|
|||
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
|
||||
decode.arbitration.isValid := decodeInput.valid && !decodeRemoved
|
||||
|
@ -461,7 +444,7 @@ abstract class IBusFetcherImpl(val resetVector : BigInt,
|
|||
}
|
||||
val fetchContext = DynamicContext()
|
||||
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())
|
||||
decode.insert(PREDICTION_CONTEXT) := stage1ToInjectorPipe(fetchContext)._2
|
||||
|
@ -499,13 +482,14 @@ abstract class IBusFetcherImpl(val resetVector : BigInt,
|
|||
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
|
||||
if(relaxPredictorAddress) KeepAttribute(predictionJumpInterface.payload)
|
||||
|
||||
// when(predictionJumpInterface.payload((if(pipeline(RVC_GEN)) 0 else 1) downto 0) =/= 0){
|
||||
// decodePrediction.cmd.hadBranch := False
|
||||
// }
|
||||
when(predictionJumpInterface.valid && decode.arbitration.isFiring){
|
||||
flushIt()
|
||||
}
|
||||
}
|
||||
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")
|
||||
|
@ -520,7 +504,7 @@ abstract class IBusFetcherImpl(val resetVector : BigInt,
|
|||
val history = Mem(BranchPredictorLine(), 1 << historyRamSizeLog2)
|
||||
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)
|
||||
|
||||
//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 hazard = historyWriteLast.valid && historyWriteLast.address === (iBusRsp.stages(1).input.payload >> 2).resized
|
||||
//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
|
||||
|
||||
case class PredictionResult() extends Bundle{
|
||||
|
@ -600,7 +584,7 @@ abstract class IBusFetcherImpl(val resetVector : BigInt,
|
|||
when(decompressor.input.fire){
|
||||
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)
|
||||
|
||||
|
@ -612,6 +596,7 @@ abstract class IBusFetcherImpl(val resetVector : BigInt,
|
|||
historyWrite.data.branchWish := 0
|
||||
|
||||
decode.arbitration.isValid := False
|
||||
decode.arbitration.flushNext := True
|
||||
dynamicTargetFailureCorrection.valid := True
|
||||
}
|
||||
})
|
||||
|
|
|
@ -19,7 +19,7 @@ class HazardSimplePlugin(bypassExecute : Boolean = false,
|
|||
|
||||
|
||||
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 = {
|
||||
|
|
|
@ -157,7 +157,7 @@ class IBusCachedPlugin(resetVector : BigInt = 0x80000000l,
|
|||
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
|
||||
}
|
||||
|
||||
redoFetch clearWhen(!iBusRsp.readyForError)
|
||||
cache.io.cpu.fill.valid clearWhen(!iBusRsp.readyForError)
|
||||
if (catchSomething) decodeExceptionPort.valid clearWhen(fetcherHalt)
|
||||
when(!iBusRsp.readyForError){
|
||||
redoFetch := False
|
||||
cache.io.cpu.fill.valid := False
|
||||
}
|
||||
// when(pipeline.stages.map(_.arbitration.flushIt).orR){
|
||||
// cache.io.cpu.fill.valid := False
|
||||
// }
|
||||
|
||||
|
||||
|
||||
redoBranch.valid := redoFetch
|
||||
redoBranch.payload := (if (decodePcGen) decode.input(PC) else cacheRsp.pc)
|
||||
decode.arbitration.flushNext setWhen(redoBranch.valid)
|
||||
|
||||
|
||||
cacheRspArbitration.halt setWhen (issueDetected || iBusRspOutputHalt)
|
||||
iBusRsp.output.valid := cacheRspArbitration.output.valid
|
||||
|
|
|
@ -314,7 +314,7 @@ class IBusSimplePlugin( resetVector : BigInt,
|
|||
mmuBus.cmd.isValid := cmdForkStage.input.valid
|
||||
mmuBus.cmd.virtualAddress := cmdForkStage.input.payload
|
||||
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"
|
||||
|
||||
|
@ -341,7 +341,7 @@ class IBusSimplePlugin( resetVector : BigInt,
|
|||
//Manage flush for iBus transactions in flight
|
||||
val discardCounter = Reg(UInt(log2Up(pendingMax + 1) bits)) init (0)
|
||||
discardCounter := discardCounter - (iBus.rsp.fire && discardCounter =/= 0).asUInt
|
||||
when(flush) {
|
||||
when(fetcherflushIt) {
|
||||
if(secondStagePersistence)
|
||||
discardCounter := pendingCmd + cmd.valid.asUInt - iBus.rsp.fire.asUInt
|
||||
else
|
||||
|
@ -353,7 +353,7 @@ class IBusSimplePlugin( resetVector : BigInt,
|
|||
val rspBuffer = if(!rspHoldValue) new Area{
|
||||
val c = StreamFifoLowLatency(IBusSimpleRsp(), busLatencyMin + (if(cmdForkOnSecondStage && cmdForkPersistence) 1 else 0))
|
||||
c.io.push << iBus.rsp.throwWhen(discardCounter =/= 0).toStream
|
||||
c.io.flush := flush
|
||||
c.io.flush := fetcherflushIt
|
||||
rspBufferOutput << c.io.pop
|
||||
} else new Area{
|
||||
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)
|
||||
redoBranch.valid := redoRequired && iBusRsp.readyForError
|
||||
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
|
||||
}
|
||||
}
|
||||
decodeExceptionPort.valid := exceptionDetected && iBusRsp.readyForError && !fetcherHalt
|
||||
decodeExceptionPort.valid := exceptionDetected && iBusRsp.readyForError
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1550,7 +1550,7 @@ public:
|
|||
|
||||
riscvRef.liveness(top->VexRiscv->execute_CsrPlugin_inWfi);
|
||||
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
|
||||
|
@ -3443,7 +3443,7 @@ string freeRtosTests[] = {
|
|||
// "test1","test1","test1","test1","test1","test1","test1","test1"
|
||||
|
||||
"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"
|
||||
//"BlockQ","BlockQ","BlockQ","BlockQ","BlockQ","BlockQ","BlockQ","BlockQ"
|
||||
// "flop"
|
||||
|
@ -3625,14 +3625,18 @@ static void multiThreading(queue<std::function<void()>> *lambdas, std::mutex *mu
|
|||
|
||||
|
||||
static void multiThreadedExecute(queue<std::function<void()>> &lambdas){
|
||||
std::mutex mutex;
|
||||
std::thread * t[THREAD_COUNT];
|
||||
for(int id = 0;id < THREAD_COUNT;id++){
|
||||
t[id] = new thread(multiThreading,&lambdas,&mutex);
|
||||
}
|
||||
for(int id = 0;id < THREAD_COUNT;id++){
|
||||
t[id]->join();
|
||||
delete t[id];
|
||||
std::mutex mutex;
|
||||
if(THREAD_COUNT == 1){
|
||||
multiThreading(&lambdas, &mutex);
|
||||
} else {
|
||||
std::thread * t[THREAD_COUNT];
|
||||
for(int id = 0;id < THREAD_COUNT;id++){
|
||||
t[id] = new thread(multiThreading,&lambdas,&mutex);
|
||||
}
|
||||
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
|
||||
|
||||
#ifdef DEBUG_PLUGIN
|
||||
#ifndef CONCURRENT_OS_EXECUTIONS
|
||||
redo(REDO,DebugPluginTest().run(1e6););
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
|
|
@ -51,7 +51,9 @@ else
|
|||
ADDCFLAGS += -CFLAGS -O3 -O3
|
||||
endif
|
||||
|
||||
|
||||
ifeq ($(CONCURRENT_OS_EXECUTIONS),yes)
|
||||
ADDCFLAGS += -CFLAGS -DCONCURRENT_OS_EXECUTIONS
|
||||
endif
|
||||
|
||||
ifeq ($(LITEX),yes)
|
||||
ADDCFLAGS += -CFLAGS -DLITEX
|
||||
|
|
|
@ -474,7 +474,7 @@ class CsrDimension(freertos : String, zephyr : String) extends VexRiscvDimension
|
|||
if(supervisor){
|
||||
new VexRiscvPosition("Supervisor") with CatchAllPosition{
|
||||
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){
|
||||
new VexRiscvPosition("MachineOs") with CatchAllPosition{
|
||||
|
@ -483,8 +483,8 @@ class CsrDimension(freertos : String, zephyr : String) extends VexRiscvDimension
|
|||
}
|
||||
} else if(r.nextDouble() < 0.3){
|
||||
new VexRiscvPosition("AllNoException") with CatchAllPosition{
|
||||
override def applyOn(config: VexRiscvConfig): Unit = config.plugins += new CsrPlugin(CsrPluginConfig.all(0x80000020l).noException)
|
||||
override def testParam = s"CSR=yes CSR_SKIP_TEST=yes FREERTOS=$freertos"
|
||||
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 ZEPHYR=$zephyr"
|
||||
}
|
||||
} else {
|
||||
new VexRiscvPosition("None") {
|
||||
|
@ -514,7 +514,8 @@ class DecoderDimension extends VexRiscvDimension("Decoder") {
|
|||
val catchAll = universes.contains(VexRiscvUniverse.CATCH_ALL)
|
||||
new VexRiscvPosition("") {
|
||||
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])
|
||||
|
@ -555,23 +556,13 @@ class TestIndividualFeatures extends FunSuite {
|
|||
new HazardDimension,
|
||||
new RegFileDimension,
|
||||
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 DebugDimension,
|
||||
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 ={
|
||||
// usedPositions ++= positionsToApply
|
||||
val noMemory = universes.contains(VexRiscvUniverse.NO_MEMORY)
|
||||
val noWriteback = universes.contains(VexRiscvUniverse.NO_WRITEBACK)
|
||||
def gen = {
|
||||
|
@ -597,8 +588,9 @@ class TestIndividualFeatures extends FunSuite {
|
|||
|
||||
|
||||
test(prefix + name + "_test") {
|
||||
println("START TEST " + prefix + name)
|
||||
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(" ")
|
||||
println(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 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(0))
|
||||
// val testId = Some(mutable.HashSet(4))
|
||||
// val testId = Some(mutable.HashSet(3,4,9,11,13,16,18,19,20,21))
|
||||
// val testId = Some(mutable.HashSet(24, 43, 49))
|
||||
// val testId = Some(mutable.HashSet(11))
|
||||
// val seed = -8309068850561113754l
|
||||
|
||||
|
||||
|
@ -655,31 +645,4 @@ class TestIndividualFeatures extends FunSuite {
|
|||
doTest(positions," random_" + i + "_", testSeed, universe)
|
||||
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
|
||||
*/
|
||||
}
|
Loading…
Reference in New Issue