af719746a286495a3caf946e9a4161653223f056
[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 if (abstractcs.busy && abstractcs.cmderr == abstractcs.CMDERR_NONE) {
225 abstractcs.cmderr = abstractcs.CMDERR_BUSY;
226 }
227
228 bool autoexec = false;
229 switch (i) {
230 case 0: autoexec = abstractcs.autoexec0; break;
231 case 1: autoexec = abstractcs.autoexec1; break;
232 case 2: autoexec = abstractcs.autoexec2; break;
233 case 3: autoexec = abstractcs.autoexec3; break;
234 case 4: autoexec = abstractcs.autoexec4; break;
235 case 5: autoexec = abstractcs.autoexec5; break;
236 case 6: autoexec = abstractcs.autoexec6; break;
237 case 7: autoexec = abstractcs.autoexec7; break;
238 }
239 if (autoexec) {
240 perform_abstract_command();
241 }
242 } else if (address >= DMI_IBUF0 && address < DMI_IBUF0 + progsize) {
243 result = read32(program_buffer, address - DMI_IBUF0);
244 } else {
245 switch (address) {
246 case DMI_DMCONTROL:
247 {
248 processor_t *proc = current_proc();
249 if (proc) {
250 if (halted[dmcontrol.hartsel]) {
251 dmcontrol.hartstatus = dmcontrol.HARTSTATUS_HALTED;
252 } else {
253 dmcontrol.hartstatus = dmcontrol.HARTSTATUS_RUNNING;
254 }
255 dmcontrol.haltreq = proc->halt_request;
256 } else {
257 dmcontrol.hartstatus = dmcontrol.HARTSTATUS_NOTEXIST;
258 }
259 result = set_field(result, DMI_DMCONTROL_HALTREQ, dmcontrol.haltreq);
260 result = set_field(result, DMI_DMCONTROL_RESET, dmcontrol.reset);
261 result = set_field(result, DMI_DMCONTROL_DMACTIVE, dmcontrol.dmactive);
262 result = set_field(result, DMI_DMCONTROL_HARTSTATUS, dmcontrol.hartstatus);
263 result = set_field(result, DMI_DMCONTROL_HARTSEL, dmcontrol.hartsel);
264 result = set_field(result, DMI_DMCONTROL_AUTHENTICATED, dmcontrol.authenticated);
265 result = set_field(result, DMI_DMCONTROL_AUTHBUSY, dmcontrol.authbusy);
266 result = set_field(result, DMI_DMCONTROL_AUTHTYPE, dmcontrol.authtype);
267 result = set_field(result, DMI_DMCONTROL_VERSION, dmcontrol.version);
268 }
269 break;
270 case DMI_ABSTRACTCS:
271 result = set_field(result, DMI_ABSTRACTCS_AUTOEXEC7, abstractcs.autoexec7);
272 result = set_field(result, DMI_ABSTRACTCS_AUTOEXEC6, abstractcs.autoexec6);
273 result = set_field(result, DMI_ABSTRACTCS_AUTOEXEC5, abstractcs.autoexec5);
274 result = set_field(result, DMI_ABSTRACTCS_AUTOEXEC4, abstractcs.autoexec4);
275 result = set_field(result, DMI_ABSTRACTCS_AUTOEXEC3, abstractcs.autoexec3);
276 result = set_field(result, DMI_ABSTRACTCS_AUTOEXEC2, abstractcs.autoexec2);
277 result = set_field(result, DMI_ABSTRACTCS_AUTOEXEC1, abstractcs.autoexec1);
278 result = set_field(result, DMI_ABSTRACTCS_AUTOEXEC0, abstractcs.autoexec0);
279 result = set_field(result, DMI_ABSTRACTCS_CMDERR, abstractcs.cmderr);
280 result = set_field(result, DMI_ABSTRACTCS_BUSY, abstractcs.busy);
281 result = set_field(result, DMI_ABSTRACTCS_DATACOUNT, abstractcs.datacount);
282 break;
283 case DMI_ACCESSCS:
284 result = progsize << DMI_ACCESSCS_PROGSIZE_OFFSET;
285 break;
286 case DMI_COMMAND:
287 result = 0;
288 break;
289 default:
290 D(fprintf(stderr, "error\n"));
291 return false;
292 }
293 }
294 D(fprintf(stderr, "0x%x\n", result));
295 *value = result;
296 return true;
297 }
298
299 bool debug_module_t::perform_abstract_command()
300 {
301 if (abstractcs.cmderr != abstractcs.CMDERR_NONE)
302 return true;
303 if (abstractcs.busy) {
304 abstractcs.cmderr = abstractcs.CMDERR_BUSY;
305 return true;
306 }
307
308 if ((command >> 24) == 0) {
309 // register access
310 unsigned size = get_field(command, AC_ACCESS_REGISTER_SIZE);
311 bool write = get_field(command, AC_ACCESS_REGISTER_WRITE);
312 unsigned regno = get_field(command, AC_ACCESS_REGISTER_REGNO);
313
314 if (regno < 0x1000 || regno >= 0x1020) {
315 abstractcs.cmderr = abstractcs.CMDERR_NOTSUP;
316 return true;
317 }
318
319 unsigned regnum = regno - 0x1000;
320
321 if (!halted[dmcontrol.hartsel]) {
322 abstractcs.cmderr = abstractcs.CMDERR_HALTRESUME;
323 return true;
324 }
325
326 switch (size) {
327 case 2:
328 if (write)
329 write32(debug_rom_code, 0, lw(regnum, ZERO, DEBUG_EXCHANGE));
330 else
331 write32(debug_rom_code, 0, sw(regnum, ZERO, DEBUG_EXCHANGE));
332 break;
333 case 3:
334 if (write)
335 write32(debug_rom_code, 0, ld(regnum, ZERO, DEBUG_EXCHANGE));
336 else
337 write32(debug_rom_code, 0, sd(regnum, ZERO, DEBUG_EXCHANGE));
338 break;
339 /*
340 case 4:
341 if (write)
342 write32(debug_rom_code, 0, lq(regnum, ZERO, DEBUG_EXCHANGE));
343 else
344 write32(debug_rom_code, 0, sq(regnum, ZERO, DEBUG_EXCHANGE));
345 break;
346 */
347 default:
348 abstractcs.cmderr = abstractcs.CMDERR_NOTSUP;
349 return true;
350 }
351 if (get_field(command, AC_ACCESS_REGISTER_POSTEXEC)) {
352 write32(debug_rom_code, 1, jal(ZERO, DEBUG_RAM_START - DEBUG_ROM_CODE - 4));
353 } else {
354 write32(debug_rom_code, 1, ebreak());
355 }
356
357 if (get_field(command, AC_ACCESS_REGISTER_PREEXEC)) {
358 write32(debug_rom_entry, dmcontrol.hartsel,
359 jal(ZERO, DEBUG_RAM_START - (DEBUG_ROM_ENTRY + 4 * dmcontrol.hartsel)));
360 next_action =
361 jal(ZERO, DEBUG_ROM_CODE - (DEBUG_ROM_ENTRY + 4 * dmcontrol.hartsel));
362 } else {
363 write32(debug_rom_entry, dmcontrol.hartsel,
364 jal(ZERO, DEBUG_ROM_CODE - (DEBUG_ROM_ENTRY + 4 * dmcontrol.hartsel)));
365 }
366
367 write32(debug_rom_exception, dmcontrol.hartsel,
368 jal(ZERO, (DEBUG_ROM_ENTRY + 4 * dmcontrol.hartsel) - DEBUG_ROM_EXCEPTION));
369 abstractcs.busy = true;
370 } else {
371 abstractcs.cmderr = abstractcs.CMDERR_NOTSUP;
372 }
373 return true;
374 }
375
376 bool debug_module_t::dmi_write(unsigned address, uint32_t value)
377 {
378 D(fprintf(stderr, "dmi_write(0x%x, 0x%x)\n", address, value));
379 if (address >= DMI_DATA0 && address < DMI_DATA0 + abstractcs.datacount) {
380 unsigned i = address - DMI_DATA0;
381 dmdata.write32(4 * i, value);
382
383 if (abstractcs.busy && abstractcs.cmderr == abstractcs.CMDERR_NONE) {
384 abstractcs.cmderr = abstractcs.CMDERR_BUSY;
385 }
386
387 bool autoexec = false;
388 switch (i) {
389 case 0: autoexec = abstractcs.autoexec0; break;
390 case 1: autoexec = abstractcs.autoexec1; break;
391 case 2: autoexec = abstractcs.autoexec2; break;
392 case 3: autoexec = abstractcs.autoexec3; break;
393 case 4: autoexec = abstractcs.autoexec4; break;
394 case 5: autoexec = abstractcs.autoexec5; break;
395 case 6: autoexec = abstractcs.autoexec6; break;
396 case 7: autoexec = abstractcs.autoexec7; break;
397 }
398 if (autoexec) {
399 perform_abstract_command();
400 }
401 return true;
402
403 } else if (address >= DMI_IBUF0 && address < DMI_IBUF0 + progsize) {
404 write32(program_buffer, address - DMI_IBUF0, value);
405 return true;
406 } else {
407 switch (address) {
408 case DMI_DMCONTROL:
409 {
410 dmcontrol.dmactive = get_field(value, DMI_DMCONTROL_DMACTIVE);
411 if (dmcontrol.dmactive) {
412 dmcontrol.haltreq = get_field(value, DMI_DMCONTROL_HALTREQ);
413 dmcontrol.resumereq = get_field(value, DMI_DMCONTROL_RESUMEREQ);
414 dmcontrol.reset = get_field(value, DMI_DMCONTROL_RESET);
415 dmcontrol.hartsel = get_field(value, DMI_DMCONTROL_HARTSEL);
416 } else {
417 reset();
418 }
419 processor_t *proc = current_proc();
420 if (proc) {
421 proc->halt_request = dmcontrol.haltreq;
422 if (dmcontrol.resumereq) {
423 write32(debug_rom_code, 0, dret());
424 write32(debug_rom_entry, dmcontrol.hartsel,
425 jal(ZERO, DEBUG_ROM_CODE - (DEBUG_ROM_ENTRY + 4 * dmcontrol.hartsel)));
426 abstractcs.busy = true;
427 }
428 }
429 }
430 return true;
431
432 case DMI_COMMAND:
433 command = value;
434 return perform_abstract_command();
435
436 case DMI_ABSTRACTCS:
437 abstractcs.autoexec7 = get_field(value, DMI_ABSTRACTCS_AUTOEXEC7);
438 abstractcs.autoexec6 = get_field(value, DMI_ABSTRACTCS_AUTOEXEC6);
439 abstractcs.autoexec5 = get_field(value, DMI_ABSTRACTCS_AUTOEXEC5);
440 abstractcs.autoexec4 = get_field(value, DMI_ABSTRACTCS_AUTOEXEC4);
441 abstractcs.autoexec3 = get_field(value, DMI_ABSTRACTCS_AUTOEXEC3);
442 abstractcs.autoexec2 = get_field(value, DMI_ABSTRACTCS_AUTOEXEC2);
443 abstractcs.autoexec1 = get_field(value, DMI_ABSTRACTCS_AUTOEXEC1);
444 abstractcs.autoexec0 = get_field(value, DMI_ABSTRACTCS_AUTOEXEC0);
445 if (get_field(value, DMI_ABSTRACTCS_CMDERR) == abstractcs.CMDERR_NONE) {
446 abstractcs.cmderr = abstractcs.CMDERR_NONE;
447 }
448 return true;
449 }
450 }
451 return false;
452 }