Add --gdb-port
authorTim Newsome <tim@sifive.com>
Sat, 19 Mar 2016 20:33:58 +0000 (13:33 -0700)
committerTim Newsome <tim@sifive.com>
Mon, 23 May 2016 19:12:10 +0000 (12:12 -0700)
It's necessary to be able to run multiple spikes at once on the same
box.

riscv/gdbserver.cc
riscv/gdbserver.h
riscv/sim.cc
spike_main/spike.cc
tests/gdbserver.py
tests/testlib.py

index 0b36421114d2f68c3ef4c4961882b014de64a637..0ab1aef2855961119a603f834b3771fba5b37157 100644 (file)
@@ -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();
 
index 8a7111fbe6a6f7c9028f4b297886d01db67ce755..0c923722f46a3543bf5b2c89bcf54c8a1b15ea73 100644 (file)
@@ -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.
index 19d3d8471906d9b57a3fbde8dc1d583095fcd231..ccaa6c8e1a5ba02e546002f131a0aafe8ecfcf05 100644 (file)
@@ -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
index 8896bc770c822525b40ef46e83a3903d57d9c9af..f63f14faa1704345770f66c24c3a9b431e2a8d42 100644 (file)
@@ -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());
index b5363e644c340edfcd194b2e3ea75d6b937b3fdd..90ebbe91115fb5e161e20ab672ce0ba4866782c7 100755 (executable)
@@ -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()
index 2590f4643f6a9373ada16d2fe92353f0410471b4..2db25491c433ed3dcdf5678e4009cd9330c6363c 100644 (file)
@@ -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):