Refactor remote bitbang code.
authorTim Newsome <tim@sifive.com>
Tue, 7 Feb 2017 03:17:23 +0000 (19:17 -0800)
committerTim Newsome <tim@sifive.com>
Tue, 7 Feb 2017 03:17:23 +0000 (19:17 -0800)
riscv/jtag_dtm.cc [new file with mode: 0644]
riscv/jtag_dtm.h [new file with mode: 0644]
riscv/remote_bitbang.cc
riscv/remote_bitbang.h
riscv/riscv.mk.in
spike_main/spike.cc

diff --git a/riscv/jtag_dtm.cc b/riscv/jtag_dtm.cc
new file mode 100644 (file)
index 0000000..c099e33
--- /dev/null
@@ -0,0 +1,81 @@
+#include <stdio.h>
+
+#include "jtag_dtm.h"
+
+#if 1
+#  define D(x) x
+#else
+#  define D(x)
+#endif
+
+void jtag_dtm_t::set_pins(bool tck, bool tms, bool tdi) {
+  if (!_tck && tck) {
+    // Positive clock edge.
+
+    switch (state) {
+      case SHIFT_DR:
+        dr >>= 1;
+        dr |= (uint64_t) _tdi << (dr_length-1);
+        break;
+      case SHIFT_IR:
+        ir >>= 1;
+        ir |= _tdi << (ir_length-1);
+        break;
+      default:
+        break;
+    }
+    state = next[state][_tms];
+    switch (state) {
+      case TEST_LOGIC_RESET:
+        ir = idcode_ir;
+        break;
+      case CAPTURE_DR:
+        capture_dr();
+        break;
+      case SHIFT_DR:
+        _tdo = dr & 1;
+        break;
+      case UPDATE_DR:
+        update_dr();
+        break;
+      case CAPTURE_IR:
+        break;
+      case SHIFT_IR:
+        _tdo = ir & 1;
+        break;
+      case UPDATE_IR:
+        break;
+      default:
+        break;
+    }
+  }
+
+  _tck = tck;
+  _tms = tms;
+  _tdi = tdi;
+
+  D(fprintf(stderr, "state=%2d tck=%d tms=%d tdi=%d tdo=%d ir=0x%x dr=0x%lx\n",
+        state, _tck, _tms, _tdi, _tdo, ir, dr));
+}
+
+void jtag_dtm_t::capture_dr()
+{
+  switch (ir) {
+    case idcode_ir:
+      dr = 0xdeadbeef;
+      dr_length = 32;
+      break;
+    case dtmcontrol_ir:
+      dr = dtmcontrol;
+      dr_length = 32;
+    default:
+      D(fprintf(stderr, "Unsupported IR: 0x%x\n", ir));
+      break;
+  }
+  D(fprintf(stderr, "Capture DR; IR=0x%x, DR=0x%lx (%d bits)\n",
+        ir, dr, dr_length));
+}
+
+void jtag_dtm_t::update_dr()
+{
+}
diff --git a/riscv/jtag_dtm.h b/riscv/jtag_dtm.h
new file mode 100644 (file)
index 0000000..e425c8e
--- /dev/null
@@ -0,0 +1,81 @@
+#ifndef JTAG_DTM_H
+#define JTAG_DTM_H
+
+#include <stdint.h>
+
+typedef enum {
+  TEST_LOGIC_RESET,
+  RUN_TEST_IDLE,
+  SELECT_DR_SCAN,
+  CAPTURE_DR,
+  SHIFT_DR,
+  EXIT1_DR,
+  PAUSE_DR,
+  EXIT2_DR,
+  UPDATE_DR,
+  SELECT_IR_SCAN,
+  CAPTURE_IR,
+  SHIFT_IR,
+  EXIT1_IR,
+  PAUSE_IR,
+  EXIT2_IR,
+  UPDATE_IR
+} jtag_state_t;
+
+class jtag_dtm_t
+{
+  static const unsigned idcode_ir = 1;
+  static const unsigned idcode_dr = 0xdeadbeef;
+  static const unsigned dtmcontrol_ir = 0x10;
+
+  public:
+    jtag_dtm_t() :
+      dtmcontrol(
+          (6 << 4) |        // abits
+          1                 // version
+          ),
+      state(TEST_LOGIC_RESET) {}
+
+    void reset() {
+      state = TEST_LOGIC_RESET;
+    }
+
+    void set_pins(bool tck, bool tms, bool tdi);
+
+    bool tdo() const { return _tdo; }
+
+  private:
+    bool _tck, _tms, _tdi, _tdo;
+    uint32_t ir;
+    const unsigned ir_length = 5;
+    uint64_t dr;
+    unsigned dr_length;
+
+    uint32_t dtmcontrol;
+
+    jtag_state_t state;
+
+    void capture_dr();
+    void update_dr();
+
+    const jtag_state_t next[16][2] = {
+      /* TEST_LOGIC_RESET */    { RUN_TEST_IDLE, TEST_LOGIC_RESET },
+      /* RUN_TEST_IDLE */       { RUN_TEST_IDLE, SELECT_DR_SCAN },
+      /* SELECT_DR_SCAN */      { CAPTURE_DR, SELECT_IR_SCAN },
+      /* CAPTURE_DR */          { SHIFT_DR, EXIT1_DR },
+      /* SHIFT_DR */            { SHIFT_DR, EXIT1_DR },
+      /* EXIT1_DR */            { PAUSE_DR, UPDATE_DR },
+      /* PAUSE_DR */            { PAUSE_DR, EXIT2_DR },
+      /* EXIT2_DR */            { SHIFT_DR, UPDATE_DR },
+      /* UPDATE_DR */           { RUN_TEST_IDLE, SELECT_DR_SCAN },
+      /* SELECT_IR_SCAN */      { CAPTURE_IR, TEST_LOGIC_RESET },
+      /* CAPTURE_IR */          { SHIFT_IR, EXIT1_IR },
+      /* SHIFT_IR */            { SHIFT_IR, EXIT1_IR },
+      /* EXIT1_IR */            { PAUSE_IR, UPDATE_IR },
+      /* PAUSE_IR */            { PAUSE_IR, EXIT2_IR },
+      /* EXIT2_IR */            { SHIFT_IR, UPDATE_IR },
+      /* UPDATE_IR */           { RUN_TEST_IDLE, SELECT_DR_SCAN }
+    };
+};
+
+#endif
index 7f22cd3223be06176c1229201f90eecfab226b5e..acfd216f83f801c23107db6854da91df4c7149a6 100644 (file)
 
 #include "remote_bitbang.h"
 
+#if 1
+#  define D(x) x
+#else
+#  define D(x)
+#endif
+
 /////////// Circular buffer
 
 template <typename T>
@@ -87,7 +93,8 @@ void circular_buffer_t<T>::append(T value)
 
 /////////// 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),
@@ -212,22 +219,27 @@ void remote_bitbang_t::tick()
 
 void remote_bitbang_t::process_input()
 {
+  // TODO: get rid of the circular buffers, and just read/write here with
+  // simple local buffers.
+  // Each message is a single character, so there's never any need to keep a
+  // partially transmitted message around.
+
   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;
+      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);
     }
index 5f2a3ea2006225a392ff4a116c312f5f63e620d1..c0aa7e040ff3909a1097b644b20dfb2808366348 100644 (file)
@@ -3,14 +3,7 @@
 
 #include <stdint.h>
 
-#define DEBUG
-#ifdef DEBUG
-#  define D(x) x
-#else
-#  define D(x)
-#endif // DEBUG
-
-class sim_t;
+#include "jtag_dtm.h"
 
 template <typename T>
 class circular_buffer_t
@@ -51,143 +44,18 @@ public:
   void append(T value);
 };
 
-typedef enum {
-  TEST_LOGIC_RESET,
-  RUN_TEST_IDLE,
-  SELECT_DR_SCAN,
-  CAPTURE_DR,
-  SHIFT_DR,
-  EXIT1_DR,
-  PAUSE_DR,
-  EXIT2_DR,
-  UPDATE_DR,
-  SELECT_IR_SCAN,
-  CAPTURE_IR,
-  SHIFT_IR,
-  EXIT1_IR,
-  PAUSE_IR,
-  EXIT2_IR,
-  UPDATE_IR
-} jtag_state_t;
-
-class jtag_tap_t
-{
-  static const unsigned idcode_ir = 1;
-  static const unsigned idcode_dr = 0xdeadbeef;
-  static const unsigned dtmcontrol_ir = 0x10;
-
-  public:
-    jtag_tap_t() :
-      state(TEST_LOGIC_RESET) {}
-
-    void reset() {
-      state = TEST_LOGIC_RESET;
-    }
-
-    void set_pins(bool tck, bool tms, bool tdi) {
-      if (!_tck && tck) {
-        // Positive clock edge.
-
-        switch (state) {
-          case SHIFT_DR:
-            dr >>= 1;
-            dr |= (uint64_t) _tdi << (dr_length-1);
-            break;
-          case SHIFT_IR:
-            ir >>= 1;
-            ir |= _tdi << (ir_length-1);
-            break;
-          default:
-            break;
-        }
-        state = next[state][_tms];
-        switch (state) {
-          case TEST_LOGIC_RESET:
-            ir = idcode_ir;
-            break;
-          case CAPTURE_DR:
-            switch (ir) {
-              case idcode_ir:
-                dr = 0xdeadbeef;
-                dr_length = 32;
-                break;
-              case dtmcontrol_ir:
-                dr = dtmcontrol;
-                dr_length = 32;
-              default:
-                D(fprintf(stderr, "Unsupported IR: 0x%x\n", ir));
-                break;
-            }
-            break;
-          case SHIFT_DR:
-            _tdo = dr & 1;
-            break;
-          case UPDATE_DR:
-            break;
-          case CAPTURE_IR:
-            break;
-          case SHIFT_IR:
-            _tdo = ir & 1;
-            break;
-          case UPDATE_IR:
-            break;
-          default:
-            break;
-        }
-      }
-
-      _tck = tck;
-      _tms = tms;
-      _tdi = tdi;
-
-      D(fprintf(stderr, "state=%2d tck=%d tms=%d tdi=%d tdo=%d ir=0x%x dr=0x%lx\n",
-            state, _tck, _tms, _tdi, _tdo, ir, dr));
-    }
-
-    bool tdo() const { return _tdo; }
-
-  private:
-    bool _tck, _tms, _tdi, _tdo;
-    uint32_t ir;
-    const unsigned ir_length = 5;
-    uint64_t dr;
-    unsigned dr_length;
-
-    uint32_t dtmcontrol = 1;
-
-    jtag_state_t state;
-    const jtag_state_t next[16][2] = {
-      /* TEST_LOGIC_RESET */    { RUN_TEST_IDLE, TEST_LOGIC_RESET },
-      /* RUN_TEST_IDLE */       { RUN_TEST_IDLE, SELECT_DR_SCAN },
-      /* SELECT_DR_SCAN */      { CAPTURE_DR, SELECT_IR_SCAN },
-      /* CAPTURE_DR */          { SHIFT_DR, EXIT1_DR },
-      /* SHIFT_DR */            { SHIFT_DR, EXIT1_DR },
-      /* EXIT1_DR */            { PAUSE_DR, UPDATE_DR },
-      /* PAUSE_DR */            { PAUSE_DR, EXIT2_DR },
-      /* EXIT2_DR */            { SHIFT_DR, UPDATE_DR },
-      /* UPDATE_DR */           { RUN_TEST_IDLE, SELECT_DR_SCAN },
-      /* SELECT_IR_SCAN */      { CAPTURE_IR, TEST_LOGIC_RESET },
-      /* CAPTURE_IR */          { SHIFT_IR, EXIT1_IR },
-      /* SHIFT_IR */            { SHIFT_IR, EXIT1_IR },
-      /* EXIT1_IR */            { PAUSE_IR, UPDATE_IR },
-      /* PAUSE_IR */            { PAUSE_IR, EXIT2_IR },
-      /* EXIT2_IR */            { SHIFT_IR, UPDATE_IR },
-      /* UPDATE_IR */           { RUN_TEST_IDLE, SELECT_DR_SCAN }
-    };
-};
-
 class remote_bitbang_t
 {
 public:
   // Create a new server, listening for connections from localhost on the given
   // port.
-  remote_bitbang_t(uint16_t port, sim_t *sim);
+  remote_bitbang_t(uint16_t port, jtag_dtm_t *tap);
 
   // Do a bit of work.
   void tick();
 
 private:
-  jtag_tap_t tap;
+  jtag_dtm_t *tap;
 
   int socket_fd;
   int client_fd;
index 695803b142ffb0b60b61d3673f379aee7eb8df47..6f12b846a5f30935709e6a3d8a3f9aae1257c250 100644 (file)
@@ -25,6 +25,7 @@ riscv_hdrs = \
        mulhi.h \
        debug_module.h \
        remote_bitbang.h \
+       jtag_dtm.h \
 
 riscv_precompiled_hdrs = \
        insn_template.h \
@@ -47,6 +48,7 @@ riscv_srcs = \
        rtc.cc \
        debug_module.cc \
        remote_bitbang.cc \
+       jtag_dtm.cc \
        $(riscv_gen_srcs) \
 
 riscv_test_srcs =
index 576c01f4ec24b8af77b86bfc79945858dc36d6b2..844d8e82d9aa927c0c2cf73215fee8f4397cc87c 100644 (file)
@@ -79,9 +79,10 @@ int main(int argc, char** argv)
   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);
+  std::unique_ptr<jtag_dtm_t> jtag_dtm(new jtag_dtm_t());
   std::unique_ptr<remote_bitbang_t> remote_bitbang;
   if (rbb_port) {
-    remote_bitbang = std::unique_ptr<remote_bitbang_t>(new remote_bitbang_t(rbb_port, &s));
+    remote_bitbang.reset(new remote_bitbang_t(rbb_port, &(*jtag_dtm)));
     s.set_remote_bitbang(&(*remote_bitbang));
   }