fixes CSR/CLIC implementation
This commit is contained in:
parent
ec55efd322
commit
a83928fd8c
|
@ -114,7 +114,7 @@ enum riscv_csr {
|
||||||
mtval = 0x343,
|
mtval = 0x343,
|
||||||
mip = 0x344,
|
mip = 0x344,
|
||||||
mxnti = 0x345, //CLIC
|
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
|
mintthresh = 0x347, // MRW Interrupt-level threshold (CLIC) - addr subject to change
|
||||||
mscratchcsw = 0x348, // MRW Conditional scratch swap on priv mode change (CLIC)
|
mscratchcsw = 0x348, // MRW Conditional scratch swap on priv mode change (CLIC)
|
||||||
mscratchcswl = 0x349, // MRW Conditional scratch swap on level change (CLIC)
|
mscratchcswl = 0x349, // MRW Conditional scratch swap on level change (CLIC)
|
||||||
|
|
|
@ -212,9 +212,9 @@ public:
|
||||||
csr[addr & csr.page_addr_mask] = val;
|
csr[addr & csr.page_addr_mask] = val;
|
||||||
}
|
}
|
||||||
|
|
||||||
void set_irq_num(unsigned i) {
|
// void set_irq_num(unsigned i) {
|
||||||
mcause_max_irq=1<<util::ilog2(i);
|
// mcause_max_irq=1<<util::ilog2(i);
|
||||||
}
|
// }
|
||||||
protected:
|
protected:
|
||||||
struct riscv_instrumentation_if : public iss::instrumentation_if {
|
struct riscv_instrumentation_if : public iss::instrumentation_if {
|
||||||
|
|
||||||
|
@ -337,7 +337,7 @@ protected:
|
||||||
std::vector<std::function<mem_write_f>> memfn_write;
|
std::vector<std::function<mem_write_f>> memfn_write;
|
||||||
void insert_mem_range(uint64_t, uint64_t, std::function<mem_read_f>, std::function<mem_write_f>);
|
void insert_mem_range(uint64_t, uint64_t, std::function<mem_read_f>, std::function<mem_write_f>);
|
||||||
feature_config cfg;
|
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;}
|
inline bool debug_mode_active() {return this->reg.PRIV&0x4;}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -428,7 +428,6 @@ 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_int_reg.resize(cfg.clic_num_irq, clic_int_reg_t{.raw=0});
|
||||||
clic_cfg_reg=0x20;
|
clic_cfg_reg=0x20;
|
||||||
clic_info_reg = (/*CLICINTCTLBITS*/ 4U<<21) + cfg.clic_num_irq;
|
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,
|
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 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);});
|
[this](phys_addr_t addr, unsigned length, uint8_t const * const data) {return write_clic(addr.val, length, data);});
|
||||||
|
@ -850,7 +849,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>::read_tvec(unsigned addr, reg_t &val) {
|
template <typename BASE, features_e FEAT> iss::status riscv_hart_m_p<BASE, FEAT>::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;
|
return iss::Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -866,7 +865,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_cause(unsigned addr, reg_t val) {
|
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));
|
csr[addr] = val & ((1UL<<(traits<BASE>::XLEN-1)) | (mcause_max_irq-1));
|
||||||
return iss::Ok;
|
return iss::Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1111,7 +1110,7 @@ template <typename BASE, features_e FEAT> void riscv_hart_m_p<BASE, FEAT>::check
|
||||||
template <typename BASE, features_e FEAT> uint64_t riscv_hart_m_p<BASE, FEAT>::enter_trap(uint64_t flags, uint64_t addr, uint64_t instr) {
|
template <typename BASE, features_e FEAT> uint64_t riscv_hart_m_p<BASE, FEAT>::enter_trap(uint64_t flags, uint64_t addr, uint64_t instr) {
|
||||||
// flags are ACTIVE[31:31], CAUSE[30:16], TRAPID[15:0]
|
// flags are ACTIVE[31:31], CAUSE[30:16], TRAPID[15:0]
|
||||||
// calculate and write mcause val
|
// 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);
|
auto cause = bit_sub<16, 15>(flags);
|
||||||
// calculate effective privilege level
|
// calculate effective privilege level
|
||||||
unsigned new_priv = PRIV_M;
|
unsigned new_priv = PRIV_M;
|
||||||
|
@ -1167,11 +1166,19 @@ template <typename BASE, features_e FEAT> uint64_t riscv_hart_m_p<BASE, FEAT>::e
|
||||||
state.mstatus.MIE = false;
|
state.mstatus.MIE = false;
|
||||||
|
|
||||||
// get trap vector
|
// get trap vector
|
||||||
auto ivec = csr[mtvec];
|
auto xtvec = csr[mtvec];
|
||||||
// calculate addr// set NEXT_PC to trap addressess to jump to based on MODE
|
// calculate adds// set NEXT_PC to trap addressess to jump to based on MODE
|
||||||
// bits in mtvec
|
if((FEAT & features_e::FEAT_CLIC) && trap_id!=0 && (xtvec & 0x3UL)==3UL) {
|
||||||
this->reg.NEXT_PC = ivec & ~0x3UL;
|
reg_t data;
|
||||||
if ((ivec & 0x1) == 1 && trap_id != 0) this->reg.NEXT_PC += 4 * cause;
|
auto ret = read(address_type::LOGICAL, access_type::READ, 0, csr[mtvt], sizeof(reg_t), reinterpret_cast<uint8_t*>(&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
|
// reset trap state
|
||||||
this->reg.PRIV = new_priv;
|
this->reg.PRIV = new_priv;
|
||||||
this->trap_state = 0;
|
this->trap_state = 0;
|
||||||
|
|
|
@ -227,9 +227,9 @@ public:
|
||||||
csr[addr & csr.page_addr_mask] = val;
|
csr[addr & csr.page_addr_mask] = val;
|
||||||
}
|
}
|
||||||
|
|
||||||
void set_irq_num(unsigned i) {
|
// void set_irq_num(unsigned i) {
|
||||||
mcause_max_irq=1<<util::ilog2(i);
|
// mcause_max_irq=1<<util::ilog2(i);
|
||||||
}
|
// }
|
||||||
protected:
|
protected:
|
||||||
struct riscv_instrumentation_if : public iss::instrumentation_if {
|
struct riscv_instrumentation_if : public iss::instrumentation_if {
|
||||||
|
|
||||||
|
@ -355,7 +355,7 @@ protected:
|
||||||
std::vector<std::function<mem_write_f>> memfn_write;
|
std::vector<std::function<mem_write_f>> memfn_write;
|
||||||
void insert_mem_range(uint64_t, uint64_t, std::function<mem_read_f>, std::function<mem_write_f>);
|
void insert_mem_range(uint64_t, uint64_t, std::function<mem_read_f>, std::function<mem_write_f>);
|
||||||
feature_config cfg;
|
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;}
|
inline bool debug_mode_active() {return this->reg.PRIV&0x4;}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -475,7 +475,6 @@ 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_int_reg.resize(cfg.clic_num_irq, clic_int_reg_t{.raw=0});
|
||||||
clic_cfg_reg=0x20;
|
clic_cfg_reg=0x20;
|
||||||
clic_info_reg = (/*CLICINTCTLBITS*/ 4U<<21) + cfg.clic_num_irq;
|
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,
|
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 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);});
|
[this](phys_addr_t addr, unsigned length, uint8_t const * const data) {return write_clic(addr.val, length, data);});
|
||||||
|
@ -1001,7 +1000,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>::read_tvec(unsigned addr, reg_t &val) {
|
template <typename BASE, features_e FEAT> iss::status riscv_hart_mu_p<BASE, FEAT>::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;
|
return iss::Ok;
|
||||||
}
|
}
|
||||||
template <typename BASE, features_e FEAT> iss::status riscv_hart_mu_p<BASE, FEAT>::read_status(unsigned addr, reg_t &val) {
|
template <typename BASE, features_e FEAT> iss::status riscv_hart_mu_p<BASE, FEAT>::read_status(unsigned addr, reg_t &val) {
|
||||||
|
@ -1350,13 +1349,26 @@ template <typename BASE, features_e FEAT> uint64_t riscv_hart_mu_p<BASE, FEAT>::
|
||||||
}
|
}
|
||||||
|
|
||||||
// get trap vector
|
// 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
|
// calculate addr// set NEXT_PC to trap addressess to jump to based on MODE
|
||||||
// bits in mtvec
|
// bits in mtvec
|
||||||
this->reg.NEXT_PC = ivec & ~0x3UL;
|
if((FEAT & features_e::FEAT_CLIC) && trap_id!=0 && (xtvec & 0x3UL)==3UL) {
|
||||||
if ((ivec & 0x1) == 1 && trap_id != 0) this->reg.NEXT_PC += 4 * cause;
|
reg_t data;
|
||||||
|
auto ret = read(address_type::LOGICAL, access_type::READ, 0, csr[mtvt], sizeof(reg_t), reinterpret_cast<uint8_t*>(&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<char, 32> buffer;
|
std::array<char, 32> buffer;
|
||||||
|
#if defined(_MSC_VER)
|
||||||
|
sprintf(buffer.data(), "0x%016llx", addr);
|
||||||
|
#else
|
||||||
sprintf(buffer.data(), "0x%016lx", addr);
|
sprintf(buffer.data(), "0x%016lx", addr);
|
||||||
|
#endif
|
||||||
if((flags&0xffffffff) != 0xffffffff)
|
if((flags&0xffffffff) != 0xffffffff)
|
||||||
CLOG(INFO, disass) << (trap_id ? "Interrupt" : "Trap") << " with cause '"
|
CLOG(INFO, disass) << (trap_id ? "Interrupt" : "Trap") << " with cause '"
|
||||||
<< (trap_id ? irq_str[cause] : trap_str[cause]) << "' (" << cause << ")"
|
<< (trap_id ? irq_str[cause] : trap_str[cause]) << "' (" << cause << ")"
|
||||||
|
|
Loading…
Reference in New Issue