Compare commits
19 Commits
1ad66a71d8
...
ec55efd322
Author | SHA1 | Date | |
---|---|---|---|
ec55efd322 | |||
8c3709f92a | |||
207dbf1071 | |||
62c118e501 | |||
65dca13b42 | |||
3187cbdfe2 | |||
8c701d55c1 | |||
f585489ff5 | |||
7113683ee0 | |||
1a0fc4bd5d | |||
40d1966e9a | |||
a977200284 | |||
b20fd3eba5 | |||
b20daa1ac2 | |||
b1a18459e7 | |||
6ba7c82f80 | |||
ad7bb28b4c | |||
fa7eda0889 | |||
00e02bf565 |
@ -8,6 +8,7 @@ include(GNUInstallDirs)
|
||||
|
||||
find_package(elfio QUIET)
|
||||
find_package(Boost COMPONENTS coroutine)
|
||||
find_package(jsoncpp)
|
||||
|
||||
if(WITH_LLVM)
|
||||
if(DEFINED ENV{LLVM_HOME})
|
||||
@ -41,7 +42,7 @@ set(LIB_SOURCES
|
||||
src/vm/fp_functions.cpp
|
||||
${GEN_SOURCES}
|
||||
)
|
||||
if(TARGET RapidJSON)
|
||||
if(TARGET RapidJSON OR TARGET RapidJSON::RapidJSON)
|
||||
list(APPEND LIB_SOURCES src/iss/plugin/cycle_estimate.cpp src/iss/plugin/pctrace.cpp)
|
||||
endif()
|
||||
|
||||
@ -73,15 +74,18 @@ elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
|
||||
endif()
|
||||
target_include_directories(${PROJECT_NAME} PUBLIC src)
|
||||
target_include_directories(${PROJECT_NAME} PUBLIC src-gen)
|
||||
target_link_libraries(${PROJECT_NAME} PUBLIC softfloat scc-util jsoncpp Boost::coroutine)
|
||||
if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
|
||||
target_link_libraries(${PROJECT_NAME} PUBLIC softfloat scc-util Boost::coroutine)
|
||||
if(TARGET jsoncpp::jsoncpp)
|
||||
target_link_libraries(${PROJECT_NAME} PUBLIC jsoncpp::jsoncpp)
|
||||
else()
|
||||
target_link_libraries(${PROJECT_NAME} PUBLIC jsoncpp)
|
||||
endif()
|
||||
if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" AND BUILD_SHARED_LIBS)
|
||||
target_link_libraries(${PROJECT_NAME} PUBLIC -Wl,--whole-archive dbt-rise-core -Wl,--no-whole-archive)
|
||||
else()
|
||||
target_link_libraries(${PROJECT_NAME} PUBLIC dbt-rise-core)
|
||||
endif()
|
||||
if(TARGET CONAN_PKG::elfio)
|
||||
target_link_libraries(${PROJECT_NAME} PUBLIC CONAN_PKG::elfio)
|
||||
elseif(TARGET elfio::elfio)
|
||||
if(TARGET elfio::elfio)
|
||||
target_link_libraries(${PROJECT_NAME} PUBLIC elfio::elfio)
|
||||
else()
|
||||
message(FATAL_ERROR "No elfio library found, maybe a find_package() call is missing")
|
||||
@ -90,7 +94,9 @@ if(TARGET lz4::lz4)
|
||||
target_compile_definitions(${PROJECT_NAME} PUBLIC WITH_LZ4)
|
||||
target_link_libraries(${PROJECT_NAME} PUBLIC lz4::lz4)
|
||||
endif()
|
||||
if(TARGET RapidJSON)
|
||||
if(TARGET RapidJSON::RapidJSON)
|
||||
target_link_libraries(${PROJECT_NAME} PUBLIC RapidJSON::RapidJSON)
|
||||
elseif(TARGET RapidJSON)
|
||||
target_link_libraries(${PROJECT_NAME} PUBLIC RapidJSON)
|
||||
endif()
|
||||
|
||||
@ -172,7 +178,7 @@ if(SystemC_FOUND)
|
||||
target_link_libraries(${PROJECT_NAME} PUBLIC ${llvm_libs})
|
||||
endif()
|
||||
|
||||
set(LIB_HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/incl/sysc/core_complex.h)
|
||||
set(LIB_HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/src/sysc/core_complex.h)
|
||||
set_target_properties(${PROJECT_NAME} PROPERTIES
|
||||
VERSION ${PROJECT_VERSION}
|
||||
FRAMEWORK FALSE
|
||||
|
@ -92,7 +92,7 @@ protected:
|
||||
using compile_ret_t = virt_addr_t;
|
||||
using compile_func = compile_ret_t (this_class::*)(virt_addr_t &pc, code_word_t instr);
|
||||
|
||||
inline const char *name(size_t index){return traits::reg_aliases.at(index);}
|
||||
inline const char *name(size_t index){return index<traits::reg_aliases.size()?traits::reg_aliases[index]:"illegal";}
|
||||
|
||||
typename arch::traits<ARCH>::opcode_e decode_inst_id(code_word_t instr);
|
||||
virt_addr_t execute_inst(finish_cond_e cond, virt_addr_t start, uint64_t icount_limit) override;
|
||||
@ -137,44 +137,6 @@ protected:
|
||||
using coro_t = boost::coroutines2::coroutine<void>::pull_type;
|
||||
std::vector<coro_t> spawn_blocks;
|
||||
|
||||
template<typename T>
|
||||
T& pc_assign(T& val){super::ex_info.branch_taken=true; return val;}
|
||||
inline uint8_t readSpace1(typename super::mem_type_e space, uint64_t addr){
|
||||
auto ret = super::template read_mem<uint8_t>(space, addr);
|
||||
if(this->core.trap_state) throw 0;
|
||||
return ret;
|
||||
}
|
||||
inline uint16_t readSpace2(typename super::mem_type_e space, uint64_t addr){
|
||||
auto ret = super::template read_mem<uint16_t>(space, addr);
|
||||
if(this->core.trap_state) throw 0;
|
||||
return ret;
|
||||
}
|
||||
inline uint32_t readSpace4(typename super::mem_type_e space, uint64_t addr){
|
||||
auto ret = super::template read_mem<uint32_t>(space, addr);
|
||||
if(this->core.trap_state) throw 0;
|
||||
return ret;
|
||||
}
|
||||
inline uint64_t readSpace8(typename super::mem_type_e space, uint64_t addr){
|
||||
auto ret = super::template read_mem<uint64_t>(space, addr);
|
||||
if(this->core.trap_state) throw 0;
|
||||
return ret;
|
||||
}
|
||||
inline void writeSpace1(typename super::mem_type_e space, uint64_t addr, uint8_t data){
|
||||
super::write_mem(space, addr, data);
|
||||
if(this->core.trap_state) throw 0;
|
||||
}
|
||||
inline void writeSpace2(typename super::mem_type_e space, uint64_t addr, uint16_t data){
|
||||
super::write_mem(space, addr, data);
|
||||
if(this->core.trap_state) throw 0;
|
||||
}
|
||||
inline void writeSpace4(typename super::mem_type_e space, uint64_t addr, uint32_t data){
|
||||
super::write_mem(space, addr, data);
|
||||
if(this->core.trap_state) throw 0;
|
||||
}
|
||||
inline void writeSpace8(typename super::mem_type_e space, uint64_t addr, uint64_t data){
|
||||
super::write_mem(space, addr, data);
|
||||
if(this->core.trap_state) throw 0;
|
||||
}
|
||||
template<unsigned W, typename U, typename S = typename std::make_signed<U>::type>
|
||||
inline S sext(U from) {
|
||||
auto mask = (1ULL<<W) - 1;
|
||||
@ -183,12 +145,15 @@ protected:
|
||||
}
|
||||
|
||||
inline void process_spawn_blocks() {
|
||||
if(spawn_blocks.size()==0) return;
|
||||
std::swap(super::ex_info.branch_taken, super::ex_info.hw_branch_taken);
|
||||
for(auto it = std::begin(spawn_blocks); it!=std::end(spawn_blocks);)
|
||||
if(*it){
|
||||
(*it)();
|
||||
++it;
|
||||
} else
|
||||
spawn_blocks.erase(it);
|
||||
std::swap(super::ex_info.branch_taken, super::ex_info.hw_branch_taken);
|
||||
}
|
||||
<%functions.each{ it.eachLine { %>
|
||||
${it}<%}%>
|
||||
@ -324,6 +289,8 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
|
||||
// post execution stuff
|
||||
process_spawn_blocks();
|
||||
if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, static_cast<unsigned>(inst_id));
|
||||
// if(!this->core.trap_state) // update trap state if there is a pending interrupt
|
||||
// this->core.trap_state = this->core.pending_trap;
|
||||
// trap check
|
||||
if(trap_state!=0){
|
||||
super::core.enter_trap(trap_state, pc.val, instr);
|
||||
|
@ -115,10 +115,9 @@ enum riscv_csr {
|
||||
mip = 0x344,
|
||||
mxnti = 0x345, //CLIC
|
||||
mintstatus = 0x346, // MRW Current interrupt levels (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)
|
||||
mscratchcswl = 0x349, // MRW Conditional scratch swap on level change (CLIC)
|
||||
mintthresh = 0x350, // MRW Interrupt-level threshold (CLIC) - addr subject to change
|
||||
mclicbase = 0x351, // MRW Base address for CLIC memory mapped registers (CLIC) - addr subject to change
|
||||
// Physical Memory Protection
|
||||
pmpcfg0 = 0x3A0,
|
||||
pmpcfg1 = 0x3A1,
|
||||
|
@ -182,7 +182,7 @@ public:
|
||||
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;
|
||||
|
||||
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,
|
||||
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); }
|
||||
virtual 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 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, uint64_t addr, uint64_t instr) override;
|
||||
uint64_t leave_trap(uint64_t flags) override;
|
||||
|
||||
const reg_t& get_mhartid() const { return mhartid_reg; }
|
||||
void set_mhartid(reg_t mhartid) { mhartid_reg = mhartid; };
|
||||
@ -208,14 +208,6 @@ public:
|
||||
|
||||
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){
|
||||
csr[addr & csr.page_addr_mask] = val;
|
||||
}
|
||||
@ -337,8 +329,6 @@ protected:
|
||||
}
|
||||
|
||||
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();
|
||||
bool pmp_check(const access_type type, const uint64_t addr, const unsigned len);
|
||||
@ -346,23 +336,21 @@ protected:
|
||||
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};
|
||||
feature_config cfg;
|
||||
unsigned mcause_max_irq{16};
|
||||
inline bool debug_mode_active() {return this->reg.PRIV&0x4;}
|
||||
};
|
||||
|
||||
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()
|
||||
, instr_if(*this) {
|
||||
, instr_if(*this)
|
||||
, cfg(cfg) {
|
||||
// reset values
|
||||
csr[misa] = traits<BASE>::MISA_VAL;
|
||||
csr[mvendorid] = 0x669;
|
||||
csr[marchid] = traits<BASE>::MARCHID_VAL;
|
||||
csr[mimpid] = 1;
|
||||
csr[mclicbase] = 0xc0000000; // TODO: should be taken from YAML file
|
||||
|
||||
uart_buf.str("");
|
||||
for (unsigned addr = mhpmcounter3; addr <= mhpmcounter31; ++addr){
|
||||
@ -385,7 +373,10 @@ riscv_hart_m_p<BASE, FEAT>::riscv_hart_m_p()
|
||||
//csr_wr_cb[addr] = &this_class::write_csr_reg;
|
||||
}
|
||||
// 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) {
|
||||
csr_rd_cb[addr] = &this_class::read_csr_reg;
|
||||
csr_wr_cb[addr] = &this_class::write_csr_reg;
|
||||
@ -433,32 +424,28 @@ riscv_hart_m_p<BASE, FEAT>::riscv_hart_m_p()
|
||||
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_int_reg.resize(cfg.clic_num_irq, clic_int_reg_t{.raw=0});
|
||||
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,
|
||||
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,
|
||||
[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);
|
||||
tcm.resize(cfg.tcm_size);
|
||||
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);
|
||||
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;
|
||||
auto offset=addr.val-this->cfg.tcm_base;
|
||||
std::copy(data, data + length, tcm.data() + offset);
|
||||
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){
|
||||
csr_wr_cb[dscratch0] = &this_class::write_dcsr_reg;
|
||||
@ -582,7 +569,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 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){
|
||||
return std::get<0>(a)<=phys_addr.val && (std::get<0>(a)+std::get<1>(a))>phys_addr.val;
|
||||
});
|
||||
@ -863,7 +850,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) {
|
||||
val = csr[mtvec] & ~2;
|
||||
val = csr[addr] & ~2;
|
||||
return iss::Ok;
|
||||
}
|
||||
|
||||
@ -879,7 +866,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) {
|
||||
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;
|
||||
}
|
||||
|
||||
@ -959,7 +946,6 @@ iss::status riscv_hart_m_p<BASE, FEAT>::write_intthresh(unsigned addr, reg_t val
|
||||
|
||||
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);
|
||||
switch (paddr.val) {
|
||||
case 0x0200BFF8: { // CLINT base, mtime reg
|
||||
if (sizeof(reg_t) < length) return iss::Err;
|
||||
@ -984,14 +970,12 @@ iss::status riscv_hart_m_p<BASE, FEAT>::read_mem(phys_addr_t paddr, unsigned len
|
||||
|
||||
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) {
|
||||
if(mem_write_cb) return mem_write_cb(paddr, length, data);
|
||||
switch (paddr.val) {
|
||||
case 0x10013000: // UART0 base, TXFIFO reg
|
||||
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("");
|
||||
}
|
||||
@ -1062,15 +1046,15 @@ iss::status riscv_hart_m_p<BASE, FEAT>::write_mem(phys_addr_t paddr, unsigned le
|
||||
|
||||
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
|
||||
if(addr==cfg.clic_base) { // 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
|
||||
} else if(addr>=(cfg.clic_base+4) && (addr+length)<=(cfg.clic_base+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
|
||||
} 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;
|
||||
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;
|
||||
read_reg_uint32(addr, clic_int_reg[offset].raw, data, length);
|
||||
} else {
|
||||
@ -1081,17 +1065,18 @@ iss::status riscv_hart_m_p<BASE, FEAT>::read_clic(uint64_t addr, unsigned length
|
||||
|
||||
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
|
||||
if(addr==cfg.clic_base) { // cliccfg
|
||||
clic_cfg_reg = *data;
|
||||
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);
|
||||
} 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;
|
||||
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;
|
||||
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;
|
||||
}
|
||||
@ -1109,8 +1094,8 @@ template <typename BASE, features_e FEAT> void riscv_hart_m_p<BASE, FEAT>::check
|
||||
// any synchronous traps.
|
||||
auto ena_irq = csr[mip] & csr[mie];
|
||||
|
||||
bool mie = state.mstatus.MIE;
|
||||
auto m_enabled = this->reg.PRIV < PRIV_M || (this->reg.PRIV == PRIV_M && mie);
|
||||
bool mstatus_mie = state.mstatus.MIE;
|
||||
auto m_enabled = this->reg.PRIV < PRIV_M || mstatus_mie;
|
||||
auto enabled_interrupts = m_enabled ? ena_irq : 0;
|
||||
|
||||
if (enabled_interrupts != 0) {
|
||||
@ -1210,6 +1195,7 @@ template <typename BASE, features_e FEAT> uint64_t riscv_hart_m_p<BASE, FEAT>::l
|
||||
this->reg.NEXT_PC = csr[mepc] & get_pc_mask();
|
||||
CLOG(INFO, disass) << "Executing xRET";
|
||||
check_interrupt();
|
||||
this->trap_state = this->pending_trap;
|
||||
return this->reg.NEXT_PC;
|
||||
}
|
||||
|
||||
|
@ -312,14 +312,6 @@ public:
|
||||
|
||||
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){
|
||||
csr[addr & csr.page_addr_mask] = val;
|
||||
}
|
||||
@ -422,8 +414,6 @@ private:
|
||||
}
|
||||
|
||||
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:
|
||||
void check_interrupt();
|
||||
@ -1031,7 +1021,6 @@ template <typename BASE> iss::status riscv_hart_msu_vp<BASE>::write_fcsr(unsigne
|
||||
|
||||
template <typename BASE>
|
||||
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) {
|
||||
case 0x0200BFF8: { // CLINT base, mtime reg
|
||||
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>
|
||||
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) {
|
||||
case 0x10013000: // UART0 base, TXFIFO reg
|
||||
case 0x10023000: // UART1 base, TXFIFO reg
|
||||
|
@ -223,14 +223,6 @@ public:
|
||||
|
||||
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){
|
||||
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; }
|
||||
|
||||
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_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_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;
|
||||
};
|
||||
|
||||
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 write_mem(phys_addr_t addr, unsigned length, const uint8_t *const data);
|
||||
@ -357,8 +347,6 @@ protected:
|
||||
}
|
||||
|
||||
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();
|
||||
bool pmp_check(const access_type type, const uint64_t addr, const unsigned len);
|
||||
@ -381,7 +369,6 @@ riscv_hart_mu_p<BASE, FEAT>::riscv_hart_mu_p(feature_config cfg)
|
||||
csr[mvendorid] = 0x669;
|
||||
csr[marchid] = traits<BASE>::MARCHID_VAL;
|
||||
csr[mimpid] = 1;
|
||||
csr[mclicbase] = cfg.clic_base; // TODO: should be taken from YAML file
|
||||
|
||||
uart_buf.str("");
|
||||
for (unsigned addr = mhpmcounter3; addr <= mhpmcounter31; ++addr){
|
||||
@ -484,10 +471,8 @@ riscv_hart_mu_p<BASE, FEAT>::riscv_hart_mu_p(feature_config cfg)
|
||||
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_int_reg.resize(cfg.clic_num_irq);
|
||||
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;
|
||||
mcause_max_irq=cfg.clic_num_irq+16;
|
||||
@ -1020,14 +1005,12 @@ template <typename BASE, features_e FEAT> iss::status riscv_hart_mu_p<BASE, FEAT
|
||||
return iss::Ok;
|
||||
}
|
||||
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(req_priv_lvl);
|
||||
val = state.mstatus & hart_state_type::get_mask((addr >> 8) & 0x3);
|
||||
return iss::Ok;
|
||||
}
|
||||
|
||||
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, req_priv_lvl);
|
||||
state.write_mstatus(val, (addr >> 8) & 0x3);
|
||||
check_interrupt();
|
||||
return iss::Ok;
|
||||
}
|
||||
@ -1129,7 +1112,6 @@ iss::status riscv_hart_mu_p<BASE, FEAT>::write_intthresh(unsigned addr, reg_t va
|
||||
|
||||
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) {
|
||||
if(mem_read_cb) return mem_read_cb(paddr, length, data);
|
||||
switch (paddr.val) {
|
||||
case 0x0200BFF8: { // CLINT base, mtime reg
|
||||
if (sizeof(reg_t) < length) return iss::Err;
|
||||
@ -1154,7 +1136,6 @@ iss::status riscv_hart_mu_p<BASE, FEAT>::read_mem(phys_addr_t paddr, unsigned le
|
||||
|
||||
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) {
|
||||
if(mem_write_cb) return mem_write_cb(paddr, length, data);
|
||||
switch (paddr.val) {
|
||||
case 0x10013000: // UART0 base, TXFIFO reg
|
||||
case 0x10023000: // UART1 base, TXFIFO reg
|
||||
@ -1261,6 +1242,7 @@ iss::status riscv_hart_mu_p<BASE, FEAT>::write_clic(uint64_t addr, unsigned leng
|
||||
} 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;
|
||||
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;
|
||||
}
|
||||
@ -1278,8 +1260,8 @@ template <typename BASE, features_e FEAT> void riscv_hart_mu_p<BASE, FEAT>::chec
|
||||
// any synchronous traps.
|
||||
auto ena_irq = csr[mip] & csr[mie];
|
||||
|
||||
bool mie = state.mstatus.MIE;
|
||||
auto m_enabled = this->reg.PRIV < PRIV_M || mie;
|
||||
bool mstatus_mie = state.mstatus.MIE;
|
||||
auto m_enabled = this->reg.PRIV < PRIV_M || mstatus_mie;
|
||||
auto enabled_interrupts = m_enabled ? ena_irq & ~ideleg : 0;
|
||||
|
||||
if (enabled_interrupts != 0) {
|
||||
|
@ -16,8 +16,9 @@ using tgc_b_plat_type = iss::arch::riscv_hart_m_p<iss::arch::tgc_b>;
|
||||
#endif
|
||||
#ifdef CORE_TGC_C_XRB_NN
|
||||
#include "riscv_hart_m_p.h"
|
||||
#include "hwl.h"
|
||||
#include <iss/arch/tgc_c_xrb_nn.h>
|
||||
using tgc_c_xrb_nn_plat_type = iss::arch::riscv_hart_m_p<iss::arch::tgc_c_xrb_nn>;
|
||||
using tgc_c_xrb_nn_plat_type = iss::arch::hwl<iss::arch::riscv_hart_m_p<iss::arch::tgc_c_xrb_nn>>;
|
||||
#endif
|
||||
#ifdef CORE_TGC_D
|
||||
#include "riscv_hart_mu_p.h"
|
||||
@ -31,8 +32,9 @@ using tgc_d_xrb_mac_plat_type = iss::arch::riscv_hart_mu_p<iss::arch::tgc_d_xrb_
|
||||
#endif
|
||||
#ifdef CORE_TGC_D_XRB_NN
|
||||
#include "riscv_hart_mu_p.h"
|
||||
#include "hwl.h"
|
||||
#include <iss/arch/tgc_d_xrb_nn.h>
|
||||
using tgc_d_xrb_nn_plat_type = iss::arch::riscv_hart_mu_p<iss::arch::tgc_d_xrb_nn, (iss::arch::features_e)(iss::arch::FEAT_PMP | iss::arch::FEAT_CLIC | iss::arch::FEAT_EXT_N)>;
|
||||
using tgc_d_xrb_nn_plat_type = iss::arch::hwl<iss::arch::riscv_hart_mu_p<iss::arch::tgc_d_xrb_nn, (iss::arch::features_e)(iss::arch::FEAT_PMP | iss::arch::FEAT_CLIC | iss::arch::FEAT_EXT_N)>>;
|
||||
#endif
|
||||
#ifdef CORE_TGC_E
|
||||
#include "riscv_hart_mu_p.h"
|
||||
|
@ -186,17 +186,17 @@ public:
|
||||
void local_irq(short id, bool value) {
|
||||
reg_t mask = 0;
|
||||
switch (id) {
|
||||
case 16: // SW
|
||||
case 3: // SW
|
||||
mask = 1 << 3;
|
||||
break;
|
||||
case 17: // timer
|
||||
case 7: // timer
|
||||
mask = 1 << 7;
|
||||
break;
|
||||
case 18: // external
|
||||
case 11: // external
|
||||
mask = 1 << 11;
|
||||
break;
|
||||
default:
|
||||
/* do nothing*/
|
||||
if(id>15) mask = 1 << id;
|
||||
break;
|
||||
}
|
||||
if (value) {
|
||||
@ -357,8 +357,11 @@ void core_complex::init(){
|
||||
sensitive << sw_irq_i;
|
||||
SC_METHOD(timer_irq_cb);
|
||||
sensitive << timer_irq_i;
|
||||
SC_METHOD(global_irq_cb);
|
||||
sensitive << global_irq_i;
|
||||
SC_METHOD(ext_irq_cb);
|
||||
sensitive << ext_irq_i;
|
||||
SC_METHOD(local_irq_cb);
|
||||
for(auto pin:local_irq_i)
|
||||
sensitive << pin;
|
||||
trc->m_db=scv_tr_db::get_default_db();
|
||||
|
||||
SC_METHOD(forward);
|
||||
@ -480,11 +483,19 @@ void core_complex::rst_cb() {
|
||||
if (rst_i.read()) cpu->set_interrupt_execution(true);
|
||||
}
|
||||
|
||||
void core_complex::sw_irq_cb() { cpu->local_irq(16, sw_irq_i.read()); }
|
||||
void core_complex::sw_irq_cb() { cpu->local_irq(3, sw_irq_i.read()); }
|
||||
|
||||
void core_complex::timer_irq_cb() { cpu->local_irq(17, timer_irq_i.read()); }
|
||||
void core_complex::timer_irq_cb() { cpu->local_irq(7, timer_irq_i.read()); }
|
||||
|
||||
void core_complex::global_irq_cb() { cpu->local_irq(18, global_irq_i.read()); }
|
||||
void core_complex::ext_irq_cb() { cpu->local_irq(11, ext_irq_i.read()); }
|
||||
|
||||
void core_complex::local_irq_cb() {
|
||||
for(auto i=0U; i<local_irq_i.size(); ++i) {
|
||||
if(local_irq_i[i].event()) {
|
||||
cpu->local_irq(16+i, local_irq_i[i].read());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void core_complex::run() {
|
||||
wait(SC_ZERO_TIME); // separate from elaboration phase
|
||||
|
@ -73,7 +73,7 @@ public:
|
||||
|
||||
sc_core::sc_in<bool> rst_i{"rst_i"};
|
||||
|
||||
sc_core::sc_in<bool> global_irq_i{"global_irq_i"};
|
||||
sc_core::sc_in<bool> ext_irq_i{"ext_irq_i"};
|
||||
|
||||
sc_core::sc_in<bool> timer_irq_i{"timer_irq_i"};
|
||||
|
||||
@ -181,7 +181,8 @@ protected:
|
||||
void rst_cb();
|
||||
void sw_irq_cb();
|
||||
void timer_irq_cb();
|
||||
void global_irq_cb();
|
||||
void ext_irq_cb();
|
||||
void local_irq_cb();
|
||||
uint64_t last_sync_cycle = 0;
|
||||
util::range_lut<tlm_dmi_ext> read_lut, write_lut;
|
||||
tlm_utils::tlm_quantumkeeper quantum_keeper;
|
||||
|
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user