2 Copyright (c) 2020 Peter Hsu. All Rights Reserved. See LICENCE file for details.
17 long report_frequency
;
23 struct fifo_t
* trace_buffer
;
25 uint64_t mem_queue
[tr_memq_len
];
28 static inline void status_report()
30 double elapse
= (clock() - start_tick
) / CLOCKS_PER_SEC
;
31 fprintf(stderr
, "\r%3.1fB insns %3.1fB mems (%ld segments) in %3.1f seconds for %3.1f MIPS",
32 insn_count
/1e9
, mem_refs
/1e9
, segments
, elapse
, insn_count
/1e6
/elapse
);
36 void stat_mem_trace(long pc
)
38 long next_report
=report_frequency
;
40 for (uint64_t tr
=fifo_get(trace_buffer
); tr
!=tr_eof
; tr
=fifo_get(trace_buffer
)) {
50 fprintf(stderr
, "Frame(pc=%d, mem=%d, reg=%d), hart#=%d, pc=0x%lx\n", (tr
&tr_has_pc
)!=0, (tr
&tr_has_mem
)!=0, (tr
&tr_has_reg
)!=0, hart
, pc
);
51 dieif(tr
& tr_has_reg
, "trace with register updates must be viewed with program binary");
55 if (tr_code(tr
) == tr_icount
) {
56 insn_count
= tr_value(tr
);
57 if (insn_count
>= next_report
) {
59 next_report
+= report_frequency
;
63 /* ignore other trace record types */
68 void stat_pc_trace(long pc
)
70 long next_report
=report_frequency
;
72 for (uint64_t tr
=fifo_get(trace_buffer
); tr
!=tr_eof
; tr
=fifo_get(trace_buffer
)) {
79 long epc
= pc
+ tr_delta(tr
);
81 const struct insn_t
* p
= insn(pc
);
82 if (p
->op_rd
!= NOREG
) {
83 long val
= fifo_get(trace_buffer
);
85 pc
+= shortOp(p
->op_code
) ? 2 : 4;
97 withregs
= (tr
& tr_has_reg
) != 0;
98 fprintf(stderr
, "Frame(pc=%d, mem=%d, reg=%d), hart#=%d, pc=0x%lx\n", (tr
&tr_has_pc
)!=0, (tr
&tr_has_mem
)!=0, withregs
, hart
, pc
);
102 if (tr_code(tr
) == tr_icount
) {
103 insn_count
= tr_value(tr
);
104 if (insn_count
>= next_report
) {
106 next_report
+= report_frequency
;
110 /* ignore other trace record types */
114 void print_listing(long pc
)
116 uint64_t* memq
= mem_queue
; /* help compiler allocate in register */
119 for (uint64_t tr
=fifo_get(trace_buffer
); tr
!=tr_eof
; tr
=fifo_get(trace_buffer
)) {
121 memq
[tail
++] = tr_value(tr
);
125 static char buf
[1024];
126 char bing
= is_goto(tr
) ? '@' : '!';
127 long epc
= pc
+ tr_delta(tr
);
130 const struct insn_t
* p
= insn(pc
);
131 if (memOp(p
->op_code
))
132 printf("%c[%016lx]", bing
, memq
[head
++]);
133 else if (insnAttr
[p
->op_code
].unit
== Unit_b
&& (pc
+(shortOp(p
->op_code
)?2:4)) == epc
)
134 printf("%c<%16lx>", bing
, tr_pc(tr
));
136 printf("%c %16s ", bing
, "");
138 if (p
->op_rd
== NOREG
&& p
->op_rd
!= 0)
141 long val
= fifo_get(trace_buffer
);
142 printf("%4s=%016lx ", regName
[p
->op_rd
], val
);
145 print_pc(pc
, stdout
);
146 print_insn(pc
, stdout
);
148 pc
+= shortOp(p
->op_code
) ? 2 : 4;
159 withregs
= (tr
& tr_has_reg
) != 0;
160 int withpc
= (tr
& tr_has_pc
) != 0;
161 fprintf(stderr
, "Frame(pc=%d, mem=%d, reg=%d, timing=%d), hart#=%d, pc=0x%lx\n", withpc
, (tr
&tr_has_mem
)!=0, withregs
, (tr
&tr_has_timing
)!=0, hart
, pc
);
163 fprintf(stderr
, "Cannot print listing of trace without pc!\n");
168 /* ignore other trace record types */
173 long atohex(const char* p
)
175 for (long n
=0; ; p
++) {
177 if ('0' <= *p
&& *p
<= '9')
179 else if ('a' <= *p
&& *p
<= 'f')
180 digit
= 10 + (*p
- 'a');
181 else if ('A' <= *p
&& *p
<= 'F')
182 digit
= 10 + (*p
- 'F');
189 static const char* shm_path
;
193 const struct options_t opt
[] =
194 { { "--in=s", .s
=&shm_path
, .ds
=0, .h
="Trace file from any cavatools =name" },
195 { "--list", .b
=&list
, .bv
=1, .h
="Print assembly listing (only traces from caveat)" },
196 { "--report=i", .i
=&report
, .di
=1000, .h
="Progress report every =number million instructions" },
199 const char* usage
= "traceinfo --in=trace [traceinfo-options] target-program";
201 int main(int argc
, const char** argv
)
204 int numopts
= parse_options(argv
+1);
207 report_frequency
= report
* 1000000;
209 if (argc
> numopts
+1) {
210 entry
= load_elf_binary(argv
[1+numopts
], 0);
213 trace_buffer
= fifo_open(shm_path
);
214 start_tick
= clock();
216 print_listing(entry
);
217 else if (argc
> numopts
+1)
218 stat_pc_trace(entry
);
220 stat_mem_trace(entry
);
221 fifo_close(trace_buffer
);
222 fprintf(stderr
, "\n%ld Instructions, %ld memory references in trace\n", insn_count
, mem_refs
);