OpenOCD can now scan out the hacked IDCODE.
authorTim Newsome <tim@sifive.com>
Fri, 3 Feb 2017 21:29:47 +0000 (13:29 -0800)
committerTim Newsome <tim@sifive.com>
Fri, 3 Feb 2017 21:29:47 +0000 (13:29 -0800)
riscv/remote_bitbang.cc
riscv/remote_bitbang.h

index 13b6a3c582c0768a029dcccdc6d375f74c8246dd..7f22cd3223be06176c1229201f90eecfab226b5e 100644 (file)
 
 #include "remote_bitbang.h"
 
-#define DEBUG
-#ifdef DEBUG
-#  define D(x) x
-#else
-#  define D(x)
-#endif // DEBUG
-
 /////////// Circular buffer
 
 template <typename T>
@@ -86,6 +79,12 @@ void circular_buffer_t<T>::append(const T *src, unsigned int count)
   }
 }
 
+template <typename T>
+void circular_buffer_t<T>::append(T value)
+{
+  append(&value, 1);
+}
+
 /////////// remote_bitbang_t
 
 remote_bitbang_t::remote_bitbang_t(uint16_t port, sim_t *sim) :
@@ -204,8 +203,34 @@ void remote_bitbang_t::tick()
 {
   if (client_fd > 0) {
     this->read();
+    process_input();
     this->write();
   } else {
     this->accept();
   }
 }
+
+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_buf.reset();
+}
index 165cc409b0adf876de3cb90542def4a6668217db..8d0f1caef16c369733e9abcf998851e514476e8d 100644 (file)
@@ -3,6 +3,13 @@
 
 #include <stdint.h>
 
+#define DEBUG
+#ifdef DEBUG
+#  define D(x) x
+#else
+#  define D(x)
+#endif // DEBUG
+
 class sim_t;
 
 template <typename T>
@@ -41,6 +48,110 @@ public:
   T operator[](unsigned int i) const { return data[(start + i) % capacity]; }
 
   void append(const T *src, unsigned int count);
+  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
+{
+  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.
+
+        D(fprintf(stderr, "Next state: %d\n", state));
+
+        state = next[state][_tms];
+
+        switch (state) {
+          case TEST_LOGIC_RESET:
+            ir = 1;
+            break;
+          case CAPTURE_DR:
+            dr = 0xdeadbeef;
+            dr_length = 32;
+            break;
+          case SHIFT_DR:
+            _tdo = dr & 1;
+            dr >>= 1;
+            dr |= (uint64_t) _tdi << (dr_length-1);
+            break;
+          case UPDATE_DR:
+            break;
+          case CAPTURE_IR:
+            break;
+          case SHIFT_IR:
+            _tdo = ir & 1;
+            ir >>= 1;
+            ir = ir | (_tdi << (ir_length-1));
+            break;
+          case UPDATE_IR:
+            break;
+          default:
+            break;
+        }
+      }
+      _tck = tck;
+      _tms = tms;
+      _tdi = tdi;
+
+      D(fprintf(stderr, "tck=%d tms=%d tdi=%d tdo=%d ir=0x%x dr=0x%lx\n",
+            _tck, _tms, _tdi, _tdo, ir, dr));
+    }
+
+    bool tdo() const { return _tdo; }
+
+  private:
+    bool _tck, _tms, _tdi, _tdo;
+    uint32_t ir;
+    unsigned ir_length;
+    uint64_t dr;
+    unsigned dr_length;
+
+    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
@@ -54,6 +165,8 @@ public:
   void tick();
 
 private:
+  jtag_tap_t tap;
+
   int socket_fd;
   int client_fd;
   circular_buffer_t<uint8_t> recv_buf;
@@ -65,6 +178,9 @@ private:
   void read();
   // Write as much of send_buf as possible.
   void write();
+
+  // Process the input buffer.
+  void process_input();
 };
 
 #endif