1 // See LICENSE for license details.
2
3 #include "csrs.h"
4 // For processor_t:
5 #include "processor.h"
6 #include "mmu.h"
7 // For get_field():
8 #include "decode.h"
9 // For trap_virtual_instruction and trap_illegal_instruction:
10 #include "trap.h"
11
12 // STATE macro used by require_privilege() macro:
13 #undef STATE
14 #define STATE (*state)
15
16
17 // implement class csr_t
csr_t(processor_t * const proc,const reg_t addr)18 csr_t::csr_t(processor_t* const proc, const reg_t addr):
19 proc(proc),
20 state(proc->get_state()),
21 address(addr),
22 csr_priv(get_field(addr, 0x300)),
23 csr_read_only(get_field(addr, 0xC00) == 3) {
24 }
25
verify_permissions(insn_t insn,bool write) const26 void csr_t::verify_permissions(insn_t insn, bool write) const {
27 // Check permissions. Raise virtual-instruction exception if V=1,
28 // privileges are insufficient, and the CSR belongs to supervisor or
29 // hypervisor. Raise illegal-instruction exception otherwise.
30 unsigned priv = state->prv == PRV_S && !state->v ? PRV_HS : state->prv;
31
32 if ((csr_priv == PRV_S && !proc->extension_enabled('S')) ||
33 (csr_priv == PRV_HS && !proc->extension_enabled('H')))
34 throw trap_illegal_instruction(insn.bits());
35
36 if (write && csr_read_only)
37 throw trap_illegal_instruction(insn.bits());
38 if (priv < csr_priv) {
39 if (state->v && csr_priv <= PRV_HS)
40 throw trap_virtual_instruction(insn.bits());
41 throw trap_illegal_instruction(insn.bits());
42 }
43 }
44
45
~csr_t()46 csr_t::~csr_t() {
47 }
48
write(const reg_t val)49 void csr_t::write(const reg_t val) noexcept {
50 const bool success = unlogged_write(val);
51 if (success) {
52 log_write();
53 }
54 }
55
log_write() const56 void csr_t::log_write() const noexcept {
57 log_special_write(address, written_value());
58 }
59
log_special_write(const reg_t address,const reg_t val) const60 void csr_t::log_special_write(const reg_t address, const reg_t val) const noexcept {
61 #if defined(RISCV_ENABLE_COMMITLOG)
62 proc->get_state()->log_reg_write[((address) << 4) | 4] = {val, 0};
63 #endif
64 }
65
written_value() const66 reg_t csr_t::written_value() const noexcept {
67 return read();
68 }
69
70 // implement class basic_csr_t
basic_csr_t(processor_t * const proc,const reg_t addr,const reg_t init)71 basic_csr_t::basic_csr_t(processor_t* const proc, const reg_t addr, const reg_t init):
72 csr_t(proc, addr),
73 val(init) {
74 }
75
read() const76 reg_t basic_csr_t::read() const noexcept {
77 return val;
78 }
79
unlogged_write(const reg_t val)80 bool basic_csr_t::unlogged_write(const reg_t val) noexcept {
81 this->val = val;
82 return true;
83 }
84
85
86 // implement class pmpaddr_csr_t
pmpaddr_csr_t(processor_t * const proc,const reg_t addr)87 pmpaddr_csr_t::pmpaddr_csr_t(processor_t* const proc, const reg_t addr):
88 csr_t(proc, addr),
89 val(0),
90 cfg(0),
91 pmpidx(address - CSR_PMPADDR0) {
92 }
93
94
verify_permissions(insn_t insn,bool write) const95 void pmpaddr_csr_t::verify_permissions(insn_t insn, bool write) const {
96 csr_t::verify_permissions(insn, write);
97 // If n_pmp is zero, that means pmp is not implemented hence raise
98 // trap if it tries to access the csr. I would prefer to implement
99 // this by not instantiating any pmpaddr_csr_t for these regs, but
100 // n_pmp can change after reset() is run.
101 if (proc->n_pmp == 0)
102 throw trap_illegal_instruction(insn.bits());
103 }
104
105
read() const106 reg_t pmpaddr_csr_t::read() const noexcept {
107 if ((cfg & PMP_A) >= PMP_NAPOT)
108 return val | (~proc->pmp_tor_mask() >> 1);
109 return val & proc->pmp_tor_mask();
110 }
111
112
unlogged_write(const reg_t val)113 bool pmpaddr_csr_t::unlogged_write(const reg_t val) noexcept {
114 // If no PMPs are configured, disallow access to all. Otherwise,
115 // allow access to all, but unimplemented ones are hardwired to
116 // zero. Note that n_pmp can change after reset(); otherwise I would
117 // implement this in state_t::reset() by instantiating the correct
118 // number of pmpaddr_csr_t.
119 if (proc->n_pmp == 0)
120 return false;
121
122 bool locked = cfg & PMP_L;
123 if (pmpidx < proc->n_pmp && !locked && !next_locked_and_tor()) {
124 this->val = val & ((reg_t(1) << (MAX_PADDR_BITS - PMP_SHIFT)) - 1);
125 }
126 else
127 return false;
128 proc->get_mmu()->flush_tlb();
129 return true;
130 }
131
next_locked_and_tor() const132 bool pmpaddr_csr_t::next_locked_and_tor() const noexcept {
133 if (pmpidx+1 >= state->max_pmp) return false; // this is the last entry
134 bool next_locked = state->pmpaddr[pmpidx+1]->cfg & PMP_L;
135 bool next_tor = (state->pmpaddr[pmpidx+1]->cfg & PMP_A) == PMP_TOR;
136 return next_locked && next_tor;
137 }
138
139
tor_paddr() const140 reg_t pmpaddr_csr_t::tor_paddr() const noexcept {
141 return (val & proc->pmp_tor_mask()) << PMP_SHIFT;
142 }
143
144
tor_base_paddr() const145 reg_t pmpaddr_csr_t::tor_base_paddr() const noexcept {
146 if (pmpidx == 0) return 0; // entry 0 always uses 0 as base
147 return state->pmpaddr[pmpidx-1]->tor_paddr();
148 }
149
150
napot_mask() const151 reg_t pmpaddr_csr_t::napot_mask() const noexcept {
152 bool is_na4 = (cfg & PMP_A) == PMP_NA4;
153 reg_t mask = (val << 1) | (!is_na4) | ~proc->pmp_tor_mask();
154 return ~(mask & ~(mask + 1)) << PMP_SHIFT;
155 }
156
157
match4(reg_t addr) const158 bool pmpaddr_csr_t::match4(reg_t addr) const noexcept {
159 if ((cfg & PMP_A) == 0) return false;
160 bool is_tor = (cfg & PMP_A) == PMP_TOR;
161 if (is_tor) return tor_base_paddr() <= addr && addr < tor_paddr();
162 // NAPOT or NA4:
163 return ((addr ^ tor_paddr()) & napot_mask()) == 0;
164 }
165
166
subset_match(reg_t addr,reg_t len) const167 bool pmpaddr_csr_t::subset_match(reg_t addr, reg_t len) const noexcept {
168 if ((addr | len) & (len - 1))
169 abort();
170 reg_t base = tor_base_paddr();
171 reg_t tor = tor_paddr();
172
173 if ((cfg & PMP_A) == 0) return false;
174
175 bool is_tor = (cfg & PMP_A) == PMP_TOR;
176 bool begins_after_lower = addr >= base;
177 bool begins_after_upper = addr >= tor;
178 bool ends_before_lower = (addr & -len) < (base & -len);
179 bool ends_before_upper = (addr & -len) < (tor & -len);
180 bool tor_homogeneous = ends_before_lower || begins_after_upper ||
181 (begins_after_lower && ends_before_upper);
182
183 bool mask_homogeneous = ~(napot_mask() << 1) & len;
184 bool napot_homogeneous = mask_homogeneous || ((addr ^ tor) / len) != 0;
185
186 return !(is_tor ? tor_homogeneous : napot_homogeneous);
187 }
188
189
access_ok(access_type type,reg_t mode) const190 bool pmpaddr_csr_t::access_ok(access_type type, reg_t mode) const noexcept {
191 return
192 (mode == PRV_M && !(cfg & PMP_L)) ||
193 (type == LOAD && (cfg & PMP_R)) ||
194 (type == STORE && (cfg & PMP_W)) ||
195 (type == FETCH && (cfg & PMP_X));
196 }
197
198
199 // implement class pmpcfg_csr_t
pmpcfg_csr_t(processor_t * const proc,const reg_t addr)200 pmpcfg_csr_t::pmpcfg_csr_t(processor_t* const proc, const reg_t addr):
201 csr_t(proc, addr) {
202 }
203
read() const204 reg_t pmpcfg_csr_t::read() const noexcept {
205 reg_t cfg_res = 0;
206 for (size_t i0 = (address - CSR_PMPCFG0) * 4, i = i0; i < i0 + proc->get_xlen() / 8 && i < state->max_pmp; i++)
207 cfg_res |= reg_t(state->pmpaddr[i]->cfg) << (8 * (i - i0));
208 return cfg_res;
209 }
210
unlogged_write(const reg_t val)211 bool pmpcfg_csr_t::unlogged_write(const reg_t val) noexcept {
212 if (proc->n_pmp == 0)
213 return false;
214
215 bool write_success = false;
216 for (size_t i0 = (address - CSR_PMPCFG0) * 4, i = i0; i < i0 + proc->get_xlen() / 8; i++) {
217 if (i < proc->n_pmp) {
218 if (!(state->pmpaddr[i]->cfg & PMP_L)) {
219 uint8_t cfg = (val >> (8 * (i - i0))) & (PMP_R | PMP_W | PMP_X | PMP_A | PMP_L);
220 cfg &= ~PMP_W | ((cfg & PMP_R) ? PMP_W : 0); // Disallow R=0 W=1
221 if (proc->lg_pmp_granularity != PMP_SHIFT && (cfg & PMP_A) == PMP_NA4)
222 cfg |= PMP_NAPOT; // Disallow A=NA4 when granularity > 4
223 state->pmpaddr[i]->cfg = cfg;
224 }
225 write_success = true;
226 }
227 }
228 proc->get_mmu()->flush_tlb();
229 return write_success;
230 }
231
232
233 // implement class virtualized_csr_t
virtualized_csr_t(processor_t * const proc,csr_t_p orig,csr_t_p virt)234 virtualized_csr_t::virtualized_csr_t(processor_t* const proc, csr_t_p orig, csr_t_p virt):
235 csr_t(proc, orig->address),
236 orig_csr(orig),
237 virt_csr(virt) {
238 }
239
240
read() const241 reg_t virtualized_csr_t::read() const noexcept {
242 return readvirt(state->v);
243 }
244
readvirt(bool virt) const245 reg_t virtualized_csr_t::readvirt(bool virt) const noexcept {
246 return virt ? virt_csr->read() : orig_csr->read();
247 }
248
unlogged_write(const reg_t val)249 bool virtualized_csr_t::unlogged_write(const reg_t val) noexcept {
250 if (state->v)
251 virt_csr->write(val);
252 else
253 orig_csr->write(val);
254 return false; // virt_csr or orig_csr has already logged
255 }
256
257
258 // implement class epc_csr_t
epc_csr_t(processor_t * const proc,const reg_t addr)259 epc_csr_t::epc_csr_t(processor_t* const proc, const reg_t addr):
260 csr_t(proc, addr),
261 val(0) {
262 }
263
264
read() const265 reg_t epc_csr_t::read() const noexcept {
266 return val & proc->pc_alignment_mask();
267 }
268
269
unlogged_write(const reg_t val)270 bool epc_csr_t::unlogged_write(const reg_t val) noexcept {
271 this->val = val & ~(reg_t)1;
272 return true;
273 }
274
275
276 // implement class tvec_csr_t
tvec_csr_t(processor_t * const proc,const reg_t addr)277 tvec_csr_t::tvec_csr_t(processor_t* const proc, const reg_t addr):
278 csr_t(proc, addr),
279 val(0) {
280 }
281
282
read() const283 reg_t tvec_csr_t::read() const noexcept {
284 return val;
285 }
286
287
unlogged_write(const reg_t val)288 bool tvec_csr_t::unlogged_write(const reg_t val) noexcept {
289 this->val = val & ~(reg_t)2;
290 return true;
291 }
292
293
294 // implement class cause_csr_t
cause_csr_t(processor_t * const proc,const reg_t addr)295 cause_csr_t::cause_csr_t(processor_t* const proc, const reg_t addr):
296 basic_csr_t(proc, addr, 0) {
297 }
298
299
read() const300 reg_t cause_csr_t::read() const noexcept {
301 reg_t val = basic_csr_t::read();
302 // When reading, the interrupt bit needs to adjust to xlen. Spike does
303 // not generally support dynamic xlen, but this code was (partly)
304 // there since at least 2015 (ea58df8 and c4350ef).
305 if (proc->get_max_xlen() > proc->get_xlen()) // Move interrupt bit to top of xlen
306 return val | ((val >> (proc->get_max_xlen()-1)) << (proc->get_xlen()-1));
307 return val;
308 }
309
310
311 // implement class base_status_csr_t
base_status_csr_t(processor_t * const proc,const reg_t addr)312 base_status_csr_t::base_status_csr_t(processor_t* const proc, const reg_t addr):
313 csr_t(proc, addr),
314 has_page(proc->extension_enabled_const('S') && proc->supports_impl(IMPL_MMU)),
315 sstatus_write_mask(compute_sstatus_write_mask()),
316 sstatus_read_mask(sstatus_write_mask | SSTATUS_UBE | SSTATUS_UXL
317 | (proc->get_const_xlen() == 32 ? SSTATUS32_SD : SSTATUS64_SD)) {
318 }
319
320
enabled(const reg_t which)321 bool base_status_csr_t::enabled(const reg_t which) {
322 // If the field doesn't exist, it is always enabled. See #823.
323 if ((sstatus_write_mask & which) == 0) return true;
324 return (read() & which) != 0;
325 }
326
compute_sstatus_write_mask() const327 reg_t base_status_csr_t::compute_sstatus_write_mask() const noexcept {
328 // If a configuration has FS bits, they will always be accessible no
329 // matter the state of misa.
330 const bool has_fs = proc->extension_enabled('S') || proc->extension_enabled('F')
331 || proc->extension_enabled_const('V');
332 const bool has_vs = proc->extension_enabled_const('V');
333 return 0
334 | (proc->extension_enabled('S') ? (SSTATUS_SIE | SSTATUS_SPIE | SSTATUS_SPP) : 0)
335 | (has_page ? (SSTATUS_SUM | SSTATUS_MXR) : 0)
336 | (has_fs ? SSTATUS_FS : 0)
337 | (proc->any_custom_extensions() ? SSTATUS_XS : 0)
338 | (has_vs ? SSTATUS_VS : 0)
339 ;
340 }
341
342
adjust_sd(const reg_t val) const343 reg_t base_status_csr_t::adjust_sd(const reg_t val) const noexcept {
344 // This uses get_const_xlen() instead of get_xlen() not only because
345 // the variable is static, so it's only called once, but also
346 // because the SD bit moves when XLEN changes, which means we would
347 // need to call adjust_sd() on every read, instead of on every
348 // write.
349 static const reg_t sd_bit = proc->get_const_xlen() == 64 ? SSTATUS64_SD : SSTATUS32_SD;
350 if (((val & SSTATUS_FS) == SSTATUS_FS) ||
351 ((val & SSTATUS_VS) == SSTATUS_VS) ||
352 ((val & SSTATUS_XS) == SSTATUS_XS)) {
353 return val | sd_bit;
354 }
355 return val & ~sd_bit;
356 }
357
358
maybe_flush_tlb(const reg_t newval)359 void base_status_csr_t::maybe_flush_tlb(const reg_t newval) noexcept {
360 if ((newval ^ read()) &
361 (MSTATUS_MPP | MSTATUS_MPRV
362 | (has_page ? (MSTATUS_MXR | MSTATUS_SUM) : 0)
363 ))
364 proc->get_mmu()->flush_tlb();
365 }
366
367
368 namespace {
xlen_to_uxl(int xlen)369 int xlen_to_uxl(int xlen) {
370 if (xlen == 32)
371 return 1;
372 if (xlen == 64)
373 return 2;
374 abort();
375 }
376 }
377
378
379 // implement class vsstatus_csr_t
vsstatus_csr_t(processor_t * const proc,const reg_t addr)380 vsstatus_csr_t::vsstatus_csr_t(processor_t* const proc, const reg_t addr):
381 base_status_csr_t(proc, addr),
382 val(proc->get_state()->mstatus->read() & sstatus_read_mask) {
383 }
384
read() const385 reg_t vsstatus_csr_t::read() const noexcept {
386 return val;
387 }
388
unlogged_write(const reg_t val)389 bool vsstatus_csr_t::unlogged_write(const reg_t val) noexcept {
390 const reg_t newval = (this->val & ~sstatus_write_mask) | (val & sstatus_write_mask);
391 if (state->v) maybe_flush_tlb(newval);
392 this->val = adjust_sd(newval);
393 return true;
394 }
395
396
397 // implement class sstatus_proxy_csr_t
sstatus_proxy_csr_t(processor_t * const proc,const reg_t addr,csr_t_p mstatus)398 sstatus_proxy_csr_t::sstatus_proxy_csr_t(processor_t* const proc, const reg_t addr, csr_t_p mstatus):
399 base_status_csr_t(proc, addr),
400 mstatus(mstatus) {
401 }
402
read() const403 reg_t sstatus_proxy_csr_t::read() const noexcept {
404 return mstatus->read() & sstatus_read_mask;
405 }
406
unlogged_write(const reg_t val)407 bool sstatus_proxy_csr_t::unlogged_write(const reg_t val) noexcept {
408 const reg_t new_mstatus = (mstatus->read() & ~sstatus_write_mask) | (val & sstatus_write_mask);
409
410 mstatus->write(new_mstatus);
411 return false; // avoid double logging: already logged by mstatus->write()
412 }
413
414
415 // implement class mstatus_csr_t
mstatus_csr_t(processor_t * const proc,const reg_t addr)416 mstatus_csr_t::mstatus_csr_t(processor_t* const proc, const reg_t addr):
417 base_status_csr_t(proc, addr),
418 val(0
419 | (proc->extension_enabled_const('U') ? set_field((reg_t)0, MSTATUS_UXL, xlen_to_uxl(proc->get_const_xlen())) : 0)
420 | (proc->extension_enabled_const('S') ? set_field((reg_t)0, MSTATUS_SXL, xlen_to_uxl(proc->get_const_xlen())) : 0)
421 #ifdef RISCV_ENABLE_DUAL_ENDIAN
422 | (proc->get_mmu()->is_target_big_endian() ? MSTATUS_UBE | MSTATUS_SBE | MSTATUS_MBE : 0)
423 #endif
424 | 0 // initial value for mstatus
425 ) {
426 }
427
428
read() const429 reg_t mstatus_csr_t::read() const noexcept {
430 return val;
431 }
432
433
unlogged_write(const reg_t val)434 bool mstatus_csr_t::unlogged_write(const reg_t val) noexcept {
435 const bool has_mpv = proc->extension_enabled('S') && proc->extension_enabled('H');
436 const bool has_gva = has_mpv;
437
438 const reg_t mask = sstatus_write_mask
439 | MSTATUS_MIE | MSTATUS_MPIE | MSTATUS_MPRV
440 | MSTATUS_MPP | MSTATUS_TW | MSTATUS_TSR
441 | (has_page ? MSTATUS_TVM : 0)
442 | (has_gva ? MSTATUS_GVA : 0)
443 | (has_mpv ? MSTATUS_MPV : 0);
444
445 const reg_t requested_mpp = proc->legalize_privilege(get_field(val, MSTATUS_MPP));
446 const reg_t adjusted_val = set_field(val, MSTATUS_MPP, requested_mpp);
447 const reg_t new_mstatus = (read() & ~mask) | (adjusted_val & mask);
448 maybe_flush_tlb(new_mstatus);
449 this->val = adjust_sd(new_mstatus);
450 return true;
451 }
452
453 // implement class mstatush_csr_t
mstatush_csr_t(processor_t * const proc,const reg_t addr,mstatus_csr_t_p mstatus)454 mstatush_csr_t::mstatush_csr_t(processor_t* const proc, const reg_t addr, mstatus_csr_t_p mstatus):
455 csr_t(proc, addr),
456 mstatus(mstatus),
457 mask(MSTATUSH_MPV | MSTATUSH_GVA | MSTATUSH_SBE | MSTATUSH_MBE) {
458 }
459
read() const460 reg_t mstatush_csr_t::read() const noexcept {
461 return (mstatus->read() >> 32) & mask;
462 }
463
unlogged_write(const reg_t val)464 bool mstatush_csr_t::unlogged_write(const reg_t val) noexcept {
465 return mstatus->unlogged_write((mstatus->written_value() & ~(mask << 32)) | ((val & mask) << 32));
466 }
467
468 // implement class sstatus_csr_t
sstatus_csr_t(processor_t * const proc,base_status_csr_t_p orig,base_status_csr_t_p virt)469 sstatus_csr_t::sstatus_csr_t(processor_t* const proc, base_status_csr_t_p orig, base_status_csr_t_p virt):
470 virtualized_csr_t(proc, orig, virt),
471 orig_sstatus(orig),
472 virt_sstatus(virt) {
473 }
474
dirty(const reg_t dirties)475 void sstatus_csr_t::dirty(const reg_t dirties) {
476 // Catch problems like #823 where P-extension instructions were not
477 // checking for mstatus.VS!=Off:
478 if (!enabled(dirties)) abort();
479
480 orig_csr->write(orig_csr->read() | dirties);
481 if (state->v) {
482 virt_csr->write(virt_csr->read() | dirties);
483 }
484 }
485
enabled(const reg_t which)486 bool sstatus_csr_t::enabled(const reg_t which) {
487 if (!orig_sstatus->enabled(which))
488 return false;
489 if (state->v && !virt_sstatus->enabled(which))
490 return false;
491 return true;
492 }
493
494
495 // implement class misa_csr_t
misa_csr_t(processor_t * const proc,const reg_t addr,const reg_t max_isa)496 misa_csr_t::misa_csr_t(processor_t* const proc, const reg_t addr, const reg_t max_isa):
497 basic_csr_t(proc, addr, max_isa),
498 max_isa(max_isa),
499 write_mask(max_isa & (0 // allow MAFDCH bits in MISA to be modified
500 | (1L << ('M' - 'A'))
501 | (1L << ('A' - 'A'))
502 | (1L << ('F' - 'A'))
503 | (1L << ('D' - 'A'))
504 | (1L << ('C' - 'A'))
505 | (1L << ('H' - 'A'))
506 )
507 ) {
508 }
509
unlogged_write(const reg_t val)510 bool misa_csr_t::unlogged_write(const reg_t val) noexcept {
511 // the write is ignored if increasing IALIGN would misalign the PC
512 if (!(val & (1L << ('C' - 'A'))) && (state->pc & 2))
513 return false;
514
515 const bool val_supports_f = val & (1L << ('F' - 'A'));
516 const reg_t val_without_d = val & ~(1L << ('D' - 'A'));
517 const reg_t adjusted_val = val_supports_f ? val : val_without_d;
518
519 const reg_t old_misa = read();
520 const bool prev_h = old_misa & (1L << ('H' - 'A'));
521 const reg_t new_misa = (adjusted_val & write_mask) | (old_misa & ~write_mask);
522 const bool new_h = new_misa & (1L << ('H' - 'A'));
523
524 // update the hypervisor-only bits in MEDELEG and other CSRs
525 if (!new_h && prev_h) {
526 reg_t hypervisor_exceptions = 0
527 | (1 << CAUSE_VIRTUAL_SUPERVISOR_ECALL)
528 | (1 << CAUSE_FETCH_GUEST_PAGE_FAULT)
529 | (1 << CAUSE_LOAD_GUEST_PAGE_FAULT)
530 | (1 << CAUSE_VIRTUAL_INSTRUCTION)
531 | (1 << CAUSE_STORE_GUEST_PAGE_FAULT)
532 ;
533 state->medeleg->write(state->medeleg->read() & ~hypervisor_exceptions);
534 state->mstatus->write(state->mstatus->read() & ~(MSTATUS_GVA | MSTATUS_MPV));
535 state->mie->write_with_mask(MIP_HS_MASK, 0); // also takes care of hie, sie
536 state->mip->write_with_mask(MIP_HS_MASK, 0); // also takes care of hip, sip, hvip
537 state->hstatus->write(0);
538 }
539
540 return basic_csr_t::unlogged_write(new_misa);
541 }
542
extension_enabled(unsigned char ext) const543 bool misa_csr_t::extension_enabled(unsigned char ext) const noexcept {
544 assert(ext >= 'A' && ext <= 'Z');
545 return (read() >> (ext - 'A')) & 1;
546 }
547
extension_enabled_const(unsigned char ext) const548 bool misa_csr_t::extension_enabled_const(unsigned char ext) const noexcept {
549 assert(!(1 & (write_mask >> (ext - 'A'))));
550 return extension_enabled(ext);
551 }
552
553
554 // implement class mip_or_mie_csr_t
mip_or_mie_csr_t(processor_t * const proc,const reg_t addr)555 mip_or_mie_csr_t::mip_or_mie_csr_t(processor_t* const proc, const reg_t addr):
556 csr_t(proc, addr),
557 val(0) {
558 }
559
read() const560 reg_t mip_or_mie_csr_t::read() const noexcept {
561 return val;
562 }
563
write_with_mask(const reg_t mask,const reg_t val)564 void mip_or_mie_csr_t::write_with_mask(const reg_t mask, const reg_t val) noexcept {
565 this->val = (this->val & ~mask) | (val & mask);
566 log_write();
567 }
568
unlogged_write(const reg_t val)569 bool mip_or_mie_csr_t::unlogged_write(const reg_t val) noexcept {
570 write_with_mask(write_mask(), val);
571 return false; // avoid double logging: already logged by write_with_mask()
572 }
573
574
mip_csr_t(processor_t * const proc,const reg_t addr)575 mip_csr_t::mip_csr_t(processor_t* const proc, const reg_t addr):
576 mip_or_mie_csr_t(proc, addr) {
577 }
578
backdoor_write_with_mask(const reg_t mask,const reg_t val)579 void mip_csr_t::backdoor_write_with_mask(const reg_t mask, const reg_t val) noexcept {
580 this->val = (this->val & ~mask) | (val & mask);
581 }
582
write_mask() const583 reg_t mip_csr_t::write_mask() const noexcept {
584 const reg_t supervisor_ints = proc->extension_enabled('S') ? MIP_SSIP | MIP_STIP | MIP_SEIP : 0;
585 const reg_t vssip_int = proc->extension_enabled('H') ? MIP_VSSIP : 0;
586 const reg_t hypervisor_ints = proc->extension_enabled('H') ? MIP_HS_MASK : 0;
587 // We must mask off sgeip, vstip, and vseip. All three of these
588 // bits are aliases for the same bits in hip. The hip spec says:
589 // * sgeip is read-only -- write hgeip instead
590 // * vseip is read-only -- write hvip instead
591 // * vstip is read-only -- write hvip instead
592 return (supervisor_ints | hypervisor_ints) &
593 (MIP_SEIP | MIP_SSIP | MIP_STIP | vssip_int);
594 }
595
596
mie_csr_t(processor_t * const proc,const reg_t addr)597 mie_csr_t::mie_csr_t(processor_t* const proc, const reg_t addr):
598 mip_or_mie_csr_t(proc, addr) {
599 }
600
601
write_mask() const602 reg_t mie_csr_t::write_mask() const noexcept {
603 const reg_t supervisor_ints = proc->extension_enabled('S') ? MIP_SSIP | MIP_STIP | MIP_SEIP : 0;
604 const reg_t hypervisor_ints = proc->extension_enabled('H') ? MIP_HS_MASK : 0;
605 const reg_t coprocessor_ints = (reg_t)proc->any_custom_extensions() << IRQ_COP;
606 const reg_t delegable_ints = supervisor_ints | coprocessor_ints;
607 const reg_t all_ints = delegable_ints | hypervisor_ints | MIP_MSIP | MIP_MTIP | MIP_MEIP;
608 return all_ints;
609 }
610
611
612 // implement class generic_int_accessor_t
generic_int_accessor_t(state_t * const state,const reg_t read_mask,const reg_t ip_write_mask,const reg_t ie_write_mask,const bool mask_mideleg,const bool mask_hideleg,const int shiftamt)613 generic_int_accessor_t::generic_int_accessor_t(state_t* const state,
614 const reg_t read_mask,
615 const reg_t ip_write_mask,
616 const reg_t ie_write_mask,
617 const bool mask_mideleg,
618 const bool mask_hideleg,
619 const int shiftamt):
620 state(state),
621 read_mask(read_mask),
622 ip_write_mask(ip_write_mask),
623 ie_write_mask(ie_write_mask),
624 mask_mideleg(mask_mideleg),
625 mask_hideleg(mask_hideleg),
626 shiftamt(shiftamt) {
627 }
628
ip_read() const629 reg_t generic_int_accessor_t::ip_read() const noexcept {
630 return (state->mip->read() & deleg_mask() & read_mask) >> shiftamt;
631 }
632
ip_write(const reg_t val)633 void generic_int_accessor_t::ip_write(const reg_t val) noexcept {
634 const reg_t mask = deleg_mask() & ip_write_mask;
635 state->mip->write_with_mask(mask, val << shiftamt);
636 }
637
ie_read() const638 reg_t generic_int_accessor_t::ie_read() const noexcept {
639 return (state->mie->read() & deleg_mask() & read_mask) >> shiftamt;
640 }
641
ie_write(const reg_t val)642 void generic_int_accessor_t::ie_write(const reg_t val) noexcept {
643 const reg_t mask = deleg_mask() & ie_write_mask;
644 state->mie->write_with_mask(mask, val << shiftamt);
645 }
646
deleg_mask() const647 reg_t generic_int_accessor_t::deleg_mask() const {
648 const reg_t hideleg_mask = mask_hideleg ? state->hideleg->read() : (reg_t)~0;
649 const reg_t mideleg_mask = mask_mideleg ? state->mideleg->read() : (reg_t)~0;
650 return hideleg_mask & mideleg_mask;
651 }
652
653
654 // implement class mip_proxy_csr_t
mip_proxy_csr_t(processor_t * const proc,const reg_t addr,generic_int_accessor_t_p accr)655 mip_proxy_csr_t::mip_proxy_csr_t(processor_t* const proc, const reg_t addr, generic_int_accessor_t_p accr):
656 csr_t(proc, addr),
657 accr(accr) {
658 }
659
read() const660 reg_t mip_proxy_csr_t::read() const noexcept {
661 return accr->ip_read();
662 }
663
unlogged_write(const reg_t val)664 bool mip_proxy_csr_t::unlogged_write(const reg_t val) noexcept {
665 accr->ip_write(val);
666 return false; // accr has already logged
667 }
668
669 // implement class mie_proxy_csr_t
mie_proxy_csr_t(processor_t * const proc,const reg_t addr,generic_int_accessor_t_p accr)670 mie_proxy_csr_t::mie_proxy_csr_t(processor_t* const proc, const reg_t addr, generic_int_accessor_t_p accr):
671 csr_t(proc, addr),
672 accr(accr) {
673 }
674
read() const675 reg_t mie_proxy_csr_t::read() const noexcept {
676 return accr->ie_read();
677 }
678
unlogged_write(const reg_t val)679 bool mie_proxy_csr_t::unlogged_write(const reg_t val) noexcept {
680 accr->ie_write(val);
681 return false; // accr has already logged
682 }
683
684
685 // implement class mideleg_csr_t
mideleg_csr_t(processor_t * const proc,const reg_t addr)686 mideleg_csr_t::mideleg_csr_t(processor_t* const proc, const reg_t addr):
687 basic_csr_t(proc, addr, 0) {
688 }
689
read() const690 reg_t mideleg_csr_t::read() const noexcept {
691 reg_t val = basic_csr_t::read();
692 if (proc->extension_enabled('H')) return val | MIDELEG_FORCED_MASK;
693 // No need to clear MIDELEG_FORCED_MASK because those bits can never
694 // get set in val.
695 return val;
696 }
697
verify_permissions(insn_t insn,bool write) const698 void mideleg_csr_t::verify_permissions(insn_t insn, bool write) const {
699 basic_csr_t::verify_permissions(insn, write);
700 if (!proc->extension_enabled('S'))
701 throw trap_illegal_instruction(insn.bits());
702 }
703
unlogged_write(const reg_t val)704 bool mideleg_csr_t::unlogged_write(const reg_t val) noexcept {
705 const reg_t supervisor_ints = proc->extension_enabled('S') ? MIP_SSIP | MIP_STIP | MIP_SEIP : 0;
706 const reg_t coprocessor_ints = (reg_t)proc->any_custom_extensions() << IRQ_COP;
707 const reg_t delegable_ints = supervisor_ints | coprocessor_ints;
708
709 return basic_csr_t::unlogged_write(val & delegable_ints);
710 }
711
712
713 // implement class medeleg_csr_t
medeleg_csr_t(processor_t * const proc,const reg_t addr)714 medeleg_csr_t::medeleg_csr_t(processor_t* const proc, const reg_t addr):
715 basic_csr_t(proc, addr, 0),
716 hypervisor_exceptions(0
717 | (1 << CAUSE_VIRTUAL_SUPERVISOR_ECALL)
718 | (1 << CAUSE_FETCH_GUEST_PAGE_FAULT)
719 | (1 << CAUSE_LOAD_GUEST_PAGE_FAULT)
720 | (1 << CAUSE_VIRTUAL_INSTRUCTION)
721 | (1 << CAUSE_STORE_GUEST_PAGE_FAULT)
722 ) {
723 }
724
verify_permissions(insn_t insn,bool write) const725 void medeleg_csr_t::verify_permissions(insn_t insn, bool write) const {
726 basic_csr_t::verify_permissions(insn, write);
727 if (!proc->extension_enabled('S'))
728 throw trap_illegal_instruction(insn.bits());
729 }
730
unlogged_write(const reg_t val)731 bool medeleg_csr_t::unlogged_write(const reg_t val) noexcept {
732 const reg_t mask = 0
733 | (1 << CAUSE_MISALIGNED_FETCH)
734 | (1 << CAUSE_BREAKPOINT)
735 | (1 << CAUSE_USER_ECALL)
736 | (1 << CAUSE_SUPERVISOR_ECALL)
737 | (1 << CAUSE_FETCH_PAGE_FAULT)
738 | (1 << CAUSE_LOAD_PAGE_FAULT)
739 | (1 << CAUSE_STORE_PAGE_FAULT)
740 | (proc->extension_enabled('H') ? hypervisor_exceptions : 0)
741 ;
742 return basic_csr_t::unlogged_write((read() & ~mask) | (val & mask));
743 }
744
745
746 // implement class masked_csr_t
masked_csr_t(processor_t * const proc,const reg_t addr,const reg_t mask,const reg_t init)747 masked_csr_t::masked_csr_t(processor_t* const proc, const reg_t addr, const reg_t mask, const reg_t init):
748 basic_csr_t(proc, addr, init),
749 mask(mask) {
750 }
751
unlogged_write(const reg_t val)752 bool masked_csr_t::unlogged_write(const reg_t val) noexcept {
753 return basic_csr_t::unlogged_write((read() & ~mask) | (val & mask));
754 }
755
756
757 // implement class base_atp_csr_t and family
base_atp_csr_t(processor_t * const proc,const reg_t addr)758 base_atp_csr_t::base_atp_csr_t(processor_t* const proc, const reg_t addr):
759 basic_csr_t(proc, addr, 0) {
760 }
761
762
unlogged_write(const reg_t val)763 bool base_atp_csr_t::unlogged_write(const reg_t val) noexcept {
764 const reg_t newval = proc->supports_impl(IMPL_MMU) ? compute_new_satp(val) : 0;
765 if (newval != read())
766 proc->get_mmu()->flush_tlb();
767 return basic_csr_t::unlogged_write(newval);
768 }
769
satp_valid(reg_t val) const770 bool base_atp_csr_t::satp_valid(reg_t val) const noexcept {
771 if (proc->get_xlen() == 32) {
772 switch (get_field(val, SATP32_MODE)) {
773 case SATP_MODE_SV32: return proc->supports_impl(IMPL_MMU_SV32);
774 case SATP_MODE_OFF: return true;
775 default: return false;
776 }
777 } else {
778 switch (get_field(val, SATP64_MODE)) {
779 case SATP_MODE_SV39: return proc->supports_impl(IMPL_MMU_SV39);
780 case SATP_MODE_SV48: return proc->supports_impl(IMPL_MMU_SV48);
781 case SATP_MODE_OFF: return true;
782 default: return false;
783 }
784 }
785 }
786
compute_new_satp(reg_t val) const787 reg_t base_atp_csr_t::compute_new_satp(reg_t val) const noexcept {
788 reg_t rv64_ppn_mask = (reg_t(1) << (MAX_PADDR_BITS - PGSHIFT)) - 1;
789
790 reg_t mode_mask = proc->get_xlen() == 32 ? SATP32_MODE : SATP64_MODE;
791 reg_t ppn_mask = proc->get_xlen() == 32 ? SATP32_PPN : SATP64_PPN & rv64_ppn_mask;
792 reg_t new_mask = (satp_valid(val) ? mode_mask : 0) | ppn_mask;
793 reg_t old_mask = satp_valid(val) ? 0 : mode_mask;
794
795 return (new_mask & val) | (old_mask & read());
796 }
797
satp_csr_t(processor_t * const proc,const reg_t addr)798 satp_csr_t::satp_csr_t(processor_t* const proc, const reg_t addr):
799 base_atp_csr_t(proc, addr) {
800 }
801
verify_permissions(insn_t insn,bool write) const802 void satp_csr_t::verify_permissions(insn_t insn, bool write) const {
803 base_atp_csr_t::verify_permissions(insn, write);
804 if (get_field(state->mstatus->read(), MSTATUS_TVM))
805 require(state->prv >= PRV_M);
806 }
807
virtualized_satp_csr_t(processor_t * const proc,satp_csr_t_p orig,csr_t_p virt)808 virtualized_satp_csr_t::virtualized_satp_csr_t(processor_t* const proc, satp_csr_t_p orig, csr_t_p virt):
809 virtualized_csr_t(proc, orig, virt),
810 orig_satp(orig) {
811 }
812
verify_permissions(insn_t insn,bool write) const813 void virtualized_satp_csr_t::verify_permissions(insn_t insn, bool write) const {
814 virtualized_csr_t::verify_permissions(insn, write);
815
816 // If satp is accessed from VS mode, it's really accessing vsatp,
817 // and the hstatus.VTVM bit controls.
818 if (state->v) {
819 if (get_field(state->hstatus->read(), HSTATUS_VTVM))
820 throw trap_virtual_instruction(insn.bits());
821 }
822 else {
823 orig_csr->verify_permissions(insn, write);
824 }
825 }
826
unlogged_write(const reg_t val)827 bool virtualized_satp_csr_t::unlogged_write(const reg_t val) noexcept {
828 // If unsupported Mode field: no change to contents
829 const reg_t newval = orig_satp->satp_valid(val) ? val : read();
830 return virtualized_csr_t::unlogged_write(newval);
831 }
832
833
834 // implement class minstret_csr_t
minstret_csr_t(processor_t * const proc,const reg_t addr)835 minstret_csr_t::minstret_csr_t(processor_t* const proc, const reg_t addr):
836 csr_t(proc, addr),
837 val(0) {
838 }
839
read() const840 reg_t minstret_csr_t::read() const noexcept {
841 return val;
842 }
843
bump(const reg_t howmuch)844 void minstret_csr_t::bump(const reg_t howmuch) noexcept {
845 val += howmuch; // to keep log reasonable size, don't log every bump
846 }
847
unlogged_write(const reg_t val)848 bool minstret_csr_t::unlogged_write(const reg_t val) noexcept {
849 if (proc->get_xlen() == 32)
850 this->val = (this->val >> 32 << 32) | (val & 0xffffffffU);
851 else
852 this->val = val;
853 // The ISA mandates that if an instruction writes instret, the write
854 // takes precedence over the increment to instret. However, Spike
855 // unconditionally increments instret after executing an instruction.
856 // Correct for this artifact by decrementing instret here.
857 this->val--;
858 return true;
859 }
860
written_value() const861 reg_t minstret_csr_t::written_value() const noexcept {
862 // Re-adjust for upcoming bump()
863 return this->val + 1;
864 }
865
write_upper_half(const reg_t val)866 void minstret_csr_t::write_upper_half(const reg_t val) noexcept {
867 this->val = (val << 32) | (this->val << 32 >> 32);
868 this->val--; // See comment above.
869 // Log upper half only.
870 log_special_write(address + (CSR_MINSTRETH - CSR_MINSTRET), written_value() >> 32);
871 }
872
873
minstreth_csr_t(processor_t * const proc,const reg_t addr,minstret_csr_t_p minstret)874 minstreth_csr_t::minstreth_csr_t(processor_t* const proc, const reg_t addr, minstret_csr_t_p minstret):
875 csr_t(proc, addr),
876 minstret(minstret) {
877 }
878
read() const879 reg_t minstreth_csr_t::read() const noexcept {
880 return minstret->read() >> 32;
881 }
882
unlogged_write(const reg_t val)883 bool minstreth_csr_t::unlogged_write(const reg_t val) noexcept {
884 minstret->write_upper_half(val);
885 return true;
886 }
887
888
proxy_csr_t(processor_t * const proc,const reg_t addr,csr_t_p delegate)889 proxy_csr_t::proxy_csr_t(processor_t* const proc, const reg_t addr, csr_t_p delegate):
890 csr_t(proc, addr),
891 delegate(delegate) {
892 }
893
read() const894 reg_t proxy_csr_t::read() const noexcept {
895 return delegate->read();
896 }
897
unlogged_write(const reg_t val)898 bool proxy_csr_t::unlogged_write(const reg_t val) noexcept {
899 delegate->write(val); // log only under the original (delegate's) name
900 return false;
901 }
902
903
const_csr_t(processor_t * const proc,const reg_t addr,reg_t val)904 const_csr_t::const_csr_t(processor_t* const proc, const reg_t addr, reg_t val):
905 csr_t(proc, addr),
906 val(val) {
907 }
908
read() const909 reg_t const_csr_t::read() const noexcept {
910 return val;
911 }
912
unlogged_write(const reg_t val)913 bool const_csr_t::unlogged_write(const reg_t val) noexcept {
914 return false;
915 }
916
917
counter_proxy_csr_t(processor_t * const proc,const reg_t addr,csr_t_p delegate)918 counter_proxy_csr_t::counter_proxy_csr_t(processor_t* const proc, const reg_t addr, csr_t_p delegate):
919 proxy_csr_t(proc, addr, delegate) {
920 }
921
myenable(csr_t_p counteren) const922 bool counter_proxy_csr_t::myenable(csr_t_p counteren) const noexcept {
923 return 1 & (counteren->read() >> (address & 31));
924 }
925
verify_permissions(insn_t insn,bool write) const926 void counter_proxy_csr_t::verify_permissions(insn_t insn, bool write) const {
927 proxy_csr_t::verify_permissions(insn, write);
928
929 const bool mctr_ok = (state->prv < PRV_M) ? myenable(state->mcounteren) : true;
930 const bool hctr_ok = state->v ? myenable(state->hcounteren) : true;
931 const bool sctr_ok = (proc->extension_enabled('S') && state->prv < PRV_S) ? myenable(state->scounteren) : true;
932
933 if (!mctr_ok)
934 throw trap_illegal_instruction(insn.bits());
935 if (!hctr_ok)
936 throw trap_virtual_instruction(insn.bits());
937 if (!sctr_ok) {
938 if (state->v)
939 throw trap_virtual_instruction(insn.bits());
940 else
941 throw trap_illegal_instruction(insn.bits());
942 }
943 }
944
945
hypervisor_csr_t(processor_t * const proc,const reg_t addr)946 hypervisor_csr_t::hypervisor_csr_t(processor_t* const proc, const reg_t addr):
947 basic_csr_t(proc, addr, 0) {
948 }
949
verify_permissions(insn_t insn,bool write) const950 void hypervisor_csr_t::verify_permissions(insn_t insn, bool write) const {
951 basic_csr_t::verify_permissions(insn, write);
952 if (!proc->extension_enabled('H'))
953 throw trap_illegal_instruction(insn.bits());
954 }
955
956
hgatp_csr_t(processor_t * const proc,const reg_t addr)957 hgatp_csr_t::hgatp_csr_t(processor_t* const proc, const reg_t addr):
958 basic_csr_t(proc, addr, 0) {
959 }
960
verify_permissions(insn_t insn,bool write) const961 void hgatp_csr_t::verify_permissions(insn_t insn, bool write) const {
962 basic_csr_t::verify_permissions(insn, write);
963 if (!state->v && get_field(state->mstatus->read(), MSTATUS_TVM))
964 require_privilege(PRV_M);
965 }
966
unlogged_write(const reg_t val)967 bool hgatp_csr_t::unlogged_write(const reg_t val) noexcept {
968 proc->get_mmu()->flush_tlb();
969
970 reg_t mask;
971 if (proc->get_const_xlen() == 32) {
972 mask = HGATP32_PPN | HGATP32_MODE;
973 } else {
974 mask = HGATP64_PPN & ((reg_t(1) << (MAX_PADDR_BITS - PGSHIFT)) - 1);
975
976 if (get_field(val, HGATP64_MODE) == HGATP_MODE_OFF ||
977 get_field(val, HGATP64_MODE) == HGATP_MODE_SV39X4 ||
978 get_field(val, HGATP64_MODE) == HGATP_MODE_SV48X4)
979 mask |= HGATP64_MODE;
980 }
981 mask &= ~(reg_t)3;
982 return basic_csr_t::unlogged_write((read() & ~mask) | (val & mask));
983 }
984
985
tselect_csr_t(processor_t * const proc,const reg_t addr)986 tselect_csr_t::tselect_csr_t(processor_t* const proc, const reg_t addr):
987 basic_csr_t(proc, addr, 0) {
988 }
989
unlogged_write(const reg_t val)990 bool tselect_csr_t::unlogged_write(const reg_t val) noexcept {
991 return basic_csr_t::unlogged_write((val < state->num_triggers) ? val : read());
992 }
993
994
tdata1_csr_t(processor_t * const proc,const reg_t addr)995 tdata1_csr_t::tdata1_csr_t(processor_t* const proc, const reg_t addr):
996 csr_t(proc, addr) {
997 }
998
read() const999 reg_t tdata1_csr_t::read() const noexcept {
1000 reg_t v = 0;
1001 auto xlen = proc->get_xlen();
1002 mcontrol_t *mc = &state->mcontrol[state->tselect->read()];
1003 v = set_field(v, MCONTROL_TYPE(xlen), mc->type);
1004 v = set_field(v, MCONTROL_DMODE(xlen), mc->dmode);
1005 v = set_field(v, MCONTROL_MASKMAX(xlen), mc->maskmax);
1006 v = set_field(v, MCONTROL_SELECT, mc->select);
1007 v = set_field(v, MCONTROL_TIMING, mc->timing);
1008 v = set_field(v, MCONTROL_ACTION, mc->action);
1009 v = set_field(v, MCONTROL_CHAIN, mc->chain);
1010 v = set_field(v, MCONTROL_MATCH, mc->match);
1011 v = set_field(v, MCONTROL_M, mc->m);
1012 v = set_field(v, MCONTROL_H, mc->h);
1013 v = set_field(v, MCONTROL_S, mc->s);
1014 v = set_field(v, MCONTROL_U, mc->u);
1015 v = set_field(v, MCONTROL_EXECUTE, mc->execute);
1016 v = set_field(v, MCONTROL_STORE, mc->store);
1017 v = set_field(v, MCONTROL_LOAD, mc->load);
1018 return v;
1019 }
1020
unlogged_write(const reg_t val)1021 bool tdata1_csr_t::unlogged_write(const reg_t val) noexcept {
1022 mcontrol_t *mc = &state->mcontrol[state->tselect->read()];
1023 if (mc->dmode && !state->debug_mode) {
1024 return false;
1025 }
1026 auto xlen = proc->get_xlen();
1027 mc->dmode = get_field(val, MCONTROL_DMODE(xlen));
1028 mc->select = get_field(val, MCONTROL_SELECT);
1029 mc->timing = get_field(val, MCONTROL_TIMING);
1030 mc->action = (mcontrol_action_t) get_field(val, MCONTROL_ACTION);
1031 mc->chain = get_field(val, MCONTROL_CHAIN);
1032 mc->match = (mcontrol_match_t) get_field(val, MCONTROL_MATCH);
1033 mc->m = get_field(val, MCONTROL_M);
1034 mc->h = get_field(val, MCONTROL_H);
1035 mc->s = get_field(val, MCONTROL_S);
1036 mc->u = get_field(val, MCONTROL_U);
1037 mc->execute = get_field(val, MCONTROL_EXECUTE);
1038 mc->store = get_field(val, MCONTROL_STORE);
1039 mc->load = get_field(val, MCONTROL_LOAD);
1040 // Assume we're here because of csrw.
1041 if (mc->execute)
1042 mc->timing = 0;
1043 proc->trigger_updated();
1044 return true;
1045 }
1046
1047
tdata2_csr_t(processor_t * const proc,const reg_t addr,const size_t count)1048 tdata2_csr_t::tdata2_csr_t(processor_t* const proc, const reg_t addr, const size_t count):
1049 csr_t(proc, addr),
1050 vals(count, 0) {
1051 }
1052
read() const1053 reg_t tdata2_csr_t::read() const noexcept {
1054 return read(state->tselect->read());
1055 }
1056
read(const size_t idx) const1057 reg_t tdata2_csr_t::read(const size_t idx) const noexcept {
1058 return vals[idx];
1059 }
1060
unlogged_write(const reg_t val)1061 bool tdata2_csr_t::unlogged_write(const reg_t val) noexcept {
1062 if (state->mcontrol[state->tselect->read()].dmode && !state->debug_mode) {
1063 return false;
1064 }
1065 vals[state->tselect->read()] = val;
1066 return true;
1067 }
1068
1069
debug_mode_csr_t(processor_t * const proc,const reg_t addr)1070 debug_mode_csr_t::debug_mode_csr_t(processor_t* const proc, const reg_t addr):
1071 basic_csr_t(proc, addr, 0) {
1072 }
1073
verify_permissions(insn_t insn,bool write) const1074 void debug_mode_csr_t::verify_permissions(insn_t insn, bool write) const {
1075 basic_csr_t::verify_permissions(insn, write);
1076 if (!state->debug_mode)
1077 throw trap_illegal_instruction(insn.bits());
1078 }
1079
dpc_csr_t(processor_t * const proc,const reg_t addr)1080 dpc_csr_t::dpc_csr_t(processor_t* const proc, const reg_t addr):
1081 epc_csr_t(proc, addr) {
1082 }
1083
verify_permissions(insn_t insn,bool write) const1084 void dpc_csr_t::verify_permissions(insn_t insn, bool write) const {
1085 epc_csr_t::verify_permissions(insn, write);
1086 if (!state->debug_mode)
1087 throw trap_illegal_instruction(insn.bits());
1088 }
1089
1090
dcsr_csr_t(processor_t * const proc,const reg_t addr)1091 dcsr_csr_t::dcsr_csr_t(processor_t* const proc, const reg_t addr):
1092 csr_t(proc, addr),
1093 prv(0),
1094 step(false),
1095 ebreakm(false),
1096 ebreakh(false),
1097 ebreaks(false),
1098 ebreaku(false),
1099 halt(false),
1100 cause(0) {
1101 }
1102
verify_permissions(insn_t insn,bool write) const1103 void dcsr_csr_t::verify_permissions(insn_t insn, bool write) const {
1104 csr_t::verify_permissions(insn, write);
1105 if (!state->debug_mode)
1106 throw trap_illegal_instruction(insn.bits());
1107 }
1108
read() const1109 reg_t dcsr_csr_t::read() const noexcept {
1110 uint32_t v = 0;
1111 v = set_field(v, DCSR_XDEBUGVER, 1);
1112 v = set_field(v, DCSR_EBREAKM, ebreakm);
1113 v = set_field(v, DCSR_EBREAKH, ebreakh);
1114 v = set_field(v, DCSR_EBREAKS, ebreaks);
1115 v = set_field(v, DCSR_EBREAKU, ebreaku);
1116 v = set_field(v, DCSR_STOPCYCLE, 0);
1117 v = set_field(v, DCSR_STOPTIME, 0);
1118 v = set_field(v, DCSR_CAUSE, cause);
1119 v = set_field(v, DCSR_STEP, step);
1120 v = set_field(v, DCSR_PRV, prv);
1121 return v;
1122 }
1123
unlogged_write(const reg_t val)1124 bool dcsr_csr_t::unlogged_write(const reg_t val) noexcept {
1125 prv = get_field(val, DCSR_PRV);
1126 step = get_field(val, DCSR_STEP);
1127 // TODO: ndreset and fullreset
1128 ebreakm = get_field(val, DCSR_EBREAKM);
1129 ebreakh = get_field(val, DCSR_EBREAKH);
1130 ebreaks = get_field(val, DCSR_EBREAKS);
1131 ebreaku = get_field(val, DCSR_EBREAKU);
1132 halt = get_field(val, DCSR_HALT);
1133 return true;
1134 }
1135
write_cause_and_prv(uint8_t cause,reg_t prv)1136 void dcsr_csr_t::write_cause_and_prv(uint8_t cause, reg_t prv) noexcept {
1137 this->cause = cause;
1138 this->prv = prv;
1139 log_write();
1140 }
1141
1142
float_csr_t(processor_t * const proc,const reg_t addr,const reg_t mask,const reg_t init)1143 float_csr_t::float_csr_t(processor_t* const proc, const reg_t addr, const reg_t mask, const reg_t init):
1144 masked_csr_t(proc, addr, mask, init) {
1145 }
1146
verify_permissions(insn_t insn,bool write) const1147 void float_csr_t::verify_permissions(insn_t insn, bool write) const {
1148 masked_csr_t::verify_permissions(insn, write);
1149 require_fp;
1150 if (!proc->extension_enabled('F'))
1151 throw trap_illegal_instruction(insn.bits());
1152 }
1153
unlogged_write(const reg_t val)1154 bool float_csr_t::unlogged_write(const reg_t val) noexcept {
1155 dirty_fp_state;
1156 return masked_csr_t::unlogged_write(val);
1157 }
1158
1159
composite_csr_t(processor_t * const proc,const reg_t addr,csr_t_p upper_csr,csr_t_p lower_csr,const unsigned upper_lsb)1160 composite_csr_t::composite_csr_t(processor_t* const proc, const reg_t addr, csr_t_p upper_csr, csr_t_p lower_csr, const unsigned upper_lsb):
1161 csr_t(proc, addr),
1162 upper_csr(upper_csr),
1163 lower_csr(lower_csr),
1164 upper_lsb(upper_lsb) {
1165 }
1166
verify_permissions(insn_t insn,bool write) const1167 void composite_csr_t::verify_permissions(insn_t insn, bool write) const {
1168 // It is reasonable to assume that either underlying CSR will have
1169 // the same permissions as this composite.
1170 upper_csr->verify_permissions(insn, write);
1171 }
1172
read() const1173 reg_t composite_csr_t::read() const noexcept {
1174 return (upper_csr->read() << upper_lsb) | lower_csr->read();
1175 }
1176
unlogged_write(const reg_t val)1177 bool composite_csr_t::unlogged_write(const reg_t val) noexcept {
1178 upper_csr->write(val >> upper_lsb);
1179 lower_csr->write(val);
1180 return false; // logging is done only by the underlying CSRs
1181 }
1182
1183
sentropy_csr_t(processor_t * const proc,const reg_t addr)1184 sentropy_csr_t::sentropy_csr_t(processor_t* const proc, const reg_t addr):
1185 csr_t(proc, addr) {
1186 }
1187
verify_permissions(insn_t insn,bool write) const1188 void sentropy_csr_t::verify_permissions(insn_t insn, bool write) const {
1189 /* Read-only access disallowed due to wipe-on-read side effect */
1190 if (!proc->extension_enabled(EXT_ZKR) || !write)
1191 throw trap_illegal_instruction(insn.bits());
1192 csr_t::verify_permissions(insn, write);
1193 }
1194
read() const1195 reg_t sentropy_csr_t::read() const noexcept {
1196 return proc->es.get_sentropy();
1197 }
1198
unlogged_write(const reg_t val)1199 bool sentropy_csr_t::unlogged_write(const reg_t val) noexcept {
1200 proc->es.set_sentropy(val);
1201 return true;
1202 }
1203
1204
1205
vector_csr_t(processor_t * const proc,const reg_t addr,const reg_t mask,const reg_t init)1206 vector_csr_t::vector_csr_t(processor_t* const proc, const reg_t addr, const reg_t mask, const reg_t init):
1207 basic_csr_t(proc, addr, init),
1208 mask(mask) {
1209 }
1210
verify_permissions(insn_t insn,bool write) const1211 void vector_csr_t::verify_permissions(insn_t insn, bool write) const {
1212 require_vector_vs;
1213 if (!proc->extension_enabled('V'))
1214 throw trap_illegal_instruction(insn.bits());
1215 basic_csr_t::verify_permissions(insn, write);
1216 }
1217
write_raw(const reg_t val)1218 void vector_csr_t::write_raw(const reg_t val) noexcept {
1219 const bool success = basic_csr_t::unlogged_write(val);
1220 if (success)
1221 log_write();
1222 }
1223
unlogged_write(const reg_t val)1224 bool vector_csr_t::unlogged_write(const reg_t val) noexcept {
1225 if (mask == 0) return false;
1226 dirty_vs_state;
1227 return basic_csr_t::unlogged_write(val & mask);
1228 }
1229
1230
vxsat_csr_t(processor_t * const proc,const reg_t addr)1231 vxsat_csr_t::vxsat_csr_t(processor_t* const proc, const reg_t addr):
1232 masked_csr_t(proc, addr, /*mask*/ 1, /*init*/ 0) {
1233 }
1234
verify_permissions(insn_t insn,bool write) const1235 void vxsat_csr_t::verify_permissions(insn_t insn, bool write) const {
1236 require_vector_vs;
1237 if (!proc->extension_enabled('V') && !proc->extension_enabled(EXT_ZPN))
1238 throw trap_illegal_instruction(insn.bits());
1239 masked_csr_t::verify_permissions(insn, write);
1240 }
1241
unlogged_write(const reg_t val)1242 bool vxsat_csr_t::unlogged_write(const reg_t val) noexcept {
1243 dirty_vs_state;
1244 return masked_csr_t::unlogged_write(val);
1245 }
1246