diff options
Diffstat (limited to 'riscv/processor.cc')
-rw-r--r-- | riscv/processor.cc | 634 |
1 files changed, 125 insertions, 509 deletions
diff --git a/riscv/processor.cc b/riscv/processor.cc index f6d68b1..f11cfc0 100644 --- a/riscv/processor.cc +++ b/riscv/processor.cc @@ -34,7 +34,8 @@ processor_t::processor_t(const char* isa_str, const char* priv_str, const cfg_t *cfg, simif_t* sim, uint32_t id, bool halt_on_reset, FILE* log_file, std::ostream& sout_) -: debug(false), halt_request(HR_NONE), isa(isa_str, priv_str), cfg(cfg), sim(sim), id(id), xlen(0), +: debug(false), halt_request(HR_NONE), isa(isa_str, priv_str), cfg(cfg), + sim(sim), id(id), xlen(isa.get_max_xlen()), histogram_enabled(false), log_commits_enabled(false), log_file(log_file), sout_(sout_.rdbuf()), halt_on_reset(halt_on_reset), in_wfi(false), check_triggers_icount(false), @@ -62,7 +63,7 @@ processor_t::processor_t(const char* isa_str, const char* priv_str, VU.vstart_alu = 0; register_base_instructions(); - mmu = new mmu_t(sim, cfg->endianness, this); + mmu = new mmu_t(sim, cfg->endianness, this, cfg->cache_blocksz); disassembler = new disassembler_t(&isa); for (auto e : isa.get_extensions()) @@ -99,453 +100,21 @@ processor_t::~processor_t() delete disassembler; } -static void bad_option_string(const char *option, const char *value, - const char *msg) -{ - fprintf(stderr, "error: bad %s option '%s'. %s\n", option, value, msg); - abort(); -} - -static std::string get_string_token(std::string str, const char delimiter, size_t& pos) -{ - size_t _pos = pos; - while (pos < str.length() && str[pos] != delimiter) ++pos; - return str.substr(_pos, pos - _pos); -} - -static bool check_pow2(int val) -{ - return ((val & (val - 1))) == 0; -} - -static std::string strtolower(const char* str) -{ - std::string res; - for (const char *r = str; *r; r++) - res += std::tolower(*r); - return res; -} - -static int xlen_to_uxl(int xlen) -{ - if (xlen == 32) - return 1; - if (xlen == 64) - return 2; - abort(); -} - void state_t::reset(processor_t* const proc, reg_t max_isa) { pc = DEFAULT_RSTVEC; XPR.reset(); FPR.reset(); - // This assumes xlen is always max_xlen, which is true today (see - // mstatus_csr_t::unlogged_write()): - auto xlen = proc->get_isa().get_max_xlen(); - prv = prev_prv = PRV_M; v = prev_v = false; prv_changed = false; v_changed = false; - csrmap[CSR_MISA] = misa = std::make_shared<misa_csr_t>(proc, CSR_MISA, max_isa); - mstatus = std::make_shared<mstatus_csr_t>(proc, CSR_MSTATUS); - if (xlen == 32) { - csrmap[CSR_MSTATUS] = std::make_shared<rv32_low_csr_t>(proc, CSR_MSTATUS, mstatus); - csrmap[CSR_MSTATUSH] = mstatush = std::make_shared<rv32_high_csr_t>(proc, CSR_MSTATUSH, mstatus); - } else { - csrmap[CSR_MSTATUS] = mstatus; - } - csrmap[CSR_MEPC] = mepc = std::make_shared<epc_csr_t>(proc, CSR_MEPC); - csrmap[CSR_MTVAL] = mtval = std::make_shared<basic_csr_t>(proc, CSR_MTVAL, 0); - csrmap[CSR_MSCRATCH] = std::make_shared<basic_csr_t>(proc, CSR_MSCRATCH, 0); - csrmap[CSR_MTVEC] = mtvec = std::make_shared<tvec_csr_t>(proc, CSR_MTVEC); - csrmap[CSR_MCAUSE] = mcause = std::make_shared<cause_csr_t>(proc, CSR_MCAUSE); - - auto smcntrpmf_enabled = proc->extension_enabled_const(EXT_SMCNTRPMF); - const reg_t mask = smcntrpmf_enabled ? MHPMEVENT_MINH | MHPMEVENT_SINH | - MHPMEVENT_UINH | MHPMEVENT_VSINH | MHPMEVENT_VUINH : 0; - auto minstretcfg = std::make_shared<smcntrpmf_csr_t>(proc, CSR_MINSTRETCFG, mask, 0); - auto mcyclecfg = std::make_shared<smcntrpmf_csr_t>(proc, CSR_MCYCLECFG, mask, 0); - - minstret = std::make_shared<wide_counter_csr_t>(proc, CSR_MINSTRET, minstretcfg); - mcycle = std::make_shared<wide_counter_csr_t>(proc, CSR_MCYCLE, mcyclecfg); - time = std::make_shared<time_counter_csr_t>(proc, CSR_TIME); - if (proc->extension_enabled_const(EXT_ZICNTR)) { - csrmap[CSR_INSTRET] = std::make_shared<counter_proxy_csr_t>(proc, CSR_INSTRET, minstret); - csrmap[CSR_CYCLE] = std::make_shared<counter_proxy_csr_t>(proc, CSR_CYCLE, mcycle); - csrmap[CSR_TIME] = time_proxy = std::make_shared<counter_proxy_csr_t>(proc, CSR_TIME, time); - } - if (xlen == 32) { - csr_t_p minstreth, mcycleh; - csrmap[CSR_MINSTRET] = std::make_shared<rv32_low_csr_t>(proc, CSR_MINSTRET, minstret); - csrmap[CSR_MINSTRETH] = minstreth = std::make_shared<rv32_high_csr_t>(proc, CSR_MINSTRETH, minstret); - csrmap[CSR_MCYCLE] = std::make_shared<rv32_low_csr_t>(proc, CSR_MCYCLE, mcycle); - csrmap[CSR_MCYCLEH] = mcycleh = std::make_shared<rv32_high_csr_t>(proc, CSR_MCYCLEH, mcycle); - if (proc->extension_enabled_const(EXT_ZICNTR)) { - auto timeh = std::make_shared<rv32_high_csr_t>(proc, CSR_TIMEH, time); - csrmap[CSR_INSTRETH] = std::make_shared<counter_proxy_csr_t>(proc, CSR_INSTRETH, minstreth); - csrmap[CSR_CYCLEH] = std::make_shared<counter_proxy_csr_t>(proc, CSR_CYCLEH, mcycleh); - csrmap[CSR_TIMEH] = std::make_shared<counter_proxy_csr_t>(proc, CSR_TIMEH, timeh); - } - } else { - csrmap[CSR_MINSTRET] = minstret; - csrmap[CSR_MCYCLE] = mcycle; - } - for (reg_t i = 0; i < N_HPMCOUNTERS; ++i) { - const reg_t which_mevent = CSR_MHPMEVENT3 + i; - const reg_t which_meventh = CSR_MHPMEVENT3H + i; - const reg_t which_mcounter = CSR_MHPMCOUNTER3 + i; - const reg_t which_mcounterh = CSR_MHPMCOUNTER3H + i; - const reg_t which_counter = CSR_HPMCOUNTER3 + i; - const reg_t which_counterh = CSR_HPMCOUNTER3H + i; - mevent[i] = std::make_shared<mevent_csr_t>(proc, which_mevent); - auto mcounter = std::make_shared<const_csr_t>(proc, which_mcounter, 0); - csrmap[which_mcounter] = mcounter; - - if (proc->extension_enabled_const(EXT_ZIHPM)) { - auto counter = std::make_shared<counter_proxy_csr_t>(proc, which_counter, mcounter); - csrmap[which_counter] = counter; - } - if (xlen == 32) { - csrmap[which_mevent] = std::make_shared<rv32_low_csr_t>(proc, which_mevent, mevent[i]);; - auto mcounterh = std::make_shared<const_csr_t>(proc, which_mcounterh, 0); - csrmap[which_mcounterh] = mcounterh; - if (proc->extension_enabled_const(EXT_ZIHPM)) { - auto counterh = std::make_shared<counter_proxy_csr_t>(proc, which_counterh, mcounterh); - csrmap[which_counterh] = counterh; - } - if (proc->extension_enabled_const(EXT_SSCOFPMF)) { - auto meventh = std::make_shared<rv32_high_csr_t>(proc, which_meventh, mevent[i]); - csrmap[which_meventh] = meventh; - } - } else { - csrmap[which_mevent] = mevent[i]; - } - } - csrmap[CSR_MCOUNTINHIBIT] = std::make_shared<const_csr_t>(proc, CSR_MCOUNTINHIBIT, 0); - if (proc->extension_enabled_const(EXT_SSCOFPMF)) - csrmap[CSR_SCOUNTOVF] = std::make_shared<scountovf_csr_t>(proc, CSR_SCOUNTOVF); - csrmap[CSR_MIE] = mie = std::make_shared<mie_csr_t>(proc, CSR_MIE); - csrmap[CSR_MIP] = mip = std::make_shared<mip_csr_t>(proc, CSR_MIP); - auto sip_sie_accr = std::make_shared<generic_int_accessor_t>( - this, - ~MIP_HS_MASK, // read_mask - MIP_SSIP | MIP_LCOFIP, // ip_write_mask - ~MIP_HS_MASK, // ie_write_mask - generic_int_accessor_t::mask_mode_t::MIDELEG, - 0 // shiftamt - ); - - auto hip_hie_accr = std::make_shared<generic_int_accessor_t>( - this, - MIP_HS_MASK, // read_mask - MIP_VSSIP, // ip_write_mask - MIP_HS_MASK, // ie_write_mask - generic_int_accessor_t::mask_mode_t::MIDELEG, - 0 // shiftamt - ); - - auto vsip_vsie_accr = std::make_shared<generic_int_accessor_t>( - this, - MIP_VS_MASK, // read_mask - MIP_VSSIP, // ip_write_mask - MIP_VS_MASK, // ie_write_mask - generic_int_accessor_t::mask_mode_t::HIDELEG, - 1 // shiftamt - ); - - auto nonvirtual_sip = std::make_shared<mip_proxy_csr_t>(proc, CSR_SIP, sip_sie_accr); - auto vsip = std::make_shared<mip_proxy_csr_t>(proc, CSR_VSIP, vsip_vsie_accr); - csrmap[CSR_VSIP] = vsip; - csrmap[CSR_SIP] = std::make_shared<virtualized_csr_t>(proc, nonvirtual_sip, vsip); - csrmap[CSR_HIP] = std::make_shared<mip_proxy_csr_t>(proc, CSR_HIP, hip_hie_accr); - csrmap[CSR_HVIP] = hvip = std::make_shared<hvip_csr_t>(proc, CSR_HVIP, 0); - - auto nonvirtual_sie = std::make_shared<mie_proxy_csr_t>(proc, CSR_SIE, sip_sie_accr); - auto vsie = std::make_shared<mie_proxy_csr_t>(proc, CSR_VSIE, vsip_vsie_accr); - csrmap[CSR_VSIE] = vsie; - csrmap[CSR_SIE] = std::make_shared<virtualized_csr_t>(proc, nonvirtual_sie, vsie); - csrmap[CSR_HIE] = std::make_shared<mie_proxy_csr_t>(proc, CSR_HIE, hip_hie_accr); - - csrmap[CSR_MEDELEG] = medeleg = std::make_shared<medeleg_csr_t>(proc, CSR_MEDELEG); - csrmap[CSR_MIDELEG] = mideleg = std::make_shared<mideleg_csr_t>(proc, CSR_MIDELEG); - const reg_t counteren_mask = (proc->extension_enabled_const(EXT_ZICNTR) ? 0x7UL : 0x0) | (proc->extension_enabled_const(EXT_ZIHPM) ? 0xfffffff8ULL : 0x0); - mcounteren = std::make_shared<masked_csr_t>(proc, CSR_MCOUNTEREN, counteren_mask, 0); - if (proc->extension_enabled_const('U')) csrmap[CSR_MCOUNTEREN] = mcounteren; - csrmap[CSR_SCOUNTEREN] = scounteren = std::make_shared<masked_csr_t>(proc, CSR_SCOUNTEREN, counteren_mask, 0); - nonvirtual_sepc = std::make_shared<epc_csr_t>(proc, CSR_SEPC); - csrmap[CSR_VSEPC] = vsepc = std::make_shared<epc_csr_t>(proc, CSR_VSEPC); - csrmap[CSR_SEPC] = sepc = std::make_shared<virtualized_csr_t>(proc, nonvirtual_sepc, vsepc); - nonvirtual_stval = std::make_shared<basic_csr_t>(proc, CSR_STVAL, 0); - csrmap[CSR_VSTVAL] = vstval = std::make_shared<basic_csr_t>(proc, CSR_VSTVAL, 0); - csrmap[CSR_STVAL] = stval = std::make_shared<virtualized_csr_t>(proc, nonvirtual_stval, vstval); - auto sscratch = std::make_shared<basic_csr_t>(proc, CSR_SSCRATCH, 0); - auto vsscratch = std::make_shared<basic_csr_t>(proc, CSR_VSSCRATCH, 0); - // Note: if max_isa does not include H, we don't really need this virtualized_csr_t at all (though it doesn't hurt): - csrmap[CSR_SSCRATCH] = std::make_shared<virtualized_csr_t>(proc, sscratch, vsscratch); - csrmap[CSR_VSSCRATCH] = vsscratch; - nonvirtual_stvec = std::make_shared<tvec_csr_t>(proc, CSR_STVEC); - csrmap[CSR_VSTVEC] = vstvec = std::make_shared<tvec_csr_t>(proc, CSR_VSTVEC); - csrmap[CSR_STVEC] = stvec = std::make_shared<virtualized_csr_t>(proc, nonvirtual_stvec, vstvec); - auto nonvirtual_satp = std::make_shared<satp_csr_t>(proc, CSR_SATP); - csrmap[CSR_VSATP] = vsatp = std::make_shared<base_atp_csr_t>(proc, CSR_VSATP); - csrmap[CSR_SATP] = satp = std::make_shared<virtualized_satp_csr_t>(proc, nonvirtual_satp, vsatp); - nonvirtual_scause = std::make_shared<cause_csr_t>(proc, CSR_SCAUSE); - csrmap[CSR_VSCAUSE] = vscause = std::make_shared<cause_csr_t>(proc, CSR_VSCAUSE); - csrmap[CSR_SCAUSE] = scause = std::make_shared<virtualized_csr_t>(proc, nonvirtual_scause, vscause); - csrmap[CSR_MTVAL2] = mtval2 = std::make_shared<mtval2_csr_t>(proc, CSR_MTVAL2); - csrmap[CSR_MTINST] = mtinst = std::make_shared<hypervisor_csr_t>(proc, CSR_MTINST); - csrmap[CSR_HSTATUS] = hstatus = std::make_shared<hstatus_csr_t>(proc, CSR_HSTATUS); - csrmap[CSR_HGEIE] = std::make_shared<const_csr_t>(proc, CSR_HGEIE, 0); - csrmap[CSR_HGEIP] = std::make_shared<const_csr_t>(proc, CSR_HGEIP, 0); - csrmap[CSR_HIDELEG] = hideleg = std::make_shared<hideleg_csr_t>(proc, CSR_HIDELEG, mideleg); - const reg_t hedeleg_mask = - (1 << CAUSE_MISALIGNED_FETCH) | - (1 << CAUSE_FETCH_ACCESS) | - (1 << CAUSE_ILLEGAL_INSTRUCTION) | - (1 << CAUSE_BREAKPOINT) | - (1 << CAUSE_MISALIGNED_LOAD) | - (1 << CAUSE_LOAD_ACCESS) | - (1 << CAUSE_MISALIGNED_STORE) | - (1 << CAUSE_STORE_ACCESS) | - (1 << CAUSE_USER_ECALL) | - (1 << CAUSE_FETCH_PAGE_FAULT) | - (1 << CAUSE_LOAD_PAGE_FAULT) | - (1 << CAUSE_STORE_PAGE_FAULT) | - (1 << CAUSE_SOFTWARE_CHECK_FAULT) | - (1 << CAUSE_HARDWARE_ERROR_FAULT); - csrmap[CSR_HEDELEG] = hedeleg = std::make_shared<masked_csr_t>(proc, CSR_HEDELEG, hedeleg_mask, 0); - csrmap[CSR_HCOUNTEREN] = hcounteren = std::make_shared<masked_csr_t>(proc, CSR_HCOUNTEREN, counteren_mask, 0); - htimedelta = std::make_shared<basic_csr_t>(proc, CSR_HTIMEDELTA, 0); - if (xlen == 32) { - csrmap[CSR_HTIMEDELTA] = std::make_shared<rv32_low_csr_t>(proc, CSR_HTIMEDELTA, htimedelta); - csrmap[CSR_HTIMEDELTAH] = std::make_shared<rv32_high_csr_t>(proc, CSR_HTIMEDELTAH, htimedelta); - } else { - csrmap[CSR_HTIMEDELTA] = htimedelta; - } - csrmap[CSR_HTVAL] = htval = std::make_shared<basic_csr_t>(proc, CSR_HTVAL, 0); - csrmap[CSR_HTINST] = htinst = std::make_shared<basic_csr_t>(proc, CSR_HTINST, 0); - csrmap[CSR_HGATP] = hgatp = std::make_shared<hgatp_csr_t>(proc, CSR_HGATP); - nonvirtual_sstatus = std::make_shared<sstatus_proxy_csr_t>(proc, CSR_SSTATUS, mstatus); - csrmap[CSR_VSSTATUS] = vsstatus = std::make_shared<vsstatus_csr_t>(proc, CSR_VSSTATUS); - csrmap[CSR_SSTATUS] = sstatus = std::make_shared<sstatus_csr_t>(proc, nonvirtual_sstatus, vsstatus); - - csrmap[CSR_DPC] = dpc = std::make_shared<dpc_csr_t>(proc, CSR_DPC); - csrmap[CSR_DSCRATCH0] = std::make_shared<debug_mode_csr_t>(proc, CSR_DSCRATCH0); - csrmap[CSR_DSCRATCH1] = std::make_shared<debug_mode_csr_t>(proc, CSR_DSCRATCH1); - csrmap[CSR_DCSR] = dcsr = std::make_shared<dcsr_csr_t>(proc, CSR_DCSR); - - csrmap[CSR_TSELECT] = tselect = std::make_shared<tselect_csr_t>(proc, CSR_TSELECT); - if (proc->get_cfg().trigger_count > 0) { - csrmap[CSR_TDATA1] = std::make_shared<tdata1_csr_t>(proc, CSR_TDATA1); - csrmap[CSR_TDATA2] = tdata2 = std::make_shared<tdata2_csr_t>(proc, CSR_TDATA2); - csrmap[CSR_TDATA3] = std::make_shared<tdata3_csr_t>(proc, CSR_TDATA3); - csrmap[CSR_TINFO] = std::make_shared<tinfo_csr_t>(proc, CSR_TINFO); - csrmap[CSR_TCONTROL] = tcontrol = std::make_shared<masked_csr_t>(proc, CSR_TCONTROL, CSR_TCONTROL_MPTE | CSR_TCONTROL_MTE, 0); - } else { - csrmap[CSR_TDATA1] = std::make_shared<const_csr_t>(proc, CSR_TDATA1, 0); - csrmap[CSR_TDATA2] = tdata2 = std::make_shared<const_csr_t>(proc, CSR_TDATA2, 0); - csrmap[CSR_TDATA3] = std::make_shared<const_csr_t>(proc, CSR_TDATA3, 0); - csrmap[CSR_TINFO] = std::make_shared<const_csr_t>(proc, CSR_TINFO, 0); - csrmap[CSR_TCONTROL] = tcontrol = std::make_shared<const_csr_t>(proc, CSR_TCONTROL, 0); - } - unsigned scontext_length = (xlen == 32 ? 16 : 32); // debug spec suggests 16-bit for RV32 and 32-bit for RV64 - csrmap[CSR_SCONTEXT] = scontext = std::make_shared<masked_csr_t>(proc, CSR_SCONTEXT, (reg_t(1) << scontext_length) - 1, 0); - unsigned hcontext_length = (xlen == 32 ? 6 : 13) + (proc->extension_enabled('H') ? 1 : 0); // debug spec suggest 7-bit (6-bit) for RV32 and 14-bit (13-bit) for RV64 with (without) H extension - csrmap[CSR_HCONTEXT] = std::make_shared<masked_csr_t>(proc, CSR_HCONTEXT, (reg_t(1) << hcontext_length) - 1, 0); - csrmap[CSR_MCONTEXT] = mcontext = std::make_shared<proxy_csr_t>(proc, CSR_MCONTEXT, csrmap[CSR_HCONTEXT]); + serialized = false; debug_mode = false; single_step = STEP_NONE; - csrmap[CSR_MSECCFG] = mseccfg = std::make_shared<mseccfg_csr_t>(proc, CSR_MSECCFG); - - for (int i = 0; i < max_pmp; ++i) { - csrmap[CSR_PMPADDR0 + i] = pmpaddr[i] = std::make_shared<pmpaddr_csr_t>(proc, CSR_PMPADDR0 + i); - } - for (int i = 0; i < max_pmp; i += xlen / 8) { - reg_t addr = CSR_PMPCFG0 + i / 4; - csrmap[addr] = std::make_shared<pmpcfg_csr_t>(proc, addr); - } - - csrmap[CSR_FFLAGS] = fflags = std::make_shared<float_csr_t>(proc, CSR_FFLAGS, FSR_AEXC >> FSR_AEXC_SHIFT, 0); - csrmap[CSR_FRM] = frm = std::make_shared<float_csr_t>(proc, CSR_FRM, FSR_RD >> FSR_RD_SHIFT, 0); - assert(FSR_AEXC_SHIFT == 0); // composite_csr_t assumes fflags begins at bit 0 - csrmap[CSR_FCSR] = std::make_shared<composite_csr_t>(proc, CSR_FCSR, frm, fflags, FSR_RD_SHIFT); - - csrmap[CSR_SEED] = std::make_shared<seed_csr_t>(proc, CSR_SEED); - - csrmap[CSR_MARCHID] = std::make_shared<const_csr_t>(proc, CSR_MARCHID, 5); - csrmap[CSR_MIMPID] = std::make_shared<const_csr_t>(proc, CSR_MIMPID, 0); - csrmap[CSR_MVENDORID] = std::make_shared<const_csr_t>(proc, CSR_MVENDORID, 0); - csrmap[CSR_MHARTID] = std::make_shared<const_csr_t>(proc, CSR_MHARTID, proc->get_id()); - csrmap[CSR_MCONFIGPTR] = std::make_shared<const_csr_t>(proc, CSR_MCONFIGPTR, 0); - const reg_t menvcfg_mask = (proc->extension_enabled(EXT_ZICBOM) ? MENVCFG_CBCFE | MENVCFG_CBIE : 0) | - (proc->extension_enabled(EXT_ZICBOZ) ? MENVCFG_CBZE : 0) | - (proc->extension_enabled(EXT_SMNPM) ? MENVCFG_PMM : 0) | - (proc->extension_enabled(EXT_SVADU) ? MENVCFG_ADUE: 0) | - (proc->extension_enabled(EXT_SVPBMT) ? MENVCFG_PBMTE : 0) | - (proc->extension_enabled(EXT_SSTC) ? MENVCFG_STCE : 0) | - (proc->extension_enabled(EXT_ZICFILP) ? MENVCFG_LPE : 0) | - (proc->extension_enabled(EXT_ZICFISS) ? MENVCFG_SSE : 0) | - (proc->extension_enabled(EXT_SSDBLTRP) ? MENVCFG_DTE : 0); - menvcfg = std::make_shared<envcfg_csr_t>(proc, CSR_MENVCFG, menvcfg_mask, 0); - if (proc->extension_enabled_const('U')) { - if (xlen == 32) { - csrmap[CSR_MENVCFG] = std::make_shared<rv32_low_csr_t>(proc, CSR_MENVCFG, menvcfg); - csrmap[CSR_MENVCFGH] = std::make_shared<rv32_high_csr_t>(proc, CSR_MENVCFGH, menvcfg); - } else { - csrmap[CSR_MENVCFG] = menvcfg; - } - } - const reg_t senvcfg_mask = (proc->extension_enabled(EXT_ZICBOM) ? SENVCFG_CBCFE | SENVCFG_CBIE : 0) | - (proc->extension_enabled(EXT_ZICBOZ) ? SENVCFG_CBZE : 0) | - (proc->extension_enabled(EXT_SSNPM) ? SENVCFG_PMM : 0) | - (proc->extension_enabled(EXT_ZICFILP) ? SENVCFG_LPE : 0) | - (proc->extension_enabled(EXT_ZICFISS) ? SENVCFG_SSE : 0); - senvcfg = std::make_shared<senvcfg_csr_t>(proc, CSR_SENVCFG, senvcfg_mask, 0); - if (proc->extension_enabled_const('S')) - csrmap[CSR_SENVCFG] = senvcfg; - const reg_t henvcfg_mask = (proc->extension_enabled(EXT_ZICBOM) ? HENVCFG_CBCFE | HENVCFG_CBIE : 0) | - (proc->extension_enabled(EXT_ZICBOZ) ? HENVCFG_CBZE : 0) | - (proc->extension_enabled(EXT_SSNPM) ? HENVCFG_PMM : 0) | - (proc->extension_enabled(EXT_SVADU) ? HENVCFG_ADUE: 0) | - (proc->extension_enabled(EXT_SVPBMT) ? HENVCFG_PBMTE : 0) | - (proc->extension_enabled(EXT_SSTC) ? HENVCFG_STCE : 0) | - (proc->extension_enabled(EXT_ZICFILP) ? HENVCFG_LPE : 0) | - (proc->extension_enabled(EXT_ZICFISS) ? HENVCFG_SSE : 0) | - (proc->extension_enabled(EXT_SSDBLTRP) ? HENVCFG_DTE : 0); - henvcfg = std::make_shared<henvcfg_csr_t>(proc, CSR_HENVCFG, henvcfg_mask, 0, menvcfg); - if (proc->extension_enabled('H')) { - if (xlen == 32) { - csrmap[CSR_HENVCFG] = std::make_shared<rv32_low_csr_t>(proc, CSR_HENVCFG, henvcfg); - csrmap[CSR_HENVCFGH] = std::make_shared<rv32_high_csr_t>(proc, CSR_HENVCFGH, henvcfg); - } else { - csrmap[CSR_HENVCFG] = henvcfg; - } - } - if (proc->extension_enabled_const(EXT_SMSTATEEN)) { - const reg_t sstateen0_mask = (proc->extension_enabled(EXT_ZFINX) ? SSTATEEN0_FCSR : 0) | - (proc->extension_enabled(EXT_ZCMT) ? SSTATEEN0_JVT : 0) | - SSTATEEN0_CS; - const reg_t hstateen0_mask = sstateen0_mask | HSTATEEN0_SENVCFG | HSTATEEN_SSTATEEN; - const reg_t mstateen0_mask = hstateen0_mask | (proc->extension_enabled(EXT_SSQOSID) ? MSTATEEN0_PRIV114 : 0); - for (int i = 0; i < 4; i++) { - const reg_t mstateen_mask = i == 0 ? mstateen0_mask : MSTATEEN_HSTATEEN; - mstateen[i] = std::make_shared<masked_csr_t>(proc, CSR_MSTATEEN0 + i, mstateen_mask, 0); - if (xlen == 32) { - csrmap[CSR_MSTATEEN0 + i] = std::make_shared<rv32_low_csr_t>(proc, CSR_MSTATEEN0 + i, mstateen[i]); - csrmap[CSR_MSTATEEN0H + i] = std::make_shared<rv32_high_csr_t>(proc, CSR_MSTATEEN0H + i, mstateen[i]); - } else { - csrmap[CSR_MSTATEEN0 + i] = mstateen[i]; - } - - const reg_t hstateen_mask = i == 0 ? hstateen0_mask : HSTATEEN_SSTATEEN; - hstateen[i] = std::make_shared<hstateen_csr_t>(proc, CSR_HSTATEEN0 + i, hstateen_mask, 0, i); - if (xlen == 32) { - csrmap[CSR_HSTATEEN0 + i] = std::make_shared<rv32_low_csr_t>(proc, CSR_HSTATEEN0 + i, hstateen[i]); - csrmap[CSR_HSTATEEN0H + i] = std::make_shared<rv32_high_csr_t>(proc, CSR_HSTATEEN0H + i, hstateen[i]); - } else { - csrmap[CSR_HSTATEEN0 + i] = hstateen[i]; - } - - const reg_t sstateen_mask = i == 0 ? sstateen0_mask : 0; - csrmap[CSR_SSTATEEN0 + i] = sstateen[i] = std::make_shared<sstateen_csr_t>(proc, CSR_SSTATEEN0 + i, sstateen_mask, 0, i); - } - } - - if (proc->extension_enabled_const(EXT_SMRNMI)) { - csrmap[CSR_MNSCRATCH] = std::make_shared<basic_csr_t>(proc, CSR_MNSCRATCH, 0); - csrmap[CSR_MNEPC] = mnepc = std::make_shared<epc_csr_t>(proc, CSR_MNEPC); - csrmap[CSR_MNCAUSE] = std::make_shared<const_csr_t>(proc, CSR_MNCAUSE, (reg_t)1 << (xlen - 1)); - csrmap[CSR_MNSTATUS] = mnstatus = std::make_shared<mnstatus_csr_t>(proc, CSR_MNSTATUS); - } - - if (proc->extension_enabled_const(EXT_SSTC)) { - stimecmp = std::make_shared<stimecmp_csr_t>(proc, CSR_STIMECMP, MIP_STIP); - vstimecmp = std::make_shared<stimecmp_csr_t>(proc, CSR_VSTIMECMP, MIP_VSTIP); - auto virtualized_stimecmp = std::make_shared<virtualized_stimecmp_csr_t>(proc, stimecmp, vstimecmp); - if (xlen == 32) { - csrmap[CSR_STIMECMP] = std::make_shared<rv32_low_csr_t>(proc, CSR_STIMECMP, virtualized_stimecmp); - csrmap[CSR_STIMECMPH] = std::make_shared<rv32_high_csr_t>(proc, CSR_STIMECMPH, virtualized_stimecmp); - csrmap[CSR_VSTIMECMP] = std::make_shared<rv32_low_csr_t>(proc, CSR_VSTIMECMP, vstimecmp); - csrmap[CSR_VSTIMECMPH] = std::make_shared<rv32_high_csr_t>(proc, CSR_VSTIMECMPH, vstimecmp); - } else { - csrmap[CSR_STIMECMP] = virtualized_stimecmp; - csrmap[CSR_VSTIMECMP] = vstimecmp; - } - } - - if (proc->extension_enabled(EXT_ZCMT)) - csrmap[CSR_JVT] = jvt = std::make_shared<jvt_csr_t>(proc, CSR_JVT, 0); - - if (proc->extension_enabled(EXT_ZICFISS)) { - reg_t ssp_mask = -reg_t(xlen / 8); - csrmap[CSR_SSP] = ssp = std::make_shared<ssp_csr_t>(proc, CSR_SSP, ssp_mask, 0); - } - - - // Smcsrind / Sscsrind - sscsrind_reg_csr_t::sscsrind_reg_csr_t_p mireg[6]; - sscsrind_reg_csr_t::sscsrind_reg_csr_t_p sireg[6]; - sscsrind_reg_csr_t::sscsrind_reg_csr_t_p vsireg[6]; - - if (proc->extension_enabled_const(EXT_SMCSRIND)) { - csr_t_p miselect = std::make_shared<basic_csr_t>(proc, CSR_MISELECT, 0); - csrmap[CSR_MISELECT] = miselect; - - const reg_t mireg_csrs[] = { CSR_MIREG, CSR_MIREG2, CSR_MIREG3, CSR_MIREG4, CSR_MIREG5, CSR_MIREG6 }; - auto i = 0; - for (auto csr : mireg_csrs) { - csrmap[csr] = mireg[i] = std::make_shared<sscsrind_reg_csr_t>(proc, csr, miselect); - i++; - } - } - - if (proc->extension_enabled_const(EXT_SSCSRIND)) { - csr_t_p vsiselect = std::make_shared<basic_csr_t>(proc, CSR_VSISELECT, 0); - csrmap[CSR_VSISELECT] = vsiselect; - csr_t_p siselect = std::make_shared<basic_csr_t>(proc, CSR_SISELECT, 0); - csrmap[CSR_SISELECT] = std::make_shared<virtualized_csr_t>(proc, siselect, vsiselect); - - const reg_t vsireg_csrs[] = { CSR_VSIREG, CSR_VSIREG2, CSR_VSIREG3, CSR_VSIREG4, CSR_VSIREG5, CSR_VSIREG6 }; - auto i = 0; - for (auto csr : vsireg_csrs) { - csrmap[csr] = vsireg[i] = std::make_shared<sscsrind_reg_csr_t>(proc, csr, vsiselect); - i++; - } - - const reg_t sireg_csrs[] = { CSR_SIREG, CSR_SIREG2, CSR_SIREG3, CSR_SIREG4, CSR_SIREG5, CSR_SIREG6 }; - i = 0; - for (auto csr : sireg_csrs) { - sireg[i] = std::make_shared<sscsrind_reg_csr_t>(proc, csr, siselect); - csrmap[csr] = std::make_shared<virtualized_indirect_csr_t>(proc, sireg[i], vsireg[i]); - i++; - } - } - - if (smcntrpmf_enabled) { - if (xlen == 32) { - csrmap[CSR_MCYCLECFG] = std::make_shared<rv32_low_csr_t>(proc, CSR_MCYCLECFG, mcyclecfg); - csrmap[CSR_MCYCLECFGH] = std::make_shared<rv32_high_csr_t>(proc, CSR_MCYCLECFGH, mcyclecfg); - csrmap[CSR_MINSTRETCFG] = std::make_shared<rv32_low_csr_t>(proc, CSR_MINSTRETCFG, minstretcfg); - csrmap[CSR_MINSTRETCFGH] = std::make_shared<rv32_high_csr_t>(proc, CSR_MINSTRETCFGH, minstretcfg); - } else { - csrmap[CSR_MCYCLECFG] = mcyclecfg; - csrmap[CSR_MINSTRETCFG] = minstretcfg; - } - } - - if (proc->extension_enabled_const(EXT_SSQOSID)) { - const reg_t srmcfg_mask = SRMCFG_MCID | SRMCFG_RCID; - srmcfg = std::make_shared<srmcfg_csr_t>(proc, CSR_SRMCFG, srmcfg_mask, 0); - csrmap[CSR_SRMCFG] = srmcfg; - } - - serialized = false; - log_reg_write.clear(); log_mem_read.clear(); log_mem_write.clear(); @@ -554,6 +123,10 @@ void state_t::reset(processor_t* const proc, reg_t max_isa) last_inst_flen = 0; elp = elp_t::NO_LP_EXPECTED; + + critical_error = false; + + csr_init(proc, max_isa); } void processor_t::set_debug(bool value) @@ -561,7 +134,7 @@ void processor_t::set_debug(bool value) debug = value; for (auto e : custom_extensions) - e.second->set_debug(value); + e.second->set_debug(value, *this); } void processor_t::set_histogram(bool value) @@ -572,14 +145,13 @@ void processor_t::set_histogram(bool value) void processor_t::enable_log_commits() { log_commits_enabled = true; + mmu->flush_tlb(); // the TLB caches this setting } void processor_t::reset() { xlen = isa.get_max_xlen(); state.reset(this, isa.get_max_isa()); - state.dcsr->halt = halt_on_reset; - halt_on_reset = false; if (any_vector_extensions()) VU.reset(); in_wfi = false; @@ -591,8 +163,11 @@ void processor_t::reset() put_csr(CSR_PMPCFG0, PMP_R | PMP_W | PMP_X | PMP_NAPOT); } - for (auto e : custom_extensions) // reset any extensions - e.second->reset(); + for (auto e : custom_extensions) { // reset any extensions + for (auto &csr: e.second->get_csrs(*this)) + state.add_csr(csr->address, csr); + e.second->reset(*this); + } if (sim) sim->proc_reset(id); @@ -649,10 +224,10 @@ void processor_t::set_mmu_capability(int cap) break; case IMPL_MMU_SV57: set_impl(IMPL_MMU_SV57, true); - // Fall through + [[fallthrough]]; case IMPL_MMU_SV48: set_impl(IMPL_MMU_SV48, true); - // Fall through + [[fallthrough]]; case IMPL_MMU_SV39: set_impl(IMPL_MMU_SV39, true); set_impl(IMPL_MMU, true); @@ -667,10 +242,53 @@ void processor_t::set_mmu_capability(int cap) } } +reg_t processor_t::select_an_interrupt_with_default_priority(reg_t enabled_interrupts) const +{ + // nonstandard interrupts have highest priority + if (enabled_interrupts >> (IRQ_LCOF + 1)) + enabled_interrupts = enabled_interrupts >> (IRQ_LCOF + 1) << (IRQ_LCOF + 1); + // standard interrupt priority is MEI, MSI, MTI, SEI, SSI, STI + else if (enabled_interrupts & MIP_MEIP) + enabled_interrupts = MIP_MEIP; + else if (enabled_interrupts & MIP_MSIP) + enabled_interrupts = MIP_MSIP; + else if (enabled_interrupts & MIP_MTIP) + enabled_interrupts = MIP_MTIP; + else if (enabled_interrupts & MIP_SEIP) + enabled_interrupts = MIP_SEIP; + else if (enabled_interrupts & MIP_SSIP) + enabled_interrupts = MIP_SSIP; + else if (enabled_interrupts & MIP_STIP) + enabled_interrupts = MIP_STIP; + else if (enabled_interrupts & MIP_LCOFIP) + enabled_interrupts = MIP_LCOFIP; + else if (enabled_interrupts & MIP_VSEIP) + enabled_interrupts = MIP_VSEIP; + else if (enabled_interrupts & MIP_VSSIP) + enabled_interrupts = MIP_VSSIP; + else if (enabled_interrupts & MIP_VSTIP) + enabled_interrupts = MIP_VSTIP; + + return enabled_interrupts; +} + void processor_t::take_interrupt(reg_t pending_interrupts) { + reg_t s_pending_interrupts = 0; + reg_t vstopi = 0; + reg_t vs_pending_interrupt = 0; + + if (extension_enabled_const(EXT_SSAIA)) { + s_pending_interrupts = state.nonvirtual_sip->read() & state.nonvirtual_sie->read(); + vstopi = state.vstopi->read(); + // Legacy VS interrupts (VSEIP/VSTIP/VSSIP) come in through pending_interrupts but are shifted + // down 1 in vstopi. AIA-extended and VTI are not shifted. Clear S bits (VS shifted down by 1). + vs_pending_interrupt = vstopi ? (reg_t(1) << get_field(vstopi, MTOPI_IID)) : 0; + vs_pending_interrupt &= ~MIP_S_MASK; + } + // Do nothing if no pending interrupts - if (!pending_interrupts) { + if (!pending_interrupts && !s_pending_interrupts && !vs_pending_interrupt) { return; } @@ -686,46 +304,20 @@ void processor_t::take_interrupt(reg_t pending_interrupts) const reg_t deleg_to_hs = state.mideleg->read() & ~state.hideleg->read(); const reg_t sie = get_field(state.sstatus->read(), MSTATUS_SIE); const reg_t hs_enabled = state.v || state.prv < PRV_S || (state.prv == PRV_S && sie); - enabled_interrupts = pending_interrupts & deleg_to_hs & -hs_enabled; + enabled_interrupts = ((pending_interrupts & deleg_to_hs) | (s_pending_interrupts & ~state.hideleg->read())) & -hs_enabled; if (state.v && enabled_interrupts == 0) { // VS-ints have least priority and can only be taken with virt enabled const reg_t deleg_to_vs = state.hideleg->read(); const reg_t vs_enabled = state.prv < PRV_S || (state.prv == PRV_S && sie); - enabled_interrupts = pending_interrupts & deleg_to_vs & -vs_enabled; + enabled_interrupts = ((pending_interrupts & deleg_to_vs) | vs_pending_interrupt) & -vs_enabled; } } const bool nmie = !(state.mnstatus && !get_field(state.mnstatus->read(), MNSTATUS_NMIE)); if (!state.debug_mode && nmie && enabled_interrupts) { - // nonstandard interrupts have highest priority - if (enabled_interrupts >> (IRQ_M_EXT + 1)) - enabled_interrupts = enabled_interrupts >> (IRQ_M_EXT + 1) << (IRQ_M_EXT + 1); - // standard interrupt priority is MEI, MSI, MTI, SEI, SSI, STI - else if (enabled_interrupts & MIP_MEIP) - enabled_interrupts = MIP_MEIP; - else if (enabled_interrupts & MIP_MSIP) - enabled_interrupts = MIP_MSIP; - else if (enabled_interrupts & MIP_MTIP) - enabled_interrupts = MIP_MTIP; - else if (enabled_interrupts & MIP_SEIP) - enabled_interrupts = MIP_SEIP; - else if (enabled_interrupts & MIP_SSIP) - enabled_interrupts = MIP_SSIP; - else if (enabled_interrupts & MIP_STIP) - enabled_interrupts = MIP_STIP; - else if (enabled_interrupts & MIP_LCOFIP) - enabled_interrupts = MIP_LCOFIP; - else if (enabled_interrupts & MIP_VSEIP) - enabled_interrupts = MIP_VSEIP; - else if (enabled_interrupts & MIP_VSSIP) - enabled_interrupts = MIP_VSSIP; - else if (enabled_interrupts & MIP_VSTIP) - enabled_interrupts = MIP_VSTIP; - else - abort(); - + reg_t selected_interrupt = select_an_interrupt_with_default_priority(enabled_interrupts); if (check_triggers_icount) TM.detect_icount_match(); - throw trap_t(((reg_t)1 << (isa.get_max_xlen() - 1)) | ctz(enabled_interrupts)); + throw trap_t(((reg_t)1 << (isa.get_max_xlen() - 1)) | ctz(selected_interrupt)); } } @@ -753,7 +345,7 @@ void processor_t::set_privilege(reg_t prv, bool virt) state.v_changed = state.v != state.prev_v; } -const char* processor_t::get_privilege_string() +const char* processor_t::get_privilege_string() const { if (state.debug_mode) return "D"; @@ -773,11 +365,11 @@ const char* processor_t::get_privilege_string() abort(); } -void processor_t::enter_debug_mode(uint8_t cause) +void processor_t::enter_debug_mode(uint8_t cause, uint8_t extcause) { const bool has_zicfilp = extension_enabled(EXT_ZICFILP); state.debug_mode = true; - state.dcsr->update_fields(cause, state.prv, state.v, state.elp); + state.dcsr->update_fields(cause, extcause, state.prv, state.v, state.elp); state.elp = elp_t::NO_LP_EXPECTED; set_privilege(PRV_M, false); state.dpc->write(state.pc); @@ -829,7 +421,7 @@ void processor_t::take_trap(trap_t& t, reg_t epc) bool supv_double_trap = false; if (interrupt) { vsdeleg = (curr_virt && state.prv <= PRV_S) ? state.hideleg->read() : 0; - hsdeleg = (state.prv <= PRV_S) ? state.mideleg->read() : 0; + hsdeleg = (state.prv <= PRV_S) ? (state.mideleg->read() | state.nonvirtual_sip->read()) : 0; bit &= ~((reg_t)1 << (max_xlen - 1)); } else { vsdeleg = (curr_virt && state.prv <= PRV_S) ? (state.medeleg->read() & state.hedeleg->read()) : 0; @@ -838,14 +430,25 @@ void processor_t::take_trap(trap_t& t, reg_t epc) // An unexpected trap - a trap when SDT is 1 - traps to M-mode if ((state.prv <= PRV_S && bit < max_xlen) && (((vsdeleg >> bit) & 1) || ((hsdeleg >> bit) & 1))) { - reg_t s = curr_virt ? state.nonvirtual_sstatus->read() : state.sstatus->read(); + // Trap is handled in VS-mode or HS-mode. Read the sstatus of the + // mode that will handle the trap based on the delegation control + reg_t s = (((vsdeleg >> bit) & 1)) ? state.sstatus->read() : + state.nonvirtual_sstatus->read(); supv_double_trap = get_field(s, MSTATUS_SDT); if (supv_double_trap) vsdeleg = hsdeleg = 0; } - if (state.prv <= PRV_S && bit < max_xlen && ((vsdeleg >> bit) & 1)) { + bool vti = false; + if (extension_enabled_const(EXT_SSAIA)) { + const reg_t hvictl = state.csrmap[CSR_HVICTL]->read(); + const reg_t iid = get_field(hvictl, HVICTL_IID); + // It is possible that hvictl is injecting VSEIP (10) and hvictl.DPR is causing mip.VSEIP to be picked over VTI. + // Check vstopi == hvictl.iid + vti = (hvictl & HVICTL_VTI) && iid != IRQ_S_EXT && iid == bit && get_field(state.vstopi->read(), MTOPI_IID) == iid; + } + if ((state.prv <= PRV_S && bit < max_xlen && ((vsdeleg >> bit) & 1)) || vti) { // Handle the trap in VS-mode - const reg_t adjusted_cause = interrupt ? bit - 1 : bit; // VSSIP -> SSIP, etc + const reg_t adjusted_cause = interrupt && bit <= IRQ_VS_EXT && !vti ? bit - 1 : bit; // VSSIP -> SSIP, etc; reg_t vector = (state.vstvec->read() & 1) && interrupt ? 4 * adjusted_cause : 0; state.pc = (state.vstvec->read() & ~(reg_t)1) + vector; state.vscause->write(adjusted_cause | (interrupt ? interrupt_bit : 0)); @@ -894,10 +497,23 @@ void processor_t::take_trap(trap_t& t, reg_t epc) // Handle the trap in M-mode const reg_t vector = (state.mtvec->read() & 1) && interrupt ? 4 * bit : 0; const reg_t trap_handler_address = (state.mtvec->read() & ~(reg_t)1) + vector; - // RNMI exception vector is implementation-defined. Since we don't model // RNMI sources, the feature isn't very useful, so pick an invalid address. + // RNMI exception vector is implementation-defined. Since we don't model const reg_t rnmi_trap_handler_address = 0; const bool nmie = !(state.mnstatus && !get_field(state.mnstatus->read(), MNSTATUS_NMIE)); + + reg_t s = state.mstatus->read(); + if ( extension_enabled(EXT_SMDBLTRP)) { + if (get_field(s, MSTATUS_MDT) || !nmie) { + // Critical error - Double trap in M-mode or trap when nmie is 0 + // RNMI is not modeled else double trap in M-mode would trap to + // RNMI handler instead of leading to a critical error + state.critical_error = 1; + return; + } + s = set_field(s, MSTATUS_MDT, 1); + } + state.pc = !nmie ? rnmi_trap_handler_address : trap_handler_address; state.mepc->write(epc); state.mcause->write(supv_double_trap ? CAUSE_DOUBLE_TRAP : t.cause()); @@ -905,7 +521,6 @@ void processor_t::take_trap(trap_t& t, reg_t epc) state.mtval2->write(supv_double_trap ? t.cause() : t.get_tval2()); state.mtinst->write(t.get_tinst()); - reg_t s = state.mstatus->read(); s = set_field(s, MSTATUS_MPIE, get_field(s, MSTATUS_MIE)); s = set_field(s, MSTATUS_MPP, state.prv); s = set_field(s, MSTATUS_MIE, 0); @@ -915,7 +530,7 @@ void processor_t::take_trap(trap_t& t, reg_t epc) state.elp = elp_t::NO_LP_EXPECTED; state.mstatus->write(s); if (state.mstatush) state.mstatush->write(s >> 32); // log mstatush change - state.tcontrol->write((state.tcontrol->read() & CSR_TCONTROL_MTE) ? CSR_TCONTROL_MPTE : 0); + if (state.tcontrol) state.tcontrol->write((state.tcontrol->read() & CSR_TCONTROL_MTE) ? CSR_TCONTROL_MPTE : 0); set_privilege(PRV_M, false); } } @@ -931,7 +546,7 @@ void processor_t::take_trigger_action(triggers::action_t action, reg_t breakpoin switch (action) { case triggers::ACTION_DEBUG_MODE: - enter_debug_mode(DCSR_CAUSE_HWBP); + enter_debug_mode(DCSR_CAUSE_HWBP, 0); break; case triggers::ACTION_DEBUG_EXCEPTION: { trap_breakpoint trap(virt, breakpoint_tval); @@ -1082,18 +697,17 @@ void processor_t::build_opcode_map() } void processor_t::register_extension(extension_t *x) { - for (auto insn : x->get_instructions()) + for (auto insn : x->get_instructions(*this)) register_custom_insn(insn); build_opcode_map(); - for (auto disasm_insn : x->get_disasms()) + for (auto disasm_insn : x->get_disasms(this)) disassembler->add_insn(disasm_insn); if (!custom_extensions.insert(std::make_pair(x->name(), x)).second) { fprintf(stderr, "extensions must have unique names (got two named \"%s\"!)\n", x->name()); abort(); } - x->set_processor(this); } void processor_t::register_base_instructions() @@ -1118,21 +732,27 @@ void processor_t::register_base_instructions() #include "insn_list.h" #undef DEFINE_INSN + #define DEFINE_INSN_UNCOND(name) { \ + insn_desc_t insn = { \ + name##_match, \ + name##_mask, \ + fast_rv32i_##name, \ + fast_rv64i_##name, \ + fast_rv32e_##name, \ + fast_rv64e_##name, \ + logged_rv32i_##name, \ + logged_rv64i_##name, \ + logged_rv32e_##name, \ + logged_rv64e_##name \ + }; \ + register_base_insn(insn); \ + } + // add overlapping instructions first, in order #define DECLARE_OVERLAP_INSN(name, ext) \ name##_overlapping = true; \ if (isa.extension_enabled(ext)) \ - register_base_insn((insn_desc_t) { \ - name##_match, \ - name##_mask, \ - fast_rv32i_##name, \ - fast_rv64i_##name, \ - fast_rv32e_##name, \ - fast_rv64e_##name, \ - logged_rv32i_##name, \ - logged_rv64i_##name, \ - logged_rv32e_##name, \ - logged_rv64e_##name}); + DEFINE_INSN_UNCOND(name); #include "overlap_list.h" #undef DECLARE_OVERLAP_INSN @@ -1141,19 +761,10 @@ void processor_t::register_base_instructions() // appear earlier to improve search time on opcode_cache misses. #define DEFINE_INSN(name) \ if (!name##_overlapping) \ - register_base_insn((insn_desc_t) { \ - name##_match, \ - name##_mask, \ - fast_rv32i_##name, \ - fast_rv64i_##name, \ - fast_rv32e_##name, \ - fast_rv64e_##name, \ - logged_rv32i_##name, \ - logged_rv64i_##name, \ - logged_rv32e_##name, \ - logged_rv64e_##name}); + DEFINE_INSN_UNCOND(name); #include "insn_list.h" #undef DEFINE_INSN + #undef DEFINE_INSN_UNCOND // terminate instruction list with a catch-all register_base_insn(insn_desc_t::illegal_instruction); @@ -1192,6 +803,11 @@ bool processor_t::store(reg_t addr, size_t len, const uint8_t* bytes) return false; } +reg_t processor_t::size() +{ + return PGSIZE; +} + void processor_t::trigger_updated(const std::vector<triggers::trigger_t *> &triggers) { mmu->flush_tlb(); |