b12a8e0976f841daaaba2847e112cd7715f04b67
[riscv-isa-sim.git] / riscv / processor.cc
1 // See LICENSE for license details.
2
3 #include "processor.h"
4 #include "extension.h"
5 #include "common.h"
6 #include "config.h"
7 #include "sim.h"
8 #include "disasm.h"
9 #include <cinttypes>
10 #include <cmath>
11 #include <cstdlib>
12 #include <iostream>
13 #include <assert.h>
14 #include <limits.h>
15 #include <stdexcept>
16 #include <algorithm>
17
18 processor_t::processor_t(sim_t* _sim, mmu_t* _mmu, uint32_t _id)
19 : sim(_sim), mmu(_mmu), ext(NULL), disassembler(new disassembler_t),
20 id(_id), run(false), debug(false)
21 {
22 reset(true);
23 mmu->set_processor(this);
24
25 #define DECLARE_INSN(name, match, mask) REGISTER_INSN(this, name, match, mask)
26 #include "encoding.h"
27 #undef DECLARE_INSN
28 build_opcode_map();
29 }
30
31 processor_t::~processor_t()
32 {
33 }
34
35 void state_t::reset()
36 {
37 // the ISA guarantees on boot that the PC is 0x2000 and the the processor
38 // is in supervisor mode, and in 64-bit mode, if supported, with traps
39 // and virtual memory disabled.
40 sr = SR_S | SR_S64;
41 pc = 0x2000;
42
43 // the following state is undefined upon boot-up,
44 // but we zero it for determinism
45 XPR.reset();
46 FPR.reset();
47
48 evec = 0;
49 epc = 0;
50 badvaddr = 0;
51 cause = 0;
52 pcr_k0 = 0;
53 pcr_k1 = 0;
54 count = 0;
55 compare = 0;
56 fflags = 0;
57 frm = 0;
58
59 load_reservation = -1;
60 }
61
62 void processor_t::set_debug(bool value)
63 {
64 debug = value;
65 if (ext)
66 ext->set_debug(value);
67 }
68
69 void processor_t::reset(bool value)
70 {
71 if (run == !value)
72 return;
73 run = !value;
74
75 state.reset(); // reset the core
76 set_pcr(CSR_STATUS, state.sr);
77
78 if (ext)
79 ext->reset(); // reset the extension
80 }
81
82 void processor_t::take_interrupt()
83 {
84 uint32_t interrupts = (state.sr & SR_IP) >> SR_IP_SHIFT;
85 interrupts &= (state.sr & SR_IM) >> SR_IM_SHIFT;
86
87 if (interrupts && (state.sr & SR_EI))
88 for (int i = 0; ; i++, interrupts >>= 1)
89 if (interrupts & 1)
90 throw trap_t((1ULL << ((state.sr & SR_S64) ? 63 : 31)) + i);
91 }
92
93 void processor_t::step(size_t n)
94 {
95 if(!run)
96 return;
97
98 size_t i = 0;
99 reg_t npc = state.pc;
100 mmu_t* _mmu = mmu;
101
102 try
103 {
104 take_interrupt();
105
106 // execute_insn fetches and executes one instruction
107 #define execute_insn(noisy) \
108 do { \
109 mmu_t::insn_fetch_t fetch = _mmu->load_insn(npc); \
110 if(noisy) disasm(fetch.insn.insn); \
111 npc = fetch.func(this, fetch.insn.insn, npc); \
112 } while(0)
113
114
115 // special execute_insn for commit log dumping
116 #ifdef RISCV_ENABLE_COMMITLOG
117 //static disassembler disasmblr;
118 #undef execute_insn
119 #define execute_insn(noisy) \
120 do { \
121 mmu_t::insn_fetch_t fetch = _mmu->load_insn(npc); \
122 if(noisy) disasm(fetch.insn.insn); \
123 bool in_spvr = state.sr & SR_S; \
124 if (!in_spvr) fprintf(stderr, "\n0x%016" PRIx64 " (0x%08" PRIx32 ") ", npc, fetch.insn.insn.bits()); \
125 /*if (!in_spvr) fprintf(stderr, "\n0x%016" PRIx64 " (0x%08" PRIx32 ") %s ", npc, fetch.insn.insn.bits(), disasmblr.disassemble(fetch.insn.insn).c_str());*/ \
126 npc = fetch.func(this, fetch.insn.insn, npc); \
127 } while(0)
128 #endif
129
130 if(debug) for( ; i < n; i++) // print out instructions as we go
131 execute_insn(true);
132 else
133 {
134 // unrolled for speed
135 for( ; n > 3 && i < n-3; i+=4)
136 {
137 execute_insn(false);
138 execute_insn(false);
139 execute_insn(false);
140 execute_insn(false);
141 }
142 for( ; i < n; i++)
143 execute_insn(false);
144 }
145
146 state.pc = npc;
147 }
148 catch(trap_t& t)
149 {
150 take_trap(npc, t);
151 }
152
153 // update timer and possibly register a timer interrupt
154 uint32_t old_count = state.count;
155 state.count += i;
156 if(old_count < state.compare && uint64_t(old_count) + i >= state.compare)
157 set_interrupt(IRQ_TIMER, true);
158 }
159
160 void processor_t::take_trap(reg_t pc, trap_t& t)
161 {
162 if (debug)
163 fprintf(stderr, "core %3d: exception %s, epc 0x%016" PRIx64 "\n",
164 id, t.name(), pc);
165
166 // switch to supervisor, set previous supervisor bit, disable interrupts
167 set_pcr(CSR_STATUS, (((state.sr & ~SR_EI) | SR_S) & ~SR_PS & ~SR_PEI) |
168 ((state.sr & SR_S) ? SR_PS : 0) |
169 ((state.sr & SR_EI) ? SR_PEI : 0));
170
171 yield_load_reservation();
172 state.cause = t.cause();
173 state.epc = pc;
174 state.pc = state.evec;
175
176 t.side_effects(&state); // might set badvaddr etc.
177 }
178
179 void processor_t::deliver_ipi()
180 {
181 if (run)
182 set_pcr(CSR_CLEAR_IPI, 1);
183 }
184
185 void processor_t::disasm(insn_t insn)
186 {
187 // the disassembler is stateless, so we share it
188 fprintf(stderr, "core %3d: 0x%016" PRIx64 " (0x%08" PRIx32 ") %s\n",
189 id, state.pc, insn.bits(), disassembler->disassemble(insn).c_str());
190 }
191
192 reg_t processor_t::set_pcr(int which, reg_t val)
193 {
194 reg_t old_pcr = get_pcr(which);
195
196 switch (which)
197 {
198 case CSR_FFLAGS:
199 state.fflags = val & (FSR_AEXC >> FSR_AEXC_SHIFT);
200 break;
201 case CSR_FRM:
202 state.frm = val & (FSR_RD >> FSR_RD_SHIFT);
203 break;
204 case CSR_FCSR:
205 state.fflags = (val & FSR_AEXC) >> FSR_AEXC_SHIFT;
206 state.frm = (val & FSR_RD) >> FSR_RD_SHIFT;
207 break;
208 case CSR_STATUS:
209 state.sr = (val & ~SR_IP) | (state.sr & SR_IP);
210 #ifndef RISCV_ENABLE_64BIT
211 state.sr &= ~(SR_S64 | SR_U64);
212 #endif
213 #ifndef RISCV_ENABLE_FPU
214 state.sr &= ~SR_EF;
215 #endif
216 if (!ext)
217 state.sr &= ~SR_EA;
218 state.sr &= ~SR_ZERO;
219 rv64 = (state.sr & SR_S) ? (state.sr & SR_S64) : (state.sr & SR_U64);
220 mmu->flush_tlb();
221 break;
222 case CSR_EPC:
223 state.epc = val;
224 break;
225 case CSR_EVEC:
226 state.evec = val;
227 break;
228 case CSR_CYCLE:
229 case CSR_TIME:
230 case CSR_INSTRET:
231 case CSR_COUNT:
232 state.count = val;
233 break;
234 case CSR_COMPARE:
235 set_interrupt(IRQ_TIMER, false);
236 state.compare = val;
237 break;
238 case CSR_PTBR:
239 state.ptbr = val & ~(PGSIZE-1);
240 break;
241 case CSR_SEND_IPI:
242 sim->send_ipi(val);
243 break;
244 case CSR_CLEAR_IPI:
245 set_interrupt(IRQ_IPI, val & 1);
246 break;
247 case CSR_SUP0:
248 state.pcr_k0 = val;
249 break;
250 case CSR_SUP1:
251 state.pcr_k1 = val;
252 break;
253 case CSR_TOHOST:
254 if (state.tohost == 0)
255 state.tohost = val;
256 break;
257 case CSR_FROMHOST:
258 set_interrupt(IRQ_HOST, val != 0);
259 state.fromhost = val;
260 break;
261 }
262
263 return old_pcr;
264 }
265
266 reg_t processor_t::get_pcr(int which)
267 {
268 switch (which)
269 {
270 case CSR_FFLAGS:
271 return state.fflags;
272 case CSR_FRM:
273 return state.frm;
274 case CSR_FCSR:
275 return (state.fflags << FSR_AEXC_SHIFT) | (state.frm << FSR_RD_SHIFT);
276 case CSR_STATUS:
277 return state.sr;
278 case CSR_EPC:
279 return state.epc;
280 case CSR_BADVADDR:
281 return state.badvaddr;
282 case CSR_EVEC:
283 return state.evec;
284 case CSR_CYCLE:
285 case CSR_TIME:
286 case CSR_INSTRET:
287 case CSR_COUNT:
288 return state.count;
289 case CSR_COMPARE:
290 return state.compare;
291 case CSR_CAUSE:
292 return state.cause;
293 case CSR_PTBR:
294 return state.ptbr;
295 case CSR_ASID:
296 return 0;
297 case CSR_FATC:
298 mmu->flush_tlb();
299 return 0;
300 case CSR_HARTID:
301 return id;
302 case CSR_IMPL:
303 return 1;
304 case CSR_SUP0:
305 return state.pcr_k0;
306 case CSR_SUP1:
307 return state.pcr_k1;
308 case CSR_TOHOST:
309 return state.tohost;
310 case CSR_FROMHOST:
311 return state.fromhost;
312 default:
313 return -1;
314 }
315 }
316
317 void processor_t::set_interrupt(int which, bool on)
318 {
319 uint32_t mask = (1 << (which + SR_IP_SHIFT)) & SR_IP;
320 if (on)
321 state.sr |= mask;
322 else
323 state.sr &= ~mask;
324 }
325
326 reg_t illegal_instruction(processor_t* p, insn_t insn, reg_t pc)
327 {
328 throw trap_illegal_instruction();
329 }
330
331 insn_func_t processor_t::decode_insn(insn_t insn)
332 {
333 size_t mask = opcode_map.size()-1;
334 insn_desc_t* desc = opcode_map[insn.bits() & mask];
335
336 while ((insn.bits() & desc->mask) != desc->match)
337 desc++;
338
339 return rv64 ? desc->rv64 : desc->rv32;
340 }
341
342 void processor_t::register_insn(insn_desc_t desc)
343 {
344 assert(desc.mask & 1);
345 instructions.push_back(desc);
346 }
347
348 void processor_t::build_opcode_map()
349 {
350 size_t buckets = -1;
351 for (auto& inst : instructions)
352 while ((inst.mask & buckets) != buckets)
353 buckets /= 2;
354 buckets++;
355
356 struct cmp {
357 decltype(insn_desc_t::match) mask;
358 cmp(decltype(mask) mask) : mask(mask) {}
359 bool operator()(const insn_desc_t& lhs, const insn_desc_t& rhs) {
360 if ((lhs.match & mask) != (rhs.match & mask))
361 return (lhs.match & mask) < (rhs.match & mask);
362 return lhs.match < rhs.match;
363 }
364 };
365 std::sort(instructions.begin(), instructions.end(), cmp(buckets-1));
366
367 opcode_map.resize(buckets);
368 opcode_store.resize(instructions.size() + 1);
369
370 size_t j = 0;
371 for (size_t b = 0, i = 0; b < buckets; b++)
372 {
373 opcode_map[b] = &opcode_store[j];
374 while (i < instructions.size() && b == (instructions[i].match & (buckets-1)))
375 opcode_store[j++] = instructions[i++];
376 }
377
378 assert(j == opcode_store.size()-1);
379 opcode_store[j].match = opcode_store[j].mask = 0;
380 opcode_store[j].rv32 = &illegal_instruction;
381 opcode_store[j].rv64 = &illegal_instruction;
382 }
383
384 void processor_t::register_extension(extension_t* x)
385 {
386 for (auto insn : x->get_instructions())
387 register_insn(insn);
388 build_opcode_map();
389 for (auto disasm_insn : x->get_disasms())
390 disassembler->add_insn(disasm_insn);
391 if (ext != NULL)
392 throw std::logic_error("only one extension may be registered");
393 ext = x;
394 x->set_processor(this);
395 }