dbc37fc222958dd2c6331b94a0b5a0de0ffc8d6d
[riscv-tests.git] / debug / gdbserver.py
1 #!/usr/bin/env python
2
3 import argparse
4 import binascii
5 import random
6 import sys
7 import tempfile
8 import time
9 import os
10
11 import targets
12 import testlib
13 from testlib import assertEqual, assertNotEqual, assertIn
14 from testlib import assertGreater, assertTrue, assertRegexpMatches, assertLess
15 from testlib import GdbTest
16
17 MSTATUS_UIE = 0x00000001
18 MSTATUS_SIE = 0x00000002
19 MSTATUS_HIE = 0x00000004
20 MSTATUS_MIE = 0x00000008
21 MSTATUS_UPIE = 0x00000010
22 MSTATUS_SPIE = 0x00000020
23 MSTATUS_HPIE = 0x00000040
24 MSTATUS_MPIE = 0x00000080
25 MSTATUS_SPP = 0x00000100
26 MSTATUS_HPP = 0x00000600
27 MSTATUS_MPP = 0x00001800
28 MSTATUS_FS = 0x00006000
29 MSTATUS_XS = 0x00018000
30 MSTATUS_MPRV = 0x00020000
31 MSTATUS_PUM = 0x00040000
32 MSTATUS_MXR = 0x00080000
33 MSTATUS_VM = 0x1F000000
34 MSTATUS32_SD = 0x80000000
35 MSTATUS64_SD = 0x8000000000000000
36
37 # pylint: disable=abstract-method
38
39 def ihex_line(address, record_type, data):
40 assert len(data) < 128
41 line = ":%02X%04X%02X" % (len(data), address, record_type)
42 check = len(data)
43 check += address % 256
44 check += address >> 8
45 check += record_type
46 for char in data:
47 value = ord(char)
48 check += value
49 line += "%02X" % value
50 line += "%02X\n" % ((256-check)%256)
51 return line
52
53 def ihex_parse(line):
54 assert line.startswith(":")
55 line = line[1:]
56 data_len = int(line[:2], 16)
57 address = int(line[2:6], 16)
58 record_type = int(line[6:8], 16)
59 data = ""
60 for i in range(data_len):
61 data += "%c" % int(line[8+2*i:10+2*i], 16)
62 return record_type, address, data
63
64 def readable_binary_string(s):
65 return "".join("%02x" % ord(c) for c in s)
66
67 class SimpleRegisterTest(GdbTest):
68 def check_reg(self, name):
69 a = random.randrange(1<<self.target.xlen)
70 b = random.randrange(1<<self.target.xlen)
71 self.gdb.p("$%s=0x%x" % (name, a))
72 self.gdb.stepi()
73 assertEqual(self.gdb.p("$%s" % name), a)
74 self.gdb.p("$%s=0x%x" % (name, b))
75 self.gdb.stepi()
76 assertEqual(self.gdb.p("$%s" % name), b)
77
78 def setup(self):
79 # 0x13 is nop
80 self.gdb.command("p *((int*) 0x%x)=0x13" % self.target.ram)
81 self.gdb.command("p *((int*) 0x%x)=0x13" % (self.target.ram + 4))
82 self.gdb.command("p *((int*) 0x%x)=0x13" % (self.target.ram + 8))
83 self.gdb.command("p *((int*) 0x%x)=0x13" % (self.target.ram + 12))
84 self.gdb.command("p *((int*) 0x%x)=0x13" % (self.target.ram + 16))
85 self.gdb.p("$pc=0x%x" % self.target.ram)
86
87 class SimpleS0Test(SimpleRegisterTest):
88 def test(self):
89 self.check_reg("s0")
90
91 class SimpleS1Test(SimpleRegisterTest):
92 def test(self):
93 self.check_reg("s1")
94
95 class SimpleT0Test(SimpleRegisterTest):
96 def test(self):
97 self.check_reg("t0")
98
99 class SimpleT1Test(SimpleRegisterTest):
100 def test(self):
101 self.check_reg("t1")
102
103 class SimpleF18Test(SimpleRegisterTest):
104 def check_reg(self, name):
105 self.gdb.p_raw("$mstatus=$mstatus | 0x00006000")
106 self.gdb.stepi()
107 a = random.random()
108 b = random.random()
109 self.gdb.p_raw("$%s=%f" % (name, a))
110 self.gdb.stepi()
111 assertLess(abs(float(self.gdb.p_raw("$%s" % name)) - a), .001)
112 self.gdb.p_raw("$%s=%f" % (name, b))
113 self.gdb.stepi()
114 assertLess(abs(float(self.gdb.p_raw("$%s" % name)) - b), .001)
115
116 def early_applicable(self):
117 return self.target.extensionSupported('F')
118
119 def test(self):
120 self.check_reg("f18")
121
122 class SimpleMemoryTest(GdbTest):
123 def access_test(self, size, data_type):
124 assertEqual(self.gdb.p("sizeof(%s)" % data_type), size)
125 a = 0x86753095555aaaa & ((1<<(size*8))-1)
126 b = 0xdeadbeef12345678 & ((1<<(size*8))-1)
127 self.gdb.p("*((%s*)0x%x) = 0x%x" % (data_type, self.target.ram, a))
128 self.gdb.p("*((%s*)0x%x) = 0x%x" % (data_type, self.target.ram + size,
129 b))
130 assertEqual(self.gdb.p("*((%s*)0x%x)" % (data_type, self.target.ram)),
131 a)
132 assertEqual(self.gdb.p("*((%s*)0x%x)" % (
133 data_type, self.target.ram + size)), b)
134
135 class MemTest8(SimpleMemoryTest):
136 def test(self):
137 self.access_test(1, 'char')
138
139 class MemTest16(SimpleMemoryTest):
140 def test(self):
141 self.access_test(2, 'short')
142
143 class MemTest32(SimpleMemoryTest):
144 def test(self):
145 self.access_test(4, 'int')
146
147 class MemTest64(SimpleMemoryTest):
148 def test(self):
149 self.access_test(8, 'long long')
150
151 # FIXME: I'm not passing back invalid addresses correctly in read/write memory.
152 #class MemTestReadInvalid(SimpleMemoryTest):
153 # def test(self):
154 # # This test relies on 'gdb_report_data_abort enable' being executed in
155 # # the openocd.cfg file.
156 # try:
157 # self.gdb.p("*((int*)0xdeadbeef)")
158 # assert False, "Read should have failed."
159 # except testlib.CannotAccess as e:
160 # assertEqual(e.address, 0xdeadbeef)
161 # self.gdb.p("*((int*)0x%x)" % self.target.ram)
162 #
163 #class MemTestWriteInvalid(SimpleMemoryTest):
164 # def test(self):
165 # # This test relies on 'gdb_report_data_abort enable' being executed in
166 # # the openocd.cfg file.
167 # try:
168 # self.gdb.p("*((int*)0xdeadbeef)=8675309")
169 # assert False, "Write should have failed."
170 # except testlib.CannotAccess as e:
171 # assertEqual(e.address, 0xdeadbeef)
172 # self.gdb.p("*((int*)0x%x)=6874742" % self.target.ram)
173
174 class MemTestBlock(GdbTest):
175 def test(self):
176 length = 1024
177 line_length = 16
178 a = tempfile.NamedTemporaryFile(suffix=".ihex")
179 data = ""
180 for i in range(length / line_length):
181 line_data = "".join(["%c" % random.randrange(256)
182 for _ in range(line_length)])
183 data += line_data
184 a.write(ihex_line(i * line_length, 0, line_data))
185 a.flush()
186
187 self.gdb.command("restore %s 0x%x" % (a.name, self.target.ram))
188 for offset in range(0, length, 19*4) + [length-4]:
189 value = self.gdb.p("*((int*)0x%x)" % (self.target.ram + offset))
190 written = ord(data[offset]) | \
191 (ord(data[offset+1]) << 8) | \
192 (ord(data[offset+2]) << 16) | \
193 (ord(data[offset+3]) << 24)
194 assertEqual(value, written)
195
196 b = tempfile.NamedTemporaryFile(suffix=".ihex")
197 self.gdb.command("dump ihex memory %s 0x%x 0x%x" % (b.name,
198 self.target.ram, self.target.ram + length))
199 for line in b:
200 record_type, address, line_data = ihex_parse(line)
201 if record_type == 0:
202 assertEqual(readable_binary_string(line_data),
203 readable_binary_string(
204 data[address:address+len(line_data)]))
205
206 class InstantHaltTest(GdbTest):
207 def test(self):
208 assertEqual(self.target.reset_vector, self.gdb.p("$pc"))
209 # mcycle and minstret have no defined reset value.
210 mstatus = self.gdb.p("$mstatus")
211 assertEqual(mstatus & (MSTATUS_MIE | MSTATUS_MPRV |
212 MSTATUS_VM), 0)
213
214 class InstantChangePc(GdbTest):
215 def test(self):
216 """Change the PC right as we come out of reset."""
217 # 0x13 is nop
218 self.gdb.command("p *((int*) 0x%x)=0x13" % self.target.ram)
219 self.gdb.command("p *((int*) 0x%x)=0x13" % (self.target.ram + 4))
220 self.gdb.command("p *((int*) 0x%x)=0x13" % (self.target.ram + 8))
221 self.gdb.p("$pc=0x%x" % self.target.ram)
222 self.gdb.stepi()
223 assertEqual((self.target.ram + 4), self.gdb.p("$pc"))
224 self.gdb.stepi()
225 assertEqual((self.target.ram + 8), self.gdb.p("$pc"))
226
227 class DebugTest(GdbTest):
228 # Include malloc so that gdb can make function calls. I suspect this malloc
229 # will silently blow through the memory set aside for it, so be careful.
230 compile_args = ("programs/debug.c", "programs/checksum.c",
231 "programs/tiny-malloc.c", "-DDEFINE_MALLOC", "-DDEFINE_FREE")
232
233 def setup(self):
234 self.gdb.load()
235 self.gdb.b("_exit")
236
237 def exit(self, expected_result=0xc86455d4):
238 output = self.gdb.c()
239 assertIn("Breakpoint", output)
240 assertIn("_exit", output)
241 assertEqual(self.gdb.p("status"), expected_result)
242
243 class DebugCompareSections(DebugTest):
244 def test(self):
245 output = self.gdb.command("compare-sections")
246 matched = 0
247 for line in output.splitlines():
248 if line.startswith("Section"):
249 assert line.endswith("matched.")
250 matched += 1
251 assertGreater(matched, 1)
252
253 class DebugFunctionCall(DebugTest):
254 def test(self):
255 self.gdb.b("main:start")
256 self.gdb.c()
257 assertEqual(self.gdb.p('fib(6)'), 8)
258 assertEqual(self.gdb.p('fib(7)'), 13)
259 self.exit()
260
261 class DebugChangeString(DebugTest):
262 def test(self):
263 text = "This little piggy went to the market."
264 self.gdb.b("main:start")
265 self.gdb.c()
266 self.gdb.p('fox = "%s"' % text)
267 self.exit(0x43b497b8)
268
269 class DebugTurbostep(DebugTest):
270 def test(self):
271 """Single step a bunch of times."""
272 self.gdb.b("main:start")
273 self.gdb.c()
274 self.gdb.command("p i=0")
275 last_pc = None
276 advances = 0
277 jumps = 0
278 for _ in range(100):
279 self.gdb.stepi()
280 pc = self.gdb.p("$pc")
281 assertNotEqual(last_pc, pc)
282 if last_pc and pc > last_pc and pc - last_pc <= 4:
283 advances += 1
284 else:
285 jumps += 1
286 last_pc = pc
287 # Some basic sanity that we're not running between breakpoints or
288 # something.
289 assertGreater(jumps, 10)
290 assertGreater(advances, 50)
291
292 class DebugExit(DebugTest):
293 def test(self):
294 self.exit()
295
296 class DebugSymbols(DebugTest):
297 def test(self):
298 self.gdb.b("main")
299 self.gdb.b("rot13")
300 output = self.gdb.c()
301 assertIn(", main ", output)
302 output = self.gdb.c()
303 assertIn(", rot13 ", output)
304
305 class DebugBreakpoint(DebugTest):
306 def test(self):
307 self.gdb.b("rot13")
308 # The breakpoint should be hit exactly 2 times.
309 for _ in range(2):
310 output = self.gdb.c()
311 self.gdb.p("$pc")
312 assertIn("Breakpoint ", output)
313 assertIn("rot13 ", output)
314 self.exit()
315
316 class Hwbp1(DebugTest):
317 def test(self):
318 if self.target.instruction_hardware_breakpoint_count < 1:
319 return 'not_applicable'
320
321 self.gdb.hbreak("rot13")
322 # The breakpoint should be hit exactly 2 times.
323 for _ in range(2):
324 output = self.gdb.c()
325 self.gdb.p("$pc")
326 assertRegexpMatches(output, r"[bB]reakpoint")
327 assertIn("rot13 ", output)
328 self.exit()
329
330 class Hwbp2(DebugTest):
331 def test(self):
332 if self.target.instruction_hardware_breakpoint_count < 2:
333 return 'not_applicable'
334
335 self.gdb.hbreak("main")
336 self.gdb.hbreak("rot13")
337 # We should hit 3 breakpoints.
338 for expected in ("main", "rot13", "rot13"):
339 output = self.gdb.c()
340 self.gdb.p("$pc")
341 assertRegexpMatches(output, r"[bB]reakpoint")
342 assertIn("%s " % expected, output)
343 self.exit()
344
345 class TooManyHwbp(DebugTest):
346 def run(self):
347 for i in range(30):
348 self.gdb.hbreak("*rot13 + %d" % (i * 4))
349
350 output = self.gdb.c()
351 assertIn("Cannot insert hardware breakpoint", output)
352 # Clean up, otherwise the hardware breakpoints stay set and future
353 # tests may fail.
354 self.gdb.command("D")
355
356 class Registers(DebugTest):
357 def test(self):
358 # Get to a point in the code where some registers have actually been
359 # used.
360 self.gdb.b("rot13")
361 self.gdb.c()
362 self.gdb.c()
363 # Try both forms to test gdb.
364 for cmd in ("info all-registers", "info registers all"):
365 output = self.gdb.command(cmd)
366 for reg in ('zero', 'ra', 'sp', 'gp', 'tp'):
367 assertIn(reg, output)
368
369 #TODO
370 # mcpuid is one of the few registers that should have the high bit set
371 # (for rv64).
372 # Leave this commented out until gdb and spike agree on the encoding of
373 # mcpuid (which is going to be renamed to misa in any case).
374 #assertRegexpMatches(output, ".*mcpuid *0x80")
375
376 #TODO:
377 # The instret register should always be changing.
378 #last_instret = None
379 #for _ in range(5):
380 # instret = self.gdb.p("$instret")
381 # assertNotEqual(instret, last_instret)
382 # last_instret = instret
383 # self.gdb.stepi()
384
385 self.exit()
386
387 class UserInterrupt(DebugTest):
388 def test(self):
389 """Sending gdb ^C while the program is running should cause it to
390 halt."""
391 self.gdb.b("main:start")
392 self.gdb.c()
393 self.gdb.p("i=123")
394 self.gdb.c(wait=False)
395 time.sleep(0.5)
396 output = self.gdb.interrupt()
397 assert "main" in output
398 assertGreater(self.gdb.p("j"), 10)
399 self.gdb.p("i=0")
400 self.exit()
401
402 class StepTest(GdbTest):
403 compile_args = ("programs/step.S", )
404
405 def setup(self):
406 self.gdb.load()
407 self.gdb.b("main")
408 self.gdb.c()
409
410 def test(self):
411 main_address = self.gdb.p("$pc")
412 if self.target.extensionSupported("c"):
413 sequence = (4, 8, 0xc, 0xe, 0x14, 0x18, 0x22, 0x1c, 0x24, 0x24)
414 else:
415 sequence = (4, 8, 0xc, 0x10, 0x18, 0x1c, 0x28, 0x20, 0x2c, 0x2c)
416 for expected in sequence:
417 self.gdb.stepi()
418 pc = self.gdb.p("$pc")
419 assertEqual("%x" % (pc - main_address), "%x" % expected)
420
421 class TriggerTest(GdbTest):
422 compile_args = ("programs/trigger.S", )
423 def setup(self):
424 self.gdb.load()
425 self.gdb.b("_exit")
426 self.gdb.b("main")
427 self.gdb.c()
428
429 def exit(self):
430 output = self.gdb.c()
431 assertIn("Breakpoint", output)
432 assertIn("_exit", output)
433
434 class TriggerExecuteInstant(TriggerTest):
435 """Test an execute breakpoint on the first instruction executed out of
436 debug mode."""
437 def test(self):
438 main_address = self.gdb.p("$pc")
439 self.gdb.command("hbreak *0x%x" % (main_address + 4))
440 self.gdb.c()
441 assertEqual(self.gdb.p("$pc"), main_address+4)
442
443 # FIXME: Triggers aren't quite working yet
444 #class TriggerLoadAddress(TriggerTest):
445 # def test(self):
446 # self.gdb.command("rwatch *((&data)+1)")
447 # output = self.gdb.c()
448 # assertIn("read_loop", output)
449 # assertEqual(self.gdb.p("$a0"),
450 # self.gdb.p("(&data)+1"))
451 # self.exit()
452
453 class TriggerLoadAddressInstant(TriggerTest):
454 """Test a load address breakpoint on the first instruction executed out of
455 debug mode."""
456 def test(self):
457 self.gdb.command("b just_before_read_loop")
458 self.gdb.c()
459 read_loop = self.gdb.p("&read_loop")
460 self.gdb.command("rwatch data")
461 self.gdb.c()
462 # Accept hitting the breakpoint before or after the load instruction.
463 assertIn(self.gdb.p("$pc"), [read_loop, read_loop + 4])
464 assertEqual(self.gdb.p("$a0"), self.gdb.p("&data"))
465
466 # FIXME: Triggers aren't quite working yet
467 #class TriggerStoreAddress(TriggerTest):
468 # def test(self):
469 # self.gdb.command("watch *((&data)+3)")
470 # output = self.gdb.c()
471 # assertIn("write_loop", output)
472 # assertEqual(self.gdb.p("$a0"),
473 # self.gdb.p("(&data)+3"))
474 # self.exit()
475
476 class TriggerStoreAddressInstant(TriggerTest):
477 def test(self):
478 """Test a store address breakpoint on the first instruction executed out
479 of debug mode."""
480 self.gdb.command("b just_before_write_loop")
481 self.gdb.c()
482 write_loop = self.gdb.p("&write_loop")
483 self.gdb.command("watch data")
484 self.gdb.c()
485 # Accept hitting the breakpoint before or after the store instruction.
486 assertIn(self.gdb.p("$pc"), [write_loop, write_loop + 4])
487 assertEqual(self.gdb.p("$a0"), self.gdb.p("&data"))
488
489 class TriggerDmode(TriggerTest):
490 def check_triggers(self, tdata1_lsbs, tdata2):
491 dmode = 1 << (self.target.xlen-5)
492
493 triggers = []
494
495 if self.target.xlen == 32:
496 xlen_type = 'int'
497 elif self.target.xlen == 64:
498 xlen_type = 'long long'
499 else:
500 raise NotImplementedError
501
502 dmode_count = 0
503 i = 0
504 for i in range(16):
505 tdata1 = self.gdb.p("((%s *)&data)[%d]" % (xlen_type, 2*i))
506 if tdata1 == 0:
507 break
508 tdata2 = self.gdb.p("((%s *)&data)[%d]" % (xlen_type, 2*i+1))
509
510 if tdata1 & dmode:
511 dmode_count += 1
512 else:
513 assertEqual(tdata1 & 0xffff, tdata1_lsbs)
514 assertEqual(tdata2, tdata2)
515
516 assertGreater(i, 1)
517 assertEqual(dmode_count, 1)
518
519 return triggers
520
521 def test(self):
522 self.gdb.command("hbreak write_load_trigger")
523 self.gdb.b("clear_triggers")
524 self.gdb.p("$pc=write_store_trigger")
525 output = self.gdb.c()
526 assertIn("write_load_trigger", output)
527 self.check_triggers((1<<6) | (1<<1), 0xdeadbee0)
528 output = self.gdb.c()
529 assertIn("clear_triggers", output)
530 self.check_triggers((1<<6) | (1<<0), 0xfeedac00)
531
532 class RegsTest(GdbTest):
533 compile_args = ("programs/regs.S", )
534 def setup(self):
535 self.gdb.load()
536 self.gdb.b("main")
537 self.gdb.b("handle_trap")
538 self.gdb.c()
539
540 class WriteGprs(RegsTest):
541 def test(self):
542 regs = [("x%d" % n) for n in range(2, 32)]
543
544 self.gdb.p("$pc=write_regs")
545 for i, r in enumerate(regs):
546 self.gdb.p("$%s=%d" % (r, (0xdeadbeef<<i)+17))
547 self.gdb.p("$x1=data")
548 self.gdb.command("b all_done")
549 output = self.gdb.c()
550 assertIn("Breakpoint ", output)
551
552 # Just to get this data in the log.
553 self.gdb.command("x/30gx data")
554 self.gdb.command("info registers")
555 for n in range(len(regs)):
556 assertEqual(self.gdb.x("data+%d" % (8*n), 'g'),
557 ((0xdeadbeef<<n)+17) & ((1<<self.target.xlen)-1))
558
559 class WriteCsrs(RegsTest):
560 def test(self):
561 # As much a test of gdb as of the simulator.
562 self.gdb.p("$mscratch=0")
563 self.gdb.stepi()
564 assertEqual(self.gdb.p("$mscratch"), 0)
565 self.gdb.p("$mscratch=123")
566 self.gdb.stepi()
567 assertEqual(self.gdb.p("$mscratch"), 123)
568
569 self.gdb.p("$pc=write_regs")
570 self.gdb.p("$x1=data")
571 self.gdb.command("b all_done")
572 self.gdb.command("c")
573
574 assertEqual(123, self.gdb.p("$mscratch"))
575 assertEqual(123, self.gdb.p("$x1"))
576 assertEqual(123, self.gdb.p("$csr832"))
577
578 class DownloadTest(GdbTest):
579 def setup(self):
580 # pylint: disable=attribute-defined-outside-init
581 length = min(2**20, self.target.ram_size - 2048)
582 self.download_c = tempfile.NamedTemporaryFile(prefix="download_",
583 suffix=".c", delete=False)
584 self.download_c.write("#include <stdint.h>\n")
585 self.download_c.write(
586 "unsigned int crc32a(uint8_t *message, unsigned int size);\n")
587 self.download_c.write("uint32_t length = %d;\n" % length)
588 self.download_c.write("uint8_t d[%d] = {\n" % length)
589 self.crc = 0
590 assert length % 16 == 0
591 for i in range(length / 16):
592 self.download_c.write(" /* 0x%04x */ " % (i * 16))
593 for _ in range(16):
594 value = random.randrange(1<<8)
595 self.download_c.write("0x%02x, " % value)
596 self.crc = binascii.crc32("%c" % value, self.crc)
597 self.download_c.write("\n")
598 self.download_c.write("};\n")
599 self.download_c.write("uint8_t *data = &d[0];\n")
600 self.download_c.write(
601 "uint32_t main() { return crc32a(data, length); }\n")
602 self.download_c.flush()
603
604 if self.crc < 0:
605 self.crc += 2**32
606
607 self.binary = self.target.compile(self.download_c.name,
608 "programs/checksum.c")
609 self.gdb.command("file %s" % self.binary)
610
611 def test(self):
612 self.gdb.load()
613 self.gdb.command("b _exit")
614 self.gdb.c(timeout=60)
615 assertEqual(self.gdb.p("status"), self.crc)
616 os.unlink(self.download_c.name)
617
618 # FIXME: PRIV isn't implemented in the current OpenOCD
619 #class MprvTest(GdbTest):
620 # compile_args = ("programs/mprv.S", )
621 # def setup(self):
622 # self.gdb.load()
623 #
624 # def test(self):
625 # """Test that the debugger can access memory when MPRV is set."""
626 # self.gdb.c(wait=False)
627 # time.sleep(0.5)
628 # self.gdb.interrupt()
629 # output = self.gdb.command("p/x *(int*)(((char*)&data)-0x80000000)")
630 # assertIn("0xbead", output)
631 #
632 #class PrivTest(GdbTest):
633 # compile_args = ("programs/priv.S", )
634 # def setup(self):
635 # # pylint: disable=attribute-defined-outside-init
636 # self.gdb.load()
637 #
638 # misa = self.target.misa
639 # self.supported = set()
640 # if misa & (1<<20):
641 # self.supported.add(0)
642 # if misa & (1<<18):
643 # self.supported.add(1)
644 # if misa & (1<<7):
645 # self.supported.add(2)
646 # self.supported.add(3)
647 #
648 #class PrivRw(PrivTest):
649 # def test(self):
650 # """Test reading/writing priv."""
651 # for privilege in range(4):
652 # self.gdb.p("$priv=%d" % privilege)
653 # self.gdb.stepi()
654 # actual = self.gdb.p("$priv")
655 # assertIn(actual, self.supported)
656 # if privilege in self.supported:
657 # assertEqual(actual, privilege)
658 #
659 #class PrivChange(PrivTest):
660 # def test(self):
661 # """Test that the core's privilege level actually changes."""
662 #
663 # if 0 not in self.supported:
664 # return 'not_applicable'
665 #
666 # self.gdb.b("main")
667 # self.gdb.c()
668 #
669 # # Machine mode
670 # self.gdb.p("$priv=3")
671 # main_address = self.gdb.p("$pc")
672 # self.gdb.stepi()
673 # assertEqual("%x" % self.gdb.p("$pc"), "%x" % (main_address+4))
674 #
675 # # User mode
676 # self.gdb.p("$priv=0")
677 # self.gdb.stepi()
678 # # Should have taken an exception, so be nowhere near main.
679 # pc = self.gdb.p("$pc")
680 # assertTrue(pc < main_address or pc > main_address + 0x100)
681
682 parsed = None
683 def main():
684 parser = argparse.ArgumentParser(
685 description="Test that gdb can talk to a RISC-V target.",
686 epilog="""
687 Example command line from the real world:
688 Run all RegsTest cases against a physical FPGA, with custom openocd command:
689 ./gdbserver.py --freedom-e300 --server_cmd "$HOME/SiFive/openocd/src/openocd -s $HOME/SiFive/openocd/tcl -d" Simple
690 """)
691 targets.add_target_options(parser)
692
693 testlib.add_test_run_options(parser)
694
695 # TODO: remove global
696 global parsed # pylint: disable=global-statement
697 parsed = parser.parse_args()
698
699 target = parsed.target(parsed.server_cmd, parsed.sim_cmd, parsed.isolate)
700 if parsed.xlen:
701 target.xlen = parsed.xlen
702
703 module = sys.modules[__name__]
704
705 return testlib.run_all_tests(module, target, parsed)
706
707 # TROUBLESHOOTING TIPS
708 # If a particular test fails, run just that one test, eg.:
709 # ./gdbserver.py MprvTest.test_mprv
710 # Then inspect gdb.log and spike.log to see what happened in more detail.
711
712 if __name__ == '__main__':
713 sys.exit(main())