implements and fixes CLIC CSR behavior
This commit is contained in:
parent
a943dd3bdf
commit
39b2788b7e
|
@ -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};
|
||||
|
|
|
@ -289,6 +289,8 @@ protected:
|
|||
uint32_t raw;
|
||||
};
|
||||
std::vector<clic_int_reg_t> clic_int_reg;
|
||||
uint8_t clic_mprev_lvl{0};
|
||||
uint8_t clic_mact_lvl{0};
|
||||
|
||||
std::vector<uint8_t> tcm;
|
||||
|
||||
|
@ -430,6 +432,8 @@ riscv_hart_m_p<BASE, FEAT>::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 <typename BASE, features_e FEAT> iss::status riscv_hart_m_p<BASE, FEAT>
|
|||
template <typename BASE, features_e FEAT> iss::status riscv_hart_m_p<BASE, FEAT>::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<BASE>::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<BASE>::XLEN-1)) | (mcause_max_irq-1));
|
||||
return iss::Ok;
|
||||
}
|
||||
|
||||
template <typename BASE, features_e FEAT> iss::status riscv_hart_m_p<BASE, FEAT>::write_cause(unsigned addr, reg_t val) {
|
||||
csr[addr] = val & ((1UL<<(traits<BASE>::XLEN-1)) | (mcause_max_irq-1));
|
||||
if((FEAT & features_e::FEAT_CLIC) && (csr[mtvec]&0x3)==3) {
|
||||
auto mask = ((1UL<<(traits<BASE>::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<BASE>::XLEN-1)) | (mcause_max_irq-1));
|
||||
csr[addr] = (val & mask) | (csr[addr] & ~mask);
|
||||
}
|
||||
return iss::Ok;
|
||||
}
|
||||
|
@ -955,7 +967,7 @@ template <typename BASE, features_e FEAT> iss::status riscv_hart_m_p<BASE, FEAT>
|
|||
|
||||
template<typename BASE, features_e FEAT>
|
||||
iss::status riscv_hart_m_p<BASE, FEAT>::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 <typename BASE, features_e FEAT> inline void riscv_hart_m_p<BASE, FEAT>
|
|||
}
|
||||
|
||||
template <typename BASE, features_e FEAT> void riscv_hart_m_p<BASE, FEAT>::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:
|
||||
|
|
|
@ -304,6 +304,8 @@ protected:
|
|||
uint32_t raw;
|
||||
};
|
||||
std::vector<clic_int_reg_t> 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<uint8_t> tcm;
|
||||
|
||||
|
@ -486,6 +488,10 @@ riscv_hart_mu_p<BASE, FEAT>::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<BASE, FEAT>::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 <typename BASE, features_e FEAT> iss::status riscv_hart_mu_p<BASE, FEAT
|
|||
}
|
||||
|
||||
template <typename BASE, features_e FEAT> iss::status riscv_hart_mu_p<BASE, FEAT>::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<BASE>::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<BASE>::XLEN-1)) | (mcause_max_irq-1));
|
||||
return iss::Ok;
|
||||
}
|
||||
|
||||
template <typename BASE, features_e FEAT> iss::status riscv_hart_mu_p<BASE, FEAT>::write_cause(unsigned addr, reg_t val) {
|
||||
csr[addr] = val & ((1UL<<(traits<BASE>::XLEN-1))|(mcause_max_irq-1));
|
||||
if((FEAT & features_e::FEAT_CLIC) && (csr[mtvec]&0x3)==3) {
|
||||
auto mask = ((1UL<<(traits<BASE>::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<BASE>::XLEN-1)) | (mcause_max_irq-1));
|
||||
csr[addr] = (val & mask) | (csr[addr] & ~mask);
|
||||
}
|
||||
return iss::Ok;
|
||||
}
|
||||
|
@ -1146,7 +1160,7 @@ template <typename BASE, features_e FEAT> iss::status riscv_hart_mu_p<BASE, FEAT
|
|||
|
||||
template<typename BASE, features_e FEAT>
|
||||
iss::status riscv_hart_mu_p<BASE, FEAT>::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 <typename BASE, features_e FEAT> inline void riscv_hart_mu_p<BASE, FEAT
|
|||
}
|
||||
|
||||
template <typename BASE, features_e FEAT> void riscv_hart_mu_p<BASE, FEAT>::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:
|
||||
|
|
Loading…
Reference in New Issue