aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTim Newsome <tim@sifive.com>2016-03-19 13:33:58 -0700
committerTim Newsome <tim@sifive.com>2016-05-23 12:12:10 -0700
commitd1d8863086c57f04236418f21ef8a7fbfc184b0b (patch)
tree30aaae62cff08366500bd3e29166dd2d8b07a473
parentc57bdaa03373688f76703d20d6df5e0dc4a21eb5 (diff)
downloadspike-d1d8863086c57f04236418f21ef8a7fbfc184b0b.zip
spike-d1d8863086c57f04236418f21ef8a7fbfc184b0b.tar.gz
spike-d1d8863086c57f04236418f21ef8a7fbfc184b0b.tar.bz2
Add --gdb-port
It's necessary to be able to run multiple spikes at once on the same box.
-rw-r--r--riscv/gdbserver.cc44
-rw-r--r--riscv/gdbserver.h2
-rw-r--r--riscv/sim.cc2
-rw-r--r--spike_main/spike.cc14
-rwxr-xr-xtests/gdbserver.py8
-rw-r--r--tests/testlib.py16
6 files changed, 52 insertions, 34 deletions
diff --git a/riscv/gdbserver.cc b/riscv/gdbserver.cc
index 0b36421..0ab1aef 100644
--- a/riscv/gdbserver.cc
+++ b/riscv/gdbserver.cc
@@ -700,30 +700,30 @@ void gdbserver_t::handle_interrupt()
void gdbserver_t::handle()
{
- processor_t *p = sim->get_core(0);
- if (running && p->halted) {
- // The core was running, but now it's halted. Better tell gdb.
- switch (p->halt_reason) {
- case HR_NONE:
- fprintf(stderr, "Internal error. Processor halted without reason.\n");
- abort();
- case HR_STEPPED:
- case HR_INTERRUPT:
- case HR_CMDLINE:
- case HR_ATTACHED:
- // There's no gdb code for this.
- send_packet("T05");
- break;
- case HR_SWBP:
- send_packet("T05swbreak:;");
- break;
+ if (client_fd > 0) {
+ processor_t *p = sim->get_core(0);
+ if (running && p->halted) {
+ // The core was running, but now it's halted. Better tell gdb.
+ switch (p->halt_reason) {
+ case HR_NONE:
+ fprintf(stderr, "Internal error. Processor halted without reason.\n");
+ abort();
+ case HR_STEPPED:
+ case HR_INTERRUPT:
+ case HR_CMDLINE:
+ case HR_ATTACHED:
+ // There's no gdb code for this.
+ send_packet("T05");
+ break;
+ case HR_SWBP:
+ send_packet("T05swbreak:;");
+ break;
+ }
+ send_packet("T00");
+ // TODO: Actually include register values here
+ running = false;
}
- send_packet("T00");
- // TODO: Actually include register values here
- running = false;
- }
- if (client_fd > 0) {
this->read();
this->write();
diff --git a/riscv/gdbserver.h b/riscv/gdbserver.h
index 8a7111f..0c92372 100644
--- a/riscv/gdbserver.h
+++ b/riscv/gdbserver.h
@@ -13,7 +13,7 @@ public:
circular_buffer_t(unsigned int capacity) : data(new T[capacity]),
start(0), end(0), capacity(capacity) {}
circular_buffer_t() : start(0), end(0), capacity(0) {}
- ~circular_buffer_t() { delete data; }
+ ~circular_buffer_t() { delete[] data; }
T *data;
unsigned int start; // Data start, inclusive.
diff --git a/riscv/sim.cc b/riscv/sim.cc
index 19d3d84..ccaa6c8 100644
--- a/riscv/sim.cc
+++ b/riscv/sim.cc
@@ -23,7 +23,7 @@ static void handle_signal(int sig)
sim_t::sim_t(const char* isa, size_t nprocs, size_t mem_mb, bool halted,
const std::vector<std::string>& args)
: htif(new htif_isasim_t(this, args)), procs(std::max(nprocs, size_t(1))),
- current_step(0), current_proc(0), debug(false)
+ current_step(0), current_proc(0), debug(false), gdbserver(NULL)
{
signal(SIGINT, &handle_signal);
// allocate target machine's memory, shrinking it as necessary
diff --git a/spike_main/spike.cc b/spike_main/spike.cc
index 8896bc7..f63f14f 100644
--- a/spike_main/spike.cc
+++ b/spike_main/spike.cc
@@ -31,6 +31,7 @@ static void help()
fprintf(stderr, " --l2=<S>:<W>:<B> B both powers of 2).\n");
fprintf(stderr, " --extension=<name> Specify RoCC Extension\n");
fprintf(stderr, " --extlib=<name> Shared library to load\n");
+ fprintf(stderr, " --gdb-port=<port> Listen on <port> for gdb to connect\n");
fprintf(stderr, " --dump-config-string Print platform configuration string and exit\n");
exit(1);
}
@@ -49,6 +50,7 @@ int main(int argc, char** argv)
std::unique_ptr<cache_sim_t> l2;
std::function<extension_t*()> extension;
const char* isa = DEFAULT_ISA;
+ uint16_t gdb_port = 0;
option_parser_t parser;
parser.help(&help);
@@ -58,6 +60,9 @@ int main(int argc, char** argv)
parser.option('l', 0, 0, [&](const char* s){log = true;});
parser.option('p', 0, 1, [&](const char* s){nprocs = atoi(s);});
parser.option('m', 0, 1, [&](const char* s){mem_mb = atoi(s);});
+ // I wanted to use --halted, but for some reason that doesn't work.
+ parser.option('H', 0, 0, [&](const char* s){halted = true;});
+ parser.option(0, "gdb-port", 1, [&](const char* s){gdb_port = atoi(s);});
parser.option(0, "ic", 1, [&](const char* s){ic.reset(new icache_sim_t(s));});
parser.option(0, "dc", 1, [&](const char* s){dc.reset(new dcache_sim_t(s));});
parser.option(0, "l2", 1, [&](const char* s){l2.reset(cache_sim_t::construct(s, "L2$"));});
@@ -71,14 +76,15 @@ int main(int argc, char** argv)
exit(-1);
}
});
- // I wanted to use --halted, but for some reason that doesn't work.
- parser.option('H', 0, 0, [&](const char* s){halted = true;});
auto argv1 = parser.parse(argv);
std::vector<std::string> htif_args(argv1, (const char*const*)argv + argc);
sim_t s(isa, nprocs, mem_mb, halted, htif_args);
- gdbserver_t gdbserver(9824, &s);
- s.set_gdbserver(&gdbserver);
+ std::unique_ptr<gdbserver_t> gdbserver;
+ if (gdb_port) {
+ gdbserver = std::unique_ptr<gdbserver_t>(new gdbserver_t(gdb_port, &s));
+ s.set_gdbserver(&(*gdbserver));
+ }
if (dump_config_string) {
printf("%s", s.get_config_string());
diff --git a/tests/gdbserver.py b/tests/gdbserver.py
index b5363e6..90ebbe9 100755
--- a/tests/gdbserver.py
+++ b/tests/gdbserver.py
@@ -9,10 +9,10 @@ import time
class DebugTest(unittest.TestCase):
def setUp(self):
self.binary = testlib.compile("debug.c")
- self.spike = testlib.spike(self.binary, halted=False)
+ self.spike, self.port = testlib.spike(self.binary, halted=False)
self.gdb = testlib.Gdb()
self.gdb.command("file %s" % self.binary)
- self.gdb.command("target extended-remote localhost:9824")
+ self.gdb.command("target extended-remote localhost:%d" % self.port)
self.gdb.command("p i=0");
def tearDown(self):
@@ -68,10 +68,10 @@ class DebugTest(unittest.TestCase):
class RegsTest(unittest.TestCase):
def setUp(self):
self.binary = testlib.compile("regs.s")
- self.spike = testlib.spike(self.binary, halted=False)
+ self.spike, self.port = testlib.spike(self.binary, halted=False)
self.gdb = testlib.Gdb()
self.gdb.command("file %s" % self.binary)
- self.gdb.command("target extended-remote localhost:9824")
+ self.gdb.command("target extended-remote localhost:%d" % self.port)
def tearDown(self):
self.spike.kill()
diff --git a/tests/testlib.py b/tests/testlib.py
index 2590f46..2db2549 100644
--- a/tests/testlib.py
+++ b/tests/testlib.py
@@ -25,13 +25,25 @@ def compile(src):
assert result == 0, "%r failed" % cmd
return dst
+def unused_port():
+ # http://stackoverflow.com/questions/2838244/get-open-tcp-port-in-python/2838309#2838309
+ import socket
+ s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+ s.bind(("",0))
+ port = s.getsockname()[1]
+ s.close()
+ return port
+
def spike(binary, halted=False):
+ """Launch spike. Return tuple of its process and the port it's running on."""
cmd = [find_file("spike")]
if halted:
cmd.append('-H')
- cmd += ['pk', binary]
+ port = unused_port()
+ cmd += ['--gdb-port', str(port), 'pk', binary]
logfile = open("spike.log", "w")
- return subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=logfile, stderr=logfile)
+ return subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=logfile,
+ stderr=logfile), port
class Gdb(object):
def __init__(self):