cavatools: initialize repository
[cavatools.git] / caveat / caveat.h
1 /*
2 Copyright (c) 2020 Peter Hsu. All Rights Reserved. See LICENCE file for details.
3 */
4
5 #ifndef CAVEAT_H
6 #define CAVEAT_H
7
8 /*
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.
14
15 6 5 4 3 2 1 0 bit pos
16 3210987654321098765432109876543210987654321098765432109876543210 --------
17 v.......v.......v.......v.......v.......v.......v.......vccccccc M format
18 nnnnnnnnnn......p.......p.......p.......p.......p.......pccccccc P format
19
20 */
21 #define tr_max_number (1UL<<10) /* P-format number field */
22 #define tr_memq_len (tr_max_number/2) /* number of instructions */
23
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)
29
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)) == \
33 (0b0000000L))
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 */
39
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 */
45
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. */
50
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 */
62
63 /*
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.
67 */
68 #define is_write(tr) ((0b1000100L & tr_code(tr)) == \
69 (0b1000100L))
70 #define is_ldst(tr) ((0b1100000L & tr_code(tr)) == \
71 (0b1000000L))
72 #define is_getput(tr) ((0b1100000L & tr_code(tr)) == \
73 (0b1100000L))
74
75 #define is_amo(tr) ((0b1111100L & tr_code(tr)) == \
76 (0b1000000L))
77 #define tr_amo4 0b1000110L
78 #define tr_amo8 0b1000111L
79
80 #define is_lrsc(tr) ((0b1111100L & tr_code(tr)) == \
81 (0b1001000L))
82 #define tr_lr4 0b1001010L
83 #define tr_lr8 0b1001011L
84 #define tr_sc4 0b1001110L
85 #define tr_sc8 0b1001111L
86
87 #define is_load(tr) ((0b1111100L & tr_code(tr)) == \
88 (0b1010000L))
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)) == \
94 (0b1010100L))
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))
100
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)) == \
106 (0b1100000L))
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)) == \
111 (0b1110000L))
112 #define tr_clevel(tr) (tr_code(tr)&0x3L)
113
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. */
117
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) */
121
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 */
125
126
127
128 /*
129 Macros to create trace records.
130 */
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) )
133
134
135
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(); }
138
139
140 static inline uint64_t tr_print(uint64_t tr, FILE* f)
141 {
142 if (is_mem(tr))
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));
146 else if (is_bbk(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));
152 else
153 fprintf(f, "OtherOp=%016lx, code=%02lx, delta=%ld, pc=0x%lx\n", tr, tr_code(tr), tr_delta(tr), tr_pc(tr));
154 return tr;
155 }
156
157
158 struct options_t {
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 =) */
164 };
165 union { /* default value */
166 const char* ds; /* name=s */
167 long di; /* name=i */
168 long bv; /* value if flag given */
169 };
170 const char* h; /* help string */
171 };
172
173 extern const struct options_t opt[];
174 extern const char* usage;
175
176 void help_exit();
177 int parse_options( const char** argv );
178
179
180
181 #endif