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