caveat: introduce header guards
[cavatools.git] / caveat / caveat.h
1 /*
2 Copyright (c) 2020 Peter Hsu. All Rights Reserved. See LICENCE file for details.
3 */
4
5 #pragma once
6
7 /*
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.
13
14 6 5 4 3 2 1 0 bit pos
15 3210987654321098765432109876543210987654321098765432109876543210 --------
16 v.......v.......v.......v.......v.......v.......v.......vccccccc M format
17 nnnnnnnnnn......p.......p.......p.......p.......p.......pccccccc P format
18
19 */
20 #define tr_max_number (1UL<<10) /* P-format number field */
21 #define tr_memq_len (tr_max_number/2) /* number of instructions */
22
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)
28
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)) == \
32 (0b0000000L))
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 */
38
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 */
44
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. */
49
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 */
61
62 /*
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.
66 */
67 #define is_write(tr) ((0b1000100L & tr_code(tr)) == \
68 (0b1000100L))
69 #define is_ldst(tr) ((0b1100000L & tr_code(tr)) == \
70 (0b1000000L))
71 #define is_getput(tr) ((0b1100000L & tr_code(tr)) == \
72 (0b1100000L))
73
74 #define is_amo(tr) ((0b1111100L & tr_code(tr)) == \
75 (0b1000000L))
76 #define tr_amo4 0b1000110L
77 #define tr_amo8 0b1000111L
78
79 #define is_lrsc(tr) ((0b1111100L & tr_code(tr)) == \
80 (0b1001000L))
81 #define tr_lr4 0b1001010L
82 #define tr_lr8 0b1001011L
83 #define tr_sc4 0b1001110L
84 #define tr_sc8 0b1001111L
85
86 #define is_load(tr) ((0b1111100L & tr_code(tr)) == \
87 (0b1010000L))
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)) == \
93 (0b1010100L))
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))
99
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)) == \
105 (0b1100000L))
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)) == \
110 (0b1110000L))
111 #define tr_clevel(tr) (tr_code(tr)&0x3L)
112
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. */
116
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) */
120
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 */
124
125
126
127 /*
128 Macros to create trace records.
129 */
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) )
132
133
134
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(); }
137
138
139 static inline uint64_t tr_print(uint64_t tr, FILE* f)
140 {
141 if (is_mem(tr))
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));
145 else if (is_bbk(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));
151 else
152 fprintf(f, "OtherOp=%016lx, code=%02lx, delta=%ld, pc=0x%lx\n", tr, tr_code(tr), tr_delta(tr), tr_pc(tr));
153 return tr;
154 }
155
156
157 struct options_t {
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 =) */
163 };
164 union { /* default value */
165 const char* ds; /* name=s */
166 long di; /* name=i */
167 long bv; /* value if flag given */
168 };
169 const char* h; /* help string */
170 };
171
172 extern const struct options_t opt[];
173 extern const char* usage;
174
175 void help_exit();
176 int parse_options( const char** argv );