|
|
@ -197,7 +197,7 @@ public:
|
|
|
|
return traits<BASE>::MISA_VAL&0b0100?~1:~3;
|
|
|
|
return traits<BASE>::MISA_VAL&0b0100?~1:~3;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
riscv_hart_mu_p();
|
|
|
|
riscv_hart_mu_p(feature_config cfg = feature_config{});
|
|
|
|
virtual ~riscv_hart_mu_p() = default;
|
|
|
|
virtual ~riscv_hart_mu_p() = default;
|
|
|
|
|
|
|
|
|
|
|
|
void reset(uint64_t address) override;
|
|
|
|
void reset(uint64_t address) override;
|
|
|
@ -363,23 +363,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_mu_p<BASE, FEAT>::riscv_hart_mu_p()
|
|
|
|
riscv_hart_mu_p<BASE, FEAT>::riscv_hart_mu_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){
|
|
|
@ -485,29 +484,27 @@ riscv_hart_mu_p<BASE, FEAT>::riscv_hart_mu_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_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;
|
|
|
@ -1239,15 +1236,15 @@ iss::status riscv_hart_mu_p<BASE, FEAT>::write_mem(phys_addr_t paddr, unsigned l
|
|
|
|
|
|
|
|
|
|
|
|
template<typename BASE, features_e FEAT>
|
|
|
|
template<typename BASE, features_e FEAT>
|
|
|
|
iss::status riscv_hart_mu_p<BASE, FEAT>::read_clic(uint64_t addr, unsigned length, uint8_t *const data) {
|
|
|
|
iss::status riscv_hart_mu_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+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 {
|
|
|
@ -1258,15 +1255,15 @@ iss::status riscv_hart_mu_p<BASE, FEAT>::read_clic(uint64_t addr, unsigned lengt
|
|
|
|
|
|
|
|
|
|
|
|
template<typename BASE, features_e FEAT>
|
|
|
|
template<typename BASE, features_e FEAT>
|
|
|
|
iss::status riscv_hart_mu_p<BASE, FEAT>::write_clic(uint64_t addr, unsigned length, const uint8_t *const data) {
|
|
|
|
iss::status riscv_hart_mu_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+0xC0)){ // 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+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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|