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