2f183cfd64b84048fa70ac3a133d34bdfaca01a3
[fw/openocd] / 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 };