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
, unsigned progbufsize
) :
20 progbufsize(progbufsize
),
21 program_buffer_bytes(4 + 4*progbufsize
),
22 debug_progbuf_start(debug_data_start
- program_buffer_bytes
),
23 debug_abstract_start(debug_progbuf_start
- debug_abstract_size
*4),
29 dmstatus
.impebreak
= true;
30 dmstatus
.authenticated
= 1;
34 abstractcs
.progbufsize
= progbufsize
;
38 program_buffer
= new uint8_t[program_buffer_bytes
];
40 memset(halted
, 0, sizeof(halted
));
41 memset(debug_rom_flags
, 0, sizeof(debug_rom_flags
));
42 memset(resumeack
, 0, sizeof(resumeack
));
43 memset(program_buffer
, 0, program_buffer_bytes
);
44 program_buffer
[4*progbufsize
] = ebreak();
45 program_buffer
[4*progbufsize
+1] = ebreak() >> 8;
46 program_buffer
[4*progbufsize
+2] = ebreak() >> 16;
47 program_buffer
[4*progbufsize
+3] = ebreak() >> 24;
48 memset(dmdata
, 0, sizeof(dmdata
));
50 write32(debug_rom_whereto
, 0,
51 jal(ZERO
, debug_abstract_start
- DEBUG_ROM_WHERETO
));
53 memset(debug_abstract
, 0, sizeof(debug_abstract
));
56 debug_module_t::~debug_module_t()
58 delete[] program_buffer
;
61 void debug_module_t::reset()
63 for (unsigned i
= 0; i
< sim
->nprocs(); i
++) {
64 processor_t
*proc
= sim
->get_core(i
);
66 proc
->halt_request
= false;
72 dmstatus
.impebreak
= true;
73 dmstatus
.authenticated
= 1;
77 abstractcs
.datacount
= sizeof(dmdata
) / 4;
78 abstractcs
.progbufsize
= progbufsize
;
83 void debug_module_t::add_device(bus_t
*bus
) {
84 bus
->add_device(DEBUG_START
, this);
87 bool debug_module_t::load(reg_t addr
, size_t len
, uint8_t* bytes
)
89 addr
= DEBUG_START
+ addr
;
91 if (addr
>= DEBUG_ROM_ENTRY
&&
92 (addr
+ len
) <= (DEBUG_ROM_ENTRY
+ debug_rom_raw_len
)) {
93 memcpy(bytes
, debug_rom_raw
+ addr
- DEBUG_ROM_ENTRY
, len
);
97 if (addr
>= DEBUG_ROM_WHERETO
&& (addr
+ len
) <= (DEBUG_ROM_WHERETO
+ 4)) {
98 memcpy(bytes
, debug_rom_whereto
+ addr
- DEBUG_ROM_WHERETO
, len
);
102 if (addr
>= DEBUG_ROM_FLAGS
&& ((addr
+ len
) <= DEBUG_ROM_FLAGS
+ 1024)) {
103 memcpy(bytes
, debug_rom_flags
+ addr
- DEBUG_ROM_FLAGS
, len
);
107 if (addr
>= debug_abstract_start
&& ((addr
+ len
) <= (debug_abstract_start
+ sizeof(debug_abstract
)))) {
108 memcpy(bytes
, debug_abstract
+ addr
- debug_abstract_start
, len
);
112 if (addr
>= debug_data_start
&& (addr
+ len
) <= (debug_data_start
+ sizeof(dmdata
))) {
113 memcpy(bytes
, dmdata
+ addr
- debug_data_start
, len
);
117 if (addr
>= debug_progbuf_start
&& ((addr
+ len
) <= (debug_progbuf_start
+ program_buffer_bytes
))) {
118 memcpy(bytes
, program_buffer
+ addr
- debug_progbuf_start
, len
);
122 fprintf(stderr
, "ERROR: invalid load from debug module: %zd bytes at 0x%016"
123 PRIx64
"\n", len
, addr
);
128 bool debug_module_t::store(reg_t addr
, size_t len
, const uint8_t* bytes
)
133 fprintf(stderr
, "store(addr=0x%lx, len=%d, bytes=0x%08x); "
134 "hartsel=0x%x\n", addr
, (unsigned) len
, *(uint32_t *) bytes
,
138 fprintf(stderr
, "store(addr=0x%lx, len=%d, bytes=...); "
139 "hartsel=0x%x\n", addr
, (unsigned) len
, dmcontrol
.hartsel
);
147 memcpy(id_bytes
, bytes
, 4);
148 id
= read32(id_bytes
, 0);
151 addr
= DEBUG_START
+ addr
;
153 if (addr
>= debug_data_start
&& (addr
+ len
) <= (debug_data_start
+ sizeof(dmdata
))) {
154 memcpy(dmdata
+ addr
- debug_data_start
, bytes
, len
);
158 if (addr
>= debug_progbuf_start
&& ((addr
+ len
) <= (debug_progbuf_start
+ program_buffer_bytes
))) {
159 memcpy(program_buffer
+ addr
- debug_progbuf_start
, bytes
, len
);
164 if (addr
== DEBUG_ROM_HALTED
) {
167 if (dmcontrol
.hartsel
== id
) {
168 if (0 == (debug_rom_flags
[id
] & (1 << DEBUG_ROM_FLAG_GO
))){
169 if (dmcontrol
.hartsel
== id
) {
170 abstractcs
.busy
= false;
177 if (addr
== DEBUG_ROM_GOING
) {
178 debug_rom_flags
[dmcontrol
.hartsel
] &= ~(1 << DEBUG_ROM_FLAG_GO
);
182 if (addr
== DEBUG_ROM_RESUMING
) {
185 resumeack
[id
] = true;
186 debug_rom_flags
[id
] &= ~(1 << DEBUG_ROM_FLAG_RESUME
);
190 if (addr
== DEBUG_ROM_EXCEPTION
) {
191 if (abstractcs
.cmderr
== CMDERR_NONE
) {
192 abstractcs
.cmderr
= CMDERR_EXCEPTION
;
197 fprintf(stderr
, "ERROR: invalid store to debug module: %zd bytes at 0x%016"
198 PRIx64
"\n", len
, addr
);
202 void debug_module_t::write32(uint8_t *memory
, unsigned int index
, uint32_t value
)
204 uint8_t* base
= memory
+ index
* 4;
205 base
[0] = value
& 0xff;
206 base
[1] = (value
>> 8) & 0xff;
207 base
[2] = (value
>> 16) & 0xff;
208 base
[3] = (value
>> 24) & 0xff;
211 uint32_t debug_module_t::read32(uint8_t *memory
, unsigned int index
)
213 uint8_t* base
= memory
+ index
* 4;
214 uint32_t value
= ((uint32_t) base
[0]) |
215 (((uint32_t) base
[1]) << 8) |
216 (((uint32_t) base
[2]) << 16) |
217 (((uint32_t) base
[3]) << 24);
221 processor_t
*debug_module_t::current_proc() const
223 processor_t
*proc
= NULL
;
225 proc
= sim
->get_core(dmcontrol
.hartsel
);
226 } catch (const std::out_of_range
&) {
231 bool debug_module_t::dmi_read(unsigned address
, uint32_t *value
)
234 D(fprintf(stderr
, "dmi_read(0x%x) -> ", address
));
235 if (address
>= DMI_DATA0
&& address
< DMI_DATA0
+ abstractcs
.datacount
) {
236 unsigned i
= address
- DMI_DATA0
;
237 result
= read32(dmdata
, i
);
238 if (abstractcs
.busy
) {
240 fprintf(stderr
, "\ndmi_read(0x%02x (data[%d]) -> -1 because abstractcs.busy==true\n", address
, i
);
243 if (abstractcs
.busy
&& abstractcs
.cmderr
== CMDERR_NONE
) {
244 abstractcs
.cmderr
= CMDERR_BUSY
;
247 if (!abstractcs
.busy
&& ((abstractauto
.autoexecdata
>> i
) & 1)) {
248 perform_abstract_command();
250 } else if (address
>= DMI_PROGBUF0
&& address
< DMI_PROGBUF0
+ progbufsize
) {
251 unsigned i
= address
- DMI_PROGBUF0
;
252 result
= read32(program_buffer
, i
);
253 if (abstractcs
.busy
) {
255 fprintf(stderr
, "\ndmi_read(0x%02x (progbuf[%d]) -> -1 because abstractcs.busy==true\n", address
, i
);
257 if (!abstractcs
.busy
&& ((abstractauto
.autoexecprogbuf
>> i
) & 1)) {
258 perform_abstract_command();
265 processor_t
*proc
= current_proc();
267 dmcontrol
.haltreq
= proc
->halt_request
;
269 result
= set_field(result
, DMI_DMCONTROL_HALTREQ
, dmcontrol
.haltreq
);
270 result
= set_field(result
, DMI_DMCONTROL_RESUMEREQ
, dmcontrol
.resumereq
);
271 result
= set_field(result
, DMI_DMCONTROL_HARTSEL
, dmcontrol
.hartsel
);
272 result
= set_field(result
, DMI_DMCONTROL_HARTRESET
, dmcontrol
.hartreset
);
273 result
= set_field(result
, DMI_DMCONTROL_NDMRESET
, dmcontrol
.ndmreset
);
274 result
= set_field(result
, DMI_DMCONTROL_DMACTIVE
, dmcontrol
.dmactive
);
279 processor_t
*proc
= current_proc();
281 dmstatus
.allnonexistant
= false;
282 dmstatus
.allunavail
= false;
283 dmstatus
.allrunning
= false;
284 dmstatus
.allhalted
= false;
285 dmstatus
.allresumeack
= false;
287 if (halted
[dmcontrol
.hartsel
]) {
288 dmstatus
.allhalted
= true;
290 dmstatus
.allrunning
= true;
293 dmstatus
.allnonexistant
= true;
295 dmstatus
.anynonexistant
= dmstatus
.allnonexistant
;
296 dmstatus
.anyunavail
= dmstatus
.allunavail
;
297 dmstatus
.anyrunning
= dmstatus
.allrunning
;
298 dmstatus
.anyhalted
= dmstatus
.allhalted
;
300 if (resumeack
[dmcontrol
.hartsel
]) {
301 dmstatus
.allresumeack
= true;
303 dmstatus
.allresumeack
= false;
306 dmstatus
.allresumeack
= false;
309 result
= set_field(result
, DMI_DMSTATUS_IMPEBREAK
,
311 result
= set_field(result
, DMI_DMSTATUS_ALLNONEXISTENT
, dmstatus
.allnonexistant
);
312 result
= set_field(result
, DMI_DMSTATUS_ALLUNAVAIL
, dmstatus
.allunavail
);
313 result
= set_field(result
, DMI_DMSTATUS_ALLRUNNING
, dmstatus
.allrunning
);
314 result
= set_field(result
, DMI_DMSTATUS_ALLHALTED
, dmstatus
.allhalted
);
315 result
= set_field(result
, DMI_DMSTATUS_ALLRESUMEACK
, dmstatus
.allresumeack
);
316 result
= set_field(result
, DMI_DMSTATUS_ANYNONEXISTENT
, dmstatus
.anynonexistant
);
317 result
= set_field(result
, DMI_DMSTATUS_ANYUNAVAIL
, dmstatus
.anyunavail
);
318 result
= set_field(result
, DMI_DMSTATUS_ANYRUNNING
, dmstatus
.anyrunning
);
319 result
= set_field(result
, DMI_DMSTATUS_ANYHALTED
, dmstatus
.anyhalted
);
320 result
= set_field(result
, DMI_DMSTATUS_ANYRESUMEACK
, dmstatus
.anyresumeack
);
321 result
= set_field(result
, DMI_DMSTATUS_AUTHENTICATED
, dmstatus
.authenticated
);
322 result
= set_field(result
, DMI_DMSTATUS_AUTHBUSY
, dmstatus
.authbusy
);
323 result
= set_field(result
, DMI_DMSTATUS_VERSION
, dmstatus
.version
);
327 result
= set_field(result
, DMI_ABSTRACTCS_CMDERR
, abstractcs
.cmderr
);
328 result
= set_field(result
, DMI_ABSTRACTCS_BUSY
, abstractcs
.busy
);
329 result
= set_field(result
, DMI_ABSTRACTCS_DATACOUNT
, abstractcs
.datacount
);
330 result
= set_field(result
, DMI_ABSTRACTCS_PROGBUFSIZE
,
331 abstractcs
.progbufsize
);
333 case DMI_ABSTRACTAUTO
:
334 result
= set_field(result
, DMI_ABSTRACTAUTO_AUTOEXECPROGBUF
, abstractauto
.autoexecprogbuf
);
335 result
= set_field(result
, DMI_ABSTRACTAUTO_AUTOEXECDATA
, abstractauto
.autoexecdata
);
341 result
= set_field(result
, DMI_HARTINFO_NSCRATCH
, 1);
342 result
= set_field(result
, DMI_HARTINFO_DATAACCESS
, 1);
343 result
= set_field(result
, DMI_HARTINFO_DATASIZE
, abstractcs
.datacount
);
344 result
= set_field(result
, DMI_HARTINFO_DATAADDR
, debug_data_start
);
348 D(fprintf(stderr
, "Unexpected. Returning Error."));
352 D(fprintf(stderr
, "0x%x\n", result
));
357 bool debug_module_t::perform_abstract_command()
359 if (abstractcs
.cmderr
!= CMDERR_NONE
)
361 if (abstractcs
.busy
) {
362 abstractcs
.cmderr
= CMDERR_BUSY
;
366 if ((command
>> 24) == 0) {
368 unsigned size
= get_field(command
, AC_ACCESS_REGISTER_SIZE
);
369 bool write
= get_field(command
, AC_ACCESS_REGISTER_WRITE
);
370 unsigned regno
= get_field(command
, AC_ACCESS_REGISTER_REGNO
);
372 if (!halted
[dmcontrol
.hartsel
]) {
373 abstractcs
.cmderr
= CMDERR_HALTRESUME
;
377 if (get_field(command
, AC_ACCESS_REGISTER_TRANSFER
)) {
379 if (regno
< 0x1000 || regno
>= 0x1020) {
380 abstractcs
.cmderr
= CMDERR_NOTSUP
;
384 unsigned regnum
= regno
- 0x1000;
389 write32(debug_abstract
, 0, lw(regnum
, ZERO
, debug_data_start
));
391 write32(debug_abstract
, 0, sw(regnum
, ZERO
, debug_data_start
));
395 write32(debug_abstract
, 0, ld(regnum
, ZERO
, debug_data_start
));
397 write32(debug_abstract
, 0, sd(regnum
, ZERO
, debug_data_start
));
402 write32(debug_rom_code, 0, lq(regnum, ZERO, debug_data_start));
404 write32(debug_rom_code, 0, sq(regnum, ZERO, debug_data_start));
408 abstractcs
.cmderr
= CMDERR_NOTSUP
;
413 write32(debug_abstract
, 0, addi(ZERO
, ZERO
, 0));
416 if (get_field(command
, AC_ACCESS_REGISTER_POSTEXEC
)) {
417 // Since the next instruction is what we will use, just use nother NOP
419 write32(debug_abstract
, 1, addi(ZERO
, ZERO
, 0));
421 write32(debug_abstract
, 1, ebreak());
424 debug_rom_flags
[dmcontrol
.hartsel
] |= 1 << DEBUG_ROM_FLAG_GO
;
426 abstractcs
.busy
= true;
428 abstractcs
.cmderr
= CMDERR_NOTSUP
;
433 bool debug_module_t::dmi_write(unsigned address
, uint32_t value
)
435 D(fprintf(stderr
, "dmi_write(0x%x, 0x%x)\n", address
, value
));
436 if (address
>= DMI_DATA0
&& address
< DMI_DATA0
+ abstractcs
.datacount
) {
437 unsigned i
= address
- DMI_DATA0
;
438 if (!abstractcs
.busy
)
439 write32(dmdata
, address
- DMI_DATA0
, value
);
441 if (abstractcs
.busy
&& abstractcs
.cmderr
== CMDERR_NONE
) {
442 abstractcs
.cmderr
= CMDERR_BUSY
;
445 if (!abstractcs
.busy
&& ((abstractauto
.autoexecdata
>> i
) & 1)) {
446 perform_abstract_command();
450 } else if (address
>= DMI_PROGBUF0
&& address
< DMI_PROGBUF0
+ progbufsize
) {
451 unsigned i
= address
- DMI_PROGBUF0
;
453 if (!abstractcs
.busy
)
454 write32(program_buffer
, i
, value
);
456 if (!abstractcs
.busy
&& ((abstractauto
.autoexecprogbuf
>> i
) & 1)) {
457 perform_abstract_command();
465 dmcontrol
.dmactive
= get_field(value
, DMI_DMCONTROL_DMACTIVE
);
466 if (dmcontrol
.dmactive
) {
467 dmcontrol
.haltreq
= get_field(value
, DMI_DMCONTROL_HALTREQ
);
468 dmcontrol
.resumereq
= get_field(value
, DMI_DMCONTROL_RESUMEREQ
);
469 dmcontrol
.hartreset
= get_field(value
, DMI_DMCONTROL_HARTRESET
);
470 dmcontrol
.ndmreset
= get_field(value
, DMI_DMCONTROL_NDMRESET
);
471 dmcontrol
.hartsel
= get_field(value
, DMI_DMCONTROL_HARTSEL
);
475 processor_t
*proc
= current_proc();
477 proc
->halt_request
= dmcontrol
.haltreq
;
478 if (dmcontrol
.resumereq
) {
479 debug_rom_flags
[dmcontrol
.hartsel
] |= (1 << DEBUG_ROM_FLAG_RESUME
);
480 resumeack
[dmcontrol
.hartsel
] = false;
482 if (dmcontrol
.hartreset
) {
486 if (dmcontrol
.ndmreset
) {
487 for (size_t i
= 0; i
< sim
->nprocs(); i
++) {
488 proc
= sim
->get_core(i
);
497 return perform_abstract_command();
500 abstractcs
.cmderr
= (cmderr_t
) (((uint32_t) (abstractcs
.cmderr
)) & (~(uint32_t)(get_field(value
, DMI_ABSTRACTCS_CMDERR
))));
503 case DMI_ABSTRACTAUTO
:
504 abstractauto
.autoexecprogbuf
= get_field(value
,
505 DMI_ABSTRACTAUTO_AUTOEXECPROGBUF
);
506 abstractauto
.autoexecdata
= get_field(value
,
507 DMI_ABSTRACTAUTO_AUTOEXECDATA
);