diff options
author | Tim Newsome <tim@sifive.com> | 2017-02-03 13:29:47 -0800 |
---|---|---|
committer | Tim Newsome <tim@sifive.com> | 2017-02-03 13:29:47 -0800 |
commit | f6a7fe2c4e4b03a17729a730bf48d4b80efaa104 (patch) | |
tree | 5333eb33ac346e1ade8f38ba04b906042cbd1a1e /riscv/remote_bitbang.h | |
parent | d1f2cf337e1a0be8eada2afadd745e1374b4a000 (diff) | |
download | spike-f6a7fe2c4e4b03a17729a730bf48d4b80efaa104.zip spike-f6a7fe2c4e4b03a17729a730bf48d4b80efaa104.tar.gz spike-f6a7fe2c4e4b03a17729a730bf48d4b80efaa104.tar.bz2 |
OpenOCD can now scan out the hacked IDCODE.
Diffstat (limited to 'riscv/remote_bitbang.h')
-rw-r--r-- | riscv/remote_bitbang.h | 116 |
1 files changed, 116 insertions, 0 deletions
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 <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 |