From 4695be7cea868b34082787d5728c35577d0c05d1 Mon Sep 17 00:00:00 2001 From: Tim Newsome Date: Mon, 6 Feb 2017 19:17:23 -0800 Subject: [PATCH] Refactor remote bitbang code. --- riscv/jtag_dtm.cc | 81 +++++++++++++++++++++++ riscv/jtag_dtm.h | 81 +++++++++++++++++++++++ riscv/remote_bitbang.cc | 34 ++++++---- riscv/remote_bitbang.h | 138 +--------------------------------------- riscv/riscv.mk.in | 2 + spike_main/spike.cc | 3 +- 6 files changed, 192 insertions(+), 147 deletions(-) create mode 100644 riscv/jtag_dtm.cc create mode 100644 riscv/jtag_dtm.h diff --git a/riscv/jtag_dtm.cc b/riscv/jtag_dtm.cc new file mode 100644 index 0000000..c099e33 --- /dev/null +++ b/riscv/jtag_dtm.cc @@ -0,0 +1,81 @@ +#include + +#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 index 0000000..e425c8e --- /dev/null +++ b/riscv/jtag_dtm.h @@ -0,0 +1,81 @@ +#ifndef JTAG_DTM_H +#define JTAG_DTM_H + +#include + +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 diff --git a/riscv/remote_bitbang.cc b/riscv/remote_bitbang.cc index 7f22cd3..acfd216 100644 --- a/riscv/remote_bitbang.cc +++ b/riscv/remote_bitbang.cc @@ -11,6 +11,12 @@ #include "remote_bitbang.h" +#if 1 +# define D(x) x +#else +# define D(x) +#endif + /////////// Circular buffer template @@ -87,7 +93,8 @@ void circular_buffer_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); } diff --git a/riscv/remote_bitbang.h b/riscv/remote_bitbang.h index 5f2a3ea..c0aa7e0 100644 --- a/riscv/remote_bitbang.h +++ b/riscv/remote_bitbang.h @@ -3,14 +3,7 @@ #include -#define DEBUG -#ifdef DEBUG -# define D(x) x -#else -# define D(x) -#endif // DEBUG - -class sim_t; +#include "jtag_dtm.h" template 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; diff --git a/riscv/riscv.mk.in b/riscv/riscv.mk.in index 695803b..6f12b84 100644 --- a/riscv/riscv.mk.in +++ b/riscv/riscv.mk.in @@ -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 = diff --git a/spike_main/spike.cc b/spike_main/spike.cc index 576c01f..844d8e8 100644 --- a/spike_main/spike.cc +++ b/spike_main/spike.cc @@ -79,9 +79,10 @@ int main(int argc, char** argv) auto argv1 = parser.parse(argv); std::vector htif_args(argv1, (const char*const*)argv + argc); sim_t s(isa, nprocs, mem_mb, halted, htif_args); + std::unique_ptr jtag_dtm(new jtag_dtm_t()); std::unique_ptr remote_bitbang; if (rbb_port) { - remote_bitbang = std::unique_ptr(new remote_bitbang_t(rbb_port, &s)); + remote_bitbang.reset(new remote_bitbang_t(rbb_port, &(*jtag_dtm))); s.set_remote_bitbang(&(*remote_bitbang)); } -- 2.30.2