diff --git a/src/iss/arch/riscv_hart_common.h b/src/iss/arch/riscv_hart_common.h index 3e8eb83..704fc2f 100644 --- a/src/iss/arch/riscv_hart_common.h +++ b/src/iss/arch/riscv_hart_common.h @@ -114,7 +114,7 @@ enum riscv_csr { mtval = 0x343, mip = 0x344, mxnti = 0x345, //CLIC - mintstatus = 0x346, // MRW Current interrupt levels (CLIC) - addr subject to change + mintstatus = 0xFB1, // MRW Current interrupt levels (CLIC) - addr subject to change mintthresh = 0x347, // MRW Interrupt-level threshold (CLIC) - addr subject to change mscratchcsw = 0x348, // MRW Conditional scratch swap on priv mode change (CLIC) mscratchcswl = 0x349, // MRW Conditional scratch swap on level change (CLIC) diff --git a/src/iss/arch/riscv_hart_m_p.h b/src/iss/arch/riscv_hart_m_p.h index 101b096..5b0c92a 100644 --- a/src/iss/arch/riscv_hart_m_p.h +++ b/src/iss/arch/riscv_hart_m_p.h @@ -212,9 +212,9 @@ public: csr[addr & csr.page_addr_mask] = val; } - void set_irq_num(unsigned i) { - mcause_max_irq=1<> memfn_write; void insert_mem_range(uint64_t, uint64_t, std::function, std::function); feature_config cfg; - unsigned mcause_max_irq{16}; + unsigned mcause_max_irq{(FEAT&features_e::FEAT_CLIC)?4096:16}; inline bool debug_mode_active() {return this->reg.PRIV&0x4;} }; @@ -428,7 +428,6 @@ riscv_hart_m_p::riscv_hart_m_p(feature_config cfg) clic_int_reg.resize(cfg.clic_num_irq, clic_int_reg_t{.raw=0}); clic_cfg_reg=0x20; clic_info_reg = (/*CLICINTCTLBITS*/ 4U<<21) + cfg.clic_num_irq; - mcause_max_irq=cfg.clic_num_irq+16; insert_mem_range(cfg.clic_base, 0x5000UL, [this](phys_addr_t addr, unsigned length, uint8_t * const data) { return read_clic(addr.val, length, data);}, [this](phys_addr_t addr, unsigned length, uint8_t const * const data) {return write_clic(addr.val, length, data);}); @@ -850,7 +849,7 @@ template iss::status riscv_hart_m_p } template iss::status riscv_hart_m_p::read_tvec(unsigned addr, reg_t &val) { - val = csr[addr] & ~2; + val = FEAT & features_e::FEAT_CLIC? csr[addr] : csr[addr] & ~2; return iss::Ok; } @@ -866,7 +865,7 @@ template iss::status riscv_hart_m_p } template iss::status riscv_hart_m_p::write_cause(unsigned addr, reg_t val) { - csr[addr] = val & ((1UL<<(traits::XLEN-1))| (mcause_max_irq-1)); + csr[addr] = val & ((1UL<<(traits::XLEN-1)) | (mcause_max_irq-1)); return iss::Ok; } @@ -1111,7 +1110,7 @@ template void riscv_hart_m_p::check template uint64_t riscv_hart_m_p::enter_trap(uint64_t flags, uint64_t addr, uint64_t instr) { // flags are ACTIVE[31:31], CAUSE[30:16], TRAPID[15:0] // calculate and write mcause val - auto trap_id = bit_sub<0, 16>(flags); + auto const trap_id = bit_sub<0, 16>(flags); auto cause = bit_sub<16, 15>(flags); // calculate effective privilege level unsigned new_priv = PRIV_M; @@ -1167,11 +1166,19 @@ template uint64_t riscv_hart_m_p::e state.mstatus.MIE = false; // get trap vector - auto ivec = csr[mtvec]; - // calculate addr// set NEXT_PC to trap addressess to jump to based on MODE - // bits in mtvec - this->reg.NEXT_PC = ivec & ~0x3UL; - if ((ivec & 0x1) == 1 && trap_id != 0) this->reg.NEXT_PC += 4 * cause; + auto xtvec = csr[mtvec]; + // calculate adds// set NEXT_PC to trap addressess to jump to based on MODE + if((FEAT & features_e::FEAT_CLIC) && trap_id!=0 && (xtvec & 0x3UL)==3UL) { + reg_t data; + auto ret = read(address_type::LOGICAL, access_type::READ, 0, csr[mtvt], sizeof(reg_t), reinterpret_cast(&data)); + if(ret == iss::Err) + return this->reg.PC; + this->reg.NEXT_PC = data; + } else { + // bits in mtvec + this->reg.NEXT_PC = xtvec & ~0x3UL; + if ((xtvec & 0x1) == 1 && trap_id != 0) this->reg.NEXT_PC += 4 * cause; + } // reset trap state this->reg.PRIV = new_priv; this->trap_state = 0; diff --git a/src/iss/arch/riscv_hart_mu_p.h b/src/iss/arch/riscv_hart_mu_p.h index 45b932b..7cf099f 100644 --- a/src/iss/arch/riscv_hart_mu_p.h +++ b/src/iss/arch/riscv_hart_mu_p.h @@ -227,9 +227,9 @@ public: csr[addr & csr.page_addr_mask] = val; } - void set_irq_num(unsigned i) { - mcause_max_irq=1<> memfn_write; void insert_mem_range(uint64_t, uint64_t, std::function, std::function); feature_config cfg; - unsigned mcause_max_irq{16}; + unsigned mcause_max_irq{(FEAT&features_e::FEAT_CLIC)?4096:16}; inline bool debug_mode_active() {return this->reg.PRIV&0x4;} }; @@ -475,7 +475,6 @@ riscv_hart_mu_p::riscv_hart_mu_p(feature_config cfg) clic_int_reg.resize(cfg.clic_num_irq, clic_int_reg_t{.raw=0}); clic_cfg_reg=0x20; clic_info_reg = (/*CLICINTCTLBITS*/ 4U<<21) + cfg.clic_num_irq; - mcause_max_irq=cfg.clic_num_irq+16; insert_mem_range(cfg.clic_base, 0x5000UL, [this](phys_addr_t addr, unsigned length, uint8_t * const data) { return read_clic(addr.val, length, data);}, [this](phys_addr_t addr, unsigned length, uint8_t const * const data) {return write_clic(addr.val, length, data);}); @@ -1001,7 +1000,7 @@ template iss::status riscv_hart_mu_p iss::status riscv_hart_mu_p::read_tvec(unsigned addr, reg_t &val) { - val = csr[addr] & ~2; + val = FEAT & features_e::FEAT_CLIC? csr[addr] : csr[addr] & ~2; return iss::Ok; } template iss::status riscv_hart_mu_p::read_status(unsigned addr, reg_t &val) { @@ -1350,13 +1349,26 @@ template uint64_t riscv_hart_mu_p:: } // get trap vector - auto ivec = csr[utvec | (new_priv << 8)]; + auto xtvec = csr[utvec | (new_priv << 8)]; // calculate addr// set NEXT_PC to trap addressess to jump to based on MODE // bits in mtvec - this->reg.NEXT_PC = ivec & ~0x3UL; - if ((ivec & 0x1) == 1 && trap_id != 0) this->reg.NEXT_PC += 4 * cause; + if((FEAT & features_e::FEAT_CLIC) && trap_id!=0 && (xtvec & 0x3UL)==3UL) { + reg_t data; + auto ret = read(address_type::LOGICAL, access_type::READ, 0, csr[mtvt], sizeof(reg_t), reinterpret_cast(&data)); + if(ret == iss::Err) + return this->reg.PC; + this->reg.NEXT_PC = data; + } else { + this->reg.NEXT_PC = xtvec & ~0x3UL; + if ((xtvec & 0x1) == 1 && trap_id != 0) + this->reg.NEXT_PC += 4 * cause; + } std::array buffer; +#if defined(_MSC_VER) + sprintf(buffer.data(), "0x%016llx", addr); +#else sprintf(buffer.data(), "0x%016lx", addr); +#endif if((flags&0xffffffff) != 0xffffffff) CLOG(INFO, disass) << (trap_id ? "Interrupt" : "Trap") << " with cause '" << (trap_id ? irq_str[cause] : trap_str[cause]) << "' (" << cause << ")"