self.gdb.p("i=0")
self.exit()
+class InterruptTest(GdbSingleHartTest):
+ compile_args = ("programs/interrupt.c",)
+
+ def early_applicable(self):
+ return self.target.supports_clint_mtime
+
+ def setup(self):
+ self.gdb.load()
+
+ def test(self):
+ self.gdb.b("main")
+ output = self.gdb.c()
+ assertIn(" main ", output)
+ self.gdb.b("trap_entry")
+ output = self.gdb.c()
+ assertIn(" trap_entry ", output)
+ assertEqual(self.gdb.p("$mip") & 0x80, 0x80)
+ assertEqual(self.gdb.p("interrupt_count"), 0)
+ # You'd expect local to still be 0, but it looks like spike doesn't
+ # jump to the interrupt handler immediately after the write to
+ # mtimecmp.
+ assertLess(self.gdb.p("local"), 1000)
+ self.gdb.command("delete breakpoints")
+ for _ in range(10):
+ self.gdb.c(wait=False)
+ time.sleep(2)
+ self.gdb.interrupt()
+ interrupt_count = self.gdb.p("interrupt_count")
+ local = self.gdb.p("local")
+ if interrupt_count > 1000 and \
+ local > 1000:
+ return
+
+ assertGreater(interrupt_count, 1000)
+ assertGreater(local, 1000)
+
+ def postMortem(self):
+ GdbSingleHartTest.postMortem(self)
+ self.gdb.p("*((long long*) 0x200bff8)")
+ self.gdb.p("*((long long*) 0x2004000)")
+ self.gdb.p("interrupt_count")
+ self.gdb.p("local")
+
class MulticoreRegTest(GdbTest):
compile_args = ("programs/infinite_loop.S", "-DMULTICORE")
set_csr(mstatus, MSTATUS_MIE);
}
-void handle_trap(unsigned int mcause, unsigned int mepc, unsigned int sp)
+void handle_trap(unsigned int mcause, void *mepc, void *sp)
{
unsigned hartid = csr_read(mhartid);
if (trap_handler[hartid]) {
--- /dev/null
+#include "init.h"
+#include "encoding.h"
+
+static volatile unsigned interrupt_count;
+static volatile unsigned local;
+
+static unsigned delta = 0x100;
+void *increment_count(unsigned hartid, unsigned mcause, void *mepc, void *sp)
+{
+ interrupt_count++;
+ // There is no guarantee that the interrupt is cleared immediately when
+ // MTIMECMP is written, so stick around here until that happens.
+ while (csr_read(mip) & MIP_MTIP) {
+ MTIMECMP[hartid] = MTIME + delta;
+ }
+ return mepc;
+}
+
+int main()
+{
+ interrupt_count = 0;
+ local = 0;
+ unsigned hartid = csr_read(mhartid);
+
+ set_trap_handler(increment_count);
+ MTIMECMP[hartid] = MTIME - 1;
+ enable_timer_interrupts();
+
+ while (1) {
+ local++;
+ }
+}