diff --git a/src/main/scala/vexriscv/plugin/CsrPlugin.scala b/src/main/scala/vexriscv/plugin/CsrPlugin.scala index 5f81f6f..4030ab7 100644 --- a/src/main/scala/vexriscv/plugin/CsrPlugin.scala +++ b/src/main/scala/vexriscv/plugin/CsrPlugin.scala @@ -68,6 +68,7 @@ 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) @@ -729,32 +730,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 +769,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 +779,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 } diff --git a/src/test/cpp/regression/main.cpp b/src/test/cpp/regression/main.cpp index 6f50a1c..2730c46 100644 --- a/src/test/cpp/regression/main.cpp +++ b/src/test/cpp/regression/main.cpp @@ -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