aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Waterman <aswaterman@gmail.com>2017-11-20 11:58:14 -0800
committerGitHub <noreply@github.com>2017-11-20 11:58:14 -0800
commitd7ceeabbe6bb2bfc153c6b8d9a1db98f0c975347 (patch)
treee04ca4b6688723ddbe5d850803202550b8f1420b
parent86426a333608827faf6cb712ed06cf10ff3f73cd (diff)
downloadspike-d7ceeabbe6bb2bfc153c6b8d9a1db98f0c975347.zip
spike-d7ceeabbe6bb2bfc153c6b8d9a1db98f0c975347.tar.gz
spike-d7ceeabbe6bb2bfc153c6b8d9a1db98f0c975347.tar.bz2
Implement priv-1.11 interrupt-priority scheme (#161)
Closes #159. https://github.com/riscv/riscv-isa-manual/commit/a62e76cb16eb508199f74632eb8bf263739f25a3
-rw-r--r--riscv/processor.cc19
1 files changed, 18 insertions, 1 deletions
diff --git a/riscv/processor.cc b/riscv/processor.cc
index 2dd2749..722ca45 100644
--- a/riscv/processor.cc
+++ b/riscv/processor.cc
@@ -173,11 +173,28 @@ void processor_t::take_interrupt(reg_t pending_interrupts)
reg_t sie = get_field(state.mstatus, MSTATUS_SIE);
reg_t s_enabled = state.prv < PRV_S || (state.prv == PRV_S && sie);
+ // M-ints have highest priority; consider S-ints only if no M-ints pending
if (enabled_interrupts == 0)
enabled_interrupts = pending_interrupts & state.mideleg & -s_enabled;
- if (state.dcsr.cause == 0 && enabled_interrupts)
+ if (state.dcsr.cause == 0 && enabled_interrupts) {
+ // nonstandard interrupts have highest priority
+ if (enabled_interrupts >> IRQ_M_EXT)
+ enabled_interrupts = enabled_interrupts >> IRQ_M_EXT << IRQ_M_EXT;
+ // external interrupts have next-highest priority
+ else if (enabled_interrupts & (MIP_MEIP | MIP_SEIP))
+ enabled_interrupts = enabled_interrupts & (MIP_MEIP | MIP_SEIP);
+ // software interrupts have next-highest priority
+ else if (enabled_interrupts & (MIP_MSIP | MIP_SSIP))
+ enabled_interrupts = enabled_interrupts & (MIP_MSIP | MIP_SSIP);
+ // timer interrupts have next-highest priority
+ else if (enabled_interrupts & (MIP_MTIP | MIP_STIP))
+ enabled_interrupts = enabled_interrupts & (MIP_MTIP | MIP_STIP);
+ else
+ abort();
+
throw trap_t(((reg_t)1 << (max_xlen-1)) | ctz(enabled_interrupts));
+ }
}
static int xlen_to_uxl(int xlen)