Reduce dependences on auto-generated code
[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 "htif.h"
9 #include "disasm.h"
10 #include <cinttypes>
11 #include <cmath>
12 #include <cstdlib>
13 #include <iostream>
14 #include <assert.h>
15 #include <limits.h>
16 #include <stdexcept>
17 #include <algorithm>
18
19 #undef STATE
20 #define STATE state
21
22 processor_t::processor_t(sim_t* _sim, mmu_t* _mmu, uint32_t _id)
23 : sim(_sim), mmu(_mmu), ext(NULL), disassembler(new disassembler_t),
24 id(_id), run(false), debug(false), serialized(false)
25 {
26 reset(true);
27 mmu->set_processor(this);
28
29 #define DECLARE_INSN(name, match, mask) REGISTER_INSN(this, name, match, mask)
30 #include "encoding.h"
31 #undef DECLARE_INSN
32 build_opcode_map();
33 }
34
35 processor_t::~processor_t()
36 {
37 #ifdef RISCV_ENABLE_HISTOGRAM
38 if (histogram_enabled)
39 {
40 fprintf(stderr, "PC Histogram size:%lu\n", pc_histogram.size());
41 for(auto iterator = pc_histogram.begin(); iterator != pc_histogram.end(); ++iterator) {
42 fprintf(stderr, "%0lx %lu\n", (iterator->first << 2), iterator->second);
43 }
44 }
45 #endif
46
47 delete disassembler;
48 }
49
50 void state_t::reset()
51 {
52 // the ISA guarantees on boot that the PC is 0x2000 and the the processor
53 // is in supervisor mode, and in 64-bit mode, if supported, with traps
54 // and virtual memory disabled.
55 sr = SR_S | SR_S64 | SR_U64;
56 pc = 0x2000;
57
58 // the following state is undefined upon boot-up,
59 // but we zero it for determinism
60 XPR.reset();
61 FPR.reset();
62
63 epc = 0;
64 badvaddr = 0;
65 evec = 0;
66 ptbr = 0;
67 pcr_k0 = 0;
68 pcr_k1 = 0;
69 cause = 0;
70 tohost = 0;
71 fromhost = 0;
72 count = 0;
73 compare = 0;
74 fflags = 0;
75 frm = 0;
76
77 load_reservation = -1;
78 }
79
80 void processor_t::set_debug(bool value)
81 {
82 debug = value;
83 if (ext)
84 ext->set_debug(value);
85 }
86
87 void processor_t::set_histogram(bool value)
88 {
89 histogram_enabled = value;
90 }
91
92 void processor_t::reset(bool value)
93 {
94 if (run == !value)
95 return;
96 run = !value;
97
98 state.reset(); // reset the core
99 set_pcr(CSR_STATUS, state.sr);
100
101 if (ext)
102 ext->reset(); // reset the extension
103 }
104
105 struct serialize_t {};
106
107 void processor_t::serialize()
108 {
109 if (serialized)
110 serialized = false;
111 else
112 serialized = true, throw serialize_t();
113 }
114
115 void processor_t::take_interrupt()
116 {
117 int irqs = ((state.sr & SR_IP) >> SR_IP_SHIFT) & (state.sr >> SR_IM_SHIFT);
118 if (likely(!irqs) || likely(!(state.sr & SR_EI)))
119 return;
120
121 for (int i = 0; ; i++)
122 if ((irqs >> i) & 1)
123 throw trap_t((1ULL << ((state.sr & SR_S64) ? 63 : 31)) + i);
124 }
125
126 static void commit_log(state_t* state, insn_t insn)
127 {
128 #ifdef RISCV_ENABLE_COMMITLOG
129 if (state->sr & SR_EI) {
130 if (state->log_reg_write.addr) {
131 fprintf(stderr, "0x%016" PRIx64 " (0x%08" PRIx64 ") %c%2u 0x%016" PRIx64 "\n",
132 state->pc, insn.bits(),
133 state->log_reg_write.addr & 1 ? 'f' : 'x',
134 state->log_reg_write.addr >> 1, state->log_reg_write.data);
135 }
136 else {
137 fprintf(stderr, "0x%016" PRIx64 " (0x%08" PRIx64 ")\n",
138 state->pc, insn.bits());
139 }
140 }
141 state->log_reg_write.addr = 0;
142 #endif
143 }
144
145 inline void processor_t::update_histogram(size_t pc)
146 {
147 #ifdef RISCV_ENABLE_HISTOGRAM
148 size_t idx = pc >> 2;
149 pc_histogram[idx]++;
150 #endif
151 }
152
153 static reg_t execute_insn(processor_t* p, reg_t pc, insn_fetch_t fetch)
154 {
155 reg_t npc = fetch.func(p, fetch.insn, pc);
156 commit_log(p->get_state(), fetch.insn);
157 p->update_histogram(pc);
158 return npc;
159 }
160
161 static void update_timer(state_t* state, size_t instret)
162 {
163 uint64_t count0 = (uint64_t)(uint32_t)state->count;
164 state->count += instret;
165 uint64_t before = count0 - state->compare;
166 if (int64_t(before ^ (before + instret)) < 0)
167 state->sr |= (1 << (IRQ_TIMER + SR_IP_SHIFT));
168 }
169
170 static size_t next_timer(state_t* state)
171 {
172 return state->compare - (uint32_t)state->count;
173 }
174
175 void processor_t::step(size_t n)
176 {
177 size_t instret = 0;
178 reg_t pc = state.pc;
179 mmu_t* _mmu = mmu;
180
181 if (unlikely(!run || !n))
182 return;
183 n = std::min(n, next_timer(&state) | 1U);
184
185 try
186 {
187 take_interrupt();
188
189 if (unlikely(debug))
190 {
191 while (instret++ < n)
192 {
193 insn_fetch_t fetch = mmu->load_insn(pc);
194 disasm(fetch.insn);
195 pc = execute_insn(this, pc, fetch);
196 }
197 }
198 else while (instret < n)
199 {
200 size_t idx = _mmu->icache_index(pc);
201 auto ic_entry = _mmu->access_icache(pc);
202
203 #define ICACHE_ACCESS(idx) { \
204 insn_fetch_t fetch = ic_entry->data; \
205 ic_entry++; \
206 pc = execute_insn(this, pc, fetch); \
207 instret++; \
208 if (idx == mmu_t::ICACHE_ENTRIES-1) break; \
209 if (unlikely(ic_entry->tag != pc)) break; \
210 }
211
212 switch (idx) {
213 #include "icache.h"
214 }
215 }
216 }
217 catch(trap_t& t)
218 {
219 pc = take_trap(t, pc);
220 }
221 catch(serialize_t& s) {}
222
223 state.pc = pc;
224 update_timer(&state, instret);
225 }
226
227 reg_t processor_t::take_trap(trap_t& t, reg_t epc)
228 {
229 if (debug)
230 fprintf(stderr, "core %3d: exception %s, epc 0x%016" PRIx64 "\n",
231 id, t.name(), epc);
232
233 // switch to supervisor, set previous supervisor bit, disable interrupts
234 set_pcr(CSR_STATUS, (((state.sr & ~SR_EI) | SR_S) & ~SR_PS & ~SR_PEI) |
235 ((state.sr & SR_S) ? SR_PS : 0) |
236 ((state.sr & SR_EI) ? SR_PEI : 0));
237
238 yield_load_reservation();
239 state.cause = t.cause();
240 state.epc = epc;
241 t.side_effects(&state); // might set badvaddr etc.
242 return state.evec;
243 }
244
245 void processor_t::deliver_ipi()
246 {
247 if (run)
248 set_pcr(CSR_CLEAR_IPI, 1);
249 }
250
251 void processor_t::disasm(insn_t insn)
252 {
253 uint64_t bits = insn.bits() & ((1ULL << (8 * insn_length(insn.bits()))) - 1);
254 fprintf(stderr, "core %3d: 0x%016" PRIx64 " (0x%08" PRIx64 ") %s\n",
255 id, state.pc, bits, disassembler->disassemble(insn).c_str());
256 }
257
258 void processor_t::set_pcr(int which, reg_t val)
259 {
260 switch (which)
261 {
262 case CSR_FFLAGS:
263 state.fflags = val & (FSR_AEXC >> FSR_AEXC_SHIFT);
264 break;
265 case CSR_FRM:
266 state.frm = val & (FSR_RD >> FSR_RD_SHIFT);
267 break;
268 case CSR_FCSR:
269 state.fflags = (val & FSR_AEXC) >> FSR_AEXC_SHIFT;
270 state.frm = (val & FSR_RD) >> FSR_RD_SHIFT;
271 break;
272 case CSR_STATUS:
273 state.sr = (val & ~SR_IP) | (state.sr & SR_IP);
274 #ifndef RISCV_ENABLE_64BIT
275 state.sr &= ~(SR_S64 | SR_U64);
276 #endif
277 #ifndef RISCV_ENABLE_FPU
278 state.sr &= ~SR_EF;
279 #endif
280 if (!ext)
281 state.sr &= ~SR_EA;
282 state.sr &= ~SR_ZERO;
283 rv64 = (state.sr & SR_S) ? (state.sr & SR_S64) : (state.sr & SR_U64);
284 mmu->flush_tlb();
285 break;
286 case CSR_EPC:
287 state.epc = val;
288 break;
289 case CSR_EVEC:
290 state.evec = val & ~3;
291 break;
292 case CSR_COUNT:
293 state.count = val;
294 break;
295 case CSR_COUNTH:
296 state.count = (val << 32) | (uint32_t)state.count;
297 break;
298 case CSR_COMPARE:
299 serialize();
300 set_interrupt(IRQ_TIMER, false);
301 state.compare = val;
302 break;
303 case CSR_PTBR:
304 state.ptbr = val & ~(PGSIZE-1);
305 break;
306 case CSR_SEND_IPI:
307 sim->send_ipi(val);
308 break;
309 case CSR_CLEAR_IPI:
310 set_interrupt(IRQ_IPI, val & 1);
311 break;
312 case CSR_SUP0:
313 state.pcr_k0 = val;
314 break;
315 case CSR_SUP1:
316 state.pcr_k1 = val;
317 break;
318 case CSR_TOHOST:
319 if (state.tohost == 0)
320 state.tohost = val;
321 break;
322 case CSR_FROMHOST:
323 set_fromhost(val);
324 break;
325 }
326 }
327
328 void processor_t::set_fromhost(reg_t val)
329 {
330 set_interrupt(IRQ_HOST, val != 0);
331 state.fromhost = val;
332 }
333
334 reg_t processor_t::get_pcr(int which)
335 {
336 switch (which)
337 {
338 case CSR_FFLAGS:
339 require_fp;
340 return state.fflags;
341 case CSR_FRM:
342 require_fp;
343 return state.frm;
344 case CSR_FCSR:
345 require_fp;
346 return (state.fflags << FSR_AEXC_SHIFT) | (state.frm << FSR_RD_SHIFT);
347 case CSR_STATUS:
348 return state.sr;
349 case CSR_EPC:
350 return state.epc;
351 case CSR_BADVADDR:
352 return state.badvaddr;
353 case CSR_EVEC:
354 return state.evec;
355 case CSR_CYCLE:
356 case CSR_TIME:
357 case CSR_INSTRET:
358 case CSR_COUNT:
359 serialize();
360 return state.count;
361 case CSR_CYCLEH:
362 case CSR_TIMEH:
363 case CSR_INSTRETH:
364 case CSR_COUNTH:
365 if (rv64)
366 break;
367 serialize();
368 return state.count >> 32;
369 case CSR_COMPARE:
370 return state.compare;
371 case CSR_CAUSE:
372 return state.cause;
373 case CSR_PTBR:
374 return state.ptbr;
375 case CSR_SEND_IPI:
376 case CSR_CLEAR_IPI:
377 return 0;
378 case CSR_ASID:
379 return 0;
380 case CSR_FATC:
381 mmu->flush_tlb();
382 return 0;
383 case CSR_HARTID:
384 return id;
385 case CSR_IMPL:
386 return 1;
387 case CSR_SUP0:
388 return state.pcr_k0;
389 case CSR_SUP1:
390 return state.pcr_k1;
391 case CSR_TOHOST:
392 sim->get_htif()->tick(); // not necessary, but faster
393 return state.tohost;
394 case CSR_FROMHOST:
395 sim->get_htif()->tick(); // not necessary, but faster
396 return state.fromhost;
397 case CSR_UARCH0:
398 case CSR_UARCH1:
399 case CSR_UARCH2:
400 case CSR_UARCH3:
401 case CSR_UARCH4:
402 case CSR_UARCH5:
403 case CSR_UARCH6:
404 case CSR_UARCH7:
405 case CSR_UARCH8:
406 case CSR_UARCH9:
407 case CSR_UARCH10:
408 case CSR_UARCH11:
409 case CSR_UARCH12:
410 case CSR_UARCH13:
411 case CSR_UARCH14:
412 case CSR_UARCH15:
413 return 0;
414 }
415 throw trap_illegal_instruction();
416 }
417
418 void processor_t::set_interrupt(int which, bool on)
419 {
420 uint32_t mask = (1 << (which + SR_IP_SHIFT)) & SR_IP;
421 if (on)
422 state.sr |= mask;
423 else
424 state.sr &= ~mask;
425 }
426
427 reg_t illegal_instruction(processor_t* p, insn_t insn, reg_t pc)
428 {
429 throw trap_illegal_instruction();
430 }
431
432 insn_func_t processor_t::decode_insn(insn_t insn)
433 {
434 size_t mask = opcode_map.size()-1;
435 insn_desc_t* desc = opcode_map[insn.bits() & mask];
436
437 while ((insn.bits() & desc->mask) != desc->match)
438 desc++;
439
440 return rv64 ? desc->rv64 : desc->rv32;
441 }
442
443 void processor_t::register_insn(insn_desc_t desc)
444 {
445 assert(desc.mask & 1);
446 instructions.push_back(desc);
447 }
448
449 void processor_t::build_opcode_map()
450 {
451 size_t buckets = -1;
452 for (auto& inst : instructions)
453 while ((inst.mask & buckets) != buckets)
454 buckets /= 2;
455 buckets++;
456
457 struct cmp {
458 decltype(insn_desc_t::match) mask;
459 cmp(decltype(mask) mask) : mask(mask) {}
460 bool operator()(const insn_desc_t& lhs, const insn_desc_t& rhs) {
461 if ((lhs.match & mask) != (rhs.match & mask))
462 return (lhs.match & mask) < (rhs.match & mask);
463 return lhs.match < rhs.match;
464 }
465 };
466 std::sort(instructions.begin(), instructions.end(), cmp(buckets-1));
467
468 opcode_map.resize(buckets);
469 opcode_store.resize(instructions.size() + 1);
470
471 size_t j = 0;
472 for (size_t b = 0, i = 0; b < buckets; b++)
473 {
474 opcode_map[b] = &opcode_store[j];
475 while (i < instructions.size() && b == (instructions[i].match & (buckets-1)))
476 opcode_store[j++] = instructions[i++];
477 }
478
479 assert(j == opcode_store.size()-1);
480 opcode_store[j].match = opcode_store[j].mask = 0;
481 opcode_store[j].rv32 = &illegal_instruction;
482 opcode_store[j].rv64 = &illegal_instruction;
483 }
484
485 void processor_t::register_extension(extension_t* x)
486 {
487 for (auto insn : x->get_instructions())
488 register_insn(insn);
489 build_opcode_map();
490 for (auto disasm_insn : x->get_disasms())
491 disassembler->add_insn(disasm_insn);
492 if (ext != NULL)
493 throw std::logic_error("only one extension may be registered");
494 ext = x;
495 x->set_processor(this);
496 }