OpenOCD RISC-V code now gets to scan out dtmcontrol.
[riscv-isa-sim.git] / riscv / remote_bitbang.h
1 #ifndef REMOTE_BITBANG_H
2 #define REMOTE_BITBANG_H
3
4 #include <stdint.h>
5
6 #define DEBUG
7 #ifdef DEBUG
8 # define D(x) x
9 #else
10 # define D(x)
11 #endif // DEBUG
12
13 class sim_t;
14
15 template <typename T>
16 class circular_buffer_t
17 {
18 public:
19 // The buffer can store capacity-1 data elements.
20 circular_buffer_t(unsigned int capacity) : data(new T[capacity]),
21 start(0), end(0), capacity(capacity) {}
22 circular_buffer_t() : start(0), end(0), capacity(0) {}
23 ~circular_buffer_t() { delete[] data; }
24
25 T *data;
26 unsigned int start; // Data start, inclusive.
27 unsigned int end; // Data end, exclusive.
28 unsigned int capacity; // Size of the buffer.
29 unsigned int size() const;
30 bool empty() const { return start == end; }
31 bool full() const { return ((end+1) % capacity) == start; }
32 T entry(unsigned index) { return data[(start + index) % capacity]; }
33
34 // Return size and address of the block of RAM where more data can be copied
35 // to be added to the buffer.
36 unsigned int contiguous_empty_size() const;
37 T *contiguous_empty() { return data + end; }
38 void data_added(unsigned int bytes);
39
40 unsigned int contiguous_data_size() const;
41 T *contiguous_data() { return data + start; }
42 // Tell the buffer that some bytes were consumed from the start of the
43 // buffer.
44 void consume(unsigned int bytes);
45
46 void reset();
47
48 T operator[](unsigned int i) const { return data[(start + i) % capacity]; }
49
50 void append(const T *src, unsigned int count);
51 void append(T value);
52 };
53
54 typedef enum {
55 TEST_LOGIC_RESET,
56 RUN_TEST_IDLE,
57 SELECT_DR_SCAN,
58 CAPTURE_DR,
59 SHIFT_DR,
60 EXIT1_DR,
61 PAUSE_DR,
62 EXIT2_DR,
63 UPDATE_DR,
64 SELECT_IR_SCAN,
65 CAPTURE_IR,
66 SHIFT_IR,
67 EXIT1_IR,
68 PAUSE_IR,
69 EXIT2_IR,
70 UPDATE_IR
71 } jtag_state_t;
72
73 class jtag_tap_t
74 {
75 static const unsigned idcode_ir = 1;
76 static const unsigned idcode_dr = 0xdeadbeef;
77 static const unsigned dtmcontrol_ir = 0x10;
78
79 public:
80 jtag_tap_t() :
81 state(TEST_LOGIC_RESET) {}
82
83 void reset() {
84 state = TEST_LOGIC_RESET;
85 }
86
87 void set_pins(bool tck, bool tms, bool tdi) {
88 if (!_tck && tck) {
89 // Positive clock edge.
90
91 switch (state) {
92 case SHIFT_DR:
93 dr >>= 1;
94 dr |= (uint64_t) _tdi << (dr_length-1);
95 break;
96 case SHIFT_IR:
97 ir >>= 1;
98 ir |= _tdi << (ir_length-1);
99 break;
100 default:
101 break;
102 }
103 state = next[state][_tms];
104 switch (state) {
105 case TEST_LOGIC_RESET:
106 ir = idcode_ir;
107 break;
108 case CAPTURE_DR:
109 switch (ir) {
110 case idcode_ir:
111 dr = 0xdeadbeef;
112 dr_length = 32;
113 break;
114 case dtmcontrol_ir:
115 dr = dtmcontrol;
116 dr_length = 32;
117 default:
118 D(fprintf(stderr, "Unsupported IR: 0x%x\n", ir));
119 break;
120 }
121 break;
122 case SHIFT_DR:
123 _tdo = dr & 1;
124 break;
125 case UPDATE_DR:
126 break;
127 case CAPTURE_IR:
128 break;
129 case SHIFT_IR:
130 _tdo = ir & 1;
131 break;
132 case UPDATE_IR:
133 break;
134 default:
135 break;
136 }
137 }
138
139 _tck = tck;
140 _tms = tms;
141 _tdi = tdi;
142
143 D(fprintf(stderr, "state=%2d tck=%d tms=%d tdi=%d tdo=%d ir=0x%x dr=0x%lx\n",
144 state, _tck, _tms, _tdi, _tdo, ir, dr));
145 }
146
147 bool tdo() const { return _tdo; }
148
149 private:
150 bool _tck, _tms, _tdi, _tdo;
151 uint32_t ir;
152 const unsigned ir_length = 5;
153 uint64_t dr;
154 unsigned dr_length;
155
156 uint32_t dtmcontrol = 1;
157
158 jtag_state_t state;
159 const jtag_state_t next[16][2] = {
160 /* TEST_LOGIC_RESET */ { RUN_TEST_IDLE, TEST_LOGIC_RESET },
161 /* RUN_TEST_IDLE */ { RUN_TEST_IDLE, SELECT_DR_SCAN },
162 /* SELECT_DR_SCAN */ { CAPTURE_DR, SELECT_IR_SCAN },
163 /* CAPTURE_DR */ { SHIFT_DR, EXIT1_DR },
164 /* SHIFT_DR */ { SHIFT_DR, EXIT1_DR },
165 /* EXIT1_DR */ { PAUSE_DR, UPDATE_DR },
166 /* PAUSE_DR */ { PAUSE_DR, EXIT2_DR },
167 /* EXIT2_DR */ { SHIFT_DR, UPDATE_DR },
168 /* UPDATE_DR */ { RUN_TEST_IDLE, SELECT_DR_SCAN },
169 /* SELECT_IR_SCAN */ { CAPTURE_IR, TEST_LOGIC_RESET },
170 /* CAPTURE_IR */ { SHIFT_IR, EXIT1_IR },
171 /* SHIFT_IR */ { SHIFT_IR, EXIT1_IR },
172 /* EXIT1_IR */ { PAUSE_IR, UPDATE_IR },
173 /* PAUSE_IR */ { PAUSE_IR, EXIT2_IR },
174 /* EXIT2_IR */ { SHIFT_IR, UPDATE_IR },
175 /* UPDATE_IR */ { RUN_TEST_IDLE, SELECT_DR_SCAN }
176 };
177 };
178
179 class remote_bitbang_t
180 {
181 public:
182 // Create a new server, listening for connections from localhost on the given
183 // port.
184 remote_bitbang_t(uint16_t port, sim_t *sim);
185
186 // Do a bit of work.
187 void tick();
188
189 private:
190 jtag_tap_t tap;
191
192 int socket_fd;
193 int client_fd;
194 circular_buffer_t<uint8_t> recv_buf;
195 circular_buffer_t<uint8_t> send_buf;
196
197 // Check for a client connecting, and accept if there is one.
198 void accept();
199 // Read as much into recv_buf as possible.
200 void read();
201 // Write as much of send_buf as possible.
202 void write();
203
204 // Process the input buffer.
205 void process_input();
206 };
207
208 #endif