Make -H halt the core right out of reset.
[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 class DebugTest(unittest.TestCase):
29 def setUp(self):
30 self.binary = testlib.compile("debug.c")
31 self.spike, self.port = testlib.spike(self.binary, halted=False)
32 self.gdb = testlib.Gdb()
33 self.gdb.command("file %s" % self.binary)
34 self.gdb.command("target extended-remote localhost:%d" % self.port)
35
36 def tearDown(self):
37 self.spike.kill()
38 self.spike.wait()
39
40 def test_turbostep(self):
41 """Single step a bunch of times."""
42 self.gdb.command("p i=0");
43 last_pc = None
44 for _ in range(100):
45 self.gdb.command("stepi")
46 pc = self.gdb.command("p $pc")
47 self.assertNotEqual(last_pc, pc)
48 last_pc = pc
49
50 def test_exit(self):
51 self.gdb.command("p i=0");
52 output = self.gdb.command("c")
53 self.assertIn("Continuing", output)
54 self.assertIn("Remote connection closed", output)
55
56 def test_breakpoint(self):
57 self.gdb.command("p i=0");
58 self.gdb.command("b print_row")
59 # The breakpoint should be hit exactly 10 times.
60 for i in range(10):
61 output = self.gdb.command("c")
62 self.assertIn("Continuing", output)
63 self.assertIn("length=%d" % i, output)
64 self.assertIn("Breakpoint 1", output)
65 output = self.gdb.command("c")
66 self.assertIn("Continuing", output)
67 self.assertIn("Remote connection closed", output)
68
69 def test_registers(self):
70 self.gdb.command("p i=0");
71 # Try both forms to test gdb.
72 for cmd in ("info all-registers", "info registers all"):
73 output = self.gdb.command(cmd)
74 self.assertNotIn("Could not", output)
75 for reg in ('zero', 'ra', 'sp', 'gp', 'tp'):
76 self.assertIn(reg, output)
77 # mcpuid is one of the few registers that should have the high bit set
78 # (for rv64).
79 # Leave this commented out until gdb and spike agree on the encoding of
80 # mcpuid (which is going to be renamed to misa in any case).
81 #self.assertRegexpMatches(output, ".*mcpuid *0x80")
82
83 # The instret register should always be changing.
84 last_instret = None
85 for _ in range(5):
86 instret = self.gdb.p("$instret")
87 self.assertNotEqual(instret, last_instret)
88 last_instret = instret
89 self.gdb.command("stepi")
90
91 def test_interrupt(self):
92 """Sending gdb ^C while the program is running should cause it to halt."""
93 self.gdb.c(wait=False)
94 time.sleep(0.1)
95 self.gdb.interrupt()
96 self.gdb.command("p i=123");
97 self.gdb.c(wait=False)
98 time.sleep(0.1)
99 self.gdb.interrupt()
100 self.gdb.command("p i=0");
101 output = self.gdb.c()
102 self.assertIn("Continuing", output)
103 self.assertIn("Remote connection closed", output)
104
105 class RegsTest(unittest.TestCase):
106 def setUp(self):
107 self.binary = testlib.compile("regs.s")
108 self.spike, self.port = testlib.spike(self.binary, halted=False)
109 self.gdb = testlib.Gdb()
110 self.gdb.command("file %s" % self.binary)
111 self.gdb.command("target extended-remote localhost:%d" % self.port)
112
113 def tearDown(self):
114 self.spike.kill()
115 self.spike.wait()
116
117 def test_write_gprs(self):
118 # Note a0 is missing from this list since it's used to hold the
119 # address.
120 regs = ("ra", "sp", "gp", "tp", "t0", "t1", "t2", "fp", "s1",
121 "a1", "a2", "a3", "a4", "a5", "a6", "a7", "s2", "s3", "s4",
122 "s5", "s6", "s7", "s8", "s9", "s10", "s11", "t3", "t4", "t5",
123 "t6")
124
125 self.gdb.command("p $pc=write_regs")
126 for i, r in enumerate(regs):
127 self.gdb.command("p $%s=%d" % (r, (0xdeadbeef<<i)+17))
128 self.gdb.command("p $a0=data")
129 self.gdb.command("b all_done")
130 output = self.gdb.command("c")
131 self.assertIn("Breakpoint 1", output)
132
133 # Just to get this data in the log.
134 self.gdb.command("x/30gx data")
135 self.gdb.command("info registers")
136 for n in range(len(regs)):
137 self.assertEqual(self.gdb.x("data+%d" % (8*n), 'g'),
138 (0xdeadbeef<<n)+17)
139
140 def test_write_csrs(self):
141 # As much a test of gdb as of the simulator.
142 self.gdb.p("$mscratch=0")
143 self.gdb.stepi()
144 self.assertEqual(self.gdb.p("$mscratch"), 0)
145 self.gdb.p("$mscratch=123")
146 self.gdb.stepi()
147 self.assertEqual(self.gdb.p("$mscratch"), 123)
148
149 self.gdb.command("p $fflags=9")
150 self.gdb.command("p $pc=write_regs")
151 self.gdb.command("p $a0=data")
152 self.gdb.command("b all_done")
153 self.gdb.command("c")
154
155 self.assertEqual(9, self.gdb.p("$fflags"))
156 self.assertEqual(9, self.gdb.p("$x1"))
157 self.assertEqual(9, self.gdb.p("$csr1"))
158
159 #class MprvTest(unittest.TestCase):
160 # def setUp(self):
161 # self.binary = testlib.compile("mprv.S")
162 # self.spike, self.port = testlib.spike(self.binary, halted=False)
163 # self.gdb = testlib.Gdb()
164 # self.gdb.command("file %s" % self.binary)
165 # self.gdb.command("target extended-remote localhost:%d" % self.port)
166 #
167 # def tearDown(self):
168 # self.spike.kill()
169 # self.spike.wait()
170 #
171 # def test_mprv(self):
172 # """Test that the debugger can access memory when MPRV is set."""
173 # output = self.gdb.command("p/x data");
174 # self.assertIn("0xbead", output)
175
176 if __name__ == '__main__':
177 unittest.main()