summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPrashanth Mundkur2018-04-18 16:58:21 -0700
committerPrashanth Mundkur2018-04-18 16:58:21 -0700
commitae7fbb4ce5f5e52ec39ca17b152db63bbd0cfc69 (patch)
tree29821a7fc0c8113f8efacfc4696e8644cf34bb7a
parent2bf408e37eabfa0dfb7cee5165a4208de5846b9e (diff)
Add interrupt prioritization and delegation.
-rw-r--r--riscv/riscv_sys.sail44
1 files changed, 43 insertions, 1 deletions
diff --git a/riscv/riscv_sys.sail b/riscv/riscv_sys.sail
index 37c487cf..fc58d72e 100644
--- a/riscv/riscv_sys.sail
+++ b/riscv/riscv_sys.sail
@@ -461,7 +461,7 @@ function check_CSR(csr : csreg, p : Privilege, isWrite : bool) -> bool =
& check_CSR_access(csrAccess(csr), csrPriv(csr), p, isWrite)
& check_TVM_SATP(csr, p)
-/* exception delegation: given an exception and the privilege at which
+/* Exception delegation: given an exception and the privilege at which
* it occured, returns the privilege at which it should be handled.
*/
function exception_delegatee(e : ExceptionType, p : Privilege) -> Privilege = {
@@ -477,6 +477,48 @@ function exception_delegatee(e : ExceptionType, p : Privilege) -> Privilege = {
then p else deleg
}
+/* Interrupts are prioritized in privilege order, and for each
+ * privilege, in the order: external, software, timers.
+ */
+function findPendingInterrupt(ip : xlenbits) -> option(InterruptType) = {
+ let ip = Mk_Minterrupts(ip);
+ if ip.MEI() == true then Some(I_M_External)
+ else if ip.MSI() == true then Some(I_M_Software)
+ else if ip.MTI() == true then Some(I_M_Timer)
+ else if ip.SEI() == true then Some(I_S_External)
+ else if ip.SSI() == true then Some(I_S_Software)
+ else if ip.STI() == true then Some(I_S_Timer)
+ else if ip.UEI() == true then Some(I_U_External)
+ else if ip.USI() == true then Some(I_U_Software)
+ else if ip.UTI() == true then Some(I_U_Timer)
+ else None()
+}
+
+/* Examines current M-mode interrupt state and returns an interrupt to be
+ * handled, and the privilege it should be handled at.
+ * For now, it assumes 'S' and no 'N' extension, which is the common case.
+ */
+function curInterrupt(pend : Minterrupts, enbl : Minterrupts, delg : Minterrupts)
+ -> option((InterruptType, Privilege)) = {
+ let en_mip : xlenbits = pend.bits() & enbl.bits();
+ if en_mip == EXTZ(0b0) then None() /* fast path */
+ else {
+ let eff_mip = en_mip & (~ (delg.bits())); /* retained at M-mode */
+ let eff_sip = en_mip & delg.bits(); /* delegated to S-mode */
+ if (mstatus.MIE() == true) & (eff_mip != EXTZ(0b0))
+ then match findPendingInterrupt(eff_mip) {
+ Some(i) => let r = (i, Machine) in Some(r),
+ None() => None()
+ }
+ else if (mstatus.SIE() == true) & (eff_sip != EXTZ(0b0))
+ then match findPendingInterrupt(eff_sip) {
+ Some(i) => let r = (i, Supervisor) in Some(r),
+ None() => None()
+ }
+ else None()
+ }
+}
+
/* instruction control flow */
struct sync_exception = {