1c89da08cf06235694ea402a1b675533ebe11feb
[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 sv_reg_csr_entry sv_csrs[SV_CSR_SZ];
133 sv_reg_entry sv_int_tb[NXPR];
134 sv_reg_entry sv_fp_tb[NFPR];
135 sv_pred_csr_entry sv_pred_csrs[SV_CSR_SZ];
136 sv_pred_entry sv_pred_int_tb[NXPR];
137 sv_pred_entry sv_pred_fp_tb[NFPR];
138 #endif
139
140 uint32_t fflags;
141 uint32_t frm;
142 bool serialized; // whether timer CSRs are in a well-defined state
143
144 // When true, execute a single instruction and then enter debug mode. This
145 // can only be set by executing dret.
146 enum {
147 STEP_NONE,
148 STEP_STEPPING,
149 STEP_STEPPED
150 } single_step;
151
152 #ifdef RISCV_ENABLE_COMMITLOG
153 commit_log_reg_t log_reg_write;
154 reg_t last_inst_priv;
155 int last_inst_xlen;
156 int last_inst_flen;
157 #endif
158 };
159
160 typedef enum {
161 OPERATION_EXECUTE,
162 OPERATION_STORE,
163 OPERATION_LOAD,
164 } trigger_operation_t;
165
166 // Count number of contiguous 1 bits starting from the LSB.
167 static int cto(reg_t val)
168 {
169 int res = 0;
170 while ((val & 1) == 1)
171 val >>= 1, res++;
172 return res;
173 }
174
175 // this class represents one processor in a RISC-V machine.
176 class processor_t : public abstract_device_t
177 {
178 public:
179 processor_t(const char* isa, simif_t* sim, uint32_t id, bool halt_on_reset=false);
180 ~processor_t();
181
182 void set_debug(bool value);
183 void set_histogram(bool value);
184 void reset();
185 void step(size_t n); // run for n cycles
186 void set_csr(int which, reg_t val);
187 reg_t get_csr(int which);
188 mmu_t* get_mmu() { return mmu; }
189 state_t* get_state() { return &state; }
190 unsigned get_xlen() { return xlen; }
191 unsigned get_max_xlen() { return max_xlen; }
192 std::string get_isa_string() { return isa_string; }
193 unsigned get_flen() {
194 return supports_extension('Q') ? 128 :
195 supports_extension('D') ? 64 :
196 supports_extension('F') ? 32 : 0;
197 }
198 extension_t* get_extension() { return ext; }
199 bool supports_extension(unsigned char ext) {
200 if (ext >= 'a' && ext <= 'z') ext += 'A' - 'a';
201 return ext >= 'A' && ext <= 'Z' && ((state.misa >> (ext - 'A')) & 1);
202 }
203 reg_t pc_alignment_mask() {
204 return ~(reg_t)(supports_extension('C') ? 0 : 2);
205 }
206 void check_pc_alignment(reg_t pc) {
207 if (unlikely(pc & ~pc_alignment_mask()))
208 throw trap_instruction_address_misaligned(pc);
209 }
210 reg_t legalize_privilege(reg_t);
211 void set_privilege(reg_t);
212 void update_histogram(reg_t pc);
213 const disassembler_t* get_disassembler() { return disassembler; }
214
215 void register_insn(insn_desc_t);
216 void register_extension(extension_t*);
217
218 // MMIO slave interface
219 bool load(reg_t addr, size_t len, uint8_t* bytes);
220 bool store(reg_t addr, size_t len, const uint8_t* bytes);
221
222 // When true, display disassembly of each instruction that's executed.
223 bool debug;
224 // When true, take the slow simulation path.
225 bool slow_path();
226 bool halted() { return state.dcsr.cause ? true : false; }
227 bool halt_request;
228
229 // Return the index of a trigger that matched, or -1.
230 inline int trigger_match(trigger_operation_t operation, reg_t address, reg_t data)
231 {
232 if (state.dcsr.cause)
233 return -1;
234
235 bool chain_ok = true;
236
237 for (unsigned int i = 0; i < state.num_triggers; i++) {
238 if (!chain_ok) {
239 chain_ok |= !state.mcontrol[i].chain;
240 continue;
241 }
242
243 if ((operation == OPERATION_EXECUTE && !state.mcontrol[i].execute) ||
244 (operation == OPERATION_STORE && !state.mcontrol[i].store) ||
245 (operation == OPERATION_LOAD && !state.mcontrol[i].load) ||
246 (state.prv == PRV_M && !state.mcontrol[i].m) ||
247 (state.prv == PRV_S && !state.mcontrol[i].s) ||
248 (state.prv == PRV_U && !state.mcontrol[i].u)) {
249 continue;
250 }
251
252 reg_t value;
253 if (state.mcontrol[i].select) {
254 value = data;
255 } else {
256 value = address;
257 }
258
259 // We need this because in 32-bit mode sometimes the PC bits get sign
260 // extended.
261 if (xlen == 32) {
262 value &= 0xffffffff;
263 }
264
265 switch (state.mcontrol[i].match) {
266 case MATCH_EQUAL:
267 if (value != state.tdata2[i])
268 continue;
269 break;
270 case MATCH_NAPOT:
271 {
272 reg_t mask = ~((1 << cto(state.tdata2[i])) - 1);
273 if ((value & mask) != (state.tdata2[i] & mask))
274 continue;
275 }
276 break;
277 case MATCH_GE:
278 if (value < state.tdata2[i])
279 continue;
280 break;
281 case MATCH_LT:
282 if (value >= state.tdata2[i])
283 continue;
284 break;
285 case MATCH_MASK_LOW:
286 {
287 reg_t mask = state.tdata2[i] >> (xlen/2);
288 if ((value & mask) != (state.tdata2[i] & mask))
289 continue;
290 }
291 break;
292 case MATCH_MASK_HIGH:
293 {
294 reg_t mask = state.tdata2[i] >> (xlen/2);
295 if (((value >> (xlen/2)) & mask) != (state.tdata2[i] & mask))
296 continue;
297 }
298 break;
299 }
300
301 if (!state.mcontrol[i].chain) {
302 return i;
303 }
304 chain_ok = true;
305 }
306 return -1;
307 }
308
309 void trigger_updated();
310
311 private:
312 simif_t* sim;
313 mmu_t* mmu; // main memory is always accessed via the mmu
314 extension_t* ext;
315 disassembler_t* disassembler;
316 state_t state;
317 uint32_t id;
318 unsigned max_xlen;
319 unsigned xlen;
320 reg_t max_isa;
321 std::string isa_string;
322 bool histogram_enabled;
323 bool halt_on_reset;
324
325 std::vector<insn_desc_t> instructions;
326 std::map<reg_t,uint64_t> pc_histogram;
327
328 static const size_t OPCODE_CACHE_SIZE = 8191;
329 insn_desc_t opcode_cache[OPCODE_CACHE_SIZE];
330
331 void take_pending_interrupt() { take_interrupt(state.mip & state.mie); }
332 void take_interrupt(reg_t mask); // take first enabled interrupt in mask
333 void take_trap(trap_t& t, reg_t epc); // take an exception
334 void disasm(insn_t insn); // disassemble and print an instruction
335 int paddr_bits();
336
337 void enter_debug_mode(uint8_t cause);
338
339 friend class mmu_t;
340 friend class clint_t;
341 friend class extension_t;
342
343 void parse_isa_string(const char* isa);
344 void build_opcode_map();
345 void register_base_instructions();
346 insn_func_t decode_insn(insn_t insn);
347
348 // Track repeated executions for processor_t::disasm()
349 uint64_t last_pc, last_bits, executions;
350 };
351
352 reg_t illegal_instruction(processor_t* p, insn_t insn, reg_t pc);
353
354 #define REGISTER_INSN(proc, name, match, mask) \
355 extern reg_t rv32_##name(processor_t*, insn_t, reg_t); \
356 extern reg_t rv64_##name(processor_t*, insn_t, reg_t); \
357 proc->register_insn((insn_desc_t){match, mask, rv32_##name, rv64_##name});
358
359 #endif