This commit is contained in:
Eyck Jentzsch 2022-03-27 15:38:18 +02:00
parent b0cb997009
commit 6ea7721961
4 changed files with 251 additions and 66 deletions

View File

@ -43,7 +43,7 @@ namespace arch {
enum { tohost_dflt = 0xF0001000, fromhost_dflt = 0xF0001040 };
enum features_e{FEAT_NONE, FEAT_PMP=1, FEAT_EXT_N=2, FEAT_CLIC=4, FEAT_DEBUG=8};
enum features_e{FEAT_NONE, FEAT_PMP=1, FEAT_EXT_N=2, FEAT_CLIC=4, FEAT_DEBUG=8, FEAT_TCM=16};
enum riscv_csr {
/* user-level CSR */
@ -239,6 +239,49 @@ public:
trap_store_page_fault(uint64_t badaddr)
: trap_access(15 << 16, badaddr) {}
};
inline void read_reg_uint32(uint64_t offs, uint32_t& reg, uint8_t *const data, unsigned length) {
auto reg_ptr = reinterpret_cast<uint8_t*>(&reg);
switch (offs & 0x3) {
case 0:
for (auto i = 0U; i < length; ++i)
*(data + i) = *(reg_ptr + i);
break;
case 1:
for (auto i = 0U; i < length; ++i)
*(data + i) = *(reg_ptr + 1 + i);
break;
case 2:
for (auto i = 0U; i < length; ++i)
*(data + i) = *(reg_ptr + 2 + i);
break;
case 3:
*data = *(reg_ptr + 3);
break;
}
}
inline void write_reg_uint32(uint64_t offs, uint32_t& reg, const uint8_t *const data, unsigned length) {
auto reg_ptr = reinterpret_cast<uint8_t*>(&reg);
switch (offs & 0x3) {
case 0:
for (auto i = 0U; i < length; ++i)
*(reg_ptr + i) = *(data + i);
break;
case 1:
for (auto i = 0U; i < length; ++i)
*(reg_ptr + 1 + i) = *(data + i);
break;
case 2:
for (auto i = 0U; i < length; ++i)
*(reg_ptr + 2 + i) = *(data + i);
break;
case 3:
*(reg_ptr + 3) = *data ;
break;
}
}
}
}

View File

@ -99,6 +99,8 @@ public:
using rd_csr_f = iss::status (this_class::*)(unsigned addr, reg_t &);
using wr_csr_f = iss::status (this_class::*)(unsigned addr, reg_t);
using mem_read_f = iss::status(phys_addr_t addr, unsigned, uint8_t *const);
using mem_write_f = iss::status(phys_addr_t addr, unsigned, uint8_t const *const);
// primary template
template <class T, class Enable = void> struct hart_state {};
@ -294,6 +296,8 @@ protected:
};
std::vector<clic_int_reg_t> clic_int_reg;
std::vector<uint8_t> tcm;
iss::status read_csr_reg(unsigned addr, reg_t &val);
iss::status write_csr_reg(unsigned addr, reg_t val);
iss::status read_null(unsigned addr, reg_t &val);
@ -337,6 +341,10 @@ protected:
void check_interrupt();
bool pmp_check(const access_type type, const uint64_t addr, const unsigned len);
std::vector<std::tuple<uint64_t, uint64_t>> memfn_range;
std::vector<std::function<mem_read_f>> memfn_read;
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>);
uint64_t clic_base_addr{0};
unsigned clic_num_irq{0};
unsigned clic_num_trigger{0};
@ -407,10 +415,52 @@ riscv_hart_m_p<BASE, FEAT>::riscv_hart_m_p()
csr_rd_cb[mie] = &this_class::read_ie;
csr_wr_cb[mie] = &this_class::write_ie;
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[mvendorid] = &this_class::write_null;
csr_wr_cb[marchid] = &this_class::write_null;
csr_wr_cb[mimpid] = &this_class::write_null;
if(FEAT & FEAT_CLIC) {
csr_rd_cb[mtvt] = &this_class::read_csr_reg;
csr_wr_cb[mtvt] = &this_class::write_csr_reg;
csr_rd_cb[mxnti] = &this_class::read_csr_reg;
csr_wr_cb[mxnti] = &this_class::write_csr_reg;
csr_rd_cb[mintstatus] = &this_class::read_csr_reg;
csr_wr_cb[mintstatus] = &this_class::write_null;
csr_rd_cb[mscratchcsw] = &this_class::read_csr_reg;
csr_wr_cb[mscratchcsw] = &this_class::write_csr_reg;
csr_rd_cb[mscratchcswl] = &this_class::read_csr_reg;
csr_wr_cb[mscratchcswl] = &this_class::write_csr_reg;
csr_rd_cb[mintthresh] = &this_class::read_csr_reg;
csr_wr_cb[mintthresh] = &this_class::write_intthresh;
csr_rd_cb[mclicbase] = &this_class::read_csr_reg;
csr_wr_cb[mclicbase] = &this_class::write_null;
clic_base_addr=0xC0000000;
clic_num_irq=16;
clic_int_reg.resize(clic_num_irq);
clic_cfg_reg=0x20;
clic_info_reg = (/*CLICINTCTLBITS*/ 4U<<21) + clic_num_irq;
mcause_max_irq=clic_num_irq+16;
insert_mem_range(clic_base_addr, 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);});
}
if(FEAT & FEAT_TCM) {
tcm.resize(0x8000);
std::function<mem_read_f> read_clic_cb = [this](phys_addr_t addr, unsigned length, uint8_t * const data) {
auto offset=addr.val-0x10000000;
std::copy(tcm.data() + offset, tcm.data() + offset + length, data);
return iss::Ok;
};
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;
std::copy(data, data + length, tcm.data() + offset);
return iss::Ok;
};
insert_mem_range(0x10000000, 0x8000UL, read_clic_cb, write_clic_cb);
}
if(FEAT & FEAT_DEBUG){
csr_wr_cb[dscratch0] = &this_class::write_dcsr_reg;
csr_rd_cb[dscratch0] = &this_class::read_dcsr_reg;
@ -489,6 +539,20 @@ template <typename BASE, features_e FEAT> std::pair<uint64_t, bool> riscv_hart_m
throw std::runtime_error("memory load file not found");
}
template<typename BASE, features_e FEAT>
inline void riscv_hart_m_p<BASE, FEAT>::insert_mem_range(uint64_t base, uint64_t size, std::function<mem_read_f> rd_f,
std::function<mem_write_f> wr_fn) {
std::tuple<uint64_t, uint64_t> entry{base, size};
auto it = std::upper_bound( memfn_range.begin(), memfn_range.end(), entry,
[](std::tuple<uint64_t, uint64_t> const& a, std::tuple<uint64_t, uint64_t> const& b){
return std::get<0>(a)<std::get<0>(b);
});
auto idx = std::distance(memfn_range.begin(), it);
memfn_range.insert(it, entry);
memfn_read.insert(std::begin(memfn_read)+idx, rd_f);
memfn_write.insert(std::begin(memfn_write)+idx, wr_fn);
}
template <typename BASE, features_e FEAT>
iss::status riscv_hart_m_p<BASE, FEAT>::read(const address_type type, const access_type access, const uint32_t space,
const uint64_t addr, const unsigned length, uint8_t *const data) {
@ -517,9 +581,20 @@ iss::status riscv_hart_m_p<BASE, FEAT>::read(const address_type type, const acce
fault_data=addr;
return iss::Err;
}
auto res = type==iss::address_type::PHYSICAL?
read_mem( BASE::v2p(phys_addr_t{access, space, addr}), length, data):
read_mem( BASE::v2p(iss::addr_t{access, type, space, addr}), length, data);
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;
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){
return std::get<0>(a)<=phys_addr.val && (std::get<0>(a)+std::get<1>(a))>phys_addr.val;
});
if(it!=std::end(memfn_range)) {
auto idx = std::distance(std::begin(memfn_range), it);
res = memfn_read[idx](phys_addr, length, data);
} else
res = read_mem( phys_addr, length, data);
} else {
res = read_mem( phys_addr, length, data);
}
if (unlikely(res != iss::Ok)){
this->reg.trap_state = (1 << 31) | (5 << 16); // issue trap 5 (load access fault
fault_data=addr;
@ -594,14 +669,25 @@ iss::status riscv_hart_m_p<BASE, FEAT>::write(const address_type type, const acc
return iss::Err;
}
try {
if(!(access && iss::access_type::DEBUG) && length>1 && (addr&(length-1))){
if(length>1 && (addr&(length-1)) && (access&access_type::DEBUG) != access_type::DEBUG){
this->reg.trap_state = 1<<31 | 6<<16;
fault_data=addr;
return iss::Err;
}
auto res = type==iss::address_type::PHYSICAL?
write_mem(phys_addr_t{access, space, addr}, length, data):
write_mem(BASE::v2p(iss::addr_t{access, type, space, addr}), length, data);
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;
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){
return std::get<0>(a)<=phys_addr.val && (std::get<0>(a)+std::get<1>(a))>phys_addr.val;
});
if(it!=std::end(memfn_range)) {
auto idx = std::distance(std::begin(memfn_range), it);
res = memfn_write[idx]( phys_addr, length, data);
} else
res = write_mem( phys_addr, length, data);
} else {
res = write_mem( phys_addr, length, data);
}
if (unlikely(res != iss::Ok)) {
this->reg.trap_state = (1 << 31) | (7 << 16); // issue trap 7 (Store/AMO access fault)
fault_data=addr;
@ -874,6 +960,12 @@ template <typename BASE, features_e FEAT> iss::status riscv_hart_m_p<BASE, FEAT>
return iss::Ok;
}
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;
return iss::Ok;
}
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) {
if(mem_read_cb) return mem_read_cb(paddr, length, data);
@ -977,6 +1069,42 @@ iss::status riscv_hart_m_p<BASE, FEAT>::write_mem(phys_addr_t paddr, unsigned le
return iss::Ok;
}
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) {
if(addr==clic_base_addr) { // cliccfg
*data=clic_cfg_reg;
for(auto i=1; i<length; ++i) *(data+i)=0;
} else if(addr>=(clic_base_addr+4) && (addr+length)<=(clic_base_addr+8)){ // clicinfo
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
auto offset = ((addr&0x7fff)-0x40)/4;
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
auto offset = ((addr&0x7fff)-0x1000)/4;
read_reg_uint32(addr, clic_int_reg[offset].raw, data, length);
} else {
for(auto i = 0U; i<length; ++i) *(data+i)=0;
}
return iss::Ok;
}
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) {
if(addr==clic_base_addr) { // cliccfg
clic_cfg_reg = *data;
clic_cfg_reg&= 0x7e;
// } else if(addr>=(clic_base_addr+4) && (addr+length)<=(clic_base_addr+4)){ // clicinfo
// write_uint32(addr, clic_info_reg, data, length);
} else if(addr>=(clic_base_addr+0x40) && (addr+length)<=(clic_base_addr+0xC0)){ // clicinttrig
auto offset = ((addr&0x7fff)-0x40)/4;
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
auto offset = ((addr&0x7fff)-0x1000)/4;
write_reg_uint32(addr, clic_int_reg[offset].raw, data, length);
}
return iss::Ok;
}
template <typename BASE, features_e FEAT> inline void riscv_hart_m_p<BASE, FEAT>::reset(uint64_t address) {
BASE::reset(address);
state.mstatus = hart_state_type::mstatus_reset_val;

View File

@ -99,6 +99,8 @@ public:
using rd_csr_f = iss::status (this_class::*)(unsigned addr, reg_t &);
using wr_csr_f = iss::status (this_class::*)(unsigned addr, reg_t);
using mem_read_f = iss::status(phys_addr_t addr, unsigned, uint8_t *const);
using mem_write_f = iss::status(phys_addr_t addr, unsigned, uint8_t const *const);
// primary template
template <class T, class Enable = void> struct hart_state {};
@ -309,6 +311,8 @@ protected:
};
std::vector<clic_int_reg_t> clic_int_reg;
std::vector<uint8_t> tcm;
iss::status read_csr_reg(unsigned addr, reg_t &val);
iss::status write_csr_reg(unsigned addr, reg_t val);
iss::status read_null(unsigned addr, reg_t &val);
@ -355,6 +359,10 @@ protected:
void check_interrupt();
bool pmp_check(const access_type type, const uint64_t addr, const unsigned len);
std::vector<std::tuple<uint64_t, uint64_t>> memfn_range;
std::vector<std::function<mem_read_f>> memfn_read;
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>);
uint64_t clic_base_addr{0};
unsigned clic_num_irq{0};
unsigned clic_num_trigger{0};
@ -483,6 +491,23 @@ riscv_hart_mu_p<BASE, FEAT>::riscv_hart_mu_p()
clic_cfg_reg=0x20;
clic_info_reg = (/*CLICINTCTLBITS*/ 4U<<21) + clic_num_irq;
mcause_max_irq=clic_num_irq+16;
insert_mem_range(clic_base_addr, 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);});
}
if(FEAT & FEAT_TCM) {
tcm.resize(0x8000);
std::function<mem_read_f> read_clic_cb = [this](phys_addr_t addr, unsigned length, uint8_t * const data) {
auto offset=addr.val-0x10000000;
std::copy(tcm.data() + offset, tcm.data() + offset + length, data);
return iss::Ok;
};
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;
std::copy(data, data + length, tcm.data() + offset);
return iss::Ok;
};
insert_mem_range(0x10000000, 0x8000UL, read_clic_cb, write_clic_cb);
}
if(FEAT & FEAT_DEBUG){
csr_wr_cb[dscratch0] = &this_class::write_dcsr_reg;
@ -562,6 +587,20 @@ template <typename BASE, features_e FEAT> std::pair<uint64_t, bool> riscv_hart_m
throw std::runtime_error("memory load file not found");
}
template<typename BASE, features_e FEAT>
inline void riscv_hart_mu_p<BASE, FEAT>::insert_mem_range(uint64_t base, uint64_t size, std::function<mem_read_f> rd_f,
std::function<mem_write_f> wr_fn) {
std::tuple<uint64_t, uint64_t> entry{base, size};
auto it = std::upper_bound( memfn_range.begin(), memfn_range.end(), entry,
[](std::tuple<uint64_t, uint64_t> const& a, std::tuple<uint64_t, uint64_t> const& b){
return std::get<0>(a)<std::get<0>(b);
});
auto idx = std::distance(memfn_range.begin(), it);
memfn_range.insert(it, entry);
memfn_read.insert(std::begin(memfn_read)+idx, rd_f);
memfn_write.insert(std::begin(memfn_write)+idx, wr_fn);
}
template<typename BASE, features_e FEAT>
inline iss::status riscv_hart_mu_p<BASE, FEAT>::write_pmpcfg_reg(unsigned addr, reg_t val) {
csr[addr] = val & 0x9f9f9f9f;
@ -688,8 +727,15 @@ iss::status riscv_hart_mu_p<BASE, FEAT>::read(const address_type type, const acc
}
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;
if((FEAT & FEAT_CLIC) && access != access_type::FETCH && phys_addr.val>=clic_base_addr && (phys_addr.val+length)<=(clic_base_addr+0x5000)){ //TODO: should be a constant
res = read_clic(phys_addr.val, length, data);
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){
return std::get<0>(a)<=phys_addr.val && (std::get<0>(a)+std::get<1>(a))>phys_addr.val;
});
if(it!=std::end(memfn_range)) {
auto idx = std::distance(std::begin(memfn_range), it);
res = memfn_read[idx](phys_addr, length, data);
} else
res = read_mem( phys_addr, length, data);
} else {
res = read_mem( phys_addr, length, data);
}
@ -781,8 +827,19 @@ iss::status riscv_hart_mu_p<BASE, FEAT>::write(const address_type type, const ac
return iss::Err;
}
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 = ((FEAT & FEAT_CLIC) && phys_addr.val>=clic_base_addr && (phys_addr.val+length)<=(clic_base_addr+0x5000))? //TODO: should be a constant
write_clic(phys_addr.val, length, data) : write_mem( phys_addr, length, data);
auto res = iss::Err;
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){
return std::get<0>(a)<=phys_addr.val && (std::get<0>(a)+std::get<1>(a))>phys_addr.val;
});
if(it!=std::end(memfn_range)) {
auto idx = std::distance(std::begin(memfn_range), it);
res = memfn_write[idx]( phys_addr, length, data);
} else
res = write_mem( phys_addr, length, data);
} else {
res = write_mem( phys_addr, length, data);
}
if (unlikely(res != iss::Ok)) {
this->reg.trap_state = (1 << 31) | (7 << 16); // issue trap 7 (Store/AMO access fault)
fault_data=addr;
@ -1111,8 +1168,7 @@ iss::status riscv_hart_mu_p<BASE, FEAT>::write_mem(phys_addr_t paddr, unsigned l
case 0x10023000: // UART1 base, TXFIFO reg
uart_buf << (char)data[0];
if (((char)data[0]) == '\n' || data[0] == 0) {
// LOG(INFO)<<"UART"<<((paddr.val>>16)&0x3)<<" send
// '"<<uart_buf.str()<<"'";
LOG(INFO)<<"UART"<<((paddr.val>>16)&0x3)<<" send '"<<uart_buf.str()<<"'";
std::cout << uart_buf.str();
uart_buf.str("");
}
@ -1181,61 +1237,19 @@ iss::status riscv_hart_mu_p<BASE, FEAT>::write_mem(phys_addr_t paddr, unsigned l
return iss::Ok;
}
void read_uint32(uint64_t offs, uint32_t& reg, uint8_t *const data, unsigned length) {
auto reg_ptr = reinterpret_cast<uint8_t*>(&reg);
switch (offs & 0x3) {
case 0:
for (auto i = 0U; i < length; ++i)
*(data + i) = *(reg_ptr + i);
break;
case 1:
for (auto i = 0U; i < length; ++i)
*(data + i) = *(reg_ptr + 1 + i);
break;
case 2:
for (auto i = 0U; i < length; ++i)
*(data + i) = *(reg_ptr + 2 + i);
break;
case 3:
*data = *(reg_ptr + 3);
break;
}
}
void write_uint32(uint64_t offs, uint32_t& reg, const uint8_t *const data, unsigned length) {
auto reg_ptr = reinterpret_cast<uint8_t*>(&reg);
switch (offs & 0x3) {
case 0:
for (auto i = 0U; i < length; ++i)
*(reg_ptr + i) = *(data + i);
break;
case 1:
for (auto i = 0U; i < length; ++i)
*(reg_ptr + 1 + i) = *(data + i);
break;
case 2:
for (auto i = 0U; i < length; ++i)
*(reg_ptr + 2 + i) = *(data + i);
break;
case 3:
*(reg_ptr + 3) = *data ;
break;
}
}
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) {
if(addr==clic_base_addr) { // cliccfg
*data=clic_cfg_reg;
for(auto i=1; i<length; ++i) *(data+i)=0;
} else if(addr>=(clic_base_addr+4) && (addr+length)<=(clic_base_addr+8)){ // clicinfo
read_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
auto offset = ((addr&0x7fff)-0x40)/4;
read_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
auto offset = ((addr&0x7fff)-0x1000)/4;
read_uint32(addr, clic_int_reg[offset].raw, data, length);
read_reg_uint32(addr, clic_int_reg[offset].raw, data, length);
} else {
for(auto i = 0U; i<length; ++i) *(data+i)=0;
}
@ -1251,10 +1265,10 @@ iss::status riscv_hart_mu_p<BASE, FEAT>::write_clic(uint64_t addr, unsigned leng
// write_uint32(addr, clic_info_reg, data, length);
} else if(addr>=(clic_base_addr+0x40) && (addr+length)<=(clic_base_addr+0xC0)){ // clicinttrig
auto offset = ((addr&0x7fff)-0x40)/4;
write_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
auto offset = ((addr&0x7fff)-0x1000)/4;
write_uint32(addr, clic_int_reg[offset].raw, data, length);
write_reg_uint32(addr, clic_int_reg[offset].raw, data, length);
}
return iss::Ok;
}

View File

@ -37,7 +37,7 @@ using tgc_e_plat_type = iss::arch::riscv_hart_mu_p<iss::arch::tgc_e, (iss::arch:
#ifdef CORE_TGC_X
#include "riscv_hart_mu_p.h"
#include "tgc_x.h"
using tgc_x_plat_type = iss::arch::riscv_hart_mu_p<iss::arch::tgc_x, (iss::arch::features_e)(iss::arch::FEAT_PMP | iss::arch::FEAT_CLIC | iss::arch::FEAT_EXT_N)>;
using tgc_x_plat_type = iss::arch::riscv_hart_mu_p<iss::arch::tgc_x, (iss::arch::features_e)(iss::arch::FEAT_PMP | iss::arch::FEAT_CLIC | iss::arch::FEAT_EXT_N | iss::arch::FEAT_TCM)>;
#endif
#endif