add srcoffs and destoffs sv state, alter CSRs
[riscv-isa-sim.git] / riscv / processor.h
1 // See LICENSE for license details.
2 #ifndef _RISCV_PROCESSOR_H
3 #define _RISCV_PROCESSOR_H
4
5 #include "decode.h"
6 #include "config.h"
7 #include "devices.h"
8 #include "trap.h"
9 #include <string>
10 #include <vector>
11 #include <map>
12 #include "debug_rom_defines.h"
13 #ifdef SPIKE_SIMPLEV
14 #include "sv_decode.h"
15 #endif
16
17 class processor_t;
18 class mmu_t;
19 typedef reg_t (*insn_func_t)(processor_t*, insn_t, reg_t);
20 class simif_t;
21 class trap_t;
22 class extension_t;
23 class disassembler_t;
24
25 struct insn_desc_t
26 {
27 insn_bits_t match;
28 insn_bits_t mask;
29 insn_func_t rv32;
30 insn_func_t rv64;
31 };
32
33 struct commit_log_reg_t
34 {
35 reg_t addr;
36 freg_t data;
37 };
38
39 typedef struct
40 {
41 uint8_t prv;
42 bool step;
43 bool ebreakm;
44 bool ebreakh;
45 bool ebreaks;
46 bool ebreaku;
47 bool halt;
48 uint8_t cause;
49 } dcsr_t;
50
51 typedef enum
52 {
53 ACTION_DEBUG_EXCEPTION = MCONTROL_ACTION_DEBUG_EXCEPTION,
54 ACTION_DEBUG_MODE = MCONTROL_ACTION_DEBUG_MODE,
55 ACTION_TRACE_START = MCONTROL_ACTION_TRACE_START,
56 ACTION_TRACE_STOP = MCONTROL_ACTION_TRACE_STOP,
57 ACTION_TRACE_EMIT = MCONTROL_ACTION_TRACE_EMIT
58 } mcontrol_action_t;
59
60 typedef enum
61 {
62 MATCH_EQUAL = MCONTROL_MATCH_EQUAL,
63 MATCH_NAPOT = MCONTROL_MATCH_NAPOT,
64 MATCH_GE = MCONTROL_MATCH_GE,
65 MATCH_LT = MCONTROL_MATCH_LT,
66 MATCH_MASK_LOW = MCONTROL_MATCH_MASK_LOW,
67 MATCH_MASK_HIGH = MCONTROL_MATCH_MASK_HIGH
68 } mcontrol_match_t;
69
70 typedef struct
71 {
72 uint8_t type;
73 bool dmode;
74 uint8_t maskmax;
75 bool select;
76 bool timing;
77 mcontrol_action_t action;
78 bool chain;
79 mcontrol_match_t match;
80 bool m;
81 bool h;
82 bool s;
83 bool u;
84 bool execute;
85 bool store;
86 bool load;
87 } mcontrol_t;
88
89 // architectural state of a RISC-V hart
90 struct state_t
91 {
92 void reset(reg_t max_isa);
93
94 static const int num_triggers = 4;
95
96 reg_t pc;
97 regfile_t<reg_t, NXPR, true> XPR;
98 regfile_t<freg_t, NFPR, false> FPR;
99
100 // control and status registers
101 reg_t prv; // TODO: Can this be an enum instead?
102 reg_t misa;
103 reg_t mstatus;
104 reg_t mepc;
105 reg_t mtval;
106 reg_t mscratch;
107 reg_t mtvec;
108 reg_t mcause;
109 reg_t minstret;
110 reg_t mie;
111 reg_t mip;
112 reg_t medeleg;
113 reg_t mideleg;
114 uint32_t mcounteren;
115 uint32_t scounteren;
116 reg_t sepc;
117 reg_t stval;
118 reg_t sscratch;
119 reg_t stvec;
120 reg_t satp;
121 reg_t scause;
122 reg_t dpc;
123 reg_t dscratch;
124 dcsr_t dcsr;
125 reg_t tselect;
126 mcontrol_t mcontrol[num_triggers];
127 reg_t tdata2[num_triggers];
128
129 #ifdef SPIKE_SIMPLEV
130 uint64_t vl;
131 uint64_t mvl;
132 uint64_t destoffs; // destination loop element offset
133 uint64_t srcoffs; // source loop element offset (used in twin-predication)
134 sv_reg_csr_entry sv_csrs[SV_CSR_SZ];
135 sv_reg_entry sv_int_tb[NXPR];
136 sv_reg_entry sv_fp_tb[NFPR];
137 sv_pred_csr_entry sv_pred_csrs[SV_CSR_SZ];
138 sv_pred_entry sv_pred_int_tb[NXPR];
139 sv_pred_entry sv_pred_fp_tb[NFPR];
140 #endif
141
142 uint32_t fflags;
143 uint32_t frm;
144 bool serialized; // whether timer CSRs are in a well-defined state
145
146 // When true, execute a single instruction and then enter debug mode. This
147 // can only be set by executing dret.
148 enum {
149 STEP_NONE,
150 STEP_STEPPING,
151 STEP_STEPPED
152 } single_step;
153
154 #ifdef RISCV_ENABLE_COMMITLOG
155 commit_log_reg_t log_reg_write;
156 reg_t last_inst_priv;
157 int last_inst_xlen;
158 int last_inst_flen;
159 #endif
160 };
161
162 typedef enum {
163 OPERATION_EXECUTE,
164 OPERATION_STORE,
165 OPERATION_LOAD,
166 } trigger_operation_t;
167
168 // Count number of contiguous 1 bits starting from the LSB.
169 static int cto(reg_t val)
170 {
171 int res = 0;
172 while ((val & 1) == 1)
173 val >>= 1, res++;
174 return res;
175 }
176
177 // this class represents one processor in a RISC-V machine.
178 class processor_t : public abstract_device_t
179 {
180 public:
181 processor_t(const char* isa, simif_t* sim, uint32_t id, bool halt_on_reset=false);
182 ~processor_t();
183
184 void set_debug(bool value);
185 void set_histogram(bool value);
186 void reset();
187 void step(size_t n); // run for n cycles
188 void set_csr(int which, reg_t val);
189 reg_t get_csr(int which);
190 mmu_t* get_mmu() { return mmu; }
191 state_t* get_state() { return &state; }
192 unsigned get_xlen() { return xlen; }
193 unsigned get_max_xlen() { return max_xlen; }
194 std::string get_isa_string() { return isa_string; }
195 unsigned get_flen() {
196 return supports_extension('Q') ? 128 :
197 supports_extension('D') ? 64 :
198 supports_extension('F') ? 32 : 0;
199 }
200 extension_t* get_extension() { return ext; }
201 bool supports_extension(unsigned char ext) {
202 if (ext >= 'a' && ext <= 'z') ext += 'A' - 'a';
203 return ext >= 'A' && ext <= 'Z' && ((state.misa >> (ext - 'A')) & 1);
204 }
205 reg_t pc_alignment_mask() {
206 return ~(reg_t)(supports_extension('C') ? 0 : 2);
207 }
208 void check_pc_alignment(reg_t pc) {
209 if (unlikely(pc & ~pc_alignment_mask()))
210 throw trap_instruction_address_misaligned(pc);
211 }
212 reg_t legalize_privilege(reg_t);
213 void set_privilege(reg_t);
214 void update_histogram(reg_t pc);
215 const disassembler_t* get_disassembler() { return disassembler; }
216
217 void register_insn(insn_desc_t);
218 void register_extension(extension_t*);
219
220 // MMIO slave interface
221 bool load(reg_t addr, size_t len, uint8_t* bytes);
222 bool store(reg_t addr, size_t len, const uint8_t* bytes);
223
224 // When true, display disassembly of each instruction that's executed.
225 bool debug;
226 // When true, take the slow simulation path.
227 bool slow_path();
228 bool halted() { return state.dcsr.cause ? true : false; }
229 bool halt_request;
230
231 // Return the index of a trigger that matched, or -1.
232 inline int trigger_match(trigger_operation_t operation, reg_t address, reg_t data)
233 {
234 if (state.dcsr.cause)
235 return -1;
236
237 bool chain_ok = true;
238
239 for (unsigned int i = 0; i < state.num_triggers; i++) {
240 if (!chain_ok) {
241 chain_ok |= !state.mcontrol[i].chain;
242 continue;
243 }
244
245 if ((operation == OPERATION_EXECUTE && !state.mcontrol[i].execute) ||
246 (operation == OPERATION_STORE && !state.mcontrol[i].store) ||
247 (operation == OPERATION_LOAD && !state.mcontrol[i].load) ||
248 (state.prv == PRV_M && !state.mcontrol[i].m) ||
249 (state.prv == PRV_S && !state.mcontrol[i].s) ||
250 (state.prv == PRV_U && !state.mcontrol[i].u)) {
251 continue;
252 }
253
254 reg_t value;
255 if (state.mcontrol[i].select) {
256 value = data;
257 } else {
258 value = address;
259 }
260
261 // We need this because in 32-bit mode sometimes the PC bits get sign
262 // extended.
263 if (xlen == 32) {
264 value &= 0xffffffff;
265 }
266
267 switch (state.mcontrol[i].match) {
268 case MATCH_EQUAL:
269 if (value != state.tdata2[i])
270 continue;
271 break;
272 case MATCH_NAPOT:
273 {
274 reg_t mask = ~((1 << cto(state.tdata2[i])) - 1);
275 if ((value & mask) != (state.tdata2[i] & mask))
276 continue;
277 }
278 break;
279 case MATCH_GE:
280 if (value < state.tdata2[i])
281 continue;
282 break;
283 case MATCH_LT:
284 if (value >= state.tdata2[i])
285 continue;
286 break;
287 case MATCH_MASK_LOW:
288 {
289 reg_t mask = state.tdata2[i] >> (xlen/2);
290 if ((value & mask) != (state.tdata2[i] & mask))
291 continue;
292 }
293 break;
294 case MATCH_MASK_HIGH:
295 {
296 reg_t mask = state.tdata2[i] >> (xlen/2);
297 if (((value >> (xlen/2)) & mask) != (state.tdata2[i] & mask))
298 continue;
299 }
300 break;
301 }
302
303 if (!state.mcontrol[i].chain) {
304 return i;
305 }
306 chain_ok = true;
307 }
308 return -1;
309 }
310
311 void trigger_updated();
312
313 private:
314 simif_t* sim;
315 mmu_t* mmu; // main memory is always accessed via the mmu
316 extension_t* ext;
317 disassembler_t* disassembler;
318 state_t state;
319 uint32_t id;
320 unsigned max_xlen;
321 unsigned xlen;
322 reg_t max_isa;
323 std::string isa_string;
324 bool histogram_enabled;
325 bool halt_on_reset;
326
327 std::vector<insn_desc_t> instructions;
328 std::map<reg_t,uint64_t> pc_histogram;
329
330 static const size_t OPCODE_CACHE_SIZE = 8191;
331 insn_desc_t opcode_cache[OPCODE_CACHE_SIZE];
332
333 void take_pending_interrupt() { take_interrupt(state.mip & state.mie); }
334 void take_interrupt(reg_t mask); // take first enabled interrupt in mask
335 void take_trap(trap_t& t, reg_t epc); // take an exception
336 void disasm(insn_t insn); // disassemble and print an instruction
337 int paddr_bits();
338
339 void enter_debug_mode(uint8_t cause);
340
341 friend class mmu_t;
342 friend class clint_t;
343 friend class extension_t;
344
345 void parse_isa_string(const char* isa);
346 void build_opcode_map();
347 void register_base_instructions();
348 insn_func_t decode_insn(insn_t insn);
349
350 // Track repeated executions for processor_t::disasm()
351 uint64_t last_pc, last_bits, executions;
352 };
353
354 reg_t illegal_instruction(processor_t* p, insn_t insn, reg_t pc);
355
356 #define REGISTER_INSN(proc, name, match, mask) \
357 extern reg_t rv32_##name(processor_t*, insn_t, reg_t); \
358 extern reg_t rv64_##name(processor_t*, insn_t, reg_t); \
359 proc->register_insn((insn_desc_t){match, mask, rv32_##name, rv64_##name});
360
361 #endif