2db25491c433ed3dcdf5678e4009cd9330c6363c
[riscv-isa-sim.git] / tests / testlib.py
1 import os.path
2 import pexpect
3 import subprocess
4 import tempfile
5 import testlib
6 import unittest
7
8 # Note that gdb comes with its own testsuite. I was unable to figure out how to
9 # run that testsuite against the spike simulator.
10
11 def find_file(path):
12 for directory in (os.getcwd(), os.path.dirname(testlib.__file__)):
13 fullpath = os.path.join(directory, path)
14 if os.path.exists(fullpath):
15 return fullpath
16 raise ValueError("Couldn't find %r." % path)
17
18 def compile(src):
19 """Compile a single .c file into a binary."""
20 src = find_file(src)
21 dst = os.path.splitext(src)[0]
22 cc = os.path.expandvars("$RISCV/bin/riscv64-unknown-elf-gcc")
23 cmd = "%s -g -o %s %s" % (cc, dst, src)
24 result = os.system(cmd)
25 assert result == 0, "%r failed" % cmd
26 return dst
27
28 def unused_port():
29 # http://stackoverflow.com/questions/2838244/get-open-tcp-port-in-python/2838309#2838309
30 import socket
31 s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
32 s.bind(("",0))
33 port = s.getsockname()[1]
34 s.close()
35 return port
36
37 def spike(binary, halted=False):
38 """Launch spike. Return tuple of its process and the port it's running on."""
39 cmd = [find_file("spike")]
40 if halted:
41 cmd.append('-H')
42 port = unused_port()
43 cmd += ['--gdb-port', str(port), 'pk', binary]
44 logfile = open("spike.log", "w")
45 return subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=logfile,
46 stderr=logfile), port
47
48 class Gdb(object):
49 def __init__(self):
50 path = os.path.expandvars("$RISCV/bin/riscv64-unknown-elf-gdb")
51 self.child = pexpect.spawn(path)
52 self.child.logfile = file("gdb.log", "w")
53 self.wait()
54 self.command("set width 0")
55 self.command("set height 0")
56
57 def wait(self):
58 """Wait for prompt."""
59 self.child.expect("\(gdb\)")
60
61 def command(self, command):
62 self.child.sendline(command)
63 self.child.expect("\n")
64 self.child.expect("\(gdb\)")
65 return self.child.before.strip()
66
67 def x(self, address, size='w'):
68 output = self.command("x/%s %s" % (size, address))
69 value = int(output.split(':')[1].strip(), 0)
70 return value
71
72 def p(self, obj):
73 output = self.command("p %s" % obj)
74 value = int(output.split('=')[-1].strip())
75 return value
76
77 def stepi(self):
78 return self.command("stepi")