diff --git a/model/riscv_sys_control.sail b/model/riscv_sys_control.sail index f8ec00ac8..da04278b7 100644 --- a/model/riscv_sys_control.sail +++ b/model/riscv_sys_control.sail @@ -277,14 +277,16 @@ function dispatchInterrupt(priv : Privilege) -> option((InterruptType, Privilege /* If we don't have different privilege levels, we don't need to check delegation. * Absence of U-mode implies absence of S-mode. */ - if not(extensionEnabled(Ext_U)) | (not(extensionEnabled(Ext_S)) & not(extensionEnabled(Ext_N))) then { - assert(priv == Machine, "invalid current privilege"); - let enabled_pending = mip.bits & mie.bits; - match findPendingInterrupt(enabled_pending) { - Some(i) => let r = (i, Machine) in Some(r), - None() => None() - } - } else { + let multipleModesSupported = extensionEnabled(Ext_U); + if not(multipleModesSupported) then { + assert(priv == Machine, "invalid current privilege") + }; + /* Even with U-mode, we don't need to check delegation when M-mode is the only + one that can take interrupts, i.e. when we don't have S-mode and don't have + the N extension + */ + let delegationPossible = extensionEnabled(Ext_S) | extensionEnabled(Ext_N); + if multipleModesSupported & delegationPossible then { match getPendingSet(priv) { None() => None(), Some(ip, p) => match findPendingInterrupt(ip) { @@ -292,6 +294,12 @@ function dispatchInterrupt(priv : Privilege) -> option((InterruptType, Privilege Some(i) => let r = (i, p) in Some(r) } } + } else { + let enabled_pending = mip.bits & mie.bits; + match findPendingInterrupt(enabled_pending) { + Some(i) => let r = (i, Machine) in Some(r), + None() => None() + } } }