esirisc: support eSi-Trace
[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_context *cmd_ctx, 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_context *cmd_ctx, 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_context *cmd_ctx, 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_ctx, buffer, size);
528
529 case ESIRISC_TRACE_FORMAT_BRANCH:
530 command_print(cmd_ctx, "--- branches taken ---");
531 return esirisc_trace_analyze_full(cmd_ctx, buffer, size);
532
533 case ESIRISC_TRACE_FORMAT_ICACHE:
534 command_print(cmd_ctx, "--- icache misses ---");
535 return esirisc_trace_analyze_simple(cmd_ctx, 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_context *cmd_ctx)
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_ctx, buffer, size);
564
565 done:
566 free(buffer);
567
568 return retval;
569 }
570
571 static int esirisc_trace_analyze_memory(struct command_context *cmd_ctx,
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_ctx, 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_CTX);
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_CTX, 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 };

Linking to existing account procedure

If you already have an account and want to add another login method you MUST first sign in with your existing account and then change URL to read https://review.openocd.org/login/?link to get to this page again but this time it'll work for linking. Thank you.

SSH host keys fingerprints

1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=..              |
|+o..   .         |
|*.o   . .        |
|+B . . .         |
|Bo. = o S        |
|Oo.+ + =         |
|oB=.* = . o      |
| =+=.+   + E     |
|. .=o   . o      |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)