2 Copyright (c) 2020 Peter Hsu. All Rights Reserved. See LICENCE file for details.
8 Caveat trace records are a kind of instruction set with a 7-bit 'opcode'.
9 There are two main instruction formats:
10 M (memory reference) has signed 54-bit value, usually a virtual address
11 P (program counter) has 47-bit PC (RISC-V instructions minimum 16-bytes)
12 plus a 10 bit number field, usually byte count since last P record.
15 3210987654321098765432109876543210987654321098765432109876543210 --------
16 v.......v.......v.......v.......v.......v.......v.......vccccccc M format
17 nnnnnnnnnn......p.......p.......p.......p.......p.......pccccccc P format
20 #define tr_max_number (1UL<<10) /* P-format number field */
21 #define tr_memq_len (tr_max_number/2) /* number of instructions */
23 #define tr_code(tr) ((uint64_t)(tr) & 0x000000000000007fL)
24 #define tr_value(tr) ( ( int64_t)(tr) >> 7)
25 #define tr_pc(tr) (((uint64_t)(tr) & 0x003fffffffffff80L) >> 6)
26 #define tr_delta(tr) ( (uint64_t)(tr) >> 54)
27 #define tr_number(tr) (((uint64_t)(tr) & 0x003fffffffffff80L) >> 7)
29 /* Trace file is broken into frames. Each frame comes from a single HART.
30 Frame records are P-format with number=hart# and pc=begining value. */
31 #define is_frame(tr) ((0b1110000L & tr_code(tr)) == \
33 #define tr_eof 0b0000000L
34 #define tr_has_pc 0b0000001L /* taken branch targets */
35 #define tr_has_mem 0b0000010L /* load/store addresses */
36 #define tr_has_reg 0b0000100L /* register update values */
37 #define tr_has_timing 0b0001000L /* pipeline timing information */
39 /* The main trace file record types are memory and basic block records. */
40 #define is_mem(tr) ((0b1000000L & tr_code(tr)) == \
41 (0b1000000L)) /* M-format */
42 #define is_bbk(tr) ((0b1100000L & tr_code(tr)) == \
43 (0b0100000L)) /* P-format */
45 /* Basic block records are P-format, describing a series sequential instructions.
46 The number tr_field gives the length of the instruction block in bytes.
47 If the block ends in a taken branch, the tr_pc field gives the target address.
48 Otherwise the tr_pc field is the next sequential basic block beginning address. */
50 #define tr_jump 0b0100000L
51 #define tr_branch 0b0100001L
52 #define tr_call 0b0100010L
53 #define tr_return 0b0100011L
54 #define is_goto(tr) ((0b1111000L & tr_code(tr)) == \
55 (0b0100000L)) /* 4 spare opcodes */
56 /* Below are basic block records not ending in taken branch. */
57 #define tr_any 0b0101000L /* P-format */
58 #define tr_fence 0b0101001L /* P-format */
59 #define tr_ecall 0b0101010L /* M-format */
60 #define tr_csr 0b0101011L /* M-format */
63 All memory records are M-format, have consistent bit for read/write, are
64 divided into is_ldst() load/store group with tr_size() 1, 2, 4 8 bytes,
65 and cache line is_getput() group for tr_level() 0, 1, 2, 3 caches.
67 #define is_write(tr) ((0b1000100L & tr_code(tr)) == \
69 #define is_ldst(tr) ((0b1100000L & tr_code(tr)) == \
71 #define is_getput(tr) ((0b1100000L & tr_code(tr)) == \
74 #define is_amo(tr) ((0b1111100L & tr_code(tr)) == \
76 #define tr_amo4 0b1000110L
77 #define tr_amo8 0b1000111L
79 #define is_lrsc(tr) ((0b1111100L & tr_code(tr)) == \
81 #define tr_lr4 0b1001010L
82 #define tr_lr8 0b1001011L
83 #define tr_sc4 0b1001110L
84 #define tr_sc8 0b1001111L
86 #define is_load(tr) ((0b1111100L & tr_code(tr)) == \
88 #define tr_read1 0b1010000L
89 #define tr_read2 0b1010001L
90 #define tr_read4 0b1010010L
91 #define tr_read8 0b1010011L
92 #define is_store(tr) ((0b1111100L & tr_code(tr)) == \
94 #define tr_write1 0b1010100L
95 #define tr_write2 0b1010101L
96 #define tr_write4 0b1010110L
97 #define tr_write8 0b1010111L
98 #define tr_size(tr) (1L<<(tr_code(tr)&0x3L))
100 #define tr_d1get 0b1100001L /* L1 data cache load from L2 */
101 #define tr_d1put 0b1100101L /* L1 data cache write back to L2 */
102 #define tr_d2get 0b1100010L /* L2 data cache load from L3 */
103 #define tr_d2put 0b1100110L /* L2 data cache write back to L3 */
104 #define is_dcache(tr) ((0b1111000L & tr_code(tr)) == \
106 #define tr_i0get 0b1110000L /* instruction buffer fetchfrom L1 */
107 #define tr_i1get 0b1110001L /* L1 instruction cache load from L2 */
108 #define tr_i2get 0b1110010L /* L2 instruction cache load from L3 */
109 #define is_icache(tr) ((0b1111000L & tr_code(tr)) == \
111 #define tr_clevel(tr) (tr_code(tr)&0x3L)
113 /* Out-Of-Band Records. These records can be inserted anytime between
114 mem and bbk records, but not in the register value section because
115 there the 64-bit values have no opcode field. */
117 /* Tracing instruction issue cycle time */
118 #define tr_stall 0b0010000L /* begin stall cycle time (M-fmt) */
119 #define tr_issue 0b0010001L /* issue after number cycles (P-fmt) */
121 /* Periodical counters to help synchronize simulator components (M-format). */
122 #define tr_icount 0b0010010L /* instructions executed */
123 #define tr_cycles 0b0010011L /* pipeline cycles simulated */
128 Macros to create trace records.
130 #define trM(code, value) ( ((uint64_t)( value)<< 7) | ((uint64_t)(code)&0x7fL) )
131 #define trP(code, number, pc) ( ((uint64_t)(number)<<54) | ((uint64_t)(pc)<<6) & 0x003fffffffffff80L | ((uint64_t)(code)&0x7fL) )
135 #define quitif(bad, fmt, ...) if (bad) { fprintf(stderr, fmt, ##__VA_ARGS__); fprintf(stderr, "\n\n"); exit(0); }
136 #define dieif(bad, fmt, ...) if (bad) { fprintf(stderr, fmt, ##__VA_ARGS__); fprintf(stderr, "\n\n"); abort(); }
139 static inline uint64_t tr_print(uint64_t tr
, FILE* f
)
142 fprintf(f
, "MemOp: code=%02lx, w=%d, sz=%ldB, addr=0x%lx\n", tr_code(tr
), is_write(tr
), tr_size(tr
), tr_value(tr
));
143 else if (is_goto(tr
))
144 fprintf(f
, "GotoOp: code=%02lx, delta=%ld, pc=0x%lx\n", tr_code(tr
), tr_delta(tr
), tr_pc(tr
));
146 fprintf(f
, "BbkOp: code=%02lx, delta=%ld\n", tr_code(tr
), tr_delta(tr
));
147 else if (tr_code(tr
) == tr_stall
)
148 fprintf(f
, "Stall: number=%ld\n", tr_number(tr
));
149 else if (tr_code(tr
) == tr_issue
)
150 fprintf(f
, "after=%ld, pc=0x%lx\n", tr_delta(tr
), tr_pc(tr
));
152 fprintf(f
, "OtherOp=%016lx, code=%02lx, delta=%ld, pc=0x%lx\n", tr
, tr_code(tr
), tr_delta(tr
), tr_pc(tr
));
158 const char* name
; /* name=type[si] or name, preceeded by - or -- */
159 union { /* pointer to option value location */
160 const char** s
; /* name=s */
161 long* i
; /* name=i */
162 long* b
; /* name (no =) */
164 union { /* default value */
165 const char* ds
; /* name=s */
166 long di
; /* name=i */
167 long bv
; /* value if flag given */
169 const char* h
; /* help string */
172 extern const struct options_t opt
[];
173 extern const char* usage
;
176 int parse_options( const char** argv
);