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