84182bbf02b7fcd361e5d1fd5329b2edc85456f1
[riscv-isa-sim.git] / riscv / jtag_dtm.cc
1 #include <stdio.h>
2
3 #include "decode.h"
4 #include "jtag_dtm.h"
5 #include "debug_module.h"
6 #include "debug_defines.h"
7
8 #if 0
9 # define D(x) x
10 #else
11 # define D(x)
12 #endif
13
14 enum {
15 IR_IDCODE=1,
16 IR_DTMCONTROL=0x10,
17 IR_DBUS=0x11
18 };
19
20 #define DTMCONTROL_VERSION 0xf
21 #define DTMCONTROL_ABITS (0x3f << 4)
22 #define DTMCONTROL_DBUSSTAT (3<<10)
23 #define DTMCONTROL_IDLE (7<<12)
24 #define DTMCONTROL_DBUSRESET (1<<16)
25
26 #define DMI_OP 3
27 #define DMI_DATA (0xffffffffL<<2)
28 #define DMI_ADDRESS ((1L<<(abits+34)) - (1L<<34))
29
30 #define DMI_OP_STATUS_SUCCESS 0
31 #define DMI_OP_STATUS_RESERVED 1
32 #define DMI_OP_STATUS_FAILED 2
33 #define DMI_OP_STATUS_BUSY 3
34
35 #define DMI_OP_NOP 0
36 #define DMI_OP_READ 1
37 #define DMI_OP_WRITE 2
38 #define DMI_OP_RESERVED 3
39
40 jtag_dtm_t::jtag_dtm_t(debug_module_t *dm) :
41 dm(dm),
42 _tck(false), _tms(false), _tdi(false), _tdo(false),
43 dtmcontrol((abits << DTM_DTMCONTROL_ABITS_OFFSET) | 1),
44 dmi(DMI_OP_STATUS_FAILED << DTM_DMI_OP_OFFSET),
45 state(TEST_LOGIC_RESET)
46 {
47 }
48
49 void jtag_dtm_t::reset() {
50 state = TEST_LOGIC_RESET;
51 }
52
53 void jtag_dtm_t::set_pins(bool tck, bool tms, bool tdi) {
54 const jtag_state_t next[16][2] = {
55 /* TEST_LOGIC_RESET */ { RUN_TEST_IDLE, TEST_LOGIC_RESET },
56 /* RUN_TEST_IDLE */ { RUN_TEST_IDLE, SELECT_DR_SCAN },
57 /* SELECT_DR_SCAN */ { CAPTURE_DR, SELECT_IR_SCAN },
58 /* CAPTURE_DR */ { SHIFT_DR, EXIT1_DR },
59 /* SHIFT_DR */ { SHIFT_DR, EXIT1_DR },
60 /* EXIT1_DR */ { PAUSE_DR, UPDATE_DR },
61 /* PAUSE_DR */ { PAUSE_DR, EXIT2_DR },
62 /* EXIT2_DR */ { SHIFT_DR, UPDATE_DR },
63 /* UPDATE_DR */ { RUN_TEST_IDLE, SELECT_DR_SCAN },
64 /* SELECT_IR_SCAN */ { CAPTURE_IR, TEST_LOGIC_RESET },
65 /* CAPTURE_IR */ { SHIFT_IR, EXIT1_IR },
66 /* SHIFT_IR */ { SHIFT_IR, EXIT1_IR },
67 /* EXIT1_IR */ { PAUSE_IR, UPDATE_IR },
68 /* PAUSE_IR */ { PAUSE_IR, EXIT2_IR },
69 /* EXIT2_IR */ { SHIFT_IR, UPDATE_IR },
70 /* UPDATE_IR */ { RUN_TEST_IDLE, SELECT_DR_SCAN }
71 };
72
73 if (!_tck && tck) {
74 // Positive clock edge.
75
76 switch (state) {
77 case SHIFT_DR:
78 dr >>= 1;
79 dr |= (uint64_t) _tdi << (dr_length-1);
80 break;
81 case SHIFT_IR:
82 ir >>= 1;
83 ir |= _tdi << (ir_length-1);
84 break;
85 default:
86 break;
87 }
88 state = next[state][_tms];
89 switch (state) {
90 case TEST_LOGIC_RESET:
91 ir = IR_IDCODE;
92 break;
93 case CAPTURE_DR:
94 capture_dr();
95 break;
96 case SHIFT_DR:
97 _tdo = dr & 1;
98 break;
99 case UPDATE_DR:
100 update_dr();
101 break;
102 case CAPTURE_IR:
103 break;
104 case SHIFT_IR:
105 _tdo = ir & 1;
106 break;
107 case UPDATE_IR:
108 break;
109 default:
110 break;
111 }
112 }
113
114 /*
115 D(fprintf(stderr, "state=%2d, tdi=%d, tdo=%d, tms=%d, tck=%d, ir=0x%02x, "
116 "dr=0x%lx\n",
117 state, _tdi, _tdo, _tms, _tck, ir, dr));
118 */
119
120 _tck = tck;
121 _tms = tms;
122 _tdi = tdi;
123 }
124
125 void jtag_dtm_t::capture_dr()
126 {
127 switch (ir) {
128 case IR_IDCODE:
129 dr = idcode;
130 dr_length = 32;
131 break;
132 case IR_DTMCONTROL:
133 dr = dtmcontrol;
134 dr_length = 32;
135 break;
136 case IR_DBUS:
137 dr = dmi;
138 dr_length = abits + 34;
139 break;
140 default:
141 D(fprintf(stderr, "Unsupported IR: 0x%x\n", ir));
142 break;
143 }
144 D(fprintf(stderr, "Capture DR; IR=0x%x, DR=0x%lx (%d bits)\n",
145 ir, dr, dr_length));
146 }
147
148 void jtag_dtm_t::update_dr()
149 {
150 D(fprintf(stderr, "Update DR; IR=0x%x, DR=0x%lx (%d bits)\n",
151 ir, dr, dr_length));
152 switch (ir) {
153 case IR_DBUS:
154 {
155 unsigned op = get_field(dr, DMI_OP);
156 uint32_t data = get_field(dr, DMI_DATA);
157 unsigned address = get_field(dr, DMI_ADDRESS);
158
159 dmi = dr;
160
161 bool success = true;
162 if (op == DMI_OP_READ) {
163 uint32_t value;
164 if (dm->dmi_read(address, &value)) {
165 dmi = set_field(dmi, DMI_DATA, value);
166 } else {
167 success = false;
168 }
169 } else if (op == DMI_OP_WRITE) {
170 success = dm->dmi_write(address, data);
171 }
172
173 if (success) {
174 dmi = set_field(dmi, DMI_OP, DMI_OP_STATUS_SUCCESS);
175 } else {
176 dmi = set_field(dmi, DMI_OP, DMI_OP_STATUS_FAILED);
177 }
178 D(fprintf(stderr, "dmi=0x%lx\n", dmi));
179 }
180 break;
181 }
182 }