target/xtensa: virtualize XDM registers
[openocd.git] / src / target / esirisc_trace.c
blob2f183cfd64b84048fa70ac3a133d34bdfaca01a3
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
3 /***************************************************************************
4 * Copyright (C) 2018 by Square, Inc. *
5 * Steven Stallion <stallion@squareup.com> *
6 ***************************************************************************/
8 #ifdef HAVE_CONFIG_H
9 #include "config.h"
10 #endif
12 #include <helper/binarybuffer.h>
13 #include <helper/command.h>
14 #include <helper/fileio.h>
15 #include <helper/log.h>
16 #include <helper/types.h>
17 #include <target/target.h>
19 #include "esirisc.h"
21 #define BIT_MASK(x) ((1 << (x)) - 1)
23 /* Control Fields */
24 #define CONTROL_ST (1<<0) /* Start */
25 #define CONTROL_SP (1<<1) /* Stop */
26 #define CONTROL_W (1<<2) /* Wrap */
27 #define CONTROL_FC (1<<3) /* Flow Control */
28 #define CONTROL_FMT(x) (((x) << 4) & 0x30) /* Format */
29 #define CONTROL_PCB(x) (((x) << 10) & 0x7c00) /* PC Bits */
31 /* Status Fields */
32 #define STATUS_T (1<<0) /* Trace Started */
33 #define STATUS_TD (1<<1) /* Trace Disabled */
34 #define STATUS_W (1<<2) /* Wrapped */
35 #define STATUS_O (1<<3) /* Overflow */
37 /* Trigger Fields */
38 #define TRIGGER_TST(x) (((x) << 0) & 0xf) /* Trigger Start */
39 #define TRIGGER_DST (1<<7) /* Delay Start */
40 #define TRIGGER_TSP(x) (((x) << 8) & 0xf00) /* Trigger Stop */
41 #define TRIGGER_DSP (1<<15) /* Delay Start */
43 static const char * const esirisc_trace_delay_strings[] = {
44 "none", "start", "stop", "both",
47 static const char * const esirisc_trace_format_strings[] = {
48 "full", "branch", "icache",
51 static const char * const esirisc_trace_id_strings[] = {
52 "sequential instruction",
53 "pipeline stall",
54 "direct branch",
55 "extended ID",
58 static const char * const esirisc_trace_ext_id_strings[] = {
59 "", /* unused */
60 "exception",
61 "eret",
62 "stop instruction",
63 "wait instruction",
64 "multicycle instruction",
65 "count",
66 "initial",
67 "indirect branch",
68 "end of trace",
69 "final",
72 static const char * const esirisc_trace_trigger_strings[] = {
73 "none", "pc", "load", "store", "exception", "eret", "wait", "stop",
74 "high", "low", /* start only */
77 static int esirisc_trace_clear_status(struct target *target)
79 struct esirisc_common *esirisc = target_to_esirisc(target);
80 struct esirisc_jtag *jtag_info = &esirisc->jtag_info;
81 int retval;
83 if (target->state != TARGET_HALTED)
84 return ERROR_TARGET_NOT_HALTED;
86 retval = esirisc_jtag_write_csr(jtag_info, CSR_TRACE, CSR_TRACE_STATUS, ~0);
87 if (retval != ERROR_OK) {
88 LOG_ERROR("%s: failed to write Trace CSR: Status", target_name(target));
89 return retval;
92 return ERROR_OK;
95 static int esirisc_trace_get_status(struct target *target, uint32_t *status)
97 struct esirisc_common *esirisc = target_to_esirisc(target);
98 struct esirisc_jtag *jtag_info = &esirisc->jtag_info;
100 if (target->state != TARGET_HALTED)
101 return ERROR_TARGET_NOT_HALTED;
103 int retval = esirisc_jtag_read_csr(jtag_info, CSR_TRACE, CSR_TRACE_STATUS, status);
104 if (retval != ERROR_OK) {
105 LOG_ERROR("%s: failed to read Trace CSR: Status", target_name(target));
106 return retval;
109 return ERROR_OK;
112 static int esirisc_trace_start(struct target *target)
114 struct esirisc_common *esirisc = target_to_esirisc(target);
115 struct esirisc_jtag *jtag_info = &esirisc->jtag_info;
116 uint32_t control;
117 int retval;
119 if (target->state != TARGET_HALTED)
120 return ERROR_TARGET_NOT_HALTED;
122 retval = esirisc_jtag_read_csr(jtag_info, CSR_TRACE, CSR_TRACE_CONTROL, &control);
123 if (retval != ERROR_OK) {
124 LOG_ERROR("%s: failed to read Trace CSR: Control", target_name(target));
125 return retval;
128 control |= CONTROL_ST;
130 retval = esirisc_jtag_write_csr(jtag_info, CSR_TRACE, CSR_TRACE_CONTROL, control);
131 if (retval != ERROR_OK) {
132 LOG_ERROR("%s: failed to write Trace CSR: Control", target_name(target));
133 return retval;
136 return ERROR_OK;
139 static int esirisc_trace_stop(struct target *target)
141 struct esirisc_common *esirisc = target_to_esirisc(target);
142 struct esirisc_jtag *jtag_info = &esirisc->jtag_info;
143 uint32_t control;
144 int retval;
146 if (target->state != TARGET_HALTED)
147 return ERROR_TARGET_NOT_HALTED;
149 retval = esirisc_jtag_read_csr(jtag_info, CSR_TRACE, CSR_TRACE_CONTROL, &control);
150 if (retval != ERROR_OK) {
151 LOG_ERROR("%s: failed to read Trace CSR: Control", target_name(target));
152 return retval;
155 control |= CONTROL_SP;
157 retval = esirisc_jtag_write_csr(jtag_info, CSR_TRACE, CSR_TRACE_CONTROL, control);
158 if (retval != ERROR_OK) {
159 LOG_ERROR("%s: failed to write Trace CSR: Control", target_name(target));
160 return retval;
163 return ERROR_OK;
166 static int esirisc_trace_init(struct target *target)
168 struct esirisc_common *esirisc = target_to_esirisc(target);
169 struct esirisc_jtag *jtag_info = &esirisc->jtag_info;
170 struct esirisc_trace *trace_info = &esirisc->trace_info;
171 uint32_t control, trigger;
172 int retval;
174 if (target->state != TARGET_HALTED)
175 return ERROR_TARGET_NOT_HALTED;
177 /* stop if running and clear status */
178 retval = esirisc_trace_stop(target);
179 if (retval != ERROR_OK)
180 return retval;
182 retval = esirisc_trace_clear_status(target);
183 if (retval != ERROR_OK)
184 return retval;
186 /* initialize Control CSR */
187 control = CONTROL_FMT(trace_info->format)
188 | CONTROL_PCB(trace_info->pc_bits);
190 if (trace_info->buffer_wrap)
191 control |= CONTROL_W;
193 if (trace_info->flow_control)
194 control |= CONTROL_FC;
196 retval = esirisc_jtag_write_csr(jtag_info, CSR_TRACE, CSR_TRACE_CONTROL, control);
197 if (retval != ERROR_OK) {
198 LOG_ERROR("%s: failed to write Trace CSR: Control", target_name(target));
199 return retval;
202 /* initialize buffer CSRs */
203 retval = esirisc_jtag_write_csr(jtag_info, CSR_TRACE, CSR_TRACE_BUFFER_START,
204 trace_info->buffer_start);
205 if (retval != ERROR_OK) {
206 LOG_ERROR("%s: failed to write Trace CSR: BufferStart", target_name(target));
207 return retval;
210 retval = esirisc_jtag_write_csr(jtag_info, CSR_TRACE, CSR_TRACE_BUFFER_END,
211 trace_info->buffer_end);
212 if (retval != ERROR_OK) {
213 LOG_ERROR("%s: failed to write Trace CSR: BufferEnd", target_name(target));
214 return retval;
218 * The BufferCurrent CSR must be initialized to the same value as
219 * BufferStart before tracing can be enabled:
221 retval = esirisc_jtag_write_csr(jtag_info, CSR_TRACE, CSR_TRACE_BUFFER_CUR,
222 trace_info->buffer_start);
223 if (retval != ERROR_OK) {
224 LOG_ERROR("%s: failed to write Trace CSR: BufferCurrent", target_name(target));
225 return retval;
228 /* initialize Trigger CSR */
229 trigger = TRIGGER_TST(trace_info->start_trigger)
230 | TRIGGER_TSP(trace_info->stop_trigger);
232 if (trace_info->delay == ESIRISC_TRACE_DELAY_START
233 || trace_info->delay == ESIRISC_TRACE_DELAY_BOTH) {
234 trigger |= TRIGGER_DST;
237 if (trace_info->delay == ESIRISC_TRACE_DELAY_STOP
238 || trace_info->delay == ESIRISC_TRACE_DELAY_BOTH) {
239 trigger |= TRIGGER_DSP;
242 retval = esirisc_jtag_write_csr(jtag_info, CSR_TRACE, CSR_TRACE_TRIGGER, trigger);
243 if (retval != ERROR_OK) {
244 LOG_ERROR("%s: failed to write Trace CSR: Trigger", target_name(target));
245 return retval;
248 /* initialize StartData/StartMask CSRs */
249 retval = esirisc_jtag_write_csr(jtag_info, CSR_TRACE, CSR_TRACE_START_DATA,
250 trace_info->start_data);
251 if (retval != ERROR_OK) {
252 LOG_ERROR("%s: failed to write Trace CSR: StartData", target_name(target));
253 return retval;
256 retval = esirisc_jtag_write_csr(jtag_info, CSR_TRACE, CSR_TRACE_START_MASK,
257 trace_info->start_mask);
258 if (retval != ERROR_OK) {
259 LOG_ERROR("%s: failed to write Trace CSR: StartMask", target_name(target));
260 return retval;
263 /* initialize StopData/StopMask CSRs */
264 retval = esirisc_jtag_write_csr(jtag_info, CSR_TRACE, CSR_TRACE_STOP_DATA,
265 trace_info->stop_data);
266 if (retval != ERROR_OK) {
267 LOG_ERROR("%s: failed to write Trace CSR: StopData", target_name(target));
268 return retval;
271 retval = esirisc_jtag_write_csr(jtag_info, CSR_TRACE, CSR_TRACE_STOP_MASK,
272 trace_info->stop_mask);
273 if (retval != ERROR_OK) {
274 LOG_ERROR("%s: failed to write Trace CSR: StopMask", target_name(target));
275 return retval;
278 /* initialize Delay CSR */
279 retval = esirisc_jtag_write_csr(jtag_info, CSR_TRACE, CSR_TRACE_DELAY,
280 trace_info->delay_cycles);
281 if (retval != ERROR_OK) {
282 LOG_ERROR("%s: failed to write Trace CSR: Delay", target_name(target));
283 return retval;
286 return ERROR_OK;
289 static int esirisc_trace_buf_get_u32(uint8_t *buffer, uint32_t size,
290 unsigned *pos, unsigned count, uint32_t *value)
292 const unsigned num_bits = size * 8;
294 if (*pos+count > num_bits)
295 return ERROR_FAIL;
297 *value = buf_get_u32(buffer, *pos, count);
298 *pos += count;
300 return ERROR_OK;
303 static int esirisc_trace_buf_get_pc(struct target *target, uint8_t *buffer, uint32_t size,
304 unsigned *pos, uint32_t *value)
306 struct esirisc_common *esirisc = target_to_esirisc(target);
307 struct esirisc_trace *trace_info = &esirisc->trace_info;
308 int retval;
310 retval = esirisc_trace_buf_get_u32(buffer, size, pos, trace_info->pc_bits, value);
311 if (retval != ERROR_OK)
312 return retval;
314 *value <<= esirisc->num_bits - trace_info->pc_bits;
316 return ERROR_OK;
319 static int esirisc_trace_read_memory(struct target *target, target_addr_t address, uint32_t size,
320 uint8_t *buffer)
322 int retval;
324 if (target->state != TARGET_HALTED)
325 return ERROR_TARGET_NOT_HALTED;
327 retval = target_read_memory(target, address, 1, size, buffer);
328 if (retval != ERROR_OK) {
329 LOG_ERROR("%s: failed to read trace data", target_name(target));
330 return retval;
333 return ERROR_OK;
336 static int esirisc_trace_read_buffer(struct target *target, uint8_t *buffer)
338 struct esirisc_common *esirisc = target_to_esirisc(target);
339 struct esirisc_jtag *jtag_info = &esirisc->jtag_info;
340 struct esirisc_trace *trace_info = &esirisc->trace_info;
341 uint32_t buffer_cur, status;
342 int retval;
344 if (target->state != TARGET_HALTED)
345 return ERROR_TARGET_NOT_HALTED;
347 retval = esirisc_jtag_read_csr(jtag_info, CSR_TRACE, CSR_TRACE_BUFFER_CUR, &buffer_cur);
348 if (retval != ERROR_OK) {
349 LOG_ERROR("%s: failed to read Trace CSR: BufferCurrent", target_name(target));
350 return retval;
354 * If the buffer has wrapped, the BufferCurrent CSR indicates the
355 * next address to be written (ie. the start address). These bytes
356 * must be dumped first to maintain coherency when analyzing
357 * captured data.
359 retval = esirisc_trace_get_status(target, &status);
360 if (retval != ERROR_OK)
361 return retval;
363 if (status & STATUS_W) {
364 uint32_t size = trace_info->buffer_end - buffer_cur;
366 retval = esirisc_trace_read_memory(target, buffer_cur, size, buffer);
367 if (retval != ERROR_OK)
368 return retval;
370 buffer += size;
373 return esirisc_trace_read_memory(target, trace_info->buffer_start,
374 buffer_cur - trace_info->buffer_start, buffer);
377 static int esirisc_trace_analyze_full(struct command_invocation *cmd, uint8_t *buffer, uint32_t size)
379 struct target *target = get_current_target(cmd->ctx);
380 const uint32_t num_bits = size * 8;
381 int retval;
383 unsigned pos = 0;
384 while (pos < num_bits) {
385 uint32_t id;
387 retval = esirisc_trace_buf_get_u32(buffer, size, &pos, 2, &id);
388 if (retval != ERROR_OK)
389 goto fail;
391 switch (id) {
392 case ESIRISC_TRACE_ID_EXECUTE:
393 case ESIRISC_TRACE_ID_STALL:
394 case ESIRISC_TRACE_ID_BRANCH:
395 command_print(cmd, "%s", esirisc_trace_id_strings[id]);
396 break;
398 case ESIRISC_TRACE_ID_EXTENDED: {
399 uint32_t ext_id;
401 retval = esirisc_trace_buf_get_u32(buffer, size, &pos, 4, &ext_id);
402 if (retval != ERROR_OK)
403 goto fail;
405 switch (ext_id) {
406 case ESIRISC_TRACE_EXT_ID_STOP:
407 case ESIRISC_TRACE_EXT_ID_WAIT:
408 case ESIRISC_TRACE_EXT_ID_MULTICYCLE:
409 command_print(cmd, "%s", esirisc_trace_ext_id_strings[ext_id]);
410 break;
412 case ESIRISC_TRACE_EXT_ID_ERET:
413 case ESIRISC_TRACE_EXT_ID_PC:
414 case ESIRISC_TRACE_EXT_ID_INDIRECT:
415 case ESIRISC_TRACE_EXT_ID_END_PC: {
416 uint32_t pc;
418 retval = esirisc_trace_buf_get_pc(target, buffer, size, &pos, &pc);
419 if (retval != ERROR_OK)
420 goto fail;
422 command_print(cmd, "%s PC: 0x%" PRIx32,
423 esirisc_trace_ext_id_strings[ext_id], pc);
425 if (ext_id == ESIRISC_TRACE_EXT_ID_END_PC) {
426 command_print(cmd, "--- end of trace ---");
427 return ERROR_OK;
429 break;
431 case ESIRISC_TRACE_EXT_ID_EXCEPTION: {
432 uint32_t eid, epc;
434 retval = esirisc_trace_buf_get_u32(buffer, size, &pos, 6, &eid);
435 if (retval != ERROR_OK)
436 goto fail;
438 retval = esirisc_trace_buf_get_pc(target, buffer, size, &pos, &epc);
439 if (retval != ERROR_OK)
440 goto fail;
442 command_print(cmd, "%s EID: 0x%" PRIx32 ", EPC: 0x%" PRIx32,
443 esirisc_trace_ext_id_strings[ext_id], eid, epc);
444 break;
446 case ESIRISC_TRACE_EXT_ID_COUNT: {
447 uint32_t count;
449 retval = esirisc_trace_buf_get_u32(buffer, size, &pos, 6, &count);
450 if (retval != ERROR_OK)
451 goto fail;
453 command_print(cmd, "repeats %" PRIu32 " %s", count,
454 (count == 1) ? "time" : "times");
455 break;
457 case ESIRISC_TRACE_EXT_ID_END:
458 command_print(cmd, "--- end of trace ---");
459 return ERROR_OK;
461 default:
462 command_print(cmd, "invalid extended trace ID: %" PRIu32, ext_id);
463 return ERROR_FAIL;
465 break;
467 default:
468 command_print(cmd, "invalid trace ID: %" PRIu32, id);
469 return ERROR_FAIL;
473 fail:
474 command_print(cmd, "trace buffer too small");
475 return ERROR_BUF_TOO_SMALL;
478 static int esirisc_trace_analyze_simple(struct command_invocation *cmd, uint8_t *buffer, uint32_t size)
480 struct target *target = get_current_target(cmd->ctx);
481 struct esirisc_common *esirisc = target_to_esirisc(target);
482 struct esirisc_trace *trace_info = &esirisc->trace_info;
483 const uint32_t end_of_trace = BIT_MASK(trace_info->pc_bits) << 1;
484 const uint32_t num_bits = size * 8;
485 int retval;
487 unsigned pos = 0;
488 while (pos < num_bits) {
489 uint32_t pc;
491 retval = esirisc_trace_buf_get_pc(target, buffer, size, &pos, &pc);
492 if (retval != ERROR_OK)
493 break;
495 if (pc == end_of_trace) {
496 command_print(cmd, "--- end of trace ---");
497 return ERROR_OK;
500 command_print(cmd, "PC: 0x%" PRIx32, pc);
503 command_print(cmd, "trace buffer too small");
504 return ERROR_BUF_TOO_SMALL;
507 static int esirisc_trace_analyze(struct command_invocation *cmd, uint8_t *buffer, uint32_t size)
509 struct target *target = get_current_target(cmd->ctx);
510 struct esirisc_common *esirisc = target_to_esirisc(target);
511 struct esirisc_trace *trace_info = &esirisc->trace_info;
513 switch (trace_info->format) {
514 case ESIRISC_TRACE_FORMAT_FULL:
515 command_print(cmd, "--- full pipeline ---");
516 return esirisc_trace_analyze_full(cmd, buffer, size);
518 case ESIRISC_TRACE_FORMAT_BRANCH:
519 command_print(cmd, "--- branches taken ---");
520 return esirisc_trace_analyze_full(cmd, buffer, size);
522 case ESIRISC_TRACE_FORMAT_ICACHE:
523 command_print(cmd, "--- icache misses ---");
524 return esirisc_trace_analyze_simple(cmd, buffer, size);
526 default:
527 command_print(cmd, "invalid trace format: %i", trace_info->format);
528 return ERROR_FAIL;
532 static int esirisc_trace_analyze_buffer(struct command_invocation *cmd)
534 struct target *target = get_current_target(cmd->ctx);
535 struct esirisc_common *esirisc = target_to_esirisc(target);
536 struct esirisc_trace *trace_info = &esirisc->trace_info;
537 uint8_t *buffer;
538 uint32_t size;
539 int retval;
541 size = esirisc_trace_buffer_size(trace_info);
542 buffer = calloc(1, size);
543 if (!buffer) {
544 command_print(cmd, "out of memory");
545 return ERROR_FAIL;
548 retval = esirisc_trace_read_buffer(target, buffer);
549 if (retval != ERROR_OK)
550 goto done;
552 retval = esirisc_trace_analyze(cmd, buffer, size);
554 done:
555 free(buffer);
557 return retval;
560 static int esirisc_trace_analyze_memory(struct command_invocation *cmd,
561 target_addr_t address, uint32_t size)
563 struct target *target = get_current_target(cmd->ctx);
564 uint8_t *buffer;
565 int retval;
567 buffer = calloc(1, size);
568 if (!buffer) {
569 command_print(cmd, "out of memory");
570 return ERROR_FAIL;
573 retval = esirisc_trace_read_memory(target, address, size, buffer);
574 if (retval != ERROR_OK)
575 goto done;
577 retval = esirisc_trace_analyze(cmd, buffer, size);
579 done:
580 free(buffer);
582 return retval;
585 static int esirisc_trace_dump(struct command_invocation *cmd, const char *filename,
586 uint8_t *buffer, uint32_t size)
588 struct fileio *fileio;
589 size_t size_written;
590 int retval;
592 retval = fileio_open(&fileio, filename, FILEIO_WRITE, FILEIO_BINARY);
593 if (retval != ERROR_OK) {
594 command_print(cmd, "could not open dump file: %s", filename);
595 return retval;
598 retval = fileio_write(fileio, size, buffer, &size_written);
599 if (retval == ERROR_OK)
600 command_print(cmd, "trace data dumped to: %s", filename);
601 else
602 command_print(cmd, "could not write dump file: %s", filename);
604 fileio_close(fileio);
606 return retval;
609 static int esirisc_trace_dump_buffer(struct command_invocation *cmd, const char *filename)
611 struct target *target = get_current_target(cmd->ctx);
612 struct esirisc_common *esirisc = target_to_esirisc(target);
613 struct esirisc_trace *trace_info = &esirisc->trace_info;
614 uint8_t *buffer;
615 uint32_t size;
616 int retval;
618 size = esirisc_trace_buffer_size(trace_info);
619 buffer = calloc(1, size);
620 if (!buffer) {
621 command_print(cmd, "out of memory");
622 return ERROR_FAIL;
625 retval = esirisc_trace_read_buffer(target, buffer);
626 if (retval != ERROR_OK)
627 goto done;
629 retval = esirisc_trace_dump(cmd, filename, buffer, size);
631 done:
632 free(buffer);
634 return retval;
637 static int esirisc_trace_dump_memory(struct command_invocation *cmd, const char *filename,
638 target_addr_t address, uint32_t size)
640 struct target *target = get_current_target(cmd->ctx);
641 uint8_t *buffer;
642 int retval;
644 buffer = calloc(1, size);
645 if (!buffer) {
646 command_print(cmd, "out of memory");
647 return ERROR_FAIL;
650 retval = esirisc_trace_read_memory(target, address, size, buffer);
651 if (retval != ERROR_OK)
652 goto done;
654 retval = esirisc_trace_dump(cmd, filename, buffer, size);
656 done:
657 free(buffer);
659 return retval;
662 COMMAND_HANDLER(handle_esirisc_trace_init_command)
664 struct target *target = get_current_target(CMD_CTX);
665 struct esirisc_common *esirisc = target_to_esirisc(target);
667 if (!esirisc->has_trace) {
668 command_print(CMD, "target does not support trace");
669 return ERROR_FAIL;
672 int retval = esirisc_trace_init(target);
673 if (retval == ERROR_OK)
674 command_print(CMD, "trace initialized");
676 return retval;
679 COMMAND_HANDLER(handle_esirisc_trace_info_command)
681 struct target *target = get_current_target(CMD_CTX);
682 struct esirisc_common *esirisc = target_to_esirisc(target);
683 struct esirisc_trace *trace_info = &esirisc->trace_info;
685 if (!esirisc->has_trace) {
686 command_print(CMD, "target does not support trace");
687 return ERROR_FAIL;
690 if (esirisc_trace_is_fifo(trace_info))
691 command_print(CMD, "trace FIFO address: 0x%" TARGET_PRIxADDR,
692 trace_info->buffer_start);
693 else {
694 command_print(CMD, "trace buffer start: 0x%" TARGET_PRIxADDR,
695 trace_info->buffer_start);
696 command_print(CMD, "trace buffer end: 0x%" TARGET_PRIxADDR,
697 trace_info->buffer_end);
698 command_print(CMD, "trace buffer will %swrap",
699 trace_info->buffer_wrap ? "" : "not ");
702 command_print(CMD, "flow control: %s",
703 trace_info->flow_control ? "enabled" : "disabled");
705 command_print(CMD, "trace format: %s",
706 esirisc_trace_format_strings[trace_info->format]);
707 command_print(CMD, "number of PC bits: %i", trace_info->pc_bits);
709 command_print(CMD, "start trigger: %s",
710 esirisc_trace_trigger_strings[trace_info->start_trigger]);
711 command_print(CMD, "start data: 0x%" PRIx32, trace_info->start_data);
712 command_print(CMD, "start mask: 0x%" PRIx32, trace_info->start_mask);
714 command_print(CMD, "stop trigger: %s",
715 esirisc_trace_trigger_strings[trace_info->stop_trigger]);
716 command_print(CMD, "stop data: 0x%" PRIx32, trace_info->stop_data);
717 command_print(CMD, "stop mask: 0x%" PRIx32, trace_info->stop_mask);
719 command_print(CMD, "trigger delay: %s",
720 esirisc_trace_delay_strings[trace_info->delay]);
721 command_print(CMD, "trigger delay cycles: %" PRIu32, trace_info->delay_cycles);
723 return ERROR_OK;
726 COMMAND_HANDLER(handle_esirisc_trace_status_command)
728 struct target *target = get_current_target(CMD_CTX);
729 struct esirisc_common *esirisc = target_to_esirisc(target);
730 uint32_t status;
732 if (!esirisc->has_trace) {
733 command_print(CMD, "target does not support trace");
734 return ERROR_FAIL;
737 int retval = esirisc_trace_get_status(target, &status);
738 if (retval != ERROR_OK)
739 return retval;
741 command_print(CMD, "trace is %s%s%s%s",
742 (status & STATUS_T) ? "started" : "stopped",
743 (status & STATUS_TD) ? ", disabled" : "",
744 (status & STATUS_W) ? ", wrapped" : "",
745 (status & STATUS_O) ? ", overflowed" : "");
747 return ERROR_OK;
750 COMMAND_HANDLER(handle_esirisc_trace_start_command)
752 struct target *target = get_current_target(CMD_CTX);
753 struct esirisc_common *esirisc = target_to_esirisc(target);
755 if (!esirisc->has_trace) {
756 command_print(CMD, "target does not support trace");
757 return ERROR_FAIL;
760 int retval = esirisc_trace_start(target);
761 if (retval == ERROR_OK)
762 command_print(CMD, "trace started");
764 return retval;
767 COMMAND_HANDLER(handle_esirisc_trace_stop_command)
769 struct target *target = get_current_target(CMD_CTX);
770 struct esirisc_common *esirisc = target_to_esirisc(target);
772 if (!esirisc->has_trace) {
773 command_print(CMD, "target does not support trace");
774 return ERROR_FAIL;
777 int retval = esirisc_trace_stop(target);
778 if (retval == ERROR_OK)
779 command_print(CMD, "trace stopped");
781 return retval;
784 COMMAND_HANDLER(handle_esirisc_trace_analyze_command)
786 struct target *target = get_current_target(CMD_CTX);
787 struct esirisc_common *esirisc = target_to_esirisc(target);
788 struct esirisc_trace *trace_info = &esirisc->trace_info;
789 target_addr_t address;
790 uint32_t size;
792 if (!esirisc->has_trace) {
793 command_print(CMD, "target does not support trace");
794 return ERROR_FAIL;
797 if (CMD_ARGC != 0 && CMD_ARGC != 2)
798 return ERROR_COMMAND_SYNTAX_ERROR;
800 if (CMD_ARGC == 0) {
802 * Use of the Trace FIFO typically involves DMA to a peripheral
803 * (eg. SPI) or a separately managed buffer in memory, neither
804 * of which may be under our control. If the destination address
805 * and size are known in the latter case, they may be specified
806 * as arguments as a workaround.
808 if (esirisc_trace_is_fifo(trace_info)) {
809 command_print(CMD, "analyze from FIFO not supported");
810 return ERROR_FAIL;
813 return esirisc_trace_analyze_buffer(CMD);
814 } else {
815 COMMAND_PARSE_ADDRESS(CMD_ARGV[0], address);
816 COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], size);
818 return esirisc_trace_analyze_memory(CMD, address, size);
822 COMMAND_HANDLER(handle_esirisc_trace_dump_command)
824 struct target *target = get_current_target(CMD_CTX);
825 struct esirisc_common *esirisc = target_to_esirisc(target);
826 struct esirisc_trace *trace_info = &esirisc->trace_info;
827 target_addr_t address;
828 uint32_t size;
830 if (!esirisc->has_trace) {
831 command_print(CMD, "target does not support trace");
832 return ERROR_FAIL;
835 if (CMD_ARGC != 1 && CMD_ARGC != 3)
836 return ERROR_COMMAND_SYNTAX_ERROR;
838 if (CMD_ARGC == 1) {
839 /* also see: handle_esirisc_trace_analyze_command() */
840 if (esirisc_trace_is_fifo(trace_info)) {
841 command_print(CMD, "dump from FIFO not supported");
842 return ERROR_FAIL;
845 return esirisc_trace_dump_buffer(CMD, CMD_ARGV[0]);
846 } else {
847 COMMAND_PARSE_ADDRESS(CMD_ARGV[0], address);
848 COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], size);
850 return esirisc_trace_dump_memory(CMD, CMD_ARGV[2], address, size);
854 COMMAND_HANDLER(handle_esirisc_trace_buffer_command)
856 struct target *target = get_current_target(CMD_CTX);
857 struct esirisc_common *esirisc = target_to_esirisc(target);
858 struct esirisc_trace *trace_info = &esirisc->trace_info;
859 uint32_t size;
861 if (CMD_ARGC < 2 || CMD_ARGC > 3)
862 return ERROR_COMMAND_SYNTAX_ERROR;
864 COMMAND_PARSE_ADDRESS(CMD_ARGV[0], trace_info->buffer_start);
865 COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], size);
867 trace_info->buffer_end = trace_info->buffer_start + size;
869 if (CMD_ARGC == 3) {
870 if (strcmp("wrap", CMD_ARGV[2]) == 0)
871 trace_info->buffer_wrap = true;
872 else
873 return ERROR_COMMAND_SYNTAX_ERROR;
876 return ERROR_OK;
879 COMMAND_HANDLER(handle_esirisc_trace_fifo_command)
881 struct target *target = get_current_target(CMD_CTX);
882 struct esirisc_common *esirisc = target_to_esirisc(target);
883 struct esirisc_trace *trace_info = &esirisc->trace_info;
885 if (CMD_ARGC != 1)
886 return ERROR_COMMAND_SYNTAX_ERROR;
888 COMMAND_PARSE_ADDRESS(CMD_ARGV[0], trace_info->buffer_start);
890 /* FIFOs have the same start and end address */
891 trace_info->buffer_end = trace_info->buffer_start;
892 trace_info->buffer_wrap = true;
894 return ERROR_OK;
897 COMMAND_HANDLER(handle_esirisc_trace_flow_control_command)
899 struct target *target = get_current_target(CMD_CTX);
900 struct esirisc_common *esirisc = target_to_esirisc(target);
901 struct esirisc_trace *trace_info = &esirisc->trace_info;
903 if (CMD_ARGC != 1)
904 return ERROR_COMMAND_SYNTAX_ERROR;
906 if (strcmp(CMD_ARGV[0], "enable") == 0)
907 trace_info->flow_control = true;
908 else if (strcmp(CMD_ARGV[0], "disable") == 0)
909 trace_info->flow_control = false;
910 else
911 return ERROR_COMMAND_SYNTAX_ERROR;
913 return ERROR_OK;
916 COMMAND_HANDLER(handle_esirisc_trace_format_command)
918 struct target *target = get_current_target(CMD_CTX);
919 struct esirisc_common *esirisc = target_to_esirisc(target);
920 struct esirisc_trace *trace_info = &esirisc->trace_info;
921 int pc_bits;
923 if (CMD_ARGC != 2)
924 return ERROR_COMMAND_SYNTAX_ERROR;
926 if (strcmp(CMD_ARGV[0], "full") == 0)
927 trace_info->format = ESIRISC_TRACE_FORMAT_FULL;
928 else if (strcmp(CMD_ARGV[0], "branch") == 0)
929 trace_info->format = ESIRISC_TRACE_FORMAT_BRANCH;
930 else if (strcmp(CMD_ARGV[0], "icache") == 0)
931 trace_info->format = ESIRISC_TRACE_FORMAT_ICACHE;
932 else
933 return ERROR_COMMAND_SYNTAX_ERROR;
935 COMMAND_PARSE_NUMBER(int, CMD_ARGV[1], pc_bits);
937 if (pc_bits < 1 || pc_bits > 31) {
938 command_print(CMD, "invalid pc_bits: %i; must be 1..31", pc_bits);
939 return ERROR_COMMAND_SYNTAX_ERROR;
942 trace_info->pc_bits = pc_bits;
944 return ERROR_OK;
947 COMMAND_HANDLER(handle_esirisc_trace_trigger_start_command)
949 struct target *target = get_current_target(CMD_CTX);
950 struct esirisc_common *esirisc = target_to_esirisc(target);
951 struct esirisc_trace *trace_info = &esirisc->trace_info;
953 if (CMD_ARGC != 1 && CMD_ARGC != 3)
954 return ERROR_COMMAND_SYNTAX_ERROR;
956 if (strcmp(CMD_ARGV[0], "none") == 0)
957 trace_info->start_trigger = ESIRISC_TRACE_TRIGGER_NONE;
958 else if (strcmp(CMD_ARGV[0], "pc") == 0)
959 trace_info->start_trigger = ESIRISC_TRACE_TRIGGER_PC;
960 else if (strcmp(CMD_ARGV[0], "load") == 0)
961 trace_info->start_trigger = ESIRISC_TRACE_TRIGGER_LOAD;
962 else if (strcmp(CMD_ARGV[0], "store") == 0)
963 trace_info->start_trigger = ESIRISC_TRACE_TRIGGER_STORE;
964 else if (strcmp(CMD_ARGV[0], "exception") == 0)
965 trace_info->start_trigger = ESIRISC_TRACE_TRIGGER_EXCEPTION;
966 else if (strcmp(CMD_ARGV[0], "eret") == 0)
967 trace_info->start_trigger = ESIRISC_TRACE_TRIGGER_ERET;
968 else if (strcmp(CMD_ARGV[0], "wait") == 0)
969 trace_info->start_trigger = ESIRISC_TRACE_TRIGGER_WAIT;
970 else if (strcmp(CMD_ARGV[0], "stop") == 0)
971 trace_info->start_trigger = ESIRISC_TRACE_TRIGGER_STOP;
972 else if (strcmp(CMD_ARGV[0], "high") == 0)
973 trace_info->start_trigger = ESIRISC_TRACE_TRIGGER_HIGH;
974 else if (strcmp(CMD_ARGV[0], "low") == 0)
975 trace_info->start_trigger = ESIRISC_TRACE_TRIGGER_LOW;
976 else
977 return ERROR_COMMAND_SYNTAX_ERROR;
979 if (CMD_ARGC == 3) {
980 COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], trace_info->start_data);
981 COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], trace_info->start_mask);
982 } else {
983 trace_info->start_data = 0;
984 trace_info->start_mask = 0;
987 return ERROR_OK;
990 COMMAND_HANDLER(handle_esirisc_trace_trigger_stop_command)
992 struct target *target = get_current_target(CMD_CTX);
993 struct esirisc_common *esirisc = target_to_esirisc(target);
994 struct esirisc_trace *trace_info = &esirisc->trace_info;
996 if (CMD_ARGC != 1 && CMD_ARGC != 3)
997 return ERROR_COMMAND_SYNTAX_ERROR;
999 if (strcmp(CMD_ARGV[0], "none") == 0)
1000 trace_info->stop_trigger = ESIRISC_TRACE_TRIGGER_NONE;
1001 else if (strcmp(CMD_ARGV[0], "pc") == 0)
1002 trace_info->stop_trigger = ESIRISC_TRACE_TRIGGER_PC;
1003 else if (strcmp(CMD_ARGV[0], "load") == 0)
1004 trace_info->stop_trigger = ESIRISC_TRACE_TRIGGER_LOAD;
1005 else if (strcmp(CMD_ARGV[0], "store") == 0)
1006 trace_info->stop_trigger = ESIRISC_TRACE_TRIGGER_STORE;
1007 else if (strcmp(CMD_ARGV[0], "exception") == 0)
1008 trace_info->stop_trigger = ESIRISC_TRACE_TRIGGER_EXCEPTION;
1009 else if (strcmp(CMD_ARGV[0], "eret") == 0)
1010 trace_info->stop_trigger = ESIRISC_TRACE_TRIGGER_ERET;
1011 else if (strcmp(CMD_ARGV[0], "wait") == 0)
1012 trace_info->stop_trigger = ESIRISC_TRACE_TRIGGER_WAIT;
1013 else if (strcmp(CMD_ARGV[0], "stop") == 0)
1014 trace_info->stop_trigger = ESIRISC_TRACE_TRIGGER_STOP;
1015 else
1016 return ERROR_COMMAND_SYNTAX_ERROR;
1018 if (CMD_ARGC == 3) {
1019 COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], trace_info->stop_data);
1020 COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], trace_info->stop_mask);
1021 } else {
1022 trace_info->stop_data = 0;
1023 trace_info->stop_mask = 0;
1026 return ERROR_OK;
1029 COMMAND_HANDLER(handle_esirisc_trace_trigger_delay_command)
1031 struct target *target = get_current_target(CMD_CTX);
1032 struct esirisc_common *esirisc = target_to_esirisc(target);
1033 struct esirisc_trace *trace_info = &esirisc->trace_info;
1035 if (CMD_ARGC < 1 || CMD_ARGC > 2)
1036 return ERROR_COMMAND_SYNTAX_ERROR;
1038 if (strcmp(CMD_ARGV[0], "none") == 0)
1039 trace_info->delay = ESIRISC_TRACE_DELAY_NONE;
1040 else if (strcmp(CMD_ARGV[0], "start") == 0)
1041 trace_info->delay = ESIRISC_TRACE_DELAY_START;
1042 else if (strcmp(CMD_ARGV[0], "stop") == 0)
1043 trace_info->delay = ESIRISC_TRACE_DELAY_STOP;
1044 else if (strcmp(CMD_ARGV[0], "both") == 0)
1045 trace_info->delay = ESIRISC_TRACE_DELAY_BOTH;
1046 else
1047 return ERROR_COMMAND_SYNTAX_ERROR;
1049 if (trace_info->delay == ESIRISC_TRACE_DELAY_NONE)
1050 trace_info->delay_cycles = 0;
1051 else {
1052 if (CMD_ARGC != 2)
1053 return ERROR_COMMAND_SYNTAX_ERROR;
1055 COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], trace_info->delay_cycles);
1058 return ERROR_OK;
1061 static const struct command_registration esirisc_trace_exec_command_handlers[] = {
1063 .name = "init",
1064 .handler = handle_esirisc_trace_init_command,
1065 .mode = COMMAND_EXEC,
1066 .help = "initialize trace collection",
1067 .usage = "",
1070 .name = "info",
1071 .handler = handle_esirisc_trace_info_command,
1072 .mode = COMMAND_EXEC,
1073 .help = "display trace configuration",
1074 .usage = "",
1077 .name = "status",
1078 .handler = handle_esirisc_trace_status_command,
1079 .mode = COMMAND_EXEC,
1080 .help = "display trace collection status",
1081 .usage = "",
1084 .name = "start",
1085 .handler = handle_esirisc_trace_start_command,
1086 .mode = COMMAND_EXEC,
1087 .help = "start trace collection",
1088 .usage = "",
1091 .name = "stop",
1092 .handler = handle_esirisc_trace_stop_command,
1093 .mode = COMMAND_EXEC,
1094 .help = "stop trace collection",
1095 .usage = "",
1098 .name = "analyze",
1099 .handler = handle_esirisc_trace_analyze_command,
1100 .mode = COMMAND_EXEC,
1101 .usage = "[address size]",
1102 .help = "analyze collected trace data",
1105 .name = "dump",
1106 .handler = handle_esirisc_trace_dump_command,
1107 .mode = COMMAND_EXEC,
1108 .help = "dump collected trace data to file",
1109 .usage = "[address size] filename",
1111 COMMAND_REGISTRATION_DONE
1114 static const struct command_registration esirisc_trace_trigger_any_command_handlers[] = {
1116 .name = "start",
1117 .handler = handle_esirisc_trace_trigger_start_command,
1118 .mode = COMMAND_ANY,
1119 .help = "configure trigger start condition",
1120 .usage = "('none'|'pc'|'load'|'store'|'exception'|'eret'|'wait'|'stop'|'high'|'low')"
1121 " [start_data start_mask]",
1124 .name = "stop",
1125 .handler = handle_esirisc_trace_trigger_stop_command,
1126 .mode = COMMAND_ANY,
1127 .help = "configure trigger stop condition",
1128 .usage = "('none'|'pc'|'load'|'store'|'exception'|'eret'|'wait'|'stop')"
1129 " [stop_data stop_mask]",
1132 .name = "delay",
1133 .handler = handle_esirisc_trace_trigger_delay_command,
1134 .mode = COMMAND_ANY,
1135 .help = "configure trigger start/stop delay in clock cycles",
1136 .usage = "('none'|'start'|'stop'|'both') [cycles]",
1138 COMMAND_REGISTRATION_DONE
1141 static const struct command_registration esirisc_trace_any_command_handlers[] = {
1143 .name = "buffer",
1144 .handler = handle_esirisc_trace_buffer_command,
1145 .mode = COMMAND_ANY,
1146 .help = "configure trace buffer",
1147 .usage = "address size ['wrap']",
1150 .name = "fifo",
1151 .handler = handle_esirisc_trace_fifo_command,
1152 .mode = COMMAND_ANY,
1153 .help = "configure trace FIFO",
1154 .usage = "address",
1157 .name = "flow_control",
1158 .handler = handle_esirisc_trace_flow_control_command,
1159 .mode = COMMAND_ANY,
1160 .help = "enable or disable stalling CPU to collect trace data",
1161 .usage = "('enable'|'disable')",
1164 .name = "format",
1165 .handler = handle_esirisc_trace_format_command,
1166 .mode = COMMAND_ANY,
1167 .help = "configure trace format",
1168 .usage = "('full'|'branch'|'icache') pc_bits",
1171 .name = "trigger",
1172 .mode = COMMAND_ANY,
1173 .help = "eSi-Trace trigger command group",
1174 .usage = "",
1175 .chain = esirisc_trace_trigger_any_command_handlers,
1178 .chain = esirisc_trace_exec_command_handlers
1180 COMMAND_REGISTRATION_DONE
1183 const struct command_registration esirisc_trace_command_handlers[] = {
1185 .name = "trace",
1186 .mode = COMMAND_ANY,
1187 .help = "eSi-Trace command group",
1188 .usage = "",
1189 .chain = esirisc_trace_any_command_handlers,
1191 COMMAND_REGISTRATION_DONE