Create TriggerTest.
authorTim Newsome <tim@sifive.com>
Thu, 1 Sep 2016 17:07:54 +0000 (10:07 -0700)
committerTim Newsome <tim@sifive.com>
Thu, 1 Sep 2016 23:35:15 +0000 (16:35 -0700)
debug/gdbserver.py
debug/programs/trigger.S [new file with mode: 0644]

index ca117622921863b35a84c1f4b5fed3c78299085e..2aa589a079401b2a32373b585991155f62e18fc0 100755 (executable)
@@ -318,27 +318,6 @@ class DebugTest(DeleteServer):
         # tests may fail.
         self.gdb.command("D")
 
         # tests may fail.
         self.gdb.command("D")
 
-    def test_address_trigger(self):
-        self.gdb.b("main:start")
-        self.gdb.c()
-        self.gdb.command("watch fox[13]");
-
-        output = self.gdb.c()
-        self.assertNotIn("Could not insert", output)
-        self.assertIn("rot13", output)
-        output = self.gdb.command("up")
-        self.assertIn("in main", output)
-        self.assertEqual(self.gdb.p_string("fox"),
-                "Gur dhvpx oebjn fox jumps of the lazy dog.")
-
-        output = self.gdb.c()
-        self.assertNotIn("Could not insert", output)
-        self.assertIn("rot13", output)
-        output = self.gdb.command("up")
-        self.assertIn("in main", output)
-        self.assertEqual(self.gdb.p_string("fox"),
-                "The quick browa sbk whzcf bs gur ynml qbt.")
-
     def test_registers(self):
         # Get to a point in the code where some registers have actually been
         # used.
     def test_registers(self):
         # Get to a point in the code where some registers have actually been
         # used.
@@ -399,6 +378,45 @@ class StepTest(DeleteServer):
             pc = self.gdb.p("$pc")
             self.assertEqual("%x" % pc, "%x" % (expected + main))
 
             pc = self.gdb.p("$pc")
             self.assertEqual("%x" % pc, "%x" % (expected + main))
 
+class TriggerTest(DeleteServer):
+    def setUp(self):
+        self.binary = target.compile("programs/trigger.S")
+        self.server = target.server()
+        self.gdb = gdb(target, self.server.port, self.binary)
+        self.gdb.load()
+        self.gdb.b("_exit")
+        self.gdb.b("main")
+        self.gdb.c()
+
+    def exit(self):
+        output = self.gdb.c()
+        self.assertIn("Breakpoint", output)
+        self.assertIn("_exit", output)
+
+    def test_load_address(self):
+        self.gdb.command("rwatch *((&data)+1)");
+        output = self.gdb.c()
+        self.assertIn("read_loop", output)
+        self.assertEqual(self.gdb.p("$a0"),
+                self.gdb.p("(&data)+1"))
+        self.exit()
+
+    def test_store_address(self):
+        self.gdb.command("watch *((&data)+3)");
+        output = self.gdb.c()
+        self.assertIn("write_loop", output)
+        self.assertEqual(self.gdb.p("$a0"),
+                self.gdb.p("(&data)+3"))
+        self.exit()
+
+    def test_dmode(self):
+        self.gdb.command("hbreak handle_trap")
+        self.gdb.p("$pc=write_valid")
+        output = self.gdb.c()
+        self.assertIn("handle_trap", output)
+        self.assertIn("mcause=2", output)
+        self.assertIn("mepc=%d" % self.gdb.p("&write_invalid_illegal"), output)
+
 class RegsTest(DeleteServer):
     def setUp(self):
         self.binary = target.compile("programs/regs.S")
 class RegsTest(DeleteServer):
     def setUp(self):
         self.binary = target.compile("programs/regs.S")
diff --git a/debug/programs/trigger.S b/debug/programs/trigger.S
new file mode 100644 (file)
index 0000000..e5dfa67
--- /dev/null
@@ -0,0 +1,97 @@
+#include "../../env/encoding.h"
+
+#undef MCONTROL_TYPE
+#undef MCONTROL_DMODE
+#ifdef __riscv64
+# define MCONTROL_TYPE    (0xfU<<((64)-4))
+# define MCONTROL_DMODE   (1U<<((64)-5))
+#else
+# define MCONTROL_TYPE    (0xfU<<((32)-4))
+# define MCONTROL_DMODE   (1U<<((32)-5))
+#endif
+
+        .global         main
+
+        .section        .text
+main:
+
+        la      a0, data
+        li      t0, 0
+        li      t2, 16
+read_loop:
+        lw      t1, 0(a0)
+        addi    a0, a0, 4
+        addi    t0, t0, 1
+        blt     t0, t2, read_loop
+
+        la      a0, data
+        li      t0, 0
+write_loop:
+        addi    t0, t0, 1
+        sw      t0, 0(a0)
+        addi    a0, a0, 4
+        blt     t0, t2, write_loop
+
+        j       main_exit
+
+write_valid:
+        li      t0, 0
+        li      t2, MCONTROL_DMODE
+        li      t3, MCONTROL_TYPE
+write_valid_loop:
+        csrw    CSR_TSELECT, t0
+        csrr    t1, CSR_TSELECT
+        bne     t0, t1, main_exit
+        addi    t0, t0, 1
+        csrr    t1, CSR_TDATA1
+        and     t4, t1, t3
+        beqz    t4, main_error  # type is 0
+        and     t1, t1, t2
+        bnez    t1, write_valid_loop
+        # Found an entry with dmode=0
+        csrw    CSR_TDATA1, zero        # this should succeed
+
+write_invalid:
+        li      t0, 0
+        li      t2, MCONTROL_DMODE
+        li      t3, MCONTROL_TYPE
+write_invalid_loop:
+        csrw    CSR_TSELECT, t0
+        csrr    t1, CSR_TSELECT
+        bne     t0, t1, main_exit
+        addi    t0, t0, 1
+        csrr    t1, CSR_TDATA1
+        and     t4, t1, t3
+        beqz    t4, main_error  # type is 0
+        and     t1, t1, t2
+        beqz    t1, write_invalid_loop
+        # Found an entry with dmode=1
+write_invalid_illegal:
+        csrw    CSR_TDATA1, zero        # this should fail
+
+
+main_exit:
+        li      a0, 0
+        j       _exit
+
+main_error:
+        li      a0, 1
+        j       _exit
+
+        .data
+data:   .word   0x40
+        .word   0x41
+        .word   0x42
+        .word   0x43
+        .word   0x44
+        .word   0x45
+        .word   0x46
+        .word   0x47
+        .word   0x48
+        .word   0x49
+        .word   0x4a
+        .word   0x4b
+        .word   0x4c
+        .word   0x4d
+        .word   0x4e
+        .word   0x4f