|
|
|
@ -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 |
|
|
|
|