mprv test now breaks like it's supposed to.
[riscv-isa-sim.git] / tests / gdbserver.py
1 #!/usr/bin/python
2
3 import os
4 import testlib
5 import unittest
6 import tempfile
7 import time
8
9 class InstantHaltTest(unittest.TestCase):
10 def setUp(self):
11 self.binary = testlib.compile("debug.c")
12 self.spike, self.port = testlib.spike(self.binary, halted=True)
13 self.gdb = testlib.Gdb()
14 self.gdb.command("file %s" % self.binary)
15 self.gdb.command("target extended-remote localhost:%d" % self.port)
16
17 def tearDown(self):
18 self.spike.kill()
19 self.spike.wait()
20
21 def test_instant_halt(self):
22 self.assertEqual(0x1000, self.gdb.p("$pc"))
23 # For some reason instret resets to 0.
24 self.assertLess(self.gdb.p("$instret"), 8)
25 self.gdb.command("stepi")
26 self.assertNotEqual(0x1000, self.gdb.p("$pc"))
27
28 def test_change_pc(self):
29 """Change the PC right as we come out of reset."""
30 # 0x13 is nop
31 self.gdb.command("p *((int*) 0x80000000)=0x13")
32 self.gdb.command("p *((int*) 0x80000004)=0x13")
33 self.gdb.command("p *((int*) 0x80000008)=0x13")
34 self.gdb.command("p $pc=0x80000000")
35 self.gdb.command("stepi")
36 self.assertEqual(0x80000004, self.gdb.p("$pc"))
37 self.gdb.command("stepi")
38 self.assertEqual(0x80000008, self.gdb.p("$pc"))
39
40 class DebugTest(unittest.TestCase):
41 def setUp(self):
42 self.binary = testlib.compile("debug.c")
43 self.spike, self.port = testlib.spike(self.binary, halted=False)
44 self.gdb = testlib.Gdb()
45 self.gdb.command("file %s" % self.binary)
46 self.gdb.command("target extended-remote localhost:%d" % self.port)
47
48 def tearDown(self):
49 self.spike.kill()
50 self.spike.wait()
51
52 def test_turbostep(self):
53 """Single step a bunch of times."""
54 self.gdb.command("p i=0");
55 last_pc = None
56 for _ in range(100):
57 self.gdb.command("stepi")
58 pc = self.gdb.command("p $pc")
59 self.assertNotEqual(last_pc, pc)
60 last_pc = pc
61
62 def test_exit(self):
63 self.gdb.command("p i=0");
64 output = self.gdb.command("c")
65 self.assertIn("Continuing", output)
66 self.assertIn("Remote connection closed", output)
67
68 def test_breakpoint(self):
69 self.gdb.command("p i=0");
70 self.gdb.command("b print_row")
71 # The breakpoint should be hit exactly 10 times.
72 for i in range(10):
73 output = self.gdb.command("c")
74 self.assertIn("Continuing", output)
75 self.assertIn("length=%d" % i, output)
76 self.assertIn("Breakpoint 1", output)
77 output = self.gdb.command("c")
78 self.assertIn("Continuing", output)
79 self.assertIn("Remote connection closed", output)
80
81 def test_registers(self):
82 self.gdb.command("p i=0");
83 # Try both forms to test gdb.
84 for cmd in ("info all-registers", "info registers all"):
85 output = self.gdb.command(cmd)
86 self.assertNotIn("Could not", output)
87 for reg in ('zero', 'ra', 'sp', 'gp', 'tp'):
88 self.assertIn(reg, output)
89 # mcpuid is one of the few registers that should have the high bit set
90 # (for rv64).
91 # Leave this commented out until gdb and spike agree on the encoding of
92 # mcpuid (which is going to be renamed to misa in any case).
93 #self.assertRegexpMatches(output, ".*mcpuid *0x80")
94
95 # The instret register should always be changing.
96 last_instret = None
97 for _ in range(5):
98 instret = self.gdb.p("$instret")
99 self.assertNotEqual(instret, last_instret)
100 last_instret = instret
101 self.gdb.command("stepi")
102
103 def test_interrupt(self):
104 """Sending gdb ^C while the program is running should cause it to halt."""
105 self.gdb.c(wait=False)
106 time.sleep(0.1)
107 self.gdb.interrupt()
108 self.gdb.command("p i=123");
109 self.gdb.c(wait=False)
110 time.sleep(0.1)
111 self.gdb.interrupt()
112 self.gdb.command("p i=0");
113 output = self.gdb.c()
114 self.assertIn("Continuing", output)
115 self.assertIn("Remote connection closed", output)
116
117 class RegsTest(unittest.TestCase):
118 def setUp(self):
119 self.binary = testlib.compile("regs.s")
120 self.spike, self.port = testlib.spike(self.binary, halted=False)
121 self.gdb = testlib.Gdb()
122 self.gdb.command("file %s" % self.binary)
123 self.gdb.command("target extended-remote localhost:%d" % self.port)
124
125 def tearDown(self):
126 self.spike.kill()
127 self.spike.wait()
128
129 def test_write_gprs(self):
130 # Note a0 is missing from this list since it's used to hold the
131 # address.
132 regs = ("ra", "sp", "gp", "tp", "t0", "t1", "t2", "fp", "s1",
133 "a1", "a2", "a3", "a4", "a5", "a6", "a7", "s2", "s3", "s4",
134 "s5", "s6", "s7", "s8", "s9", "s10", "s11", "t3", "t4", "t5",
135 "t6")
136
137 self.gdb.command("p $pc=write_regs")
138 for i, r in enumerate(regs):
139 self.gdb.command("p $%s=%d" % (r, (0xdeadbeef<<i)+17))
140 self.gdb.command("p $a0=data")
141 self.gdb.command("b all_done")
142 output = self.gdb.command("c")
143 self.assertIn("Breakpoint 1", output)
144
145 # Just to get this data in the log.
146 self.gdb.command("x/30gx data")
147 self.gdb.command("info registers")
148 for n in range(len(regs)):
149 self.assertEqual(self.gdb.x("data+%d" % (8*n), 'g'),
150 (0xdeadbeef<<n)+17)
151
152 def test_write_csrs(self):
153 # As much a test of gdb as of the simulator.
154 self.gdb.p("$mscratch=0")
155 self.gdb.stepi()
156 self.assertEqual(self.gdb.p("$mscratch"), 0)
157 self.gdb.p("$mscratch=123")
158 self.gdb.stepi()
159 self.assertEqual(self.gdb.p("$mscratch"), 123)
160
161 self.gdb.command("p $fflags=9")
162 self.gdb.command("p $pc=write_regs")
163 self.gdb.command("p $a0=data")
164 self.gdb.command("b all_done")
165 self.gdb.command("c")
166
167 self.assertEqual(9, self.gdb.p("$fflags"))
168 self.assertEqual(9, self.gdb.p("$x1"))
169 self.assertEqual(9, self.gdb.p("$csr1"))
170
171 class MprvTest(unittest.TestCase):
172 def setUp(self):
173 self.binary = testlib.compile("mprv.S", "-T", "standalone.lds",
174 "-nostartfiles")
175 self.spike, self.port = testlib.spike(None, halted=True)
176 self.gdb = testlib.Gdb()
177 self.gdb.command("file %s" % self.binary)
178 self.gdb.command("target extended-remote localhost:%d" % self.port)
179 self.gdb.command("load")
180
181 def tearDown(self):
182 self.spike.kill()
183 self.spike.wait()
184
185 def test_mprv(self):
186 """Test that the debugger can access memory when MPRV is set."""
187 self.gdb.c(wait=False)
188 self.gdb.interrupt()
189 output = self.gdb.command("p/x *(int*)(((char*)&data)-0x80000000)")
190 self.assertIn("0xbead", output)
191
192 if __name__ == '__main__':
193 # TROUBLESHOOTING TIPS
194 # If a particular test fails, run just that one test, eg.:
195 # ./tests/gdbserver.py MprvTest.test_mprv
196 # Then inspect gdb.log and spike.log to see what happened in more detail.
197 unittest.main()