import testlib
from testlib import assertEqual, assertNotEqual, assertIn, assertNotIn
from testlib import assertGreater, assertRegexpMatches, assertLess
-from testlib import GdbTest, GdbSingleHartTest, TestFailed, assertTrue
+from testlib import GdbTest, GdbSingleHartTest, TestFailed
+from testlib import assertTrue
MSTATUS_UIE = 0x00000001
MSTATUS_SIE = 0x00000002
def test(self):
self.check_reg("f18", "fs2")
+class CustomRegisterTest(SimpleRegisterTest):
+ def early_applicable(self):
+ return self.target.implements_custom_test
+
+ def check_custom(self, magic):
+ regs = {k: v for k, v in self.gdb.info_registers("all").iteritems()
+ if k.startswith("custom")}
+ assertEqual(set(regs.keys()),
+ set(("custom1",
+ "custom12345",
+ "custom12346",
+ "custom12347",
+ "custom12348")))
+ for name, value in regs.iteritems():
+ number = int(name[6:])
+ if number % 2:
+ expect = number + magic
+ assertIn(value, (expect, expect + (1<<32)))
+ else:
+ assertIn("Could not fetch register", value)
+
+ def test(self):
+ self.check_custom(0)
+
+ # Now test writing
+ magic = 6667
+ self.gdb.p("$custom12345=%d" % (12345 + magic))
+ self.gdb.stepi()
+
+ self.check_custom(magic)
+
class SimpleNoExistTest(GdbTest):
def test(self):
try:
if self.gdb.one_hart_per_gdb():
return 'not_applicable'
- # Set breakpoint near '_start' label to increase the chances of a situation
- # when all harts hit breakpoint immediately and simultaneously.
+ # Set breakpoint near '_start' label to increase the chances of a
+ # situation when all harts hit breakpoint immediately and
+ # simultaneously.
self.gdb.b("set_trap_handler")
# Check that all harts hit breakpoint one by one.
write_loop = self.gdb.p("&write_loop")
data = self.gdb.p("&data")
self.gdb.command("watch *0x%x" % data)
- self.gdb.c()
+ output = self.gdb.c()
+ if "_exit (status=0)" in output:
+ # We ran to _exit. It looks as if we didn't hit the trigger at all.
+ # However this can be "correct" behavior. gdb's definition of
+ # "watch" is to run until the value in memory changes. To do this
+ # it reads the memory value when the trigger is set, and then when
+ # the halt happens. Because our triggers can fire just before the
+ # write happens, when gdb does this check the memory hasn't
+ # changed. So it silently resumes running.
+ # https://github.com/riscv/riscv-openocd/issues/295 tracks this
+ # problem. Until it's fixed, we're going to allow running to _exit.
+ return
+
# Accept hitting the breakpoint before or after the store instruction.
assertIn(self.gdb.p("$pc"), [write_loop, write_loop + 4])
assertEqual(self.gdb.p("$a0"), self.gdb.p("&data"))
self.supported.add(2)
self.supported.add(3)
-class PrivRw(PrivTest):
- def test(self):
- """Test reading/writing priv."""
# Disable physical memory protection by allowing U mode access to all
# memory.
try:
# SATP only exists if you have S mode.
pass
+class PrivRw(PrivTest):
+ def test(self):
+ """Test reading/writing priv."""
# Leave the PC at _start, where the first 4 instructions should be
# legal in any mode.
for privilege in range(4):