+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")
+
+# Fails nondeterministically.
+#class MulticoreRegTest(GdbTest):
+# compile_args = ("programs/infinite_loop.S", "-DMULTICORE")
+#
+# def early_applicable(self):
+# return len(self.target.harts) > 1
+#
+# def setup(self):
+# self.gdb.load()
+# for hart in self.target.harts:
+# self.gdb.select_hart(hart)
+# self.gdb.p("$pc=_start")
+#
+# def test(self):
+# # Run to main
+# # Hart 0 is the first to be resumed, so we have to set the breakpoint
+# # there. gdb won't actually set the breakpoint until we tell it to
+# # resume.
+# self.gdb.select_hart(self.target.harts[0])
+# self.gdb.b("main")
+# self.gdb.c_all()
+# for hart in self.target.harts:
+# self.gdb.select_hart(hart)
+# assertIn("main", self.gdb.where())
+# self.gdb.select_hart(self.target.harts[0])
+# self.gdb.command("delete breakpoints")
+#
+# # Run through the entire loop.
+# self.gdb.b("main_end")
+# self.gdb.c_all()
+#
+# hart_ids = []
+# for hart in self.target.harts:
+# self.gdb.select_hart(hart)
+# assertIn("main_end", self.gdb.where())
+# # Check register values.
+# hart_id = self.gdb.p("$x1")
+# assertNotIn(hart_id, hart_ids)
+# hart_ids.append(hart_id)
+# for n in range(2, 32):
+# value = self.gdb.p("$x%d" % n)
+# assertEqual(value, hart_ids[-1] + n - 1)
+#
+# # Confirmed that we read different register values for different harts.
+# # Write a new value to x1, and run through the add sequence again.
+#
+# for hart in self.target.harts:
+# self.gdb.select_hart(hart)
+# self.gdb.p("$x1=0x%x" % (hart.index * 0x800))
+# self.gdb.p("$pc=main_post_csrr")
+# self.gdb.c_all()
+# for hart in self.target.harts:
+# self.gdb.select_hart(hart)
+# assertIn("main", self.gdb.where())
+# # Check register values.
+# for n in range(1, 32):
+# value = self.gdb.p("$x%d" % n)
+# assertEqual(value, hart.index * 0x800 + n - 1)
+
+class MulticoreRunHaltStepiTest(GdbTest):
+ compile_args = ("programs/multicore.c", "-DMULTICORE")
+
+ def early_applicable(self):
+ return len(self.target.harts) > 1
+
+ def setup(self):
+ self.gdb.load()
+ for hart in self.target.harts:
+ self.gdb.select_hart(hart)
+ self.gdb.p("$pc=_start")
+
+ def test(self):
+ previous_hart_count = [0 for h in self.target.harts]
+ previous_interrupt_count = [0 for h in self.target.harts]
+ for _ in range(10):
+ self.gdb.c(wait=False)
+ time.sleep(2)
+ self.gdb.interrupt()
+ self.gdb.p("$mie")
+ self.gdb.p("$mip")
+ self.gdb.p("$mstatus")
+ self.gdb.p("$priv")
+ self.gdb.p("buf", fmt="")
+ hart_count = self.gdb.p("hart_count")
+ interrupt_count = self.gdb.p("interrupt_count")
+ for i, h in enumerate(self.target.harts):
+ assertGreater(hart_count[i], previous_hart_count[i])
+ assertGreater(interrupt_count[i], previous_interrupt_count[i])
+ self.gdb.select_hart(h)
+ pc = self.gdb.p("$pc")
+ self.gdb.stepi()
+ stepped_pc = self.gdb.p("$pc")
+ assertNotEqual(pc, stepped_pc)
+
+class StepTest(GdbTest):
+ compile_args = ("programs/step.S", )
+
+ def setup(self):