308bf2157619ceb09f33363a1acbf2ecbe9feb7d
9 # Note that gdb comes with its own testsuite. I was unable to figure out how to
10 # run that testsuite against the spike simulator.
13 for directory
in (os
.getcwd(), os
.path
.dirname(__file__
)):
14 fullpath
= os
.path
.join(directory
, path
)
15 if os
.path
.exists(fullpath
):
19 def compile(args
, xlen
=32): # pylint: disable=redefined-builtin
20 cc
= os
.path
.expandvars("$RISCV/bin/riscv%d-unknown-elf-gcc" % xlen
)
23 found
= find_file(arg
)
29 result
= os
.system(cmd
)
30 assert result
== 0, "%r failed" % cmd
33 # http://stackoverflow.com/questions/2838244/get-open-tcp-port-in-python/2838309#2838309
35 s
= socket
.socket(socket
.AF_INET
, socket
.SOCK_STREAM
)
37 port
= s
.getsockname()[1]
44 def __init__(self
, cmd
, binary
=None, halted
=False, with_gdb
=True,
45 timeout
=None, xlen
=64):
46 """Launch spike. Return tuple of its process and the port it's running
49 cmd
= shlex
.split(cmd
)
53 cmd
+= ["--isa", "RV32"]
56 cmd
= ["timeout", str(timeout
)] + cmd
61 self
.port
= unused_port()
62 cmd
+= ['--gdb-port', str(self
.port
)]
67 logfile
= open(self
.logname
, "w")
68 logfile
.write("+ %s\n" % " ".join(cmd
))
70 self
.process
= subprocess
.Popen(cmd
, stdin
=subprocess
.PIPE
,
71 stdout
=logfile
, stderr
=logfile
)
80 def wait(self
, *args
, **kwargs
):
81 return self
.process
.wait(*args
, **kwargs
)
84 def __init__(self
, simv
=None, debug
=False):
86 cmd
= shlex
.split(simv
)
89 cmd
+= ["+jtag_vpi_enable"]
91 cmd
[0] = cmd
[0] + "-debug"
92 cmd
+= ["+vcdplusfile=output/gdbserver.vpd"]
93 logfile
= open("simv.log", "w")
94 logfile
.write("+ %s\n" % " ".join(cmd
))
96 listenfile
= open("simv.log", "r")
98 self
.process
= subprocess
.Popen(cmd
, stdin
=subprocess
.PIPE
,
99 stdout
=logfile
, stderr
=logfile
)
102 line
= listenfile
.readline()
105 match
= re
.match(r
"^Listening on port (\d+)$", line
)
108 self
.port
= int(match
.group(1))
109 print "Using port %d for JTAG VPI" % self
.port
118 class Openocd(object):
119 logname
= "openocd.log"
121 def __init__(self
, cmd
=None, config
=None, debug
=False, otherProcess
=None):
123 # keep handles to other processes -- don't let them be
124 # garbage collected yet.
126 self
.otherProcess
= otherProcess
128 cmd
= shlex
.split(cmd
)
132 cmd
+= ["-f", find_file(config
)]
137 self
.port
= unused_port()
138 print "Using port %d for gdb server" % self
.port
139 # This command needs to come before any config scripts on the command
140 # line, since they are executed in order.
141 cmd
[1:1] = ["--command", "gdb_port %d" % self
.port
]
143 env
= os
.environ
.copy()
144 env
['JTAG_VPI_PORT'] = str(otherProcess
.port
)
146 logfile
= open(Openocd
.logname
, "w")
147 logfile
.write("+ %s\n" % " ".join(cmd
))
149 self
.process
= subprocess
.Popen(cmd
, stdin
=subprocess
.PIPE
,
150 stdout
=logfile
, stderr
=logfile
, env
=env
)
152 # Wait for OpenOCD to have made it through riscv_examine(). When using
153 # OpenOCD to communicate with a simulator this may take a long time,
154 # and gdb will time out when trying to connect if we attempt too early.
158 log
= open(Openocd
.logname
).read()
159 if "Examined RISCV core" in log
:
161 if not self
.process
.poll() is None:
162 raise Exception("OpenOCD exited before completing riscv_examine()")
163 if not messaged
and time
.time() - start
> 1:
165 print "Waiting for OpenOCD to examine RISCV core..."
174 class CannotAccess(Exception):
175 def __init__(self
, address
):
176 Exception.__init
__(self
)
177 self
.address
= address
181 cmd
=os
.path
.expandvars("$RISCV/bin/riscv64-unknown-elf-gdb")):
182 self
.child
= pexpect
.spawn(cmd
)
183 self
.child
.logfile
= open("gdb.log", "w")
184 self
.child
.logfile
.write("+ %s\n" % cmd
)
186 self
.command("set confirm off")
187 self
.command("set width 0")
188 self
.command("set height 0")
190 self
.command("set print entry-values no")
193 """Wait for prompt."""
194 self
.child
.expect(r
"\(gdb\)")
196 def command(self
, command
, timeout
=-1):
197 self
.child
.sendline(command
)
198 self
.child
.expect("\n", timeout
=timeout
)
199 self
.child
.expect(r
"\(gdb\)", timeout
=timeout
)
200 return self
.child
.before
.strip()
202 def c(self
, wait
=True):
204 output
= self
.command("c")
205 assert "Continuing" in output
208 self
.child
.sendline("c")
209 self
.child
.expect("Continuing")
212 self
.child
.send("\003")
213 self
.child
.expect(r
"\(gdb\)", timeout
=60)
214 return self
.child
.before
.strip()
216 def x(self
, address
, size
='w'):
217 output
= self
.command("x/%s %s" % (size
, address
))
218 value
= int(output
.split(':')[1].strip(), 0)
222 output
= self
.command("p/x %s" % obj
)
223 m
= re
.search("Cannot access memory at address (0x[0-9a-f]+)", output
)
225 raise CannotAccess(int(m
.group(1), 0))
226 value
= int(output
.split('=')[-1].strip(), 0)
229 def p_string(self
, obj
):
230 output
= self
.command("p %s" % obj
)
231 value
= shlex
.split(output
.split('=')[-1].strip())[1]
235 output
= self
.command("stepi")
239 output
= self
.command("load", timeout
=60)
240 assert "failed" not in output
241 assert "Transfer rate" in output
243 def b(self
, location
):
244 output
= self
.command("b %s" % location
)
245 assert "not defined" not in output
246 assert "Breakpoint" in output
249 def hbreak(self
, location
):
250 output
= self
.command("hbreak %s" % location
)
251 assert "not defined" not in output
252 assert "Hardware assisted breakpoint" in output