cleans up priv wrappers
This commit is contained in:
parent
b20fd3eba5
commit
a977200284
|
@ -182,7 +182,7 @@ public:
|
||||||
return traits<BASE>::MISA_VAL&0b0100?~1:~3;
|
return traits<BASE>::MISA_VAL&0b0100?~1:~3;
|
||||||
}
|
}
|
||||||
|
|
||||||
riscv_hart_m_p();
|
riscv_hart_m_p(feature_config cfg = feature_config{});
|
||||||
virtual ~riscv_hart_m_p() = default;
|
virtual ~riscv_hart_m_p() = default;
|
||||||
|
|
||||||
void reset(uint64_t address) override;
|
void reset(uint64_t address) override;
|
||||||
|
@ -194,9 +194,9 @@ public:
|
||||||
iss::status write(const address_type type, const access_type access, const uint32_t space,
|
iss::status write(const address_type type, const access_type access, const uint32_t space,
|
||||||
const uint64_t addr, const unsigned length, const uint8_t *const data) override;
|
const uint64_t addr, const unsigned length, const uint8_t *const data) override;
|
||||||
|
|
||||||
virtual uint64_t enter_trap(uint64_t flags) override { return riscv_hart_m_p::enter_trap(flags, fault_data, fault_data); }
|
uint64_t enter_trap(uint64_t flags) override { return riscv_hart_m_p::enter_trap(flags, fault_data, fault_data); }
|
||||||
virtual uint64_t enter_trap(uint64_t flags, uint64_t addr, uint64_t instr) override;
|
uint64_t enter_trap(uint64_t flags, uint64_t addr, uint64_t instr) override;
|
||||||
virtual uint64_t leave_trap(uint64_t flags) override;
|
uint64_t leave_trap(uint64_t flags) override;
|
||||||
|
|
||||||
const reg_t& get_mhartid() const { return mhartid_reg; }
|
const reg_t& get_mhartid() const { return mhartid_reg; }
|
||||||
void set_mhartid(reg_t mhartid) { mhartid_reg = mhartid; };
|
void set_mhartid(reg_t mhartid) { mhartid_reg = mhartid; };
|
||||||
|
@ -208,14 +208,6 @@ public:
|
||||||
|
|
||||||
iss::instrumentation_if *get_instrumentation_if() override { return &instr_if; }
|
iss::instrumentation_if *get_instrumentation_if() override { return &instr_if; }
|
||||||
|
|
||||||
void setMemReadCb(std::function<iss::status(phys_addr_t, unsigned, uint8_t* const)> const& memReadCb) {
|
|
||||||
mem_read_cb = memReadCb;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setMemWriteCb(std::function<iss::status(phys_addr_t, unsigned, const uint8_t* const)> const& memWriteCb) {
|
|
||||||
mem_write_cb = memWriteCb;
|
|
||||||
}
|
|
||||||
|
|
||||||
void set_csr(unsigned addr, reg_t val){
|
void set_csr(unsigned addr, reg_t val){
|
||||||
csr[addr & csr.page_addr_mask] = val;
|
csr[addr & csr.page_addr_mask] = val;
|
||||||
}
|
}
|
||||||
|
@ -337,8 +329,6 @@ protected:
|
||||||
}
|
}
|
||||||
|
|
||||||
reg_t mhartid_reg{0x0};
|
reg_t mhartid_reg{0x0};
|
||||||
std::function<iss::status(phys_addr_t, unsigned, uint8_t *const)>mem_read_cb;
|
|
||||||
std::function<iss::status(phys_addr_t, unsigned, const uint8_t *const)> mem_write_cb;
|
|
||||||
|
|
||||||
void check_interrupt();
|
void check_interrupt();
|
||||||
bool pmp_check(const access_type type, const uint64_t addr, const unsigned len);
|
bool pmp_check(const access_type type, const uint64_t addr, const unsigned len);
|
||||||
|
@ -346,23 +336,22 @@ protected:
|
||||||
std::vector<std::function<mem_read_f>> memfn_read;
|
std::vector<std::function<mem_read_f>> memfn_read;
|
||||||
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>);
|
||||||
uint64_t clic_base_addr{0};
|
feature_config cfg;
|
||||||
unsigned clic_num_irq{0};
|
|
||||||
unsigned clic_num_trigger{0};
|
|
||||||
unsigned mcause_max_irq{16};
|
unsigned mcause_max_irq{16};
|
||||||
inline bool debug_mode_active() {return this->reg.PRIV&0x4;}
|
inline bool debug_mode_active() {return this->reg.PRIV&0x4;}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename BASE, features_e FEAT>
|
template <typename BASE, features_e FEAT>
|
||||||
riscv_hart_m_p<BASE, FEAT>::riscv_hart_m_p()
|
riscv_hart_m_p<BASE, FEAT>::riscv_hart_m_p(feature_config cfg)
|
||||||
: state()
|
: state()
|
||||||
, instr_if(*this) {
|
, instr_if(*this)
|
||||||
|
, cfg(cfg) {
|
||||||
// reset values
|
// reset values
|
||||||
csr[misa] = traits<BASE>::MISA_VAL;
|
csr[misa] = traits<BASE>::MISA_VAL;
|
||||||
csr[mvendorid] = 0x669;
|
csr[mvendorid] = 0x669;
|
||||||
csr[marchid] = traits<BASE>::MARCHID_VAL;
|
csr[marchid] = traits<BASE>::MARCHID_VAL;
|
||||||
csr[mimpid] = 1;
|
csr[mimpid] = 1;
|
||||||
csr[mclicbase] = 0xc0000000; // TODO: should be taken from YAML file
|
csr[mclicbase] = cfg.clic_base; // TODO: should be taken from YAML file
|
||||||
|
|
||||||
uart_buf.str("");
|
uart_buf.str("");
|
||||||
for (unsigned addr = mhpmcounter3; addr <= mhpmcounter31; ++addr){
|
for (unsigned addr = mhpmcounter3; addr <= mhpmcounter31; ++addr){
|
||||||
|
@ -385,7 +374,10 @@ riscv_hart_m_p<BASE, FEAT>::riscv_hart_m_p()
|
||||||
//csr_wr_cb[addr] = &this_class::write_csr_reg;
|
//csr_wr_cb[addr] = &this_class::write_csr_reg;
|
||||||
}
|
}
|
||||||
// common regs
|
// common regs
|
||||||
const std::array<unsigned, 10> addrs{{misa, mvendorid, marchid, mimpid, mepc, mtvec, mscratch, mcause, mtval, mscratch}};
|
const std::array<unsigned, 9> addrs{{
|
||||||
|
misa, mvendorid, marchid, mimpid,
|
||||||
|
mepc, mtvec, mscratch, mcause, mtval
|
||||||
|
}};
|
||||||
for(auto addr: addrs) {
|
for(auto addr: addrs) {
|
||||||
csr_rd_cb[addr] = &this_class::read_csr_reg;
|
csr_rd_cb[addr] = &this_class::read_csr_reg;
|
||||||
csr_wr_cb[addr] = &this_class::write_csr_reg;
|
csr_wr_cb[addr] = &this_class::write_csr_reg;
|
||||||
|
@ -416,6 +408,8 @@ riscv_hart_m_p<BASE, FEAT>::riscv_hart_m_p()
|
||||||
csr_rd_cb[mie] = &this_class::read_ie;
|
csr_rd_cb[mie] = &this_class::read_ie;
|
||||||
csr_wr_cb[mie] = &this_class::write_ie;
|
csr_wr_cb[mie] = &this_class::write_ie;
|
||||||
csr_rd_cb[mhartid] = &this_class::read_hartid;
|
csr_rd_cb[mhartid] = &this_class::read_hartid;
|
||||||
|
csr_rd_cb[mcounteren] = &this_class::read_null;
|
||||||
|
csr_wr_cb[mcounteren] = &this_class::write_null;
|
||||||
csr_wr_cb[misa] = &this_class::write_null;
|
csr_wr_cb[misa] = &this_class::write_null;
|
||||||
csr_wr_cb[mvendorid] = &this_class::write_null;
|
csr_wr_cb[mvendorid] = &this_class::write_null;
|
||||||
csr_wr_cb[marchid] = &this_class::write_null;
|
csr_wr_cb[marchid] = &this_class::write_null;
|
||||||
|
@ -436,29 +430,27 @@ riscv_hart_m_p<BASE, FEAT>::riscv_hart_m_p()
|
||||||
csr_rd_cb[mclicbase] = &this_class::read_csr_reg;
|
csr_rd_cb[mclicbase] = &this_class::read_csr_reg;
|
||||||
csr_wr_cb[mclicbase] = &this_class::write_null;
|
csr_wr_cb[mclicbase] = &this_class::write_null;
|
||||||
|
|
||||||
clic_base_addr=0xC0000000;
|
clic_int_reg.resize(cfg.clic_num_irq, clic_int_reg_t{.raw=0});
|
||||||
clic_num_irq=16;
|
|
||||||
clic_int_reg.resize(clic_num_irq);
|
|
||||||
clic_cfg_reg=0x20;
|
clic_cfg_reg=0x20;
|
||||||
clic_info_reg = (/*CLICINTCTLBITS*/ 4U<<21) + clic_num_irq;
|
clic_info_reg = (/*CLICINTCTLBITS*/ 4U<<21) + cfg.clic_num_irq;
|
||||||
mcause_max_irq=clic_num_irq+16;
|
mcause_max_irq=cfg.clic_num_irq+16;
|
||||||
insert_mem_range(clic_base_addr, 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);});
|
||||||
}
|
}
|
||||||
if(FEAT & FEAT_TCM) {
|
if(FEAT & FEAT_TCM) {
|
||||||
tcm.resize(0x8000);
|
tcm.resize(cfg.tcm_size);
|
||||||
std::function<mem_read_f> read_clic_cb = [this](phys_addr_t addr, unsigned length, uint8_t * const data) {
|
std::function<mem_read_f> read_clic_cb = [this](phys_addr_t addr, unsigned length, uint8_t * const data) {
|
||||||
auto offset=addr.val-0x10000000;
|
auto offset=addr.val-this->cfg.tcm_base;
|
||||||
std::copy(tcm.data() + offset, tcm.data() + offset + length, data);
|
std::copy(tcm.data() + offset, tcm.data() + offset + length, data);
|
||||||
return iss::Ok;
|
return iss::Ok;
|
||||||
};
|
};
|
||||||
std::function<mem_write_f> write_clic_cb = [this](phys_addr_t addr, unsigned length, uint8_t const * const data) {
|
std::function<mem_write_f> write_clic_cb = [this](phys_addr_t addr, unsigned length, uint8_t const * const data) {
|
||||||
auto offset=addr.val-0x10000000;
|
auto offset=addr.val-this->cfg.tcm_base;
|
||||||
std::copy(data, data + length, tcm.data() + offset);
|
std::copy(data, data + length, tcm.data() + offset);
|
||||||
return iss::Ok;
|
return iss::Ok;
|
||||||
};
|
};
|
||||||
insert_mem_range(0x10000000, 0x8000UL, read_clic_cb, write_clic_cb);
|
insert_mem_range(cfg.tcm_base, cfg.tcm_size, read_clic_cb, write_clic_cb);
|
||||||
}
|
}
|
||||||
if(FEAT & FEAT_DEBUG){
|
if(FEAT & FEAT_DEBUG){
|
||||||
csr_wr_cb[dscratch0] = &this_class::write_dcsr_reg;
|
csr_wr_cb[dscratch0] = &this_class::write_dcsr_reg;
|
||||||
|
@ -582,7 +574,7 @@ iss::status riscv_hart_m_p<BASE, FEAT>::read(const address_type type, const acce
|
||||||
}
|
}
|
||||||
auto phys_addr = type==iss::address_type::PHYSICAL?phys_addr_t{access, space, addr}:BASE::v2p(iss::addr_t{access, type, space, addr});
|
auto phys_addr = type==iss::address_type::PHYSICAL?phys_addr_t{access, space, addr}:BASE::v2p(iss::addr_t{access, type, space, addr});
|
||||||
auto res = iss::Err;
|
auto res = iss::Err;
|
||||||
if(!is_fetch(access) && memfn_range.size()){
|
if(access != access_type::FETCH && memfn_range.size()){
|
||||||
auto it = std::find_if(std::begin(memfn_range), std::end(memfn_range), [phys_addr](std::tuple<uint64_t, uint64_t> const& a){
|
auto it = std::find_if(std::begin(memfn_range), std::end(memfn_range), [phys_addr](std::tuple<uint64_t, uint64_t> const& a){
|
||||||
return std::get<0>(a)<=phys_addr.val && (std::get<0>(a)+std::get<1>(a))>phys_addr.val;
|
return std::get<0>(a)<=phys_addr.val && (std::get<0>(a)+std::get<1>(a))>phys_addr.val;
|
||||||
});
|
});
|
||||||
|
@ -863,7 +855,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[mtvec] & ~2;
|
val = csr[addr] & ~2;
|
||||||
return iss::Ok;
|
return iss::Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -879,7 +871,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[mcause] = 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -959,7 +951,6 @@ iss::status riscv_hart_m_p<BASE, FEAT>::write_intthresh(unsigned addr, reg_t val
|
||||||
|
|
||||||
template <typename BASE, features_e FEAT>
|
template <typename BASE, features_e FEAT>
|
||||||
iss::status riscv_hart_m_p<BASE, FEAT>::read_mem(phys_addr_t paddr, unsigned length, uint8_t *const data) {
|
iss::status riscv_hart_m_p<BASE, FEAT>::read_mem(phys_addr_t paddr, unsigned length, uint8_t *const data) {
|
||||||
if(mem_read_cb) return mem_read_cb(paddr, length, data);
|
|
||||||
switch (paddr.val) {
|
switch (paddr.val) {
|
||||||
case 0x0200BFF8: { // CLINT base, mtime reg
|
case 0x0200BFF8: { // CLINT base, mtime reg
|
||||||
if (sizeof(reg_t) < length) return iss::Err;
|
if (sizeof(reg_t) < length) return iss::Err;
|
||||||
|
@ -984,14 +975,12 @@ iss::status riscv_hart_m_p<BASE, FEAT>::read_mem(phys_addr_t paddr, unsigned len
|
||||||
|
|
||||||
template <typename BASE, features_e FEAT>
|
template <typename BASE, features_e FEAT>
|
||||||
iss::status riscv_hart_m_p<BASE, FEAT>::write_mem(phys_addr_t paddr, unsigned length, const uint8_t *const data) {
|
iss::status riscv_hart_m_p<BASE, FEAT>::write_mem(phys_addr_t paddr, unsigned length, const uint8_t *const data) {
|
||||||
if(mem_write_cb) return mem_write_cb(paddr, length, data);
|
|
||||||
switch (paddr.val) {
|
switch (paddr.val) {
|
||||||
case 0x10013000: // UART0 base, TXFIFO reg
|
case 0x10013000: // UART0 base, TXFIFO reg
|
||||||
case 0x10023000: // UART1 base, TXFIFO reg
|
case 0x10023000: // UART1 base, TXFIFO reg
|
||||||
uart_buf << (char)data[0];
|
uart_buf << (char)data[0];
|
||||||
if (((char)data[0]) == '\n' || data[0] == 0) {
|
if (((char)data[0]) == '\n' || data[0] == 0) {
|
||||||
// LOG(INFO)<<"UART"<<((paddr.val>>16)&0x3)<<" send
|
LOG(INFO)<<"UART"<<((paddr.val>>16)&0x3)<<" send '"<<uart_buf.str()<<"'";
|
||||||
// '"<<uart_buf.str()<<"'";
|
|
||||||
std::cout << uart_buf.str();
|
std::cout << uart_buf.str();
|
||||||
uart_buf.str("");
|
uart_buf.str("");
|
||||||
}
|
}
|
||||||
|
@ -1062,15 +1051,15 @@ iss::status riscv_hart_m_p<BASE, FEAT>::write_mem(phys_addr_t paddr, unsigned le
|
||||||
|
|
||||||
template<typename BASE, features_e FEAT>
|
template<typename BASE, features_e FEAT>
|
||||||
iss::status riscv_hart_m_p<BASE, FEAT>::read_clic(uint64_t addr, unsigned length, uint8_t *const data) {
|
iss::status riscv_hart_m_p<BASE, FEAT>::read_clic(uint64_t addr, unsigned length, uint8_t *const data) {
|
||||||
if(addr==clic_base_addr) { // cliccfg
|
if(addr==cfg.clic_base) { // cliccfg
|
||||||
*data=clic_cfg_reg;
|
*data=clic_cfg_reg;
|
||||||
for(auto i=1; i<length; ++i) *(data+i)=0;
|
for(auto i=1; i<length; ++i) *(data+i)=0;
|
||||||
} else if(addr>=(clic_base_addr+4) && (addr+length)<=(clic_base_addr+8)){ // clicinfo
|
} else if(addr>=(cfg.clic_base+4) && (addr+length)<=(cfg.clic_base+8)){ // clicinfo
|
||||||
read_reg_uint32(addr, clic_info_reg, data, length);
|
read_reg_uint32(addr, clic_info_reg, data, length);
|
||||||
} else if(addr>=(clic_base_addr+0x40) && (addr+length)<=(clic_base_addr+0x40+clic_num_trigger*4)){ // clicinttrig
|
} else if(addr>=(cfg.clic_base+0x40) && (addr+length)<=(cfg.clic_base+0x40+cfg.clic_num_trigger*4)){ // clicinttrig
|
||||||
auto offset = ((addr&0x7fff)-0x40)/4;
|
auto offset = ((addr&0x7fff)-0x40)/4;
|
||||||
read_reg_uint32(addr, clic_inttrig_reg[offset], data, length);
|
read_reg_uint32(addr, clic_inttrig_reg[offset], data, length);
|
||||||
} else if(addr>=(clic_base_addr+0x1000) && (addr+length)<=(clic_base_addr+clic_num_irq*4)){ // clicintip/clicintie/clicintattr/clicintctl
|
} else if(addr>=(cfg.clic_base+0x1000) && (addr+length)<=(cfg.clic_base+0x1000+cfg.clic_num_irq*4)){ // clicintip/clicintie/clicintattr/clicintctl
|
||||||
auto offset = ((addr&0x7fff)-0x1000)/4;
|
auto offset = ((addr&0x7fff)-0x1000)/4;
|
||||||
read_reg_uint32(addr, clic_int_reg[offset].raw, data, length);
|
read_reg_uint32(addr, clic_int_reg[offset].raw, data, length);
|
||||||
} else {
|
} else {
|
||||||
|
@ -1081,17 +1070,18 @@ iss::status riscv_hart_m_p<BASE, FEAT>::read_clic(uint64_t addr, unsigned length
|
||||||
|
|
||||||
template<typename BASE, features_e FEAT>
|
template<typename BASE, features_e FEAT>
|
||||||
iss::status riscv_hart_m_p<BASE, FEAT>::write_clic(uint64_t addr, unsigned length, const uint8_t *const data) {
|
iss::status riscv_hart_m_p<BASE, FEAT>::write_clic(uint64_t addr, unsigned length, const uint8_t *const data) {
|
||||||
if(addr==clic_base_addr) { // cliccfg
|
if(addr==cfg.clic_base) { // cliccfg
|
||||||
clic_cfg_reg = *data;
|
clic_cfg_reg = *data;
|
||||||
clic_cfg_reg&= 0x7e;
|
clic_cfg_reg&= 0x7e;
|
||||||
// } else if(addr>=(clic_base_addr+4) && (addr+length)<=(clic_base_addr+4)){ // clicinfo
|
// } else if(addr>=(cfg.clic_base+4) && (addr+length)<=(cfg.clic_base+4)){ // clicinfo
|
||||||
// write_uint32(addr, clic_info_reg, data, length);
|
// write_uint32(addr, clic_info_reg, data, length);
|
||||||
} else if(addr>=(clic_base_addr+0x40) && (addr+length)<=(clic_base_addr+0xC0)){ // clicinttrig
|
} else if(addr>=(cfg.clic_base+0x40) && (addr+length)<=(cfg.clic_base+0x40+cfg.clic_num_trigger*4)){ // clicinttrig
|
||||||
auto offset = ((addr&0x7fff)-0x40)/4;
|
auto offset = ((addr&0x7fff)-0x40)/4;
|
||||||
write_reg_uint32(addr, clic_inttrig_reg[offset], data, length);
|
write_reg_uint32(addr, clic_inttrig_reg[offset], data, length);
|
||||||
} else if(addr>=(clic_base_addr+0x1000) && (addr+length)<=(clic_base_addr+clic_num_irq*4)){ // clicintip/clicintie/clicintattr/clicintctl
|
} else if(addr>=(cfg.clic_base+0x1000) && (addr+length)<=(cfg.clic_base+0x1000+cfg.clic_num_irq*4)){ // clicintip/clicintie/clicintattr/clicintctl
|
||||||
auto offset = ((addr&0x7fff)-0x1000)/4;
|
auto offset = ((addr&0x7fff)-0x1000)/4;
|
||||||
write_reg_uint32(addr, clic_int_reg[offset].raw, data, length);
|
write_reg_uint32(addr, clic_int_reg[offset].raw, data, length);
|
||||||
|
clic_int_reg[offset].raw &= 0xf0c70101; // clicIntCtlBits->0xf0, clicintattr->0xc7, clicintie->0x1, clicintip->0x1
|
||||||
}
|
}
|
||||||
return iss::Ok;
|
return iss::Ok;
|
||||||
}
|
}
|
||||||
|
@ -1109,8 +1099,8 @@ template <typename BASE, features_e FEAT> void riscv_hart_m_p<BASE, FEAT>::check
|
||||||
// any synchronous traps.
|
// any synchronous traps.
|
||||||
auto ena_irq = csr[mip] & csr[mie];
|
auto ena_irq = csr[mip] & csr[mie];
|
||||||
|
|
||||||
bool mie = state.mstatus.MIE;
|
bool mstatus_mie = state.mstatus.MIE;
|
||||||
auto m_enabled = this->reg.PRIV < PRIV_M || (this->reg.PRIV == PRIV_M && mie);
|
auto m_enabled = this->reg.PRIV < PRIV_M || mstatus_mie;
|
||||||
auto enabled_interrupts = m_enabled ? ena_irq : 0;
|
auto enabled_interrupts = m_enabled ? ena_irq : 0;
|
||||||
|
|
||||||
if (enabled_interrupts != 0) {
|
if (enabled_interrupts != 0) {
|
||||||
|
|
|
@ -312,14 +312,6 @@ public:
|
||||||
|
|
||||||
iss::instrumentation_if *get_instrumentation_if() override { return &instr_if; }
|
iss::instrumentation_if *get_instrumentation_if() override { return &instr_if; }
|
||||||
|
|
||||||
void setMemReadCb(std::function<iss::status(phys_addr_t, unsigned, uint8_t* const)> const& memReadCb) {
|
|
||||||
mem_read_cb = memReadCb;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setMemWriteCb(std::function<iss::status(phys_addr_t, unsigned, const uint8_t* const)> const& memWriteCb) {
|
|
||||||
mem_write_cb = memWriteCb;
|
|
||||||
}
|
|
||||||
|
|
||||||
void set_csr(unsigned addr, reg_t val){
|
void set_csr(unsigned addr, reg_t val){
|
||||||
csr[addr & csr.page_addr_mask] = val;
|
csr[addr & csr.page_addr_mask] = val;
|
||||||
}
|
}
|
||||||
|
@ -422,8 +414,6 @@ private:
|
||||||
}
|
}
|
||||||
|
|
||||||
reg_t mhartid_reg{0x0};
|
reg_t mhartid_reg{0x0};
|
||||||
std::function<iss::status(phys_addr_t, unsigned, uint8_t *const)>mem_read_cb;
|
|
||||||
std::function<iss::status(phys_addr_t, unsigned, const uint8_t *const)> mem_write_cb;
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void check_interrupt();
|
void check_interrupt();
|
||||||
|
@ -1031,7 +1021,6 @@ template <typename BASE> iss::status riscv_hart_msu_vp<BASE>::write_fcsr(unsigne
|
||||||
|
|
||||||
template <typename BASE>
|
template <typename BASE>
|
||||||
iss::status riscv_hart_msu_vp<BASE>::read_mem(phys_addr_t paddr, unsigned length, uint8_t *const data) {
|
iss::status riscv_hart_msu_vp<BASE>::read_mem(phys_addr_t paddr, unsigned length, uint8_t *const data) {
|
||||||
if(mem_read_cb) return mem_read_cb(paddr, length, data);
|
|
||||||
switch (paddr.val) {
|
switch (paddr.val) {
|
||||||
case 0x0200BFF8: { // CLINT base, mtime reg
|
case 0x0200BFF8: { // CLINT base, mtime reg
|
||||||
if (sizeof(reg_t) < length) return iss::Err;
|
if (sizeof(reg_t) < length) return iss::Err;
|
||||||
|
@ -1056,7 +1045,6 @@ iss::status riscv_hart_msu_vp<BASE>::read_mem(phys_addr_t paddr, unsigned length
|
||||||
|
|
||||||
template <typename BASE>
|
template <typename BASE>
|
||||||
iss::status riscv_hart_msu_vp<BASE>::write_mem(phys_addr_t paddr, unsigned length, const uint8_t *const data) {
|
iss::status riscv_hart_msu_vp<BASE>::write_mem(phys_addr_t paddr, unsigned length, const uint8_t *const data) {
|
||||||
if(mem_write_cb) return mem_write_cb(paddr, length, data);
|
|
||||||
switch (paddr.val) {
|
switch (paddr.val) {
|
||||||
case 0x10013000: // UART0 base, TXFIFO reg
|
case 0x10013000: // UART0 base, TXFIFO reg
|
||||||
case 0x10023000: // UART1 base, TXFIFO reg
|
case 0x10023000: // UART1 base, TXFIFO reg
|
||||||
|
|
|
@ -223,14 +223,6 @@ public:
|
||||||
|
|
||||||
iss::instrumentation_if *get_instrumentation_if() override { return &instr_if; }
|
iss::instrumentation_if *get_instrumentation_if() override { return &instr_if; }
|
||||||
|
|
||||||
void setMemReadCb(std::function<iss::status(phys_addr_t, unsigned, uint8_t* const)> const& memReadCb) {
|
|
||||||
mem_read_cb = memReadCb;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setMemWriteCb(std::function<iss::status(phys_addr_t, unsigned, const uint8_t* const)> const& memWriteCb) {
|
|
||||||
mem_write_cb = memWriteCb;
|
|
||||||
}
|
|
||||||
|
|
||||||
void set_csr(unsigned addr, reg_t val){
|
void set_csr(unsigned addr, reg_t val){
|
||||||
csr[addr & csr.page_addr_mask] = val;
|
csr[addr & csr.page_addr_mask] = val;
|
||||||
}
|
}
|
||||||
|
@ -250,26 +242,24 @@ protected:
|
||||||
*/
|
*/
|
||||||
const std::string core_type_name() const override { return traits<BASE>::core_type; }
|
const std::string core_type_name() const override { return traits<BASE>::core_type; }
|
||||||
|
|
||||||
virtual uint64_t get_pc() { return arch.get_pc(); };
|
uint64_t get_pc() override { return arch.reg.PC; };
|
||||||
|
|
||||||
virtual uint64_t get_next_pc() { return arch.get_next_pc(); };
|
uint64_t get_next_pc() override { return arch.reg.NEXT_PC; };
|
||||||
|
|
||||||
uint64_t get_instr_word() override { return arch.instruction; }
|
uint64_t get_instr_word() override { return arch.instruction; }
|
||||||
|
|
||||||
uint64_t get_instr_count() { return arch.icount; }
|
uint64_t get_instr_count() override { return arch.icount; }
|
||||||
|
|
||||||
uint64_t get_pendig_traps() override { return arch.trap_state; }
|
uint64_t get_pendig_traps() override { return arch.trap_state; }
|
||||||
|
|
||||||
uint64_t get_total_cycles() override { return arch.icount + arch.cycle_offset; }
|
uint64_t get_total_cycles() override { return arch.icount + arch.cycle_offset; }
|
||||||
|
|
||||||
virtual void set_curr_instr_cycles(unsigned cycles) { arch.cycle_offset += cycles - 1; };
|
void set_curr_instr_cycles(unsigned cycles) override { arch.cycle_offset += cycles - 1; };
|
||||||
|
|
||||||
riscv_hart_mu_p<BASE, FEAT> &arch;
|
riscv_hart_mu_p<BASE, FEAT> &arch;
|
||||||
};
|
};
|
||||||
|
|
||||||
friend struct riscv_instrumentation_if;
|
friend struct riscv_instrumentation_if;
|
||||||
addr_t get_pc() { return this->reg.PC; }
|
|
||||||
addr_t get_next_pc() { return this->reg.NEXT_PC; }
|
|
||||||
|
|
||||||
virtual iss::status read_mem(phys_addr_t addr, unsigned length, uint8_t *const data);
|
virtual iss::status read_mem(phys_addr_t addr, unsigned length, uint8_t *const data);
|
||||||
virtual iss::status write_mem(phys_addr_t addr, unsigned length, const uint8_t *const data);
|
virtual iss::status write_mem(phys_addr_t addr, unsigned length, const uint8_t *const data);
|
||||||
|
@ -357,8 +347,6 @@ protected:
|
||||||
}
|
}
|
||||||
|
|
||||||
reg_t mhartid_reg{0x0};
|
reg_t mhartid_reg{0x0};
|
||||||
std::function<iss::status(phys_addr_t, unsigned, uint8_t *const)>mem_read_cb;
|
|
||||||
std::function<iss::status(phys_addr_t, unsigned, const uint8_t *const)> mem_write_cb;
|
|
||||||
|
|
||||||
void check_interrupt();
|
void check_interrupt();
|
||||||
bool pmp_check(const access_type type, const uint64_t addr, const unsigned len);
|
bool pmp_check(const access_type type, const uint64_t addr, const unsigned len);
|
||||||
|
@ -1020,14 +1008,12 @@ template <typename BASE, features_e FEAT> iss::status riscv_hart_mu_p<BASE, FEAT
|
||||||
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) {
|
||||||
auto req_priv_lvl = (addr >> 8) & 0x3;
|
val = state.mstatus & hart_state_type::get_mask((addr >> 8) & 0x3);
|
||||||
val = state.mstatus & hart_state_type::get_mask(req_priv_lvl);
|
|
||||||
return iss::Ok;
|
return iss::Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename BASE, features_e FEAT> iss::status riscv_hart_mu_p<BASE, FEAT>::write_status(unsigned addr, reg_t val) {
|
template <typename BASE, features_e FEAT> iss::status riscv_hart_mu_p<BASE, FEAT>::write_status(unsigned addr, reg_t val) {
|
||||||
auto req_priv_lvl = (addr >> 8) & 0x3;
|
state.write_mstatus(val, (addr >> 8) & 0x3);
|
||||||
state.write_mstatus(val, req_priv_lvl);
|
|
||||||
check_interrupt();
|
check_interrupt();
|
||||||
return iss::Ok;
|
return iss::Ok;
|
||||||
}
|
}
|
||||||
|
@ -1129,7 +1115,6 @@ iss::status riscv_hart_mu_p<BASE, FEAT>::write_intthresh(unsigned addr, reg_t va
|
||||||
|
|
||||||
template <typename BASE, features_e FEAT>
|
template <typename BASE, features_e FEAT>
|
||||||
iss::status riscv_hart_mu_p<BASE, FEAT>::read_mem(phys_addr_t paddr, unsigned length, uint8_t *const data) {
|
iss::status riscv_hart_mu_p<BASE, FEAT>::read_mem(phys_addr_t paddr, unsigned length, uint8_t *const data) {
|
||||||
if(mem_read_cb) return mem_read_cb(paddr, length, data);
|
|
||||||
switch (paddr.val) {
|
switch (paddr.val) {
|
||||||
case 0x0200BFF8: { // CLINT base, mtime reg
|
case 0x0200BFF8: { // CLINT base, mtime reg
|
||||||
if (sizeof(reg_t) < length) return iss::Err;
|
if (sizeof(reg_t) < length) return iss::Err;
|
||||||
|
@ -1154,7 +1139,6 @@ iss::status riscv_hart_mu_p<BASE, FEAT>::read_mem(phys_addr_t paddr, unsigned le
|
||||||
|
|
||||||
template <typename BASE, features_e FEAT>
|
template <typename BASE, features_e FEAT>
|
||||||
iss::status riscv_hart_mu_p<BASE, FEAT>::write_mem(phys_addr_t paddr, unsigned length, const uint8_t *const data) {
|
iss::status riscv_hart_mu_p<BASE, FEAT>::write_mem(phys_addr_t paddr, unsigned length, const uint8_t *const data) {
|
||||||
if(mem_write_cb) return mem_write_cb(paddr, length, data);
|
|
||||||
switch (paddr.val) {
|
switch (paddr.val) {
|
||||||
case 0x10013000: // UART0 base, TXFIFO reg
|
case 0x10013000: // UART0 base, TXFIFO reg
|
||||||
case 0x10023000: // UART1 base, TXFIFO reg
|
case 0x10023000: // UART1 base, TXFIFO reg
|
||||||
|
@ -1279,8 +1263,8 @@ template <typename BASE, features_e FEAT> void riscv_hart_mu_p<BASE, FEAT>::chec
|
||||||
// any synchronous traps.
|
// any synchronous traps.
|
||||||
auto ena_irq = csr[mip] & csr[mie];
|
auto ena_irq = csr[mip] & csr[mie];
|
||||||
|
|
||||||
bool mie = state.mstatus.MIE;
|
bool mstatus_mie = state.mstatus.MIE;
|
||||||
auto m_enabled = this->reg.PRIV < PRIV_M || mie;
|
auto m_enabled = this->reg.PRIV < PRIV_M || mstatus_mie;
|
||||||
auto enabled_interrupts = m_enabled ? ena_irq & ~ideleg : 0;
|
auto enabled_interrupts = m_enabled ? ena_irq & ~ideleg : 0;
|
||||||
|
|
||||||
if (enabled_interrupts != 0) {
|
if (enabled_interrupts != 0) {
|
||||||
|
|
Loading…
Reference in New Issue