jtag: linuxgpiod: drop extra parenthesis
[openocd.git] / src / target / esirisc_trace.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2
3 /***************************************************************************
4 * Copyright (C) 2018 by Square, Inc. *
5 * Steven Stallion <stallion@squareup.com> *
6 ***************************************************************************/
7
8 #ifdef HAVE_CONFIG_H
9 #include "config.h"
10 #endif
11
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>
18
19 #include "esirisc.h"
20
21 #define BIT_MASK(x) ((1 << (x)) - 1)
22
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 */
30
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 */
36
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 */
42
43 static const char * const esirisc_trace_delay_strings[] = {
44 "none", "start", "stop", "both",
45 };
46
47 static const char * const esirisc_trace_format_strings[] = {
48 "full", "branch", "icache",
49 };
50
51 static const char * const esirisc_trace_id_strings[] = {
52 "sequential instruction",
53 "pipeline stall",
54 "direct branch",
55 "extended ID",
56 };
57
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",
70 };
71
72 static const char * const esirisc_trace_trigger_strings[] = {
73 "none", "pc", "load", "store", "exception", "eret", "wait", "stop",
74 "high", "low", /* start only */
75 };
76
77 static int esirisc_trace_clear_status(struct target *target)
78 {
79 struct esirisc_common *esirisc = target_to_esirisc(target);
80 struct esirisc_jtag *jtag_info = &esirisc->jtag_info;
81 int retval;
82
83 if (target->state != TARGET_HALTED)
84 return ERROR_TARGET_NOT_HALTED;
85
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;
90 }
91
92 return ERROR_OK;
93 }
94
95 static int esirisc_trace_get_status(struct target *target, uint32_t *status)
96 {
97 struct esirisc_common *esirisc = target_to_esirisc(target);
98 struct esirisc_jtag *jtag_info = &esirisc->jtag_info;
99
100 if (target->state != TARGET_HALTED)
101 return ERROR_TARGET_NOT_HALTED;
102
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;
107 }
108
109 return ERROR_OK;
110 }
111
112 static int esirisc_trace_start(struct target *target)
113 {
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;
118
119 if (target->state != TARGET_HALTED)
120 return ERROR_TARGET_NOT_HALTED;
121
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;
126 }
127
128 control |= CONTROL_ST;
129
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;
134 }
135
136 return ERROR_OK;
137 }
138
139 static int esirisc_trace_stop(struct target *target)
140 {
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;
145
146 if (target->state != TARGET_HALTED)
147 return ERROR_TARGET_NOT_HALTED;
148
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;
153 }
154
155 control |= CONTROL_SP;
156
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;
161 }
162
163 return ERROR_OK;
164 }
165
166 static int esirisc_trace_init(struct target *target)
167 {
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;
173
174 if (target->state != TARGET_HALTED)
175 return ERROR_TARGET_NOT_HALTED;
176
177 /* stop if running and clear status */
178 retval = esirisc_trace_stop(target);
179 if (retval != ERROR_OK)
180 return retval;
181
182 retval = esirisc_trace_clear_status(target);
183 if (retval != ERROR_OK)
184 return retval;
185
186 /* initialize Control CSR */
187 control = CONTROL_FMT(trace_info->format)
188 | CONTROL_PCB(trace_info->pc_bits);
189
190 if (trace_info->buffer_wrap)
191 control |= CONTROL_W;
192
193 if (trace_info->flow_control)
194 control |= CONTROL_FC;
195
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;
200 }
201
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;
208 }
209
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;
215 }
216
217 /*
218 * The BufferCurrent CSR must be initialized to the same value as
219 * BufferStart before tracing can be enabled:
220 */
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;
226 }
227
228 /* initialize Trigger CSR */
229 trigger = TRIGGER_TST(trace_info->start_trigger)
230 | TRIGGER_TSP(trace_info->stop_trigger);
231
232 if (trace_info->delay == ESIRISC_TRACE_DELAY_START
233 || trace_info->delay == ESIRISC_TRACE_DELAY_BOTH) {
234 trigger |= TRIGGER_DST;
235 }
236
237 if (trace_info->delay == ESIRISC_TRACE_DELAY_STOP
238 || trace_info->delay == ESIRISC_TRACE_DELAY_BOTH) {
239 trigger |= TRIGGER_DSP;
240 }
241
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;
246 }
247
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;
254 }
255
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;
261 }
262
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;
269 }
270
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;
276 }
277
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;
284 }
285
286 return ERROR_OK;
287 }
288
289 static int esirisc_trace_buf_get_u32(uint8_t *buffer, uint32_t size,
290 unsigned *pos, unsigned count, uint32_t *value)
291 {
292 const unsigned num_bits = size * 8;
293
294 if (*pos+count > num_bits)
295 return ERROR_FAIL;
296
297 *value = buf_get_u32(buffer, *pos, count);
298 *pos += count;
299
300 return ERROR_OK;
301 }
302
303 static int esirisc_trace_buf_get_pc(struct target *target, uint8_t *buffer, uint32_t size,
304 unsigned *pos, uint32_t *value)
305 {
306 struct esirisc_common *esirisc = target_to_esirisc(target);
307 struct esirisc_trace *trace_info = &esirisc->trace_info;
308 int retval;
309
310 retval = esirisc_trace_buf_get_u32(buffer, size, pos, trace_info->pc_bits, value);
311 if (retval != ERROR_OK)
312 return retval;
313
314 *value <<= esirisc->num_bits - trace_info->pc_bits;
315
316 return ERROR_OK;
317 }
318
319 static int esirisc_trace_read_memory(struct target *target, target_addr_t address, uint32_t size,
320 uint8_t *buffer)
321 {
322 int retval;
323
324 if (target->state != TARGET_HALTED)
325 return ERROR_TARGET_NOT_HALTED;
326
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;
331 }
332
333 return ERROR_OK;
334 }
335
336 static int esirisc_trace_read_buffer(struct target *target, uint8_t *buffer)
337 {
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;
343
344 if (target->state != TARGET_HALTED)
345 return ERROR_TARGET_NOT_HALTED;
346
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;
351 }
352
353 /*
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.
358 */
359 retval = esirisc_trace_get_status(target, &status);
360 if (retval != ERROR_OK)
361 return retval;
362
363 if (status & STATUS_W) {
364 uint32_t size = trace_info->buffer_end - buffer_cur;
365
366 retval = esirisc_trace_read_memory(target, buffer_cur, size, buffer);
367 if (retval != ERROR_OK)
368 return retval;
369
370 buffer += size;
371 }
372
373 return esirisc_trace_read_memory(target, trace_info->buffer_start,
374 buffer_cur - trace_info->buffer_start, buffer);
375 }
376
377 static int esirisc_trace_analyze_full(struct command_invocation *cmd, uint8_t *buffer, uint32_t size)
378 {
379 struct target *target = get_current_target(cmd->ctx);
380 const uint32_t num_bits = size * 8;
381 int retval;
382
383 unsigned pos = 0;
384 while (pos < num_bits) {
385 uint32_t id;
386
387 retval = esirisc_trace_buf_get_u32(buffer, size, &pos, 2, &id);
388 if (retval != ERROR_OK)
389 goto fail;
390
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;
397
398 case ESIRISC_TRACE_ID_EXTENDED: {
399 uint32_t ext_id;
400
401 retval = esirisc_trace_buf_get_u32(buffer, size, &pos, 4, &ext_id);
402 if (retval != ERROR_OK)
403 goto fail;
404
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;
411
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;
417
418 retval = esirisc_trace_buf_get_pc(target, buffer, size, &pos, &pc);
419 if (retval != ERROR_OK)
420 goto fail;
421
422 command_print(cmd, "%s PC: 0x%" PRIx32,
423 esirisc_trace_ext_id_strings[ext_id], pc);
424
425 if (ext_id == ESIRISC_TRACE_EXT_ID_END_PC) {
426 command_print(cmd, "--- end of trace ---");
427 return ERROR_OK;
428 }
429 break;
430 }
431 case ESIRISC_TRACE_EXT_ID_EXCEPTION: {
432 uint32_t eid, epc;
433
434 retval = esirisc_trace_buf_get_u32(buffer, size, &pos, 6, &eid);
435 if (retval != ERROR_OK)
436 goto fail;
437
438 retval = esirisc_trace_buf_get_pc(target, buffer, size, &pos, &epc);
439 if (retval != ERROR_OK)
440 goto fail;
441
442 command_print(cmd, "%s EID: 0x%" PRIx32 ", EPC: 0x%" PRIx32,
443 esirisc_trace_ext_id_strings[ext_id], eid, epc);
444 break;
445 }
446 case ESIRISC_TRACE_EXT_ID_COUNT: {
447 uint32_t count;
448
449 retval = esirisc_trace_buf_get_u32(buffer, size, &pos, 6, &count);
450 if (retval != ERROR_OK)
451 goto fail;
452
453 command_print(cmd, "repeats %" PRIu32 " %s", count,
454 (count == 1) ? "time" : "times");
455 break;
456 }
457 case ESIRISC_TRACE_EXT_ID_END:
458 command_print(cmd, "--- end of trace ---");
459 return ERROR_OK;
460
461 default:
462 command_print(cmd, "invalid extended trace ID: %" PRIu32, ext_id);
463 return ERROR_FAIL;
464 }
465 break;
466 }
467 default:
468 command_print(cmd, "invalid trace ID: %" PRIu32, id);
469 return ERROR_FAIL;
470 }
471 }
472
473 fail:
474 command_print(cmd, "trace buffer too small");
475 return ERROR_BUF_TOO_SMALL;
476 }
477
478 static int esirisc_trace_analyze_simple(struct command_invocation *cmd, uint8_t *buffer, uint32_t size)
479 {
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;
486
487 unsigned pos = 0;
488 while (pos < num_bits) {
489 uint32_t pc;
490
491 retval = esirisc_trace_buf_get_pc(target, buffer, size, &pos, &pc);
492 if (retval != ERROR_OK)
493 break;
494
495 if (pc == end_of_trace) {
496 command_print(cmd, "--- end of trace ---");
497 return ERROR_OK;
498 }
499
500 command_print(cmd, "PC: 0x%" PRIx32, pc);
501 }
502
503 command_print(cmd, "trace buffer too small");
504 return ERROR_BUF_TOO_SMALL;
505 }
506
507 static int esirisc_trace_analyze(struct command_invocation *cmd, uint8_t *buffer, uint32_t size)
508 {
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;
512
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);
517
518 case ESIRISC_TRACE_FORMAT_BRANCH:
519 command_print(cmd, "--- branches taken ---");
520 return esirisc_trace_analyze_full(cmd, buffer, size);
521
522 case ESIRISC_TRACE_FORMAT_ICACHE:
523 command_print(cmd, "--- icache misses ---");
524 return esirisc_trace_analyze_simple(cmd, buffer, size);
525
526 default:
527 command_print(cmd, "invalid trace format: %i", trace_info->format);
528 return ERROR_FAIL;
529 }
530 }
531
532 static int esirisc_trace_analyze_buffer(struct command_invocation *cmd)
533 {
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;
540
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;
546 }
547
548 retval = esirisc_trace_read_buffer(target, buffer);
549 if (retval != ERROR_OK)
550 goto done;
551
552 retval = esirisc_trace_analyze(cmd, buffer, size);
553
554 done:
555 free(buffer);
556
557 return retval;
558 }
559
560 static int esirisc_trace_analyze_memory(struct command_invocation *cmd,
561 target_addr_t address, uint32_t size)
562 {
563 struct target *target = get_current_target(cmd->ctx);
564 uint8_t *buffer;
565 int retval;
566
567 buffer = calloc(1, size);
568 if (!buffer) {
569 command_print(cmd, "out of memory");
570 return ERROR_FAIL;
571 }
572
573 retval = esirisc_trace_read_memory(target, address, size, buffer);
574 if (retval != ERROR_OK)
575 goto done;
576
577 retval = esirisc_trace_analyze(cmd, buffer, size);
578
579 done:
580 free(buffer);
581
582 return retval;
583 }
584
585 static int esirisc_trace_dump(struct command_invocation *cmd, const char *filename,
586 uint8_t *buffer, uint32_t size)
587 {
588 struct fileio *fileio;
589 size_t size_written;
590 int retval;
591
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;
596 }
597
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);
603
604 fileio_close(fileio);
605
606 return retval;
607 }
608
609 static int esirisc_trace_dump_buffer(struct command_invocation *cmd, const char *filename)
610 {
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;
617
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;
623 }
624
625 retval = esirisc_trace_read_buffer(target, buffer);
626 if (retval != ERROR_OK)
627 goto done;
628
629 retval = esirisc_trace_dump(cmd, filename, buffer, size);
630
631 done:
632 free(buffer);
633
634 return retval;
635 }
636
637 static int esirisc_trace_dump_memory(struct command_invocation *cmd, const char *filename,
638 target_addr_t address, uint32_t size)
639 {
640 struct target *target = get_current_target(cmd->ctx);
641 uint8_t *buffer;
642 int retval;
643
644 buffer = calloc(1, size);
645 if (!buffer) {
646 command_print(cmd, "out of memory");
647 return ERROR_FAIL;
648 }
649
650 retval = esirisc_trace_read_memory(target, address, size, buffer);
651 if (retval != ERROR_OK)
652 goto done;
653
654 retval = esirisc_trace_dump(cmd, filename, buffer, size);
655
656 done:
657 free(buffer);
658
659 return retval;
660 }
661
662 COMMAND_HANDLER(handle_esirisc_trace_init_command)
663 {
664 struct target *target = get_current_target(CMD_CTX);
665 struct esirisc_common *esirisc = target_to_esirisc(target);
666
667 if (!esirisc->has_trace) {
668 command_print(CMD, "target does not support trace");
669 return ERROR_FAIL;
670 }
671
672 int retval = esirisc_trace_init(target);
673 if (retval == ERROR_OK)
674 command_print(CMD, "trace initialized");
675
676 return retval;
677 }
678
679 COMMAND_HANDLER(handle_esirisc_trace_info_command)
680 {
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;
684
685 if (!esirisc->has_trace) {
686 command_print(CMD, "target does not support trace");
687 return ERROR_FAIL;
688 }
689
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 ");
700 }
701
702 command_print(CMD, "flow control: %s",
703 trace_info->flow_control ? "enabled" : "disabled");
704
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);
708
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);
713
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);
718
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);
722
723 return ERROR_OK;
724 }
725
726 COMMAND_HANDLER(handle_esirisc_trace_status_command)
727 {
728 struct target *target = get_current_target(CMD_CTX);
729 struct esirisc_common *esirisc = target_to_esirisc(target);
730 uint32_t status;
731
732 if (!esirisc->has_trace) {
733 command_print(CMD, "target does not support trace");
734 return ERROR_FAIL;
735 }
736
737 int retval = esirisc_trace_get_status(target, &status);
738 if (retval != ERROR_OK)
739 return retval;
740
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" : "");
746
747 return ERROR_OK;
748 }
749
750 COMMAND_HANDLER(handle_esirisc_trace_start_command)
751 {
752 struct target *target = get_current_target(CMD_CTX);
753 struct esirisc_common *esirisc = target_to_esirisc(target);
754
755 if (!esirisc->has_trace) {
756 command_print(CMD, "target does not support trace");
757 return ERROR_FAIL;
758 }
759
760 int retval = esirisc_trace_start(target);
761 if (retval == ERROR_OK)
762 command_print(CMD, "trace started");
763
764 return retval;
765 }
766
767 COMMAND_HANDLER(handle_esirisc_trace_stop_command)
768 {
769 struct target *target = get_current_target(CMD_CTX);
770 struct esirisc_common *esirisc = target_to_esirisc(target);
771
772 if (!esirisc->has_trace) {
773 command_print(CMD, "target does not support trace");
774 return ERROR_FAIL;
775 }
776
777 int retval = esirisc_trace_stop(target);
778 if (retval == ERROR_OK)
779 command_print(CMD, "trace stopped");
780
781 return retval;
782 }
783
784 COMMAND_HANDLER(handle_esirisc_trace_analyze_command)
785 {
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;
791
792 if (!esirisc->has_trace) {
793 command_print(CMD, "target does not support trace");
794 return ERROR_FAIL;
795 }
796
797 if (CMD_ARGC != 0 && CMD_ARGC != 2)
798 return ERROR_COMMAND_SYNTAX_ERROR;
799
800 if (CMD_ARGC == 0) {
801 /*
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.
807 */
808 if (esirisc_trace_is_fifo(trace_info)) {
809 command_print(CMD, "analyze from FIFO not supported");
810 return ERROR_FAIL;
811 }
812
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);
817
818 return esirisc_trace_analyze_memory(CMD, address, size);
819 }
820 }
821
822 COMMAND_HANDLER(handle_esirisc_trace_dump_command)
823 {
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;
829
830 if (!esirisc->has_trace) {
831 command_print(CMD, "target does not support trace");
832 return ERROR_FAIL;
833 }
834
835 if (CMD_ARGC != 1 && CMD_ARGC != 3)
836 return ERROR_COMMAND_SYNTAX_ERROR;
837
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;
843 }
844
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);
849
850 return esirisc_trace_dump_memory(CMD, CMD_ARGV[2], address, size);
851 }
852 }
853
854 COMMAND_HANDLER(handle_esirisc_trace_buffer_command)
855 {
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;
860
861 if (CMD_ARGC < 2 || CMD_ARGC > 3)
862 return ERROR_COMMAND_SYNTAX_ERROR;
863
864 COMMAND_PARSE_ADDRESS(CMD_ARGV[0], trace_info->buffer_start);
865 COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], size);
866
867 trace_info->buffer_end = trace_info->buffer_start + size;
868
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;
874 }
875
876 return ERROR_OK;
877 }
878
879 COMMAND_HANDLER(handle_esirisc_trace_fifo_command)
880 {
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;
884
885 if (CMD_ARGC != 1)
886 return ERROR_COMMAND_SYNTAX_ERROR;
887
888 COMMAND_PARSE_ADDRESS(CMD_ARGV[0], trace_info->buffer_start);
889
890 /* FIFOs have the same start and end address */
891 trace_info->buffer_end = trace_info->buffer_start;
892 trace_info->buffer_wrap = true;
893
894 return ERROR_OK;
895 }
896
897 COMMAND_HANDLER(handle_esirisc_trace_flow_control_command)
898 {
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;
902
903 if (CMD_ARGC != 1)
904 return ERROR_COMMAND_SYNTAX_ERROR;
905
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;
912
913 return ERROR_OK;
914 }
915
916 COMMAND_HANDLER(handle_esirisc_trace_format_command)
917 {
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;
922
923 if (CMD_ARGC != 2)
924 return ERROR_COMMAND_SYNTAX_ERROR;
925
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;
934
935 COMMAND_PARSE_NUMBER(int, CMD_ARGV[1], pc_bits);
936
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;
940 }
941
942 trace_info->pc_bits = pc_bits;
943
944 return ERROR_OK;
945 }
946
947 COMMAND_HANDLER(handle_esirisc_trace_trigger_start_command)
948 {
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;
952
953 if (CMD_ARGC != 1 && CMD_ARGC != 3)
954 return ERROR_COMMAND_SYNTAX_ERROR;
955
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;
978
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;
985 }
986
987 return ERROR_OK;
988 }
989
990 COMMAND_HANDLER(handle_esirisc_trace_trigger_stop_command)
991 {
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;
995
996 if (CMD_ARGC != 1 && CMD_ARGC != 3)
997 return ERROR_COMMAND_SYNTAX_ERROR;
998
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;
1017
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;
1024 }
1025
1026 return ERROR_OK;
1027 }
1028
1029 COMMAND_HANDLER(handle_esirisc_trace_trigger_delay_command)
1030 {
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;
1034
1035 if (CMD_ARGC < 1 || CMD_ARGC > 2)
1036 return ERROR_COMMAND_SYNTAX_ERROR;
1037
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;
1048
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;
1054
1055 COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], trace_info->delay_cycles);
1056 }
1057
1058 return ERROR_OK;
1059 }
1060
1061 static const struct command_registration esirisc_trace_exec_command_handlers[] = {
1062 {
1063 .name = "init",
1064 .handler = handle_esirisc_trace_init_command,
1065 .mode = COMMAND_EXEC,
1066 .help = "initialize trace collection",
1067 .usage = "",
1068 },
1069 {
1070 .name = "info",
1071 .handler = handle_esirisc_trace_info_command,
1072 .mode = COMMAND_EXEC,
1073 .help = "display trace configuration",
1074 .usage = "",
1075 },
1076 {
1077 .name = "status",
1078 .handler = handle_esirisc_trace_status_command,
1079 .mode = COMMAND_EXEC,
1080 .help = "display trace collection status",
1081 .usage = "",
1082 },
1083 {
1084 .name = "start",
1085 .handler = handle_esirisc_trace_start_command,
1086 .mode = COMMAND_EXEC,
1087 .help = "start trace collection",
1088 .usage = "",
1089 },
1090 {
1091 .name = "stop",
1092 .handler = handle_esirisc_trace_stop_command,
1093 .mode = COMMAND_EXEC,
1094 .help = "stop trace collection",
1095 .usage = "",
1096 },
1097 {
1098 .name = "analyze",
1099 .handler = handle_esirisc_trace_analyze_command,
1100 .mode = COMMAND_EXEC,
1101 .usage = "[address size]",
1102 .help = "analyze collected trace data",
1103 },
1104 {
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",
1110 },
1111 COMMAND_REGISTRATION_DONE
1112 };
1113
1114 static const struct command_registration esirisc_trace_trigger_any_command_handlers[] = {
1115 {
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]",
1122 },
1123 {
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]",
1130 },
1131 {
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]",
1137 },
1138 COMMAND_REGISTRATION_DONE
1139 };
1140
1141 static const struct command_registration esirisc_trace_any_command_handlers[] = {
1142 {
1143 .name = "buffer",
1144 .handler = handle_esirisc_trace_buffer_command,
1145 .mode = COMMAND_ANY,
1146 .help = "configure trace buffer",
1147 .usage = "address size ['wrap']",
1148 },
1149 {
1150 .name = "fifo",
1151 .handler = handle_esirisc_trace_fifo_command,
1152 .mode = COMMAND_ANY,
1153 .help = "configure trace FIFO",
1154 .usage = "address",
1155 },
1156 {
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')",
1162 },
1163 {
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",
1169 },
1170 {
1171 .name = "trigger",
1172 .mode = COMMAND_ANY,
1173 .help = "eSi-Trace trigger command group",
1174 .usage = "",
1175 .chain = esirisc_trace_trigger_any_command_handlers,
1176 },
1177 {
1178 .chain = esirisc_trace_exec_command_handlers
1179 },
1180 COMMAND_REGISTRATION_DONE
1181 };
1182
1183 const struct command_registration esirisc_trace_command_handlers[] = {
1184 {
1185 .name = "trace",
1186 .mode = COMMAND_ANY,
1187 .help = "eSi-Trace command group",
1188 .usage = "",
1189 .chain = esirisc_trace_any_command_handlers,
1190 },
1191 COMMAND_REGISTRATION_DONE
1192 };

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)