From f6a7fe2c4e4b03a17729a730bf48d4b80efaa104 Mon Sep 17 00:00:00 2001 From: Tim Newsome Date: Fri, 3 Feb 2017 13:29:47 -0800 Subject: [PATCH] OpenOCD can now scan out the hacked IDCODE. --- riscv/remote_bitbang.cc | 39 +++++++++++--- riscv/remote_bitbang.h | 116 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 148 insertions(+), 7 deletions(-) diff --git a/riscv/remote_bitbang.cc b/riscv/remote_bitbang.cc index 13b6a3c..7f22cd3 100644 --- a/riscv/remote_bitbang.cc +++ b/riscv/remote_bitbang.cc @@ -11,13 +11,6 @@ #include "remote_bitbang.h" -#define DEBUG -#ifdef DEBUG -# define D(x) x -#else -# define D(x) -#endif // DEBUG - /////////// Circular buffer template @@ -86,6 +79,12 @@ void circular_buffer_t::append(const T *src, unsigned int count) } } +template +void circular_buffer_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(); +} diff --git a/riscv/remote_bitbang.h b/riscv/remote_bitbang.h index 165cc40..8d0f1ca 100644 --- a/riscv/remote_bitbang.h +++ b/riscv/remote_bitbang.h @@ -3,6 +3,13 @@ #include +#define DEBUG +#ifdef DEBUG +# define D(x) x +#else +# define D(x) +#endif // DEBUG + class sim_t; template @@ -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 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 -- 2.30.2