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