Merge remote-tracking branch 'origin/pipelinedInterrupt'

This commit is contained in:
Charles Papon 2019-06-09 12:29:20 +02:00
commit 0e2d40c37f
2 changed files with 32 additions and 26 deletions

View File

@ -68,6 +68,7 @@ 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)
@ -729,32 +730,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 +769,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 +779,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
} }

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