diff --git a/src/iss/arch/riscv_hart_common.h b/src/iss/arch/riscv_hart_common.h index 4bb2f43..45fc000 100644 --- a/src/iss/arch/riscv_hart_common.h +++ b/src/iss/arch/riscv_hart_common.h @@ -221,6 +221,7 @@ struct vm_info { struct feature_config { uint64_t clic_base{0xc0000000}; + unsigned clic_int_ctl_bits{4}; unsigned clic_num_irq{16}; unsigned clic_num_trigger{0}; uint64_t tcm_base{0x10000000}; diff --git a/src/iss/arch/riscv_hart_m_p.h b/src/iss/arch/riscv_hart_m_p.h index 36aec51..9273cab 100644 --- a/src/iss/arch/riscv_hart_m_p.h +++ b/src/iss/arch/riscv_hart_m_p.h @@ -289,6 +289,8 @@ protected: uint32_t raw; }; std::vector clic_int_reg; + uint8_t clic_mprev_lvl{0}; + uint8_t clic_mact_lvl{0}; std::vector tcm; @@ -430,6 +432,8 @@ 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; + clic_mact_lvl = clic_mprev_lvl = (1<<(cfg.clic_int_ctl_bits)) - 1; + csr[mintthresh] = (1<<(cfg.clic_int_ctl_bits)) - 1; 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);}); @@ -869,18 +873,26 @@ template iss::status riscv_hart_m_p template iss::status riscv_hart_m_p::read_cause(unsigned addr, reg_t &val) { auto res = csr[addr]; if((FEAT & features_e::FEAT_CLIC) && (csr[mtvec]&0x3)==3) { - res |= state.mstatus.MPIE<<27; - res |= state.mstatus.MPP<<28; - } - val=res; + val = csr[addr] & ((1UL<<(traits::XLEN-1)) | (mcause_max_irq-1) | (0xfUL<<16)); + val |= clic_mprev_lvl<<16; + val |= state.mstatus.MPIE<<27; + val |= state.mstatus.MPP<<28; + } else + val = csr[addr] & ((1UL<<(traits::XLEN-1)) | (mcause_max_irq-1)); return iss::Ok; } 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)); if((FEAT & features_e::FEAT_CLIC) && (csr[mtvec]&0x3)==3) { + auto mask = ((1UL<<(traits::XLEN-1)) | (mcause_max_irq-1) | (0xfUL<<16)); + csr[addr] = (val & mask) | (csr[addr] & ~mask); + clic_mprev_lvl = ((val>>16)&0xff) | (1<<(8-cfg. clic_int_ctl_bits)) - 1; state.mstatus.MPIE=(val>>27)&0x1; state.mstatus.MPP=(val>>28)&0x3; + } else { + auto mask = ((1UL<<(traits::XLEN-1)) | (mcause_max_irq-1)); + csr[addr] = (val & mask) | (csr[addr] & ~mask); } return iss::Ok; } @@ -955,7 +967,7 @@ template iss::status riscv_hart_m_p template iss::status riscv_hart_m_p::write_intthresh(unsigned addr, reg_t val) { - csr[addr]= val &0xff; + csr[addr]= (val &0xff) | (1<<(cfg.clic_int_ctl_bits)) - 1; return iss::Ok; } @@ -1107,6 +1119,7 @@ template inline void riscv_hart_m_p } template void riscv_hart_m_p::check_interrupt() { + //TODO: Implement CLIC functionality //auto ideleg = csr[mideleg]; // Multiple simultaneous interrupts and traps at the same privilege level are // handled in the following decreasing priority order: diff --git a/src/iss/arch/riscv_hart_mu_p.h b/src/iss/arch/riscv_hart_mu_p.h index ac2e6b7..1459f7c 100644 --- a/src/iss/arch/riscv_hart_mu_p.h +++ b/src/iss/arch/riscv_hart_mu_p.h @@ -304,6 +304,8 @@ protected: uint32_t raw; }; std::vector clic_int_reg; + uint8_t clic_mprev_lvl{0}, clic_uprev_lvl{0}; + uint8_t clic_mact_lvl{0}, clic_uact_lvl{0}; std::vector tcm; @@ -486,6 +488,10 @@ 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=0x30; clic_info_reg = (/*CLICINTCTLBITS*/ 4U<<21) + cfg.clic_num_irq; + clic_mact_lvl = clic_mprev_lvl = (1<<(cfg.clic_int_ctl_bits)) - 1; + clic_uact_lvl = clic_uprev_lvl = (1<<(cfg.clic_int_ctl_bits)) - 1; + csr[mintthresh] = (1<<(cfg.clic_int_ctl_bits)) - 1; + csr[uintthresh] = (1<<(cfg.clic_int_ctl_bits)) - 1; 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);}); @@ -715,7 +721,7 @@ iss::status riscv_hart_mu_p::read(const address_type type, const acc return iss::Err; } try { - if(!is_debug(access) && (addr&(alignment-1))){ + if(!is_debug(access) && (addr&(alignment-1))){ this->trap_state = (1UL << 31) | 4<<16; fault_data=addr; return iss::Err; @@ -1026,36 +1032,44 @@ template iss::status riscv_hart_mu_p iss::status riscv_hart_mu_p::read_cause(unsigned addr, reg_t &val) { - auto res = csr[addr]; if((FEAT & features_e::FEAT_CLIC) && (csr[mtvec]&0x3)==3) { + val = csr[addr] & ((1UL<<(traits::XLEN-1)) | (mcause_max_irq-1) | (0xfUL<<16)); auto mode = (addr >> 8) & 0x3; switch(mode) { case 0: - res |= state.mstatus.UPIE<<27; + val |= clic_uprev_lvl<<16; + val |= state.mstatus.UPIE<<27; break; default: - res |= state.mstatus.MPIE<<27; - res |= state.mstatus.MPP<<28; + val |= clic_mprev_lvl<<16; + val |= state.mstatus.MPIE<<27; + val |= state.mstatus.MPP<<28; break; } - } - val=res; + } else + val = csr[addr] & ((1UL<<(traits::XLEN-1)) | (mcause_max_irq-1)); return iss::Ok; } template iss::status riscv_hart_mu_p::write_cause(unsigned addr, reg_t val) { - csr[addr] = val & ((1UL<<(traits::XLEN-1))|(mcause_max_irq-1)); if((FEAT & features_e::FEAT_CLIC) && (csr[mtvec]&0x3)==3) { + auto mask = ((1UL<<(traits::XLEN-1)) | (mcause_max_irq-1) | (0xfUL<<16)); + csr[addr] = (val & mask) | (csr[addr] & ~mask); auto mode = (addr >> 8) & 0x3; switch(mode) { case 0: + clic_uprev_lvl = ((val>>16)&0xff) | (1<<(8-cfg. clic_int_ctl_bits)) - 1; state.mstatus.UPIE=(val>>27)&0x1; break; default: + clic_mprev_lvl = ((val>>16)&0xff) | (1<<(8-cfg. clic_int_ctl_bits)) - 1; state.mstatus.MPIE=(val>>27)&0x1; state.mstatus.MPP=(val>>28)&0x3; break; } + } else { + auto mask = ((1UL<<(traits::XLEN-1)) | (mcause_max_irq-1)); + csr[addr] = (val & mask) | (csr[addr] & ~mask); } return iss::Ok; } @@ -1146,7 +1160,7 @@ template iss::status riscv_hart_mu_p iss::status riscv_hart_mu_p::write_intthresh(unsigned addr, reg_t val) { - csr[addr]= val &0xff; + csr[addr]= (val &0xff) | (1<<(cfg.clic_int_ctl_bits)) - 1; return iss::Ok; } @@ -1298,6 +1312,7 @@ template inline void riscv_hart_mu_p void riscv_hart_mu_p::check_interrupt() { + //TODO: Implement CLIC functionality auto ideleg = csr[mideleg]; // Multiple simultaneous interrupts and traps at the same privilege level are // handled in the following decreasing priority order: