78cb3f535d018b18fbe64260fbddc7f6069a8bd7
[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, reg_t pc, insn_t insn)
127 {
128 #ifdef RISCV_ENABLE_COMMITLOG
129 if (state->sr & SR_EI) {
130 if (state->log_reg_write.addr) {
131 uint64_t mask = (insn.length() == 8 ? uint64_t(0) : (uint64_t(1) << (insn.length() * 8))) - 1;
132 fprintf(stderr, "0x%016" PRIx64 " (0x%08" PRIx64 ") %c%2" PRIx64 " 0x%016" PRIx64 "\n",
133 pc, insn.bits() & mask,
134 state->log_reg_write.addr & 1 ? 'f' : 'x',
135 state->log_reg_write.addr >> 1, state->log_reg_write.data);
136 } else {
137 fprintf(stderr, "0x%016" PRIx64 " (0x%08" PRIx64 ")\n", pc, insn.bits());
138 }
139 }
140 state->log_reg_write.addr = 0;
141 #endif
142 }
143
144 inline void processor_t::update_histogram(size_t pc)
145 {
146 #ifdef RISCV_ENABLE_HISTOGRAM
147 size_t idx = pc >> 2;
148 pc_histogram[idx]++;
149 #endif
150 }
151
152 static reg_t execute_insn(processor_t* p, reg_t pc, insn_fetch_t fetch)
153 {
154 reg_t npc = fetch.func(p, fetch.insn, pc);
155 commit_log(p->get_state(), pc, fetch.insn);
156 p->update_histogram(pc);
157 return npc;
158 }
159
160 static void update_timer(state_t* state, size_t instret)
161 {
162 uint64_t count0 = (uint64_t)(uint32_t)state->count;
163 state->count += instret;
164 uint64_t before = count0 - state->compare;
165 if (int64_t(before ^ (before + instret)) < 0)
166 state->sr |= (1 << (IRQ_TIMER + SR_IP_SHIFT));
167 }
168
169 static size_t next_timer(state_t* state)
170 {
171 return state->compare - (uint32_t)state->count;
172 }
173
174 void processor_t::step(size_t n)
175 {
176 size_t instret = 0;
177 reg_t pc = state.pc;
178 mmu_t* _mmu = mmu;
179
180 if (unlikely(!run || !n))
181 return;
182 n = std::min(n, next_timer(&state) | 1U);
183
184 try
185 {
186 take_interrupt();
187
188 if (unlikely(debug))
189 {
190 while (instret++ < n)
191 {
192 insn_fetch_t fetch = mmu->load_insn(pc);
193 disasm(fetch.insn);
194 pc = execute_insn(this, pc, fetch);
195 }
196 }
197 else while (instret < n)
198 {
199 size_t idx = _mmu->icache_index(pc);
200 auto ic_entry = _mmu->access_icache(pc);
201
202 #define ICACHE_ACCESS(idx) { \
203 insn_fetch_t fetch = ic_entry->data; \
204 ic_entry++; \
205 pc = execute_insn(this, pc, fetch); \
206 instret++; \
207 if (idx == mmu_t::ICACHE_ENTRIES-1) break; \
208 if (unlikely(ic_entry->tag != pc)) break; \
209 }
210
211 switch (idx) {
212 #include "icache.h"
213 }
214 }
215 }
216 catch(trap_t& t)
217 {
218 pc = take_trap(t, pc);
219 }
220 catch(serialize_t& s) {}
221
222 state.pc = pc;
223 update_timer(&state, instret);
224 }
225
226 reg_t processor_t::take_trap(trap_t& t, reg_t epc)
227 {
228 if (debug)
229 fprintf(stderr, "core %3d: exception %s, epc 0x%016" PRIx64 "\n",
230 id, t.name(), epc);
231
232 // switch to supervisor, set previous supervisor bit, disable interrupts
233 set_pcr(CSR_STATUS, (((state.sr & ~SR_EI) | SR_S) & ~SR_PS & ~SR_PEI) |
234 ((state.sr & SR_S) ? SR_PS : 0) |
235 ((state.sr & SR_EI) ? SR_PEI : 0));
236
237 yield_load_reservation();
238 state.cause = t.cause();
239 state.epc = epc;
240 t.side_effects(&state); // might set badvaddr etc.
241 return state.evec;
242 }
243
244 void processor_t::deliver_ipi()
245 {
246 if (run)
247 set_pcr(CSR_CLEAR_IPI, 1);
248 }
249
250 void processor_t::disasm(insn_t insn)
251 {
252 uint64_t bits = insn.bits() & ((1ULL << (8 * insn_length(insn.bits()))) - 1);
253 fprintf(stderr, "core %3d: 0x%016" PRIx64 " (0x%08" PRIx64 ") %s\n",
254 id, state.pc, bits, disassembler->disassemble(insn).c_str());
255 }
256
257 void processor_t::set_pcr(int which, reg_t val)
258 {
259 switch (which)
260 {
261 case CSR_FFLAGS:
262 state.fflags = val & (FSR_AEXC >> FSR_AEXC_SHIFT);
263 break;
264 case CSR_FRM:
265 state.frm = val & (FSR_RD >> FSR_RD_SHIFT);
266 break;
267 case CSR_FCSR:
268 state.fflags = (val & FSR_AEXC) >> FSR_AEXC_SHIFT;
269 state.frm = (val & FSR_RD) >> FSR_RD_SHIFT;
270 break;
271 case CSR_STATUS:
272 state.sr = (val & ~SR_IP) | (state.sr & SR_IP);
273 #ifndef RISCV_ENABLE_64BIT
274 state.sr &= ~(SR_S64 | SR_U64);
275 #endif
276 #ifndef RISCV_ENABLE_FPU
277 state.sr &= ~SR_EF;
278 #endif
279 if (!ext)
280 state.sr &= ~SR_EA;
281 state.sr &= ~SR_ZERO;
282 rv64 = (state.sr & SR_S) ? (state.sr & SR_S64) : (state.sr & SR_U64);
283 mmu->flush_tlb();
284 break;
285 case CSR_EPC:
286 state.epc = val;
287 break;
288 case CSR_EVEC:
289 state.evec = val & ~3;
290 break;
291 case CSR_COUNT:
292 state.count = val;
293 break;
294 case CSR_COUNTH:
295 state.count = (val << 32) | (uint32_t)state.count;
296 break;
297 case CSR_COMPARE:
298 serialize();
299 set_interrupt(IRQ_TIMER, false);
300 state.compare = val;
301 break;
302 case CSR_PTBR:
303 state.ptbr = val & ~(PGSIZE-1);
304 break;
305 case CSR_SEND_IPI:
306 sim->send_ipi(val);
307 break;
308 case CSR_CLEAR_IPI:
309 set_interrupt(IRQ_IPI, val & 1);
310 break;
311 case CSR_SUP0:
312 state.pcr_k0 = val;
313 break;
314 case CSR_SUP1:
315 state.pcr_k1 = val;
316 break;
317 case CSR_TOHOST:
318 if (state.tohost == 0)
319 state.tohost = val;
320 break;
321 case CSR_FROMHOST:
322 set_fromhost(val);
323 break;
324 }
325 }
326
327 void processor_t::set_fromhost(reg_t val)
328 {
329 set_interrupt(IRQ_HOST, val != 0);
330 state.fromhost = val;
331 }
332
333 reg_t processor_t::get_pcr(int which)
334 {
335 switch (which)
336 {
337 case CSR_FFLAGS:
338 require_fp;
339 return state.fflags;
340 case CSR_FRM:
341 require_fp;
342 return state.frm;
343 case CSR_FCSR:
344 require_fp;
345 return (state.fflags << FSR_AEXC_SHIFT) | (state.frm << FSR_RD_SHIFT);
346 case CSR_STATUS:
347 return state.sr;
348 case CSR_EPC:
349 return state.epc;
350 case CSR_BADVADDR:
351 return state.badvaddr;
352 case CSR_EVEC:
353 return state.evec;
354 case CSR_CYCLE:
355 case CSR_TIME:
356 case CSR_INSTRET:
357 case CSR_COUNT:
358 serialize();
359 return state.count;
360 case CSR_CYCLEH:
361 case CSR_TIMEH:
362 case CSR_INSTRETH:
363 case CSR_COUNTH:
364 if (rv64)
365 break;
366 serialize();
367 return state.count >> 32;
368 case CSR_COMPARE:
369 return state.compare;
370 case CSR_CAUSE:
371 return state.cause;
372 case CSR_PTBR:
373 return state.ptbr;
374 case CSR_SEND_IPI:
375 case CSR_CLEAR_IPI:
376 return 0;
377 case CSR_ASID:
378 return 0;
379 case CSR_FATC:
380 mmu->flush_tlb();
381 return 0;
382 case CSR_HARTID:
383 return id;
384 case CSR_IMPL:
385 return 1;
386 case CSR_SUP0:
387 return state.pcr_k0;
388 case CSR_SUP1:
389 return state.pcr_k1;
390 case CSR_TOHOST:
391 sim->get_htif()->tick(); // not necessary, but faster
392 return state.tohost;
393 case CSR_FROMHOST:
394 sim->get_htif()->tick(); // not necessary, but faster
395 return state.fromhost;
396 case CSR_UARCH0:
397 case CSR_UARCH1:
398 case CSR_UARCH2:
399 case CSR_UARCH3:
400 case CSR_UARCH4:
401 case CSR_UARCH5:
402 case CSR_UARCH6:
403 case CSR_UARCH7:
404 case CSR_UARCH8:
405 case CSR_UARCH9:
406 case CSR_UARCH10:
407 case CSR_UARCH11:
408 case CSR_UARCH12:
409 case CSR_UARCH13:
410 case CSR_UARCH14:
411 case CSR_UARCH15:
412 return 0;
413 }
414 throw trap_illegal_instruction();
415 }
416
417 void processor_t::set_interrupt(int which, bool on)
418 {
419 uint32_t mask = (1 << (which + SR_IP_SHIFT)) & SR_IP;
420 if (on)
421 state.sr |= mask;
422 else
423 state.sr &= ~mask;
424 }
425
426 reg_t illegal_instruction(processor_t* p, insn_t insn, reg_t pc)
427 {
428 throw trap_illegal_instruction();
429 }
430
431 insn_func_t processor_t::decode_insn(insn_t insn)
432 {
433 size_t mask = opcode_map.size()-1;
434 insn_desc_t* desc = opcode_map[insn.bits() & mask];
435
436 while ((insn.bits() & desc->mask) != desc->match)
437 desc++;
438
439 return rv64 ? desc->rv64 : desc->rv32;
440 }
441
442 void processor_t::register_insn(insn_desc_t desc)
443 {
444 assert(desc.mask & 1);
445 instructions.push_back(desc);
446 }
447
448 void processor_t::build_opcode_map()
449 {
450 size_t buckets = -1;
451 for (auto& inst : instructions)
452 while ((inst.mask & buckets) != buckets)
453 buckets /= 2;
454 buckets++;
455
456 struct cmp {
457 decltype(insn_desc_t::match) mask;
458 cmp(decltype(mask) mask) : mask(mask) {}
459 bool operator()(const insn_desc_t& lhs, const insn_desc_t& rhs) {
460 if ((lhs.match & mask) != (rhs.match & mask))
461 return (lhs.match & mask) < (rhs.match & mask);
462 return lhs.match < rhs.match;
463 }
464 };
465 std::sort(instructions.begin(), instructions.end(), cmp(buckets-1));
466
467 opcode_map.resize(buckets);
468 opcode_store.resize(instructions.size() + 1);
469
470 size_t j = 0;
471 for (size_t b = 0, i = 0; b < buckets; b++)
472 {
473 opcode_map[b] = &opcode_store[j];
474 while (i < instructions.size() && b == (instructions[i].match & (buckets-1)))
475 opcode_store[j++] = instructions[i++];
476 }
477
478 assert(j == opcode_store.size()-1);
479 opcode_store[j].match = opcode_store[j].mask = 0;
480 opcode_store[j].rv32 = &illegal_instruction;
481 opcode_store[j].rv64 = &illegal_instruction;
482 }
483
484 void processor_t::register_extension(extension_t* x)
485 {
486 for (auto insn : x->get_instructions())
487 register_insn(insn);
488 build_opcode_map();
489 for (auto disasm_insn : x->get_disasms())
490 disassembler->add_insn(disasm_insn);
491 if (ext != NULL)
492 throw std::logic_error("only one extension may be registered");
493 ext = x;
494 x->set_processor(this);
495 }