Improve debug performance.
[riscv-isa-sim.git] / riscv / remote_bitbang.cc
index 7f22cd3223be06176c1229201f90eecfab226b5e..9d0ca90a2b5584e38b5c14501a9e2de813d398aa 100644 (file)
 
 #include "remote_bitbang.h"
 
-/////////// Circular buffer
-
-template <typename T>
-unsigned int circular_buffer_t<T>::size() const
-{
-  if (end >= start)
-    return end - start;
-  else
-    return end + capacity - start;
-}
-
-template <typename T>
-void circular_buffer_t<T>::consume(unsigned int bytes)
-{
-  start = (start + bytes) % capacity;
-}
-
-template <typename T>
-unsigned int circular_buffer_t<T>::contiguous_empty_size() const
-{
-  if (end >= start)
-    if (start == 0)
-      return capacity - end - 1;
-    else
-      return capacity - end;
-  else
-    return start - end - 1;
-}
-
-template <typename T>
-unsigned int circular_buffer_t<T>::contiguous_data_size() const
-{
-  if (end >= start)
-    return end - start;
-  else
-    return capacity - start;
-}
-
-template <typename T>
-void circular_buffer_t<T>::data_added(unsigned int bytes)
-{
-  end += bytes;
-  assert(end <= capacity);
-  if (end == capacity)
-    end = 0;
-}
-
-template <typename T>
-void circular_buffer_t<T>::reset()
-{
-  start = 0;
-  end = 0;
-}
-
-template <typename T>
-void circular_buffer_t<T>::append(const T *src, unsigned int count)
-{
-  unsigned int copy = std::min(count, contiguous_empty_size());
-  memcpy(contiguous_empty(), src, copy * sizeof(T));
-  data_added(copy);
-  count -= copy;
-  if (count > 0) {
-    assert(count < contiguous_empty_size());
-    memcpy(contiguous_empty(), src+copy, count * sizeof(T));
-    data_added(count);
-  }
-}
-
-template <typename T>
-void circular_buffer_t<T>::append(T value)
-{
-  append(&value, 1);
-}
+#if 1
+#  define D(x) x
+#else
+#  define D(x)
+#endif
 
 /////////// remote_bitbang_t
 
-remote_bitbang_t::remote_bitbang_t(uint16_t port, sim_t *sim) :
+remote_bitbang_t::remote_bitbang_t(uint16_t port, jtag_dtm_t *tap) :
+  tap(tap),
   socket_fd(0),
   client_fd(0),
-  recv_buf(64 * 1024),
-  send_buf(64 * 1024)
+  recv_start(0),
+  recv_end(0)
 {
   socket_fd = socket(AF_INET, SOCK_STREAM, 0);
   if (socket_fd == -1) {
@@ -126,6 +59,17 @@ remote_bitbang_t::remote_bitbang_t(uint16_t port, sim_t *sim) :
         strerror(errno), errno);
     abort();
   }
+
+  socklen_t addrlen = sizeof(addr);
+  if (getsockname(socket_fd, (struct sockaddr *) &addr, &addrlen) == -1) {
+    fprintf(stderr, "remote_bitbang getsockname failed: %s (%d)\n",
+        strerror(errno), errno);
+    abort();
+  }
+
+  printf("Listening for remote bitbang connection on port %d.\n",
+      ntohs(addr.sin_port));
+  fflush(stdout);
 }
 
 void remote_bitbang_t::accept()
@@ -144,93 +88,87 @@ void remote_bitbang_t::accept()
   }
 }
 
-void remote_bitbang_t::read()
+void remote_bitbang_t::tick()
 {
-  // Reading from a non-blocking socket still blocks if there is no data
-  // available.
-
-  size_t count = recv_buf.contiguous_empty_size();
-  ssize_t bytes = ::read(client_fd, recv_buf.contiguous_empty(), count);
-  if (bytes == -1) {
-    if (errno == EAGAIN) {
-      // We'll try again the next call.
-    } else {
-      fprintf(stderr, "failed to read on socket: %s (%d)\n", strerror(errno), errno);
-      abort();
-    }
-  } else if (bytes == 0) {
-    // The remote disconnected.
-    client_fd = 0;
-    recv_buf.reset();
-    send_buf.reset();
+  if (client_fd > 0) {
+    execute_commands();
   } else {
-    recv_buf.data_added(bytes);
-    D(fprintf(stderr, "receive buffer: "));
-    for (unsigned i = 0; i < recv_buf.size(); i++) {
-      D(fprintf(stderr, "%c", recv_buf[i]));
-    }
-    D(fprintf(stderr, "\n"));
+    this->accept();
   }
 }
 
-void remote_bitbang_t::write()
+void remote_bitbang_t::execute_commands()
 {
-  if (send_buf.empty())
-    return;
-
-  while (!send_buf.empty()) {
-    unsigned int count = send_buf.contiguous_data_size();
-    assert(count > 0);
-    ssize_t bytes = ::write(client_fd, send_buf.contiguous_data(), count);
-    if (bytes == -1) {
-      fprintf(stderr, "failed to write to socket: %s (%d)\n", strerror(errno), errno);
-      abort();
-    } else if (bytes == 0) {
-      // Client can't take any more data right now.
-      break;
-    } else {
-      D(fprintf(stderr, "wrote %zd bytes: ", bytes));
-      for (int i = 0; i < bytes; i++) {
-        D(fprintf(stderr, "%c", send_buf[i]));
+  static char send_buf[buf_size];
+  unsigned total_processed = 0;
+  bool quit = false;
+  bool in_rti = tap->state() == RUN_TEST_IDLE;
+  bool entered_rti = false;
+  while (1) {
+    if (recv_start < recv_end) {
+      unsigned send_offset = 0;
+      while (recv_start < recv_end) {
+        uint8_t command = recv_buf[recv_start];
+
+        switch (command) {
+          case 'B': /* fprintf(stderr, "*BLINK*\n"); */ break;
+          case 'b': /* fprintf(stderr, "_______\n"); */ break;
+          case 'r': tap->reset(); break;
+          case '0': tap->set_pins(0, 0, 0); break;
+          case '1': tap->set_pins(0, 0, 1); break;
+          case '2': tap->set_pins(0, 1, 0); break;
+          case '3': tap->set_pins(0, 1, 1); break;
+          case '4': tap->set_pins(1, 0, 0); break;
+          case '5': tap->set_pins(1, 0, 1); break;
+          case '6': tap->set_pins(1, 1, 0); break;
+          case '7': tap->set_pins(1, 1, 1); break;
+          case 'R': send_buf[send_offset++] = tap->tdo() ? '1' : '0'; break;
+          case 'Q': quit = true; break;
+          default:
+                    fprintf(stderr, "remote_bitbang got unsupported command '%c'\n",
+                        command);
+        }
+        recv_start++;
+        total_processed++;
+        if (!in_rti && tap->state() == RUN_TEST_IDLE) {
+          entered_rti = true;
+          break;
+        }
+        in_rti = false;
+      }
+      unsigned sent = 0;
+      while (sent < send_offset) {
+        ssize_t bytes = write(client_fd, send_buf + sent, send_offset);
+        if (bytes == -1) {
+          fprintf(stderr, "failed to write to socket: %s (%d)\n", strerror(errno), errno);
+          abort();
+        }
+        sent += bytes;
       }
-      D(fprintf(stderr, "\n"));
-      send_buf.consume(bytes);
     }
-  }
-}
 
-void remote_bitbang_t::tick()
-{
-  if (client_fd > 0) {
-    this->read();
-    process_input();
-    this->write();
-  } else {
-    this->accept();
-  }
-}
+    if (total_processed > buf_size || quit || entered_rti) {
+      // Don't go forever, because that could starve the main simulation.
+      break;
+    }
 
-void remote_bitbang_t::process_input()
-{
-  for (unsigned i = 0; i < recv_buf.size(); i++) {
-    uint8_t command = recv_buf[i];
-
-    switch (command) {
-      case 'B': fprintf(stderr, "*BLINK*\n"); break;
-      case 'b': fprintf(stderr, "_______\n"); break;
-      case 'r': tap.reset(); break;
-      case '0': tap.set_pins(0, 0, 0); break;
-      case '1': tap.set_pins(0, 0, 1); break;
-      case '2': tap.set_pins(0, 1, 0); break;
-      case '3': tap.set_pins(0, 1, 1); break;
-      case '4': tap.set_pins(1, 0, 0); break;
-      case '5': tap.set_pins(1, 0, 1); break;
-      case '6': tap.set_pins(1, 1, 0); break;
-      case '7': tap.set_pins(1, 1, 1); break;
-      case 'R': send_buf.append(tap.tdo() ? '1' : '0'); break;
-      default:
-        fprintf(stderr, "remote_bitbang got unsupported command '%c'\n", command);
+    recv_start = 0;
+    recv_end = read(client_fd, recv_buf, buf_size);
+
+    if (recv_end == -1) {
+      if (errno == EAGAIN) {
+        // We'll try again the next call.
+      } else {
+        fprintf(stderr, "remote_bitbang failed to read on socket: %s (%d)\n",
+            strerror(errno), errno);
+        abort();
+      }
+    }
+    if (recv_end == 0 || quit) {
+      // The remote disconnected.
+      close(client_fd);
+      client_fd = 0;
+      break;
     }
   }
-  recv_buf.reset();
 }