Implement autoexec. DMI op 2 is just write now.
[riscv-isa-sim.git] / riscv / debug_module.cc
1 #include <cassert>
2
3 #include "debug_module.h"
4 #include "debug_defines.h"
5 #include "opcodes.h"
6 #include "mmu.h"
7
8 #include "debug_rom/debug_rom.h"
9
10 #if 1
11 # define D(x) x
12 #else
13 # define D(x)
14 #endif
15
16 ///////////////////////// debug_module_data_t
17
18 debug_module_data_t::debug_module_data_t()
19 {
20 memset(data, 0, sizeof(data));
21 }
22
23 bool debug_module_data_t::load(reg_t addr, size_t len, uint8_t* bytes)
24 {
25 D(fprintf(stderr, "debug_module_data_t load 0x%lx bytes at 0x%lx\n", len,
26 addr));
27
28 if (addr + len < sizeof(data)) {
29 memcpy(bytes, data + addr, len);
30 return true;
31 }
32
33 fprintf(stderr, "ERROR: invalid load from debug_module_data_t: %zd bytes at 0x%016"
34 PRIx64 "\n", len, addr);
35
36 return false;
37 }
38
39 bool debug_module_data_t::store(reg_t addr, size_t len, const uint8_t* bytes)
40 {
41 D(fprintf(stderr, "debug_module_data_t store 0x%lx bytes at 0x%lx\n", len,
42 addr));
43
44 if (addr + len < sizeof(data)) {
45 memcpy(data + addr, bytes, len);
46 return true;
47 }
48
49 fprintf(stderr, "ERROR: invalid store to debug_module_data_t: %zd bytes at 0x%016"
50 PRIx64 "\n", len, addr);
51 return false;
52 }
53
54 uint32_t debug_module_data_t::read32(reg_t addr) const
55 {
56 assert(addr + 4 <= sizeof(data));
57 return data[addr] |
58 (data[addr + 1] << 8) |
59 (data[addr + 2] << 16) |
60 (data[addr + 3] << 24);
61 }
62
63 void debug_module_data_t::write32(reg_t addr, uint32_t value)
64 {
65 fprintf(stderr, "debug_module_data_t::write32(0x%lx, 0x%x)\n", addr, value);
66 assert(addr + 4 <= sizeof(data));
67 data[addr] = value & 0xff;
68 data[addr + 1] = (value >> 8) & 0xff;
69 data[addr + 2] = (value >> 16) & 0xff;
70 data[addr + 3] = (value >> 24) & 0xff;
71 }
72
73 ///////////////////////// debug_module_t
74
75 debug_module_t::debug_module_t(sim_t *sim) : sim(sim),
76 next_action(jal(ZERO, 0)),
77 action_executed(false)
78 {
79 dmcontrol = {0};
80 dmcontrol.version = 1;
81
82 for (unsigned i = 0; i < DEBUG_ROM_ENTRY_SIZE / 4; i++) {
83 write32(debug_rom_entry, i, jal(ZERO, 0));
84 halted[i] = false;
85 }
86
87 memset(program_buffer, 0, sizeof(program_buffer));
88 }
89
90 void debug_module_t::reset()
91 {
92 for (unsigned i = 0; i < sim->nprocs(); i++) {
93 processor_t *proc = sim->get_core(i);
94 if (proc)
95 proc->halt_request = false;
96 }
97
98 dmcontrol = {0};
99 dmcontrol.authenticated = 1;
100 dmcontrol.version = 1;
101 dmcontrol.authtype = dmcontrol.AUTHTYPE_NOAUTH;
102
103 abstractcs = {0};
104 abstractcs.datacount = sizeof(dmdata.data) / 4;
105 }
106
107 void debug_module_t::add_device(bus_t *bus) {
108 bus->add_device(DEBUG_START, this);
109 bus->add_device(DEBUG_EXCHANGE, &dmdata);
110 }
111
112 bool debug_module_t::load(reg_t addr, size_t len, uint8_t* bytes)
113 {
114 D(fprintf(stderr, "debug_module_t load 0x%lx bytes at 0x%lx\n",
115 len, addr));
116 addr = DEBUG_START + addr;
117
118 if (addr >= DEBUG_ROM_ENTRY &&
119 addr < DEBUG_ROM_ENTRY + DEBUG_ROM_ENTRY_SIZE) {
120
121 if (read32(debug_rom_entry, dmcontrol.hartsel) == jal(ZERO, 0)) {
122 // We're here in an infinite loop. That means that whatever abstract
123 // command has complete.
124 abstractcs.busy = false;
125 }
126
127 action_executed = true;
128
129 halted[(addr - DEBUG_ROM_ENTRY) / 4] = true;
130 memcpy(bytes, debug_rom_entry + addr - DEBUG_ROM_ENTRY, len);
131 return true;
132 }
133
134 if (action_executed) {
135 // Restore the jump-to-self loop.
136 write32(debug_rom_entry, dmcontrol.hartsel, next_action);
137 next_action = jal(ZERO, 0);
138 action_executed = false;
139 }
140
141 if (addr >= DEBUG_ROM_CODE &&
142 addr < DEBUG_ROM_CODE + DEBUG_ROM_CODE_SIZE) {
143
144 if (read32(debug_rom_code, 0) == dret()) {
145 abstractcs.busy = false;
146 halted[dmcontrol.hartsel] = false;
147 }
148
149 memcpy(bytes, debug_rom_code + addr - DEBUG_ROM_CODE, len);
150 return true;
151 }
152
153 if (addr >= DEBUG_RAM_START && addr < DEBUG_RAM_END) {
154 memcpy(bytes, program_buffer + addr - DEBUG_RAM_START, len);
155 return true;
156 }
157
158 if (addr >= DEBUG_ROM_EXCEPTION &&
159 addr < DEBUG_ROM_EXCEPTION + DEBUG_ROM_EXCEPTION_SIZE) {
160 memcpy(bytes, debug_rom_exception + addr - DEBUG_ROM_EXCEPTION, len);
161 if (abstractcs.cmderr == abstractcs.CMDERR_NONE) {
162 abstractcs.cmderr = abstractcs.CMDERR_EXCEPTION;
163 }
164 return true;
165 }
166
167 fprintf(stderr, "ERROR: invalid load from debug module: %zd bytes at 0x%016"
168 PRIx64 "\n", len, addr);
169
170 return false;
171 }
172
173 bool debug_module_t::store(reg_t addr, size_t len, const uint8_t* bytes)
174 {
175 addr = DEBUG_START + addr;
176
177 if (addr >= DEBUG_RAM_START && addr < DEBUG_RAM_END) {
178 memcpy(program_buffer + addr - DEBUG_RAM_START, bytes, len);
179 return true;
180 }
181
182 fprintf(stderr, "ERROR: invalid store to debug module: %zd bytes at 0x%016"
183 PRIx64 "\n", len, addr);
184 return false;
185 }
186
187 void debug_module_t::write32(uint8_t *memory, unsigned int index, uint32_t value)
188 {
189 uint8_t* base = memory + index * 4;
190 base[0] = value & 0xff;
191 base[1] = (value >> 8) & 0xff;
192 base[2] = (value >> 16) & 0xff;
193 base[3] = (value >> 24) & 0xff;
194 }
195
196 uint32_t debug_module_t::read32(uint8_t *memory, unsigned int index)
197 {
198 uint8_t* base = memory + index * 4;
199 uint32_t value = ((uint32_t) base[0]) |
200 (((uint32_t) base[1]) << 8) |
201 (((uint32_t) base[2]) << 16) |
202 (((uint32_t) base[3]) << 24);
203 return value;
204 }
205
206 processor_t *debug_module_t::current_proc() const
207 {
208 processor_t *proc = NULL;
209 try {
210 proc = sim->get_core(dmcontrol.hartsel);
211 } catch (const std::out_of_range&) {
212 }
213 return proc;
214 }
215
216 bool debug_module_t::dmi_read(unsigned address, uint32_t *value)
217 {
218 uint32_t result = 0;
219 D(fprintf(stderr, "dmi_read(0x%x) -> ", address));
220 if (address >= DMI_DATA0 && address < DMI_DATA0 + abstractcs.datacount) {
221 unsigned i = address - DMI_DATA0;
222 result = dmdata.read32(4 * i);
223
224 bool autoexec = false;
225 switch (i) {
226 case 0: autoexec = abstractcs.autoexec0; break;
227 case 1: autoexec = abstractcs.autoexec1; break;
228 case 2: autoexec = abstractcs.autoexec2; break;
229 case 3: autoexec = abstractcs.autoexec3; break;
230 case 4: autoexec = abstractcs.autoexec4; break;
231 case 5: autoexec = abstractcs.autoexec5; break;
232 case 6: autoexec = abstractcs.autoexec6; break;
233 case 7: autoexec = abstractcs.autoexec7; break;
234 }
235 if (autoexec) {
236 perform_abstract_command();
237 }
238 } else if (address >= DMI_IBUF0 && address < DMI_IBUF0 + progsize) {
239 result = read32(program_buffer, address - DMI_IBUF0);
240 } else {
241 switch (address) {
242 case DMI_DMCONTROL:
243 {
244 processor_t *proc = current_proc();
245 if (proc) {
246 if (halted[dmcontrol.hartsel]) {
247 dmcontrol.hartstatus = dmcontrol.HARTSTATUS_HALTED;
248 } else {
249 dmcontrol.hartstatus = dmcontrol.HARTSTATUS_RUNNING;
250 }
251 dmcontrol.haltreq = proc->halt_request;
252 } else {
253 dmcontrol.hartstatus = dmcontrol.HARTSTATUS_NOTEXIST;
254 }
255 result = set_field(result, DMI_DMCONTROL_HALTREQ, dmcontrol.haltreq);
256 result = set_field(result, DMI_DMCONTROL_RESET, dmcontrol.reset);
257 result = set_field(result, DMI_DMCONTROL_DMACTIVE, dmcontrol.dmactive);
258 result = set_field(result, DMI_DMCONTROL_HARTSTATUS, dmcontrol.hartstatus);
259 result = set_field(result, DMI_DMCONTROL_HARTSEL, dmcontrol.hartsel);
260 result = set_field(result, DMI_DMCONTROL_AUTHENTICATED, dmcontrol.authenticated);
261 result = set_field(result, DMI_DMCONTROL_AUTHBUSY, dmcontrol.authbusy);
262 result = set_field(result, DMI_DMCONTROL_AUTHTYPE, dmcontrol.authtype);
263 result = set_field(result, DMI_DMCONTROL_VERSION, dmcontrol.version);
264 }
265 break;
266 case DMI_ABSTRACTCS:
267 result = set_field(result, DMI_ABSTRACTCS_AUTOEXEC7, abstractcs.autoexec7);
268 result = set_field(result, DMI_ABSTRACTCS_AUTOEXEC6, abstractcs.autoexec6);
269 result = set_field(result, DMI_ABSTRACTCS_AUTOEXEC5, abstractcs.autoexec5);
270 result = set_field(result, DMI_ABSTRACTCS_AUTOEXEC4, abstractcs.autoexec4);
271 result = set_field(result, DMI_ABSTRACTCS_AUTOEXEC3, abstractcs.autoexec3);
272 result = set_field(result, DMI_ABSTRACTCS_AUTOEXEC2, abstractcs.autoexec2);
273 result = set_field(result, DMI_ABSTRACTCS_AUTOEXEC1, abstractcs.autoexec1);
274 result = set_field(result, DMI_ABSTRACTCS_AUTOEXEC0, abstractcs.autoexec0);
275 result = set_field(result, DMI_ABSTRACTCS_CMDERR, abstractcs.cmderr);
276 result = set_field(result, DMI_ABSTRACTCS_BUSY, abstractcs.busy);
277 result = set_field(result, DMI_ABSTRACTCS_DATACOUNT, abstractcs.datacount);
278 break;
279 case DMI_ACCESSCS:
280 result = progsize << DMI_ACCESSCS_PROGSIZE_OFFSET;
281 break;
282 case DMI_COMMAND:
283 result = 0;
284 break;
285 default:
286 D(fprintf(stderr, "error\n"));
287 return false;
288 }
289 }
290 D(fprintf(stderr, "0x%x\n", result));
291 *value = result;
292 return true;
293 }
294
295 bool debug_module_t::perform_abstract_command()
296 {
297 if (abstractcs.cmderr != abstractcs.CMDERR_NONE)
298 return true;
299 if (abstractcs.busy) {
300 abstractcs.cmderr = abstractcs.CMDERR_BUSY;
301 return true;
302 }
303
304 if ((command >> 24) == 0) {
305 // register access
306 unsigned size = get_field(command, AC_ACCESS_REGISTER_SIZE);
307 bool write = get_field(command, AC_ACCESS_REGISTER_WRITE);
308 unsigned regno = get_field(command, AC_ACCESS_REGISTER_REGNO);
309
310 if (regno < 0x1000 || regno >= 0x1020) {
311 abstractcs.cmderr = abstractcs.CMDERR_NOTSUP;
312 return true;
313 }
314
315 unsigned regnum = regno - 0x1000;
316
317 if (!halted[dmcontrol.hartsel]) {
318 abstractcs.cmderr = abstractcs.CMDERR_HALTRESUME;
319 return true;
320 }
321
322 switch (size) {
323 case 2:
324 if (write)
325 write32(debug_rom_code, 0, lw(regnum, ZERO, DEBUG_EXCHANGE));
326 else
327 write32(debug_rom_code, 0, sw(regnum, ZERO, DEBUG_EXCHANGE));
328 break;
329 case 3:
330 if (write)
331 write32(debug_rom_code, 0, ld(regnum, ZERO, DEBUG_EXCHANGE));
332 else
333 write32(debug_rom_code, 0, sd(regnum, ZERO, DEBUG_EXCHANGE));
334 break;
335 /*
336 case 4:
337 if (write)
338 write32(debug_rom_code, 0, lq(regnum, ZERO, DEBUG_EXCHANGE));
339 else
340 write32(debug_rom_code, 0, sq(regnum, ZERO, DEBUG_EXCHANGE));
341 break;
342 */
343 default:
344 abstractcs.cmderr = abstractcs.CMDERR_NOTSUP;
345 return true;
346 }
347 if (get_field(command, AC_ACCESS_REGISTER_POSTEXEC)) {
348 write32(debug_rom_code, 1, jal(ZERO, DEBUG_RAM_START - DEBUG_ROM_CODE - 4));
349 } else {
350 write32(debug_rom_code, 1, ebreak());
351 }
352
353 if (get_field(command, AC_ACCESS_REGISTER_PREEXEC)) {
354 write32(debug_rom_entry, dmcontrol.hartsel,
355 jal(ZERO, DEBUG_RAM_START - (DEBUG_ROM_ENTRY + 4 * dmcontrol.hartsel)));
356 next_action =
357 jal(ZERO, DEBUG_ROM_CODE - (DEBUG_ROM_ENTRY + 4 * dmcontrol.hartsel));
358 } else {
359 write32(debug_rom_entry, dmcontrol.hartsel,
360 jal(ZERO, DEBUG_ROM_CODE - (DEBUG_ROM_ENTRY + 4 * dmcontrol.hartsel)));
361 }
362
363 write32(debug_rom_exception, dmcontrol.hartsel,
364 jal(ZERO, (DEBUG_ROM_ENTRY + 4 * dmcontrol.hartsel) - DEBUG_ROM_EXCEPTION));
365 abstractcs.busy = true;
366 } else {
367 abstractcs.cmderr = abstractcs.CMDERR_NOTSUP;
368 }
369 return true;
370 }
371
372 bool debug_module_t::dmi_write(unsigned address, uint32_t value)
373 {
374 D(fprintf(stderr, "dmi_write(0x%x, 0x%x)\n", address, value));
375 if (address >= DMI_DATA0 && address < DMI_DATA0 + abstractcs.datacount) {
376 unsigned i = address - DMI_DATA0;
377 dmdata.write32(4 * i, value);
378
379 bool autoexec = false;
380 switch (i) {
381 case 0: autoexec = abstractcs.autoexec0; break;
382 case 1: autoexec = abstractcs.autoexec1; break;
383 case 2: autoexec = abstractcs.autoexec2; break;
384 case 3: autoexec = abstractcs.autoexec3; break;
385 case 4: autoexec = abstractcs.autoexec4; break;
386 case 5: autoexec = abstractcs.autoexec5; break;
387 case 6: autoexec = abstractcs.autoexec6; break;
388 case 7: autoexec = abstractcs.autoexec7; break;
389 }
390 if (autoexec) {
391 perform_abstract_command();
392 }
393 return true;
394
395 } else if (address >= DMI_IBUF0 && address < DMI_IBUF0 + progsize) {
396 write32(program_buffer, address - DMI_IBUF0, value);
397 return true;
398 } else {
399 switch (address) {
400 case DMI_DMCONTROL:
401 {
402 dmcontrol.dmactive = get_field(value, DMI_DMCONTROL_DMACTIVE);
403 if (dmcontrol.dmactive) {
404 dmcontrol.haltreq = get_field(value, DMI_DMCONTROL_HALTREQ);
405 dmcontrol.resumereq = get_field(value, DMI_DMCONTROL_RESUMEREQ);
406 dmcontrol.reset = get_field(value, DMI_DMCONTROL_RESET);
407 dmcontrol.hartsel = get_field(value, DMI_DMCONTROL_HARTSEL);
408 } else {
409 reset();
410 }
411 processor_t *proc = current_proc();
412 if (proc) {
413 proc->halt_request = dmcontrol.haltreq;
414 if (dmcontrol.resumereq) {
415 write32(debug_rom_code, 0, dret());
416 write32(debug_rom_entry, dmcontrol.hartsel,
417 jal(ZERO, DEBUG_ROM_CODE - (DEBUG_ROM_ENTRY + 4 * dmcontrol.hartsel)));
418 abstractcs.busy = true;
419 }
420 }
421 }
422 return true;
423
424 case DMI_COMMAND:
425 command = value;
426 return perform_abstract_command();
427
428 case DMI_ABSTRACTCS:
429 abstractcs.autoexec7 = get_field(value, DMI_ABSTRACTCS_AUTOEXEC7);
430 abstractcs.autoexec6 = get_field(value, DMI_ABSTRACTCS_AUTOEXEC6);
431 abstractcs.autoexec5 = get_field(value, DMI_ABSTRACTCS_AUTOEXEC5);
432 abstractcs.autoexec4 = get_field(value, DMI_ABSTRACTCS_AUTOEXEC4);
433 abstractcs.autoexec3 = get_field(value, DMI_ABSTRACTCS_AUTOEXEC3);
434 abstractcs.autoexec2 = get_field(value, DMI_ABSTRACTCS_AUTOEXEC2);
435 abstractcs.autoexec1 = get_field(value, DMI_ABSTRACTCS_AUTOEXEC1);
436 abstractcs.autoexec0 = get_field(value, DMI_ABSTRACTCS_AUTOEXEC0);
437 if (get_field(value, DMI_ABSTRACTCS_CMDERR) == abstractcs.CMDERR_NONE) {
438 abstractcs.cmderr = abstractcs.CMDERR_NONE;
439 }
440 return true;
441 }
442 }
443 return false;
444 }