target/esirisc_trace: change prototype of trace analyse functions
[openocd.git] / src / target / esirisc_trace.c
1 /***************************************************************************
2 * Copyright (C) 2018 by Square, Inc. *
3 * Steven Stallion <stallion@squareup.com> *
4 * *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) any later version. *
9 * *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
14 * *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program. If not, see <http://www.gnu.org/licenses/>. *
17 ***************************************************************************/
18
19 #ifdef HAVE_CONFIG_H
20 #include "config.h"
21 #endif
22
23 #include <helper/binarybuffer.h>
24 #include <helper/command.h>
25 #include <helper/fileio.h>
26 #include <helper/log.h>
27 #include <helper/types.h>
28 #include <target/target.h>
29
30 #include "esirisc.h"
31
32 #define BIT_MASK(x) ((1 << (x)) - 1)
33
34 /* Control Fields */
35 #define CONTROL_ST (1<<0) /* Start */
36 #define CONTROL_SP (1<<1) /* Stop */
37 #define CONTROL_W (1<<2) /* Wrap */
38 #define CONTROL_FC (1<<3) /* Flow Control */
39 #define CONTROL_FMT(x) (((x) << 4) & 0x30) /* Format */
40 #define CONTROL_PCB(x) (((x) << 10) & 0x7c00) /* PC Bits */
41
42 /* Status Fields */
43 #define STATUS_T (1<<0) /* Trace Started */
44 #define STATUS_TD (1<<1) /* Trace Disabled */
45 #define STATUS_W (1<<2) /* Wrapped */
46 #define STATUS_O (1<<3) /* Overflow */
47
48 /* Trigger Fields */
49 #define TRIGGER_TST(x) (((x) << 0) & 0xf) /* Trigger Start */
50 #define TRIGGER_DST (1<<7) /* Delay Start */
51 #define TRIGGER_TSP(x) (((x) << 8) & 0xf00) /* Trigger Stop */
52 #define TRIGGER_DSP (1<<15) /* Delay Start */
53
54 static const char * const esirisc_trace_delay_strings[] = {
55 "none", "start", "stop", "both",
56 };
57
58 static const char * const esirisc_trace_format_strings[] = {
59 "full", "branch", "icache",
60 };
61
62 static const char * const esirisc_trace_id_strings[] = {
63 "sequential instruction",
64 "pipeline stall",
65 "direct branch",
66 "extended ID",
67 };
68
69 static const char * const esirisc_trace_ext_id_strings[] = {
70 "", /* unused */
71 "exception",
72 "eret",
73 "stop instruction",
74 "wait instruction",
75 "multicycle instruction",
76 "count",
77 "initial",
78 "indirect branch",
79 "end of trace",
80 "final",
81 };
82
83 static const char * const esirisc_trace_trigger_strings[] = {
84 "none", "pc", "load", "store", "exception", "eret", "wait", "stop",
85 "high", "low", /* start only */
86 };
87
88 static int esirisc_trace_clear_status(struct target *target)
89 {
90 struct esirisc_common *esirisc = target_to_esirisc(target);
91 struct esirisc_jtag *jtag_info = &esirisc->jtag_info;
92 int retval;
93
94 if (target->state != TARGET_HALTED)
95 return ERROR_TARGET_NOT_HALTED;
96
97 retval = esirisc_jtag_write_csr(jtag_info, CSR_TRACE, CSR_TRACE_STATUS, ~0);
98 if (retval != ERROR_OK) {
99 LOG_ERROR("%s: failed to write Trace CSR: Status", target_name(target));
100 return retval;
101 }
102
103 return ERROR_OK;
104 }
105
106 static int esirisc_trace_get_status(struct target *target, uint32_t *status)
107 {
108 struct esirisc_common *esirisc = target_to_esirisc(target);
109 struct esirisc_jtag *jtag_info = &esirisc->jtag_info;
110
111 if (target->state != TARGET_HALTED)
112 return ERROR_TARGET_NOT_HALTED;
113
114 int retval = esirisc_jtag_read_csr(jtag_info, CSR_TRACE, CSR_TRACE_STATUS, status);
115 if (retval != ERROR_OK) {
116 LOG_ERROR("%s: failed to read Trace CSR: Status", target_name(target));
117 return retval;
118 }
119
120 return ERROR_OK;
121 }
122
123 static int esirisc_trace_start(struct target *target)
124 {
125 struct esirisc_common *esirisc = target_to_esirisc(target);
126 struct esirisc_jtag *jtag_info = &esirisc->jtag_info;
127 uint32_t control;
128 int retval;
129
130 if (target->state != TARGET_HALTED)
131 return ERROR_TARGET_NOT_HALTED;
132
133 retval = esirisc_jtag_read_csr(jtag_info, CSR_TRACE, CSR_TRACE_CONTROL, &control);
134 if (retval != ERROR_OK) {
135 LOG_ERROR("%s: failed to read Trace CSR: Control", target_name(target));
136 return retval;
137 }
138
139 control |= CONTROL_ST;
140
141 retval = esirisc_jtag_write_csr(jtag_info, CSR_TRACE, CSR_TRACE_CONTROL, control);
142 if (retval != ERROR_OK) {
143 LOG_ERROR("%s: failed to write Trace CSR: Control", target_name(target));
144 return retval;
145 }
146
147 return ERROR_OK;
148 }
149
150 static int esirisc_trace_stop(struct target *target)
151 {
152 struct esirisc_common *esirisc = target_to_esirisc(target);
153 struct esirisc_jtag *jtag_info = &esirisc->jtag_info;
154 uint32_t control;
155 int retval;
156
157 if (target->state != TARGET_HALTED)
158 return ERROR_TARGET_NOT_HALTED;
159
160 retval = esirisc_jtag_read_csr(jtag_info, CSR_TRACE, CSR_TRACE_CONTROL, &control);
161 if (retval != ERROR_OK) {
162 LOG_ERROR("%s: failed to read Trace CSR: Control", target_name(target));
163 return retval;
164 }
165
166 control |= CONTROL_SP;
167
168 retval = esirisc_jtag_write_csr(jtag_info, CSR_TRACE, CSR_TRACE_CONTROL, control);
169 if (retval != ERROR_OK) {
170 LOG_ERROR("%s: failed to write Trace CSR: Control", target_name(target));
171 return retval;
172 }
173
174 return ERROR_OK;
175 }
176
177 static int esirisc_trace_init(struct target *target)
178 {
179 struct esirisc_common *esirisc = target_to_esirisc(target);
180 struct esirisc_jtag *jtag_info = &esirisc->jtag_info;
181 struct esirisc_trace *trace_info = &esirisc->trace_info;
182 uint32_t control, trigger;
183 int retval;
184
185 if (target->state != TARGET_HALTED)
186 return ERROR_TARGET_NOT_HALTED;
187
188 /* stop if running and clear status */
189 retval = esirisc_trace_stop(target);
190 if (retval != ERROR_OK)
191 return retval;
192
193 retval = esirisc_trace_clear_status(target);
194 if (retval != ERROR_OK)
195 return retval;
196
197 /* initialize Control CSR */
198 control = CONTROL_FMT(trace_info->format)
199 | CONTROL_PCB(trace_info->pc_bits);
200
201 if (trace_info->buffer_wrap)
202 control |= CONTROL_W;
203
204 if (trace_info->flow_control)
205 control |= CONTROL_FC;
206
207 retval = esirisc_jtag_write_csr(jtag_info, CSR_TRACE, CSR_TRACE_CONTROL, control);
208 if (retval != ERROR_OK) {
209 LOG_ERROR("%s: failed to write Trace CSR: Control", target_name(target));
210 return retval;
211 }
212
213 /* initialize buffer CSRs */
214 retval = esirisc_jtag_write_csr(jtag_info, CSR_TRACE, CSR_TRACE_BUFFER_START,
215 trace_info->buffer_start);
216 if (retval != ERROR_OK) {
217 LOG_ERROR("%s: failed to write Trace CSR: BufferStart", target_name(target));
218 return retval;
219 }
220
221 retval = esirisc_jtag_write_csr(jtag_info, CSR_TRACE, CSR_TRACE_BUFFER_END,
222 trace_info->buffer_end);
223 if (retval != ERROR_OK) {
224 LOG_ERROR("%s: failed to write Trace CSR: BufferEnd", target_name(target));
225 return retval;
226 }
227
228 /*
229 * The BufferCurrent CSR must be initialized to the same value as
230 * BufferStart before tracing can be enabled:
231 */
232 retval = esirisc_jtag_write_csr(jtag_info, CSR_TRACE, CSR_TRACE_BUFFER_CUR,
233 trace_info->buffer_start);
234 if (retval != ERROR_OK) {
235 LOG_ERROR("%s: failed to write Trace CSR: BufferCurrent", target_name(target));
236 return retval;
237 }
238
239 /* initialize Trigger CSR */
240 trigger = TRIGGER_TST(trace_info->start_trigger)
241 | TRIGGER_TSP(trace_info->stop_trigger);
242
243 if (trace_info->delay == ESIRISC_TRACE_DELAY_START
244 || trace_info->delay == ESIRISC_TRACE_DELAY_BOTH) {
245 trigger |= TRIGGER_DST;
246 }
247
248 if (trace_info->delay == ESIRISC_TRACE_DELAY_STOP
249 || trace_info->delay == ESIRISC_TRACE_DELAY_BOTH) {
250 trigger |= TRIGGER_DSP;
251 }
252
253 retval = esirisc_jtag_write_csr(jtag_info, CSR_TRACE, CSR_TRACE_TRIGGER, trigger);
254 if (retval != ERROR_OK) {
255 LOG_ERROR("%s: failed to write Trace CSR: Trigger", target_name(target));
256 return retval;
257 }
258
259 /* initialize StartData/StartMask CSRs */
260 retval = esirisc_jtag_write_csr(jtag_info, CSR_TRACE, CSR_TRACE_START_DATA,
261 trace_info->start_data);
262 if (retval != ERROR_OK) {
263 LOG_ERROR("%s: failed to write Trace CSR: StartData", target_name(target));
264 return retval;
265 }
266
267 retval = esirisc_jtag_write_csr(jtag_info, CSR_TRACE, CSR_TRACE_START_MASK,
268 trace_info->start_mask);
269 if (retval != ERROR_OK) {
270 LOG_ERROR("%s: failed to write Trace CSR: StartMask", target_name(target));
271 return retval;
272 }
273
274 /* initialize StopData/StopMask CSRs */
275 retval = esirisc_jtag_write_csr(jtag_info, CSR_TRACE, CSR_TRACE_STOP_DATA,
276 trace_info->stop_data);
277 if (retval != ERROR_OK) {
278 LOG_ERROR("%s: failed to write Trace CSR: StopData", target_name(target));
279 return retval;
280 }
281
282 retval = esirisc_jtag_write_csr(jtag_info, CSR_TRACE, CSR_TRACE_STOP_MASK,
283 trace_info->stop_mask);
284 if (retval != ERROR_OK) {
285 LOG_ERROR("%s: failed to write Trace CSR: StopMask", target_name(target));
286 return retval;
287 }
288
289 /* initialize Delay CSR */
290 retval = esirisc_jtag_write_csr(jtag_info, CSR_TRACE, CSR_TRACE_DELAY,
291 trace_info->delay_cycles);
292 if (retval != ERROR_OK) {
293 LOG_ERROR("%s: failed to write Trace CSR: Delay", target_name(target));
294 return retval;
295 }
296
297 return ERROR_OK;
298 }
299
300 static int esirisc_trace_buf_get_u32(uint8_t *buffer, uint32_t size,
301 unsigned *pos, unsigned count, uint32_t *value)
302 {
303 const unsigned num_bits = size * 8;
304
305 if (*pos+count > num_bits)
306 return ERROR_FAIL;
307
308 *value = buf_get_u32(buffer, *pos, count);
309 *pos += count;
310
311 return ERROR_OK;
312 }
313
314 static int esirisc_trace_buf_get_pc(struct target *target, uint8_t *buffer, uint32_t size,
315 unsigned *pos, uint32_t *value)
316 {
317 struct esirisc_common *esirisc = target_to_esirisc(target);
318 struct esirisc_trace *trace_info = &esirisc->trace_info;
319 int retval;
320
321 retval = esirisc_trace_buf_get_u32(buffer, size, pos, trace_info->pc_bits, value);
322 if (retval != ERROR_OK)
323 return retval;
324
325 *value <<= esirisc->num_bits - trace_info->pc_bits;
326
327 return ERROR_OK;
328 }
329
330 static int esirisc_trace_read_memory(struct target *target, target_addr_t address, uint32_t size,
331 uint8_t *buffer)
332 {
333 int retval;
334
335 if (target->state != TARGET_HALTED)
336 return ERROR_TARGET_NOT_HALTED;
337
338 retval = target_read_memory(target, address, 1, size, buffer);
339 if (retval != ERROR_OK) {
340 LOG_ERROR("%s: failed to read trace data", target_name(target));
341 return retval;
342 }
343
344 return ERROR_OK;
345 }
346
347 static int esirisc_trace_read_buffer(struct target *target, uint8_t *buffer)
348 {
349 struct esirisc_common *esirisc = target_to_esirisc(target);
350 struct esirisc_jtag *jtag_info = &esirisc->jtag_info;
351 struct esirisc_trace *trace_info = &esirisc->trace_info;
352 uint32_t buffer_cur, status;
353 int retval;
354
355 if (target->state != TARGET_HALTED)
356 return ERROR_TARGET_NOT_HALTED;
357
358 retval = esirisc_jtag_read_csr(jtag_info, CSR_TRACE, CSR_TRACE_BUFFER_CUR, &buffer_cur);
359 if (retval != ERROR_OK) {
360 LOG_ERROR("%s: failed to read Trace CSR: BufferCurrent", target_name(target));
361 return retval;
362 }
363
364 /*
365 * If the buffer has wrapped, the BufferCurrent CSR indicates the
366 * next address to be written (ie. the start address). These bytes
367 * must be dumped first to maintain coherency when analyzing
368 * captured data.
369 */
370 retval = esirisc_trace_get_status(target, &status);
371 if (retval != ERROR_OK)
372 return retval;
373
374 if (status & STATUS_W) {
375 uint32_t size = trace_info->buffer_end - buffer_cur;
376
377 retval = esirisc_trace_read_memory(target, buffer_cur, size, buffer);
378 if (retval != ERROR_OK)
379 return retval;
380
381 buffer += size;
382 }
383
384 return esirisc_trace_read_memory(target, trace_info->buffer_start,
385 buffer_cur - trace_info->buffer_start, buffer);
386 }
387
388 static int esirisc_trace_analyze_full(struct command_invocation *cmd, uint8_t *buffer, uint32_t size)
389 {
390 struct target *target = get_current_target(cmd->ctx);
391 const uint32_t num_bits = size * 8;
392 int retval;
393
394 unsigned pos = 0;
395 while (pos < num_bits) {
396 uint32_t id;
397
398 retval = esirisc_trace_buf_get_u32(buffer, size, &pos, 2, &id);
399 if (retval != ERROR_OK)
400 goto fail;
401
402 switch (id) {
403 case ESIRISC_TRACE_ID_EXECUTE:
404 case ESIRISC_TRACE_ID_STALL:
405 case ESIRISC_TRACE_ID_BRANCH:
406 command_print(cmd->ctx, "%s", esirisc_trace_id_strings[id]);
407 break;
408
409 case ESIRISC_TRACE_ID_EXTENDED: {
410 uint32_t ext_id;
411
412 retval = esirisc_trace_buf_get_u32(buffer, size, &pos, 4, &ext_id);
413 if (retval != ERROR_OK)
414 goto fail;
415
416 switch (ext_id) {
417 case ESIRISC_TRACE_EXT_ID_STOP:
418 case ESIRISC_TRACE_EXT_ID_WAIT:
419 case ESIRISC_TRACE_EXT_ID_MULTICYCLE:
420 command_print(cmd->ctx, "%s", esirisc_trace_ext_id_strings[ext_id]);
421 break;
422
423 case ESIRISC_TRACE_EXT_ID_ERET:
424 case ESIRISC_TRACE_EXT_ID_PC:
425 case ESIRISC_TRACE_EXT_ID_INDIRECT:
426 case ESIRISC_TRACE_EXT_ID_END_PC: {
427 uint32_t pc;
428
429 retval = esirisc_trace_buf_get_pc(target, buffer, size, &pos, &pc);
430 if (retval != ERROR_OK)
431 goto fail;
432
433 command_print(cmd->ctx, "%s PC: 0x%" PRIx32,
434 esirisc_trace_ext_id_strings[ext_id], pc);
435
436 if (ext_id == ESIRISC_TRACE_EXT_ID_END_PC) {
437 command_print(cmd->ctx, "--- end of trace ---");
438 return ERROR_OK;
439 }
440 break;
441 }
442 case ESIRISC_TRACE_EXT_ID_EXCEPTION: {
443 uint32_t eid, epc;
444
445 retval = esirisc_trace_buf_get_u32(buffer, size, &pos, 6, &eid);
446 if (retval != ERROR_OK)
447 goto fail;
448
449 retval = esirisc_trace_buf_get_pc(target, buffer, size, &pos, &epc);
450 if (retval != ERROR_OK)
451 goto fail;
452
453 command_print(cmd->ctx, "%s EID: 0x%" PRIx32 ", EPC: 0x%" PRIx32,
454 esirisc_trace_ext_id_strings[ext_id], eid, epc);
455 break;
456 }
457 case ESIRISC_TRACE_EXT_ID_COUNT: {
458 uint32_t count;
459
460 retval = esirisc_trace_buf_get_u32(buffer, size, &pos, 6, &count);
461 if (retval != ERROR_OK)
462 goto fail;
463
464 command_print(cmd->ctx, "repeats %" PRId32 " %s", count,
465 (count == 1) ? "time" : "times");
466 break;
467 }
468 case ESIRISC_TRACE_EXT_ID_END:
469 command_print(cmd->ctx, "--- end of trace ---");
470 return ERROR_OK;
471
472 default:
473 command_print(cmd->ctx, "invalid extended trace ID: %" PRId32, ext_id);
474 return ERROR_FAIL;
475 }
476 break;
477 }
478 default:
479 command_print(cmd->ctx, "invalid trace ID: %" PRId32, id);
480 return ERROR_FAIL;
481 }
482 }
483
484 fail:
485 command_print(cmd->ctx, "trace buffer too small");
486 return ERROR_BUF_TOO_SMALL;
487 }
488
489 static int esirisc_trace_analyze_simple(struct command_invocation *cmd, uint8_t *buffer, uint32_t size)
490 {
491 struct target *target = get_current_target(cmd->ctx);
492 struct esirisc_common *esirisc = target_to_esirisc(target);
493 struct esirisc_trace *trace_info = &esirisc->trace_info;
494 const uint32_t end_of_trace = BIT_MASK(trace_info->pc_bits) << 1;
495 const uint32_t num_bits = size * 8;
496 int retval;
497
498 unsigned pos = 0;
499 while (pos < num_bits) {
500 uint32_t pc;
501
502 retval = esirisc_trace_buf_get_pc(target, buffer, size, &pos, &pc);
503 if (retval != ERROR_OK)
504 break;
505
506 if (pc == end_of_trace) {
507 command_print(cmd->ctx, "--- end of trace ---");
508 return ERROR_OK;
509 }
510
511 command_print(cmd->ctx, "PC: 0x%" PRIx32, pc);
512 }
513
514 command_print(cmd->ctx, "trace buffer too small");
515 return ERROR_BUF_TOO_SMALL;
516 }
517
518 static int esirisc_trace_analyze(struct command_invocation *cmd, uint8_t *buffer, uint32_t size)
519 {
520 struct target *target = get_current_target(cmd->ctx);
521 struct esirisc_common *esirisc = target_to_esirisc(target);
522 struct esirisc_trace *trace_info = &esirisc->trace_info;
523
524 switch (trace_info->format) {
525 case ESIRISC_TRACE_FORMAT_FULL:
526 command_print(cmd->ctx, "--- full pipeline ---");
527 return esirisc_trace_analyze_full(cmd, buffer, size);
528
529 case ESIRISC_TRACE_FORMAT_BRANCH:
530 command_print(cmd->ctx, "--- branches taken ---");
531 return esirisc_trace_analyze_full(cmd, buffer, size);
532
533 case ESIRISC_TRACE_FORMAT_ICACHE:
534 command_print(cmd->ctx, "--- icache misses ---");
535 return esirisc_trace_analyze_simple(cmd, buffer, size);
536
537 default:
538 command_print(cmd->ctx, "invalid trace format: %i", trace_info->format);
539 return ERROR_FAIL;
540 }
541 }
542
543 static int esirisc_trace_analyze_buffer(struct command_invocation *cmd)
544 {
545 struct target *target = get_current_target(cmd->ctx);
546 struct esirisc_common *esirisc = target_to_esirisc(target);
547 struct esirisc_trace *trace_info = &esirisc->trace_info;
548 uint8_t *buffer;
549 uint32_t size;
550 int retval;
551
552 size = esirisc_trace_buffer_size(trace_info);
553 buffer = calloc(1, size);
554 if (buffer == NULL) {
555 command_print(cmd->ctx, "out of memory");
556 return ERROR_FAIL;
557 }
558
559 retval = esirisc_trace_read_buffer(target, buffer);
560 if (retval != ERROR_OK)
561 goto done;
562
563 retval = esirisc_trace_analyze(cmd, buffer, size);
564
565 done:
566 free(buffer);
567
568 return retval;
569 }
570
571 static int esirisc_trace_analyze_memory(struct command_invocation *cmd,
572 target_addr_t address, uint32_t size)
573 {
574 struct target *target = get_current_target(cmd->ctx);
575 uint8_t *buffer;
576 int retval;
577
578 buffer = calloc(1, size);
579 if (buffer == NULL) {
580 command_print(cmd->ctx, "out of memory");
581 return ERROR_FAIL;
582 }
583
584 retval = esirisc_trace_read_memory(target, address, size, buffer);
585 if (retval != ERROR_OK)
586 goto done;
587
588 retval = esirisc_trace_analyze(cmd, buffer, size);
589
590 done:
591 free(buffer);
592
593 return retval;
594 }
595
596 static int esirisc_trace_dump(struct command_context *cmd_ctx, const char *filename,
597 uint8_t *buffer, uint32_t size)
598 {
599 struct fileio *fileio;
600 size_t size_written;
601 int retval;
602
603 retval = fileio_open(&fileio, filename, FILEIO_WRITE, FILEIO_BINARY);
604 if (retval != ERROR_OK) {
605 command_print(cmd_ctx, "could not open dump file: %s", filename);
606 return retval;
607 }
608
609 retval = fileio_write(fileio, size, buffer, &size_written);
610 if (retval == ERROR_OK)
611 command_print(cmd_ctx, "trace data dumped to: %s", filename);
612 else
613 command_print(cmd_ctx, "could not write dump file: %s", filename);
614
615 fileio_close(fileio);
616
617 return retval;
618 }
619
620 static int esirisc_trace_dump_buffer(struct command_context *cmd_ctx, const char *filename)
621 {
622 struct target *target = get_current_target(cmd_ctx);
623 struct esirisc_common *esirisc = target_to_esirisc(target);
624 struct esirisc_trace *trace_info = &esirisc->trace_info;
625 uint8_t *buffer;
626 uint32_t size;
627 int retval;
628
629 size = esirisc_trace_buffer_size(trace_info);
630 buffer = calloc(1, size);
631 if (buffer == NULL) {
632 command_print(cmd_ctx, "out of memory");
633 return ERROR_FAIL;
634 }
635
636 retval = esirisc_trace_read_buffer(target, buffer);
637 if (retval != ERROR_OK)
638 goto done;
639
640 retval = esirisc_trace_dump(cmd_ctx, filename, buffer, size);
641
642 done:
643 free(buffer);
644
645 return retval;
646 }
647
648 static int esirisc_trace_dump_memory(struct command_context *cmd_ctx, const char *filename,
649 target_addr_t address, uint32_t size)
650 {
651 struct target *target = get_current_target(cmd_ctx);
652 uint8_t *buffer;
653 int retval;
654
655 buffer = calloc(1, size);
656 if (buffer == NULL) {
657 command_print(cmd_ctx, "out of memory");
658 return ERROR_FAIL;
659 }
660
661 retval = esirisc_trace_read_memory(target, address, size, buffer);
662 if (retval != ERROR_OK)
663 goto done;
664
665 retval = esirisc_trace_dump(cmd_ctx, filename, buffer, size);
666
667 done:
668 free(buffer);
669
670 return retval;
671 }
672
673 COMMAND_HANDLER(handle_esirisc_trace_init_command)
674 {
675 struct target *target = get_current_target(CMD_CTX);
676 struct esirisc_common *esirisc = target_to_esirisc(target);
677
678 if (!esirisc->has_trace) {
679 command_print(CMD_CTX, "target does not support trace");
680 return ERROR_FAIL;
681 }
682
683 int retval = esirisc_trace_init(target);
684 if (retval == ERROR_OK)
685 command_print(CMD_CTX, "trace initialized");
686
687 return retval;
688 }
689
690 COMMAND_HANDLER(handle_esirisc_trace_info_command)
691 {
692 struct target *target = get_current_target(CMD_CTX);
693 struct esirisc_common *esirisc = target_to_esirisc(target);
694 struct esirisc_trace *trace_info = &esirisc->trace_info;
695
696 if (!esirisc->has_trace) {
697 command_print(CMD_CTX, "target does not support trace");
698 return ERROR_FAIL;
699 }
700
701 if (esirisc_trace_is_fifo(trace_info))
702 command_print(CMD_CTX, "trace FIFO address: 0x%" TARGET_PRIxADDR,
703 trace_info->buffer_start);
704 else {
705 command_print(CMD_CTX, "trace buffer start: 0x%" TARGET_PRIxADDR,
706 trace_info->buffer_start);
707 command_print(CMD_CTX, "trace buffer end: 0x%" TARGET_PRIxADDR,
708 trace_info->buffer_end);
709 command_print(CMD_CTX, "trace buffer will %swrap",
710 trace_info->buffer_wrap ? "" : "not ");
711 }
712
713 command_print(CMD_CTX, "flow control: %s",
714 trace_info->flow_control ? "enabled" : "disabled");
715
716 command_print(CMD_CTX, "trace format: %s",
717 esirisc_trace_format_strings[trace_info->format]);
718 command_print(CMD_CTX, "number of PC bits: %i", trace_info->pc_bits);
719
720 command_print(CMD_CTX, "start trigger: %s",
721 esirisc_trace_trigger_strings[trace_info->start_trigger]);
722 command_print(CMD_CTX, "start data: 0x%" PRIx32, trace_info->start_data);
723 command_print(CMD_CTX, "start mask: 0x%" PRIx32, trace_info->start_mask);
724
725 command_print(CMD_CTX, "stop trigger: %s",
726 esirisc_trace_trigger_strings[trace_info->stop_trigger]);
727 command_print(CMD_CTX, "stop data: 0x%" PRIx32, trace_info->stop_data);
728 command_print(CMD_CTX, "stop mask: 0x%" PRIx32, trace_info->stop_mask);
729
730 command_print(CMD_CTX, "trigger delay: %s",
731 esirisc_trace_delay_strings[trace_info->delay]);
732 command_print(CMD_CTX, "trigger delay cycles: %i", trace_info->delay_cycles);
733
734 return ERROR_OK;
735 }
736
737 COMMAND_HANDLER(handle_esirisc_trace_status_command)
738 {
739 struct target *target = get_current_target(CMD_CTX);
740 struct esirisc_common *esirisc = target_to_esirisc(target);
741 uint32_t status;
742
743 if (!esirisc->has_trace) {
744 command_print(CMD_CTX, "target does not support trace");
745 return ERROR_FAIL;
746 }
747
748 int retval = esirisc_trace_get_status(target, &status);
749 if (retval != ERROR_OK)
750 return retval;
751
752 command_print(CMD_CTX, "trace is %s%s%s%s",
753 (status & STATUS_T) ? "started" : "stopped",
754 (status & STATUS_TD) ? ", disabled" : "",
755 (status & STATUS_W) ? ", wrapped" : "",
756 (status & STATUS_O) ? ", overflowed" : "");
757
758 return ERROR_OK;
759 }
760
761 COMMAND_HANDLER(handle_esirisc_trace_start_command)
762 {
763 struct target *target = get_current_target(CMD_CTX);
764 struct esirisc_common *esirisc = target_to_esirisc(target);
765
766 if (!esirisc->has_trace) {
767 command_print(CMD_CTX, "target does not support trace");
768 return ERROR_FAIL;
769 }
770
771 int retval = esirisc_trace_start(target);
772 if (retval == ERROR_OK)
773 command_print(CMD_CTX, "trace started");
774
775 return retval;
776 }
777
778 COMMAND_HANDLER(handle_esirisc_trace_stop_command)
779 {
780 struct target *target = get_current_target(CMD_CTX);
781 struct esirisc_common *esirisc = target_to_esirisc(target);
782
783 if (!esirisc->has_trace) {
784 command_print(CMD_CTX, "target does not support trace");
785 return ERROR_FAIL;
786 }
787
788 int retval = esirisc_trace_stop(target);
789 if (retval == ERROR_OK)
790 command_print(CMD_CTX, "trace stopped");
791
792 return retval;
793 }
794
795 COMMAND_HANDLER(handle_esirisc_trace_analyze_command)
796 {
797 struct target *target = get_current_target(CMD_CTX);
798 struct esirisc_common *esirisc = target_to_esirisc(target);
799 struct esirisc_trace *trace_info = &esirisc->trace_info;
800 target_addr_t address;
801 uint32_t size;
802
803 if (!esirisc->has_trace) {
804 command_print(CMD_CTX, "target does not support trace");
805 return ERROR_FAIL;
806 }
807
808 if (CMD_ARGC != 0 && CMD_ARGC != 2)
809 return ERROR_COMMAND_SYNTAX_ERROR;
810
811 if (CMD_ARGC == 0) {
812 /*
813 * Use of the Trace FIFO typically involves DMA to a peripheral
814 * (eg. SPI) or a separately managed buffer in memory, neither
815 * of which may be under our control. If the destination address
816 * and size are known in the latter case, they may be specified
817 * as arguments as a workaround.
818 */
819 if (esirisc_trace_is_fifo(trace_info)) {
820 command_print(CMD_CTX, "analyze from FIFO not supported");
821 return ERROR_FAIL;
822 }
823
824 return esirisc_trace_analyze_buffer(CMD);
825 } else {
826 COMMAND_PARSE_ADDRESS(CMD_ARGV[0], address);
827 COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], size);
828
829 return esirisc_trace_analyze_memory(CMD, address, size);
830 }
831 }
832
833 COMMAND_HANDLER(handle_esirisc_trace_dump_command)
834 {
835 struct target *target = get_current_target(CMD_CTX);
836 struct esirisc_common *esirisc = target_to_esirisc(target);
837 struct esirisc_trace *trace_info = &esirisc->trace_info;
838 target_addr_t address;
839 uint32_t size;
840
841 if (!esirisc->has_trace) {
842 command_print(CMD_CTX, "target does not support trace");
843 return ERROR_FAIL;
844 }
845
846 if (CMD_ARGC != 1 && CMD_ARGC != 3)
847 return ERROR_COMMAND_SYNTAX_ERROR;
848
849 if (CMD_ARGC == 1) {
850 /* also see: handle_esirisc_trace_analyze_command() */
851 if (esirisc_trace_is_fifo(trace_info)) {
852 command_print(CMD_CTX, "dump from FIFO not supported");
853 return ERROR_FAIL;
854 }
855
856 return esirisc_trace_dump_buffer(CMD_CTX, CMD_ARGV[0]);
857 } else {
858 COMMAND_PARSE_ADDRESS(CMD_ARGV[0], address);
859 COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], size);
860
861 return esirisc_trace_dump_memory(CMD_CTX, CMD_ARGV[2], address, size);
862 }
863 }
864
865 COMMAND_HANDLER(handle_esirisc_trace_buffer_command)
866 {
867 struct target *target = get_current_target(CMD_CTX);
868 struct esirisc_common *esirisc = target_to_esirisc(target);
869 struct esirisc_trace *trace_info = &esirisc->trace_info;
870 uint32_t size;
871
872 if (CMD_ARGC < 2 || CMD_ARGC > 3)
873 return ERROR_COMMAND_SYNTAX_ERROR;
874
875 COMMAND_PARSE_ADDRESS(CMD_ARGV[0], trace_info->buffer_start);
876 COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], size);
877
878 trace_info->buffer_end = trace_info->buffer_start + size;
879
880 if (CMD_ARGC == 3) {
881 if (strcmp("wrap", CMD_ARGV[2]) == 0)
882 trace_info->buffer_wrap = true;
883 else
884 return ERROR_COMMAND_SYNTAX_ERROR;
885 }
886
887 return ERROR_OK;
888 }
889
890 COMMAND_HANDLER(handle_esirisc_trace_fifo_command)
891 {
892 struct target *target = get_current_target(CMD_CTX);
893 struct esirisc_common *esirisc = target_to_esirisc(target);
894 struct esirisc_trace *trace_info = &esirisc->trace_info;
895
896 if (CMD_ARGC != 1)
897 return ERROR_COMMAND_SYNTAX_ERROR;
898
899 COMMAND_PARSE_ADDRESS(CMD_ARGV[0], trace_info->buffer_start);
900
901 /* FIFOs have the same start and end address */
902 trace_info->buffer_end = trace_info->buffer_start;
903 trace_info->buffer_wrap = true;
904
905 return ERROR_OK;
906 }
907
908 COMMAND_HANDLER(handle_esirisc_trace_flow_control_command)
909 {
910 struct target *target = get_current_target(CMD_CTX);
911 struct esirisc_common *esirisc = target_to_esirisc(target);
912 struct esirisc_trace *trace_info = &esirisc->trace_info;
913
914 if (CMD_ARGC != 1)
915 return ERROR_COMMAND_SYNTAX_ERROR;
916
917 if (strcmp(CMD_ARGV[0], "enable") == 0)
918 trace_info->flow_control = true;
919 else if (strcmp(CMD_ARGV[0], "disable") == 0)
920 trace_info->flow_control = false;
921 else
922 return ERROR_COMMAND_SYNTAX_ERROR;
923
924 return ERROR_OK;
925 }
926
927 COMMAND_HANDLER(handle_esirisc_trace_format_command)
928 {
929 struct target *target = get_current_target(CMD_CTX);
930 struct esirisc_common *esirisc = target_to_esirisc(target);
931 struct esirisc_trace *trace_info = &esirisc->trace_info;
932 int pc_bits;
933
934 if (CMD_ARGC != 2)
935 return ERROR_COMMAND_SYNTAX_ERROR;
936
937 if (strcmp(CMD_ARGV[0], "full") == 0)
938 trace_info->format = ESIRISC_TRACE_FORMAT_FULL;
939 else if (strcmp(CMD_ARGV[0], "branch") == 0)
940 trace_info->format = ESIRISC_TRACE_FORMAT_BRANCH;
941 else if (strcmp(CMD_ARGV[0], "icache") == 0)
942 trace_info->format = ESIRISC_TRACE_FORMAT_ICACHE;
943 else
944 return ERROR_COMMAND_SYNTAX_ERROR;
945
946 COMMAND_PARSE_NUMBER(int, CMD_ARGV[1], pc_bits);
947
948 if (pc_bits < 1 || pc_bits > 31) {
949 command_print(CMD_CTX, "invalid pc_bits: %i; must be 1..31", pc_bits);
950 return ERROR_COMMAND_SYNTAX_ERROR;
951 }
952
953 trace_info->pc_bits = pc_bits;
954
955 return ERROR_OK;
956 }
957
958 COMMAND_HANDLER(handle_esirisc_trace_trigger_start_command)
959 {
960 struct target *target = get_current_target(CMD_CTX);
961 struct esirisc_common *esirisc = target_to_esirisc(target);
962 struct esirisc_trace *trace_info = &esirisc->trace_info;
963
964 if (CMD_ARGC != 1 && CMD_ARGC != 3)
965 return ERROR_COMMAND_SYNTAX_ERROR;
966
967 if (strcmp(CMD_ARGV[0], "none") == 0)
968 trace_info->start_trigger = ESIRISC_TRACE_TRIGGER_NONE;
969 else if (strcmp(CMD_ARGV[0], "pc") == 0)
970 trace_info->start_trigger = ESIRISC_TRACE_TRIGGER_PC;
971 else if (strcmp(CMD_ARGV[0], "load") == 0)
972 trace_info->start_trigger = ESIRISC_TRACE_TRIGGER_LOAD;
973 else if (strcmp(CMD_ARGV[0], "store") == 0)
974 trace_info->start_trigger = ESIRISC_TRACE_TRIGGER_STORE;
975 else if (strcmp(CMD_ARGV[0], "exception") == 0)
976 trace_info->start_trigger = ESIRISC_TRACE_TRIGGER_EXCEPTION;
977 else if (strcmp(CMD_ARGV[0], "eret") == 0)
978 trace_info->start_trigger = ESIRISC_TRACE_TRIGGER_ERET;
979 else if (strcmp(CMD_ARGV[0], "wait") == 0)
980 trace_info->start_trigger = ESIRISC_TRACE_TRIGGER_WAIT;
981 else if (strcmp(CMD_ARGV[0], "stop") == 0)
982 trace_info->start_trigger = ESIRISC_TRACE_TRIGGER_STOP;
983 else if (strcmp(CMD_ARGV[0], "high") == 0)
984 trace_info->start_trigger = ESIRISC_TRACE_TRIGGER_HIGH;
985 else if (strcmp(CMD_ARGV[0], "low") == 0)
986 trace_info->start_trigger = ESIRISC_TRACE_TRIGGER_LOW;
987 else
988 return ERROR_COMMAND_SYNTAX_ERROR;
989
990 if (CMD_ARGC == 3) {
991 COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], trace_info->start_data);
992 COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], trace_info->start_mask);
993 } else {
994 trace_info->start_data = 0;
995 trace_info->start_mask = 0;
996 }
997
998 return ERROR_OK;
999 }
1000
1001 COMMAND_HANDLER(handle_esirisc_trace_trigger_stop_command)
1002 {
1003 struct target *target = get_current_target(CMD_CTX);
1004 struct esirisc_common *esirisc = target_to_esirisc(target);
1005 struct esirisc_trace *trace_info = &esirisc->trace_info;
1006
1007 if (CMD_ARGC != 1 && CMD_ARGC != 3)
1008 return ERROR_COMMAND_SYNTAX_ERROR;
1009
1010 if (strcmp(CMD_ARGV[0], "none") == 0)
1011 trace_info->stop_trigger = ESIRISC_TRACE_TRIGGER_NONE;
1012 else if (strcmp(CMD_ARGV[0], "pc") == 0)
1013 trace_info->stop_trigger = ESIRISC_TRACE_TRIGGER_PC;
1014 else if (strcmp(CMD_ARGV[0], "load") == 0)
1015 trace_info->stop_trigger = ESIRISC_TRACE_TRIGGER_LOAD;
1016 else if (strcmp(CMD_ARGV[0], "store") == 0)
1017 trace_info->stop_trigger = ESIRISC_TRACE_TRIGGER_STORE;
1018 else if (strcmp(CMD_ARGV[0], "exception") == 0)
1019 trace_info->stop_trigger = ESIRISC_TRACE_TRIGGER_EXCEPTION;
1020 else if (strcmp(CMD_ARGV[0], "eret") == 0)
1021 trace_info->stop_trigger = ESIRISC_TRACE_TRIGGER_ERET;
1022 else if (strcmp(CMD_ARGV[0], "wait") == 0)
1023 trace_info->stop_trigger = ESIRISC_TRACE_TRIGGER_WAIT;
1024 else if (strcmp(CMD_ARGV[0], "stop") == 0)
1025 trace_info->stop_trigger = ESIRISC_TRACE_TRIGGER_STOP;
1026 else
1027 return ERROR_COMMAND_SYNTAX_ERROR;
1028
1029 if (CMD_ARGC == 3) {
1030 COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], trace_info->stop_data);
1031 COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], trace_info->stop_mask);
1032 } else {
1033 trace_info->stop_data = 0;
1034 trace_info->stop_mask = 0;
1035 }
1036
1037 return ERROR_OK;
1038 }
1039
1040 COMMAND_HANDLER(handle_esirisc_trace_trigger_delay_command)
1041 {
1042 struct target *target = get_current_target(CMD_CTX);
1043 struct esirisc_common *esirisc = target_to_esirisc(target);
1044 struct esirisc_trace *trace_info = &esirisc->trace_info;
1045
1046 if (CMD_ARGC < 1 || CMD_ARGC > 2)
1047 return ERROR_COMMAND_SYNTAX_ERROR;
1048
1049 if (strcmp(CMD_ARGV[0], "none") == 0)
1050 trace_info->delay = ESIRISC_TRACE_DELAY_NONE;
1051 else if (strcmp(CMD_ARGV[0], "start") == 0)
1052 trace_info->delay = ESIRISC_TRACE_DELAY_START;
1053 else if (strcmp(CMD_ARGV[0], "stop") == 0)
1054 trace_info->delay = ESIRISC_TRACE_DELAY_STOP;
1055 else if (strcmp(CMD_ARGV[0], "both") == 0)
1056 trace_info->delay = ESIRISC_TRACE_DELAY_BOTH;
1057 else
1058 return ERROR_COMMAND_SYNTAX_ERROR;
1059
1060 if (trace_info->delay == ESIRISC_TRACE_DELAY_NONE)
1061 trace_info->delay_cycles = 0;
1062 else {
1063 if (CMD_ARGC != 2)
1064 return ERROR_COMMAND_SYNTAX_ERROR;
1065
1066 COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], trace_info->delay_cycles);
1067 }
1068
1069 return ERROR_OK;
1070 }
1071
1072 static const struct command_registration esirisc_trace_exec_command_handlers[] = {
1073 {
1074 .name = "init",
1075 .handler = handle_esirisc_trace_init_command,
1076 .mode = COMMAND_EXEC,
1077 .help = "initialize trace collection",
1078 .usage = "",
1079 },
1080 {
1081 .name = "info",
1082 .handler = handle_esirisc_trace_info_command,
1083 .mode = COMMAND_EXEC,
1084 .help = "display trace configuration",
1085 .usage = "",
1086 },
1087 {
1088 .name = "status",
1089 .handler = handle_esirisc_trace_status_command,
1090 .mode = COMMAND_EXEC,
1091 .help = "display trace collection status",
1092 .usage = "",
1093 },
1094 {
1095 .name = "start",
1096 .handler = handle_esirisc_trace_start_command,
1097 .mode = COMMAND_EXEC,
1098 .help = "start trace collection",
1099 .usage = "",
1100 },
1101 {
1102 .name = "stop",
1103 .handler = handle_esirisc_trace_stop_command,
1104 .mode = COMMAND_EXEC,
1105 .help = "stop trace collection",
1106 .usage = "",
1107 },
1108 {
1109 .name = "analyze",
1110 .handler = handle_esirisc_trace_analyze_command,
1111 .mode = COMMAND_EXEC,
1112 .usage = "[address size]",
1113 .help = "analyze collected trace data",
1114 },
1115 {
1116 .name = "dump",
1117 .handler = handle_esirisc_trace_dump_command,
1118 .mode = COMMAND_EXEC,
1119 .help = "dump collected trace data to file",
1120 .usage = "[address size] filename",
1121 },
1122 COMMAND_REGISTRATION_DONE
1123 };
1124
1125 static const struct command_registration esirisc_trace_trigger_any_command_handlers[] = {
1126 {
1127 .name = "start",
1128 .handler = handle_esirisc_trace_trigger_start_command,
1129 .mode = COMMAND_ANY,
1130 .help = "configure trigger start condition",
1131 .usage = "('none'|'pc'|'load'|'store'|'exception'|'eret'|'wait'|'stop'|'high'|'low')"
1132 " [start_data start_mask]",
1133 },
1134 {
1135 .name = "stop",
1136 .handler = handle_esirisc_trace_trigger_stop_command,
1137 .mode = COMMAND_ANY,
1138 .help = "configure trigger stop condition",
1139 .usage = "('none'|'pc'|'load'|'store'|'exception'|'eret'|'wait'|'stop')"
1140 " [stop_data stop_mask]",
1141 },
1142 {
1143 .name = "delay",
1144 .handler = handle_esirisc_trace_trigger_delay_command,
1145 .mode = COMMAND_ANY,
1146 .help = "configure trigger start/stop delay in clock cycles",
1147 .usage = "('none'|'start'|'stop'|'both') [cycles]",
1148 },
1149 COMMAND_REGISTRATION_DONE
1150 };
1151
1152 static const struct command_registration esirisc_trace_any_command_handlers[] = {
1153 {
1154 .name = "buffer",
1155 .handler = handle_esirisc_trace_buffer_command,
1156 .mode = COMMAND_ANY,
1157 .help = "configure trace buffer",
1158 .usage = "address size ['wrap']",
1159 },
1160 {
1161 .name = "fifo",
1162 .handler = handle_esirisc_trace_fifo_command,
1163 .mode = COMMAND_ANY,
1164 .help = "configure trace FIFO",
1165 .usage = "address",
1166 },
1167 {
1168 .name = "flow_control",
1169 .handler = handle_esirisc_trace_flow_control_command,
1170 .mode = COMMAND_ANY,
1171 .help = "enable or disable stalling CPU to collect trace data",
1172 .usage = "('enable'|'disable')",
1173 },
1174 {
1175 .name = "format",
1176 .handler = handle_esirisc_trace_format_command,
1177 .mode = COMMAND_ANY,
1178 .help = "configure trace format",
1179 .usage = "('full'|'branch'|'icache') pc_bits",
1180 },
1181 {
1182 .name = "trigger",
1183 .mode = COMMAND_ANY,
1184 .help = "eSi-Trace trigger command group",
1185 .usage = "",
1186 .chain = esirisc_trace_trigger_any_command_handlers,
1187 },
1188 {
1189 .chain = esirisc_trace_exec_command_handlers
1190 },
1191 COMMAND_REGISTRATION_DONE
1192 };
1193
1194 const struct command_registration esirisc_trace_command_handlers[] = {
1195 {
1196 .name = "trace",
1197 .mode = COMMAND_ANY,
1198 .help = "eSi-Trace command group",
1199 .usage = "",
1200 .chain = esirisc_trace_any_command_handlers,
1201 },
1202 COMMAND_REGISTRATION_DONE
1203 };