3 #include "debug_module.h"
4 #include "debug_defines.h"
8 #include "debug_rom/debug_rom.h"
9 #include "debug_rom/debug_rom_defines.h"
17 ///////////////////////// debug_module_t
19 debug_module_t::debug_module_t(sim_t
*sim
) : sim(sim
)
24 dmstatus
.authenticated
= 1;
25 dmstatus
.versionlo
= 2;
28 abstractcs
.progsize
= progsize
;
32 memset(halted
, 0, sizeof(halted
));
33 memset(debug_rom_flags
, 0, sizeof(debug_rom_flags
));
34 memset(resumeack
, 0, sizeof(resumeack
));
35 memset(program_buffer
, 0, sizeof(program_buffer
));
36 memset(dmdata
, 0, sizeof(dmdata
));
38 write32(debug_rom_whereto
, 0,
39 jal(ZERO
, debug_abstract_start
- DEBUG_ROM_WHERETO
));
41 memset(debug_abstract
, 0, sizeof(debug_abstract
));
45 void debug_module_t::reset()
47 for (unsigned i
= 0; i
< sim
->nprocs(); i
++) {
48 processor_t
*proc
= sim
->get_core(i
);
50 proc
->halt_request
= false;
56 dmstatus
.authenticated
= 1;
57 dmstatus
.versionlo
= 2;
60 abstractcs
.datacount
= sizeof(dmdata
) / 4;
61 abstractcs
.progsize
= progsize
;
66 void debug_module_t::add_device(bus_t
*bus
) {
67 bus
->add_device(DEBUG_START
, this);
70 bool debug_module_t::load(reg_t addr
, size_t len
, uint8_t* bytes
)
72 addr
= DEBUG_START
+ addr
;
74 if (addr
>= DEBUG_ROM_ENTRY
&&
75 (addr
+ len
) <= (DEBUG_ROM_ENTRY
+ debug_rom_raw_len
)) {
76 memcpy(bytes
, debug_rom_raw
+ addr
- DEBUG_ROM_ENTRY
, len
);
80 if (addr
>= DEBUG_ROM_WHERETO
&& (addr
+ len
) <= (DEBUG_ROM_WHERETO
+ 4)) {
81 memcpy(bytes
, debug_rom_whereto
+ addr
- DEBUG_ROM_WHERETO
, len
);
85 if (addr
>= DEBUG_ROM_FLAGS
&& ((addr
+ len
) <= DEBUG_ROM_FLAGS
+ 1024)) {
86 memcpy(bytes
, debug_rom_flags
+ addr
- DEBUG_ROM_FLAGS
, len
);
90 if (addr
>= debug_abstract_start
&& ((addr
+ len
) <= (debug_abstract_start
+ sizeof(debug_abstract
)))) {
91 memcpy(bytes
, debug_abstract
+ addr
- debug_abstract_start
, len
);
95 if (addr
>= debug_data_start
&& (addr
+ len
) <= (debug_data_start
+ sizeof(dmdata
))) {
96 memcpy(bytes
, dmdata
+ addr
- debug_data_start
, len
);
100 if (addr
>= debug_progbuf_start
&& ((addr
+ len
) <= (debug_progbuf_start
+ sizeof(program_buffer
)))) {
101 memcpy(bytes
, program_buffer
+ addr
- debug_progbuf_start
, len
);
105 fprintf(stderr
, "ERROR: invalid load from debug module: %zd bytes at 0x%016"
106 PRIx64
"\n", len
, addr
);
111 bool debug_module_t::store(reg_t addr
, size_t len
, const uint8_t* bytes
)
117 memcpy(id_bytes
, bytes
, 4);
118 id
= read32(id_bytes
, 0);
121 addr
= DEBUG_START
+ addr
;
123 if (addr
>= debug_data_start
&& (addr
+ len
) <= (debug_data_start
+ sizeof(dmdata
))) {
124 memcpy(dmdata
+ addr
- debug_data_start
, bytes
, len
);
128 if (addr
>= debug_progbuf_start
&& ((addr
+ len
) <= (debug_progbuf_start
+ sizeof(program_buffer
)))) {
129 fprintf(stderr
, "Successful write to program buffer %d bytes at %x\n", (int) len
, (int) addr
);
130 memcpy(program_buffer
+ addr
- debug_progbuf_start
, bytes
, len
);
135 if (addr
== DEBUG_ROM_HALTED
) {
138 if (dmcontrol
.hartsel
== id
) {
139 if (0 == (debug_rom_flags
[id
] & (1 << DEBUG_ROM_FLAG_GO
))){
140 if (dmcontrol
.hartsel
== id
) {
141 abstractcs
.busy
= false;
148 if (addr
== DEBUG_ROM_GOING
) {
149 debug_rom_flags
[dmcontrol
.hartsel
] &= ~(1 << DEBUG_ROM_FLAG_GO
);
153 if (addr
== DEBUG_ROM_RESUMING
) {
156 resumeack
[id
] = true;
157 debug_rom_flags
[id
] &= ~(1 << DEBUG_ROM_FLAG_RESUME
);
161 if (addr
== DEBUG_ROM_EXCEPTION
) {
162 if (abstractcs
.cmderr
== CMDERR_NONE
) {
163 abstractcs
.cmderr
= CMDERR_EXCEPTION
;
168 fprintf(stderr
, "ERROR: invalid store to debug module: %zd bytes at 0x%016"
169 PRIx64
"\n", len
, addr
);
173 void debug_module_t::write32(uint8_t *memory
, unsigned int index
, uint32_t value
)
175 uint8_t* base
= memory
+ index
* 4;
176 base
[0] = value
& 0xff;
177 base
[1] = (value
>> 8) & 0xff;
178 base
[2] = (value
>> 16) & 0xff;
179 base
[3] = (value
>> 24) & 0xff;
182 uint32_t debug_module_t::read32(uint8_t *memory
, unsigned int index
)
184 uint8_t* base
= memory
+ index
* 4;
185 uint32_t value
= ((uint32_t) base
[0]) |
186 (((uint32_t) base
[1]) << 8) |
187 (((uint32_t) base
[2]) << 16) |
188 (((uint32_t) base
[3]) << 24);
192 processor_t
*debug_module_t::current_proc() const
194 processor_t
*proc
= NULL
;
196 proc
= sim
->get_core(dmcontrol
.hartsel
);
197 } catch (const std::out_of_range
&) {
202 bool debug_module_t::dmi_read(unsigned address
, uint32_t *value
)
205 D(fprintf(stderr
, "dmi_read(0x%x) -> ", address
));
206 if (address
>= DMI_DATA0
&& address
< DMI_DATA0
+ abstractcs
.datacount
) {
207 unsigned i
= address
- DMI_DATA0
;
208 result
= abstractcs
.busy
? -1 : read32(dmdata
, i
);
210 if (abstractcs
.busy
&& abstractcs
.cmderr
== CMDERR_NONE
) {
211 abstractcs
.cmderr
= CMDERR_BUSY
;
214 if (!abstractcs
.busy
&& ((abstractauto
.autoexecdata
>> i
) & 1)) {
215 perform_abstract_command();
217 } else if (address
>= DMI_PROGBUF0
&& address
< DMI_PROGBUF0
+ progsize
) {
218 unsigned i
= address
- DMI_PROGBUF0
;
219 result
= abstractcs
.busy
? -1 : read32(program_buffer
, i
);
220 if (!abstractcs
.busy
&& ((abstractauto
.autoexecprogbuf
>> i
) & 1)) {
221 perform_abstract_command();
228 processor_t
*proc
= current_proc();
230 dmcontrol
.haltreq
= proc
->halt_request
;
232 result
= set_field(result
, DMI_DMCONTROL_HALTREQ
, dmcontrol
.haltreq
);
233 result
= set_field(result
, DMI_DMCONTROL_RESUMEREQ
, dmcontrol
.resumereq
);
234 result
= set_field(result
, DMI_DMCONTROL_HARTSEL
, dmcontrol
.hartsel
);
235 result
= set_field(result
, DMI_DMCONTROL_HARTRESET
, dmcontrol
.hartreset
);
236 result
= set_field(result
, DMI_DMCONTROL_NDMRESET
, dmcontrol
.ndmreset
);
237 result
= set_field(result
, DMI_DMCONTROL_DMACTIVE
, dmcontrol
.dmactive
);
242 processor_t
*proc
= current_proc();
244 dmstatus
.allnonexistant
= false;
245 dmstatus
.allunavail
= false;
246 dmstatus
.allrunning
= false;
247 dmstatus
.allhalted
= false;
248 dmstatus
.allresumeack
= false;
250 if (halted
[dmcontrol
.hartsel
]) {
251 dmstatus
.allhalted
= true;
253 dmstatus
.allrunning
= true;
256 dmstatus
.allnonexistant
= true;
258 dmstatus
.anynonexistant
= dmstatus
.allnonexistant
;
259 dmstatus
.anyunavail
= dmstatus
.allunavail
;
260 dmstatus
.anyrunning
= dmstatus
.allrunning
;
261 dmstatus
.anyhalted
= dmstatus
.allhalted
;
263 if (resumeack
[dmcontrol
.hartsel
]) {
264 dmstatus
.allresumeack
= true;
266 dmstatus
.allresumeack
= false;
269 dmstatus
.allresumeack
= false;
272 result
= set_field(result
, DMI_DMSTATUS_ALLNONEXISTENT
, dmstatus
.allnonexistant
);
273 result
= set_field(result
, DMI_DMSTATUS_ALLUNAVAIL
, dmstatus
.allunavail
);
274 result
= set_field(result
, DMI_DMSTATUS_ALLRUNNING
, dmstatus
.allrunning
);
275 result
= set_field(result
, DMI_DMSTATUS_ALLHALTED
, dmstatus
.allhalted
);
276 result
= set_field(result
, DMI_DMSTATUS_ALLRESUMEACK
, dmstatus
.allresumeack
);
277 result
= set_field(result
, DMI_DMSTATUS_ANYNONEXISTENT
, dmstatus
.anynonexistant
);
278 result
= set_field(result
, DMI_DMSTATUS_ANYUNAVAIL
, dmstatus
.anyunavail
);
279 result
= set_field(result
, DMI_DMSTATUS_ANYRUNNING
, dmstatus
.anyrunning
);
280 result
= set_field(result
, DMI_DMSTATUS_ANYHALTED
, dmstatus
.anyhalted
);
281 result
= set_field(result
, DMI_DMSTATUS_ANYRESUMEACK
, dmstatus
.anyresumeack
);
282 result
= set_field(result
, DMI_DMSTATUS_AUTHENTICATED
, dmstatus
.authenticated
);
283 result
= set_field(result
, DMI_DMSTATUS_AUTHBUSY
, dmstatus
.authbusy
);
284 result
= set_field(result
, DMI_DMSTATUS_VERSIONHI
, dmstatus
.versionhi
);
285 result
= set_field(result
, DMI_DMSTATUS_VERSIONLO
, dmstatus
.versionlo
);
289 result
= set_field(result
, DMI_ABSTRACTCS_CMDERR
, abstractcs
.cmderr
);
290 result
= set_field(result
, DMI_ABSTRACTCS_BUSY
, abstractcs
.busy
);
291 result
= set_field(result
, DMI_ABSTRACTCS_DATACOUNT
, abstractcs
.datacount
);
292 result
= set_field(result
, DMI_ABSTRACTCS_PROGSIZE
, abstractcs
.progsize
);
294 case DMI_ABSTRACTAUTO
:
295 result
= set_field(result
, DMI_ABSTRACTAUTO_AUTOEXECPROGBUF
, abstractauto
.autoexecprogbuf
);
296 result
= set_field(result
, DMI_ABSTRACTAUTO_AUTOEXECDATA
, abstractauto
.autoexecdata
);
302 result
= set_field(result
, DMI_HARTINFO_NSCRATCH
, 1);
303 result
= set_field(result
, DMI_HARTINFO_DATAACCESS
, 1);
304 result
= set_field(result
, DMI_HARTINFO_DATASIZE
, abstractcs
.datacount
);
305 result
= set_field(result
, DMI_HARTINFO_DATAADDR
, debug_data_start
);
309 D(fprintf(stderr
, "Unexpected. Returning Error."));
313 D(fprintf(stderr
, "0x%x\n", result
));
318 bool debug_module_t::perform_abstract_command()
320 if (abstractcs
.cmderr
!= CMDERR_NONE
)
322 if (abstractcs
.busy
) {
323 abstractcs
.cmderr
= CMDERR_BUSY
;
327 if ((command
>> 24) == 0) {
329 unsigned size
= get_field(command
, AC_ACCESS_REGISTER_SIZE
);
330 bool write
= get_field(command
, AC_ACCESS_REGISTER_WRITE
);
331 unsigned regno
= get_field(command
, AC_ACCESS_REGISTER_REGNO
);
333 if (!halted
[dmcontrol
.hartsel
]) {
334 abstractcs
.cmderr
= CMDERR_HALTRESUME
;
338 if (get_field(command
, AC_ACCESS_REGISTER_TRANSFER
)) {
340 if (regno
< 0x1000 || regno
>= 0x1020) {
341 abstractcs
.cmderr
= CMDERR_NOTSUP
;
345 unsigned regnum
= regno
- 0x1000;
350 write32(debug_abstract
, 0, lw(regnum
, ZERO
, debug_data_start
));
352 write32(debug_abstract
, 0, sw(regnum
, ZERO
, debug_data_start
));
356 write32(debug_abstract
, 0, ld(regnum
, ZERO
, debug_data_start
));
358 write32(debug_abstract
, 0, sd(regnum
, ZERO
, debug_data_start
));
363 write32(debug_rom_code, 0, lq(regnum, ZERO, debug_data_start));
365 write32(debug_rom_code, 0, sq(regnum, ZERO, debug_data_start));
369 abstractcs
.cmderr
= CMDERR_NOTSUP
;
374 write32(debug_abstract
, 0, addi(ZERO
, ZERO
, 0));
377 if (get_field(command
, AC_ACCESS_REGISTER_POSTEXEC
)) {
378 // Since the next instruction is what we will use, just use nother NOP
380 write32(debug_abstract
, 1, addi(ZERO
, ZERO
, 0));
382 write32(debug_abstract
, 1, ebreak());
385 debug_rom_flags
[dmcontrol
.hartsel
] |= 1 << DEBUG_ROM_FLAG_GO
;
387 abstractcs
.busy
= true;
389 abstractcs
.cmderr
= CMDERR_NOTSUP
;
394 bool debug_module_t::dmi_write(unsigned address
, uint32_t value
)
396 D(fprintf(stderr
, "dmi_write(0x%x, 0x%x)\n", address
, value
));
397 if (address
>= DMI_DATA0
&& address
< DMI_DATA0
+ abstractcs
.datacount
) {
398 unsigned i
= address
- DMI_DATA0
;
399 if (!abstractcs
.busy
)
400 write32(dmdata
, address
- DMI_DATA0
, value
);
402 if (abstractcs
.busy
&& abstractcs
.cmderr
== CMDERR_NONE
) {
403 abstractcs
.cmderr
= CMDERR_BUSY
;
406 if (!abstractcs
.busy
&& ((abstractauto
.autoexecdata
>> i
) & 1)) {
407 perform_abstract_command();
411 } else if (address
>= DMI_PROGBUF0
&& address
< DMI_PROGBUF0
+ progsize
) {
412 unsigned i
= address
- DMI_PROGBUF0
;
414 if (!abstractcs
.busy
)
415 write32(program_buffer
, i
, value
);
417 if (!abstractcs
.busy
&& ((abstractauto
.autoexecprogbuf
>> i
) & 1)) {
418 perform_abstract_command();
426 dmcontrol
.dmactive
= get_field(value
, DMI_DMCONTROL_DMACTIVE
);
427 if (dmcontrol
.dmactive
) {
428 dmcontrol
.haltreq
= get_field(value
, DMI_DMCONTROL_HALTREQ
);
429 dmcontrol
.resumereq
= get_field(value
, DMI_DMCONTROL_RESUMEREQ
);
430 dmcontrol
.ndmreset
= get_field(value
, DMI_DMCONTROL_NDMRESET
);
431 dmcontrol
.hartsel
= get_field(value
, DMI_DMCONTROL_HARTSEL
);
435 processor_t
*proc
= current_proc();
437 proc
->halt_request
= dmcontrol
.haltreq
;
438 if (dmcontrol
.resumereq
) {
439 debug_rom_flags
[dmcontrol
.hartsel
] |= (1 << DEBUG_ROM_FLAG_RESUME
);
440 resumeack
[dmcontrol
.hartsel
] = false;
442 if (dmcontrol
.ndmreset
) {
451 return perform_abstract_command();
454 abstractcs
.cmderr
= (cmderr_t
) (((uint32_t) (abstractcs
.cmderr
)) & (~(uint32_t)(get_field(value
, DMI_ABSTRACTCS_CMDERR
))));
457 case DMI_ABSTRACTAUTO
:
458 abstractauto
.autoexecprogbuf
= get_field(value
, DMI_ABSTRACTAUTO_AUTOEXECPROGBUF
);
459 abstractauto
.autoexecdata
= get_field(value
, DMI_ABSTRACTAUTO_AUTOEXECDATA
);