Reset to "success" instead of "error."
[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_DTMCS_ABITS_OFFSET) | 1),
44 dmi(DMI_OP_STATUS_SUCCESS << 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 D(fprintf(stderr, "state=%2d, tdi=%d, tdo=%d, tms=%d, tck=%d, ir=0x%02x, "
115 "dr=0x%lx\n",
116 _state, _tdi, _tdo, _tms, _tck, ir, dr));
117
118 _tck = tck;
119 _tms = tms;
120 _tdi = tdi;
121 }
122
123 void jtag_dtm_t::capture_dr()
124 {
125 switch (ir) {
126 case IR_IDCODE:
127 dr = idcode;
128 dr_length = 32;
129 break;
130 case IR_DTMCONTROL:
131 dr = dtmcontrol;
132 dr_length = 32;
133 break;
134 case IR_DBUS:
135 dr = dmi;
136 dr_length = abits + 34;
137 break;
138 default:
139 D(fprintf(stderr, "Unsupported IR: 0x%x\n", ir));
140 break;
141 }
142 D(fprintf(stderr, "Capture DR; IR=0x%x, DR=0x%lx (%d bits)\n",
143 ir, dr, dr_length));
144 }
145
146 void jtag_dtm_t::update_dr()
147 {
148 D(fprintf(stderr, "Update DR; IR=0x%x, DR=0x%lx (%d bits)\n",
149 ir, dr, dr_length));
150 switch (ir) {
151 case IR_DBUS:
152 {
153 unsigned op = get_field(dr, DMI_OP);
154 uint32_t data = get_field(dr, DMI_DATA);
155 unsigned address = get_field(dr, DMI_ADDRESS);
156
157 dmi = dr;
158
159 bool success = true;
160 if (op == DMI_OP_READ) {
161 uint32_t value;
162 if (dm->dmi_read(address, &value)) {
163 dmi = set_field(dmi, DMI_DATA, value);
164 } else {
165 success = false;
166 }
167 } else if (op == DMI_OP_WRITE) {
168 success = dm->dmi_write(address, data);
169 }
170
171 if (success) {
172 dmi = set_field(dmi, DMI_OP, DMI_OP_STATUS_SUCCESS);
173 } else {
174 dmi = set_field(dmi, DMI_OP, DMI_OP_STATUS_FAILED);
175 }
176 D(fprintf(stderr, "dmi=0x%lx\n", dmi));
177 }
178 break;
179 }
180 }