19 Commits

Author SHA1 Message Date
ec55efd322 adds generator changed files 2023-02-17 06:36:34 +01:00
8c3709f92a adds generator changed files 2023-02-17 06:29:27 +01:00
207dbf1071 fixes out of range access for register alias names 2023-02-17 06:28:30 +01:00
62c118e501 fixes CSR to match latest fast interrupts spec 2023-01-20 16:21:04 +01:00
65dca13b42 fixes WFI miss of interrupt 2023-01-14 17:40:21 +01:00
3187cbdfe2 removes CONAN_PKG from build system 2022-12-12 02:55:44 +01:00
8c701d55c1 adapt to latest changes in SCC 2022-12-05 09:15:48 +01:00
f585489ff5 fixes pin naming 2022-10-26 17:21:44 +02:00
7113683ee0 moves pending interrupt check before handling trap thus saving 1 cycle 2022-10-15 10:47:35 +02:00
1a0fc4bd5d fixes wrong mcounteren in M-mode only priv wrapper 2022-10-10 08:59:27 +02:00
40d1966e9a fixes pending irq within irq hander behavior 2022-10-08 11:20:52 +02:00
a977200284 cleans up priv wrappers 2022-10-05 08:58:57 +02:00
b20fd3eba5 fix static build 2022-09-28 19:37:47 +02:00
b20daa1ac2 fixes wrong path in install 2022-09-27 09:11:41 +02:00
b1a18459e7 adds more flexible use of availabel targets 2022-09-26 13:57:24 +02:00
6ba7c82f80 fixes wrapper definitions for hwl cores 2022-09-26 13:31:46 +02:00
ad7bb28b4c fixes write mask of clic memory mapped registers 2022-09-17 12:15:19 +02:00
fa7eda0889 fixes wrong check for exception 2022-08-31 11:45:53 +02:00
00e02bf565 adds support for different branch types in tracing 2022-08-08 06:30:37 +02:00
10 changed files with 572 additions and 443 deletions

View File

@ -8,6 +8,7 @@ include(GNUInstallDirs)
find_package(elfio QUIET) find_package(elfio QUIET)
find_package(Boost COMPONENTS coroutine) find_package(Boost COMPONENTS coroutine)
find_package(jsoncpp)
if(WITH_LLVM) if(WITH_LLVM)
if(DEFINED ENV{LLVM_HOME}) if(DEFINED ENV{LLVM_HOME})
@ -41,7 +42,7 @@ set(LIB_SOURCES
src/vm/fp_functions.cpp src/vm/fp_functions.cpp
${GEN_SOURCES} ${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) list(APPEND LIB_SOURCES src/iss/plugin/cycle_estimate.cpp src/iss/plugin/pctrace.cpp)
endif() endif()
@ -73,15 +74,18 @@ elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
endif() endif()
target_include_directories(${PROJECT_NAME} PUBLIC src) target_include_directories(${PROJECT_NAME} PUBLIC src)
target_include_directories(${PROJECT_NAME} PUBLIC src-gen) target_include_directories(${PROJECT_NAME} PUBLIC src-gen)
target_link_libraries(${PROJECT_NAME} PUBLIC softfloat scc-util jsoncpp Boost::coroutine) target_link_libraries(${PROJECT_NAME} PUBLIC softfloat scc-util Boost::coroutine)
if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") 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) target_link_libraries(${PROJECT_NAME} PUBLIC -Wl,--whole-archive dbt-rise-core -Wl,--no-whole-archive)
else() else()
target_link_libraries(${PROJECT_NAME} PUBLIC dbt-rise-core) target_link_libraries(${PROJECT_NAME} PUBLIC dbt-rise-core)
endif() endif()
if(TARGET CONAN_PKG::elfio) if(TARGET elfio::elfio)
target_link_libraries(${PROJECT_NAME} PUBLIC CONAN_PKG::elfio)
elseif(TARGET elfio::elfio)
target_link_libraries(${PROJECT_NAME} PUBLIC elfio::elfio) target_link_libraries(${PROJECT_NAME} PUBLIC elfio::elfio)
else() else()
message(FATAL_ERROR "No elfio library found, maybe a find_package() call is missing") 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_compile_definitions(${PROJECT_NAME} PUBLIC WITH_LZ4)
target_link_libraries(${PROJECT_NAME} PUBLIC lz4::lz4) target_link_libraries(${PROJECT_NAME} PUBLIC lz4::lz4)
endif() 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) target_link_libraries(${PROJECT_NAME} PUBLIC RapidJSON)
endif() endif()
@ -172,7 +178,7 @@ if(SystemC_FOUND)
target_link_libraries(${PROJECT_NAME} PUBLIC ${llvm_libs}) target_link_libraries(${PROJECT_NAME} PUBLIC ${llvm_libs})
endif() 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 set_target_properties(${PROJECT_NAME} PROPERTIES
VERSION ${PROJECT_VERSION} VERSION ${PROJECT_VERSION}
FRAMEWORK FALSE FRAMEWORK FALSE

View File

@ -92,7 +92,7 @@ protected:
using compile_ret_t = virt_addr_t; using compile_ret_t = virt_addr_t;
using compile_func = compile_ret_t (this_class::*)(virt_addr_t &pc, code_word_t instr); 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); 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; 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; using coro_t = boost::coroutines2::coroutine<void>::pull_type;
std::vector<coro_t> spawn_blocks; 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> template<unsigned W, typename U, typename S = typename std::make_signed<U>::type>
inline S sext(U from) { inline S sext(U from) {
auto mask = (1ULL<<W) - 1; auto mask = (1ULL<<W) - 1;
@ -183,12 +145,15 @@ protected:
} }
inline void process_spawn_blocks() { 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);) for(auto it = std::begin(spawn_blocks); it!=std::end(spawn_blocks);)
if(*it){ if(*it){
(*it)(); (*it)();
++it; ++it;
} else } else
spawn_blocks.erase(it); spawn_blocks.erase(it);
std::swap(super::ex_info.branch_taken, super::ex_info.hw_branch_taken);
} }
<%functions.each{ it.eachLine { %> <%functions.each{ it.eachLine { %>
${it}<%}%> ${it}<%}%>
@ -324,6 +289,8 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
// post execution stuff // post execution stuff
process_spawn_blocks(); process_spawn_blocks();
if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, static_cast<unsigned>(inst_id)); 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 // trap check
if(trap_state!=0){ if(trap_state!=0){
super::core.enter_trap(trap_state, pc.val, instr); super::core.enter_trap(trap_state, pc.val, instr);

View File

@ -115,10 +115,9 @@ enum riscv_csr {
mip = 0x344, mip = 0x344,
mxnti = 0x345, //CLIC mxnti = 0x345, //CLIC
mintstatus = 0x346, // MRW Current interrupt levels (CLIC) - addr subject to change 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) 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)
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 // Physical Memory Protection
pmpcfg0 = 0x3A0, pmpcfg0 = 0x3A0,
pmpcfg1 = 0x3A1, pmpcfg1 = 0x3A1,

View File

@ -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,21 @@ 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
uart_buf.str(""); uart_buf.str("");
for (unsigned addr = mhpmcounter3; addr <= mhpmcounter31; ++addr){ 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; //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;
@ -433,32 +424,28 @@ riscv_hart_m_p<BASE, FEAT>::riscv_hart_m_p()
csr_wr_cb[mscratchcswl] = &this_class::write_csr_reg; csr_wr_cb[mscratchcswl] = &this_class::write_csr_reg;
csr_rd_cb[mintthresh] = &this_class::read_csr_reg; csr_rd_cb[mintthresh] = &this_class::read_csr_reg;
csr_wr_cb[mintthresh] = &this_class::write_intthresh; 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_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 +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 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 +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) { 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 +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) { 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 +946,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 +970,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 +1046,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 +1065,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 +1094,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) {
@ -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(); this->reg.NEXT_PC = csr[mepc] & get_pc_mask();
CLOG(INFO, disass) << "Executing xRET"; CLOG(INFO, disass) << "Executing xRET";
check_interrupt(); check_interrupt();
this->trap_state = this->pending_trap;
return this->reg.NEXT_PC; return this->reg.NEXT_PC;
} }

View File

@ -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

View File

@ -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);
@ -381,7 +369,6 @@ riscv_hart_mu_p<BASE, FEAT>::riscv_hart_mu_p(feature_config cfg)
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] = 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){
@ -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_wr_cb[mscratchcswl] = &this_class::write_csr_reg;
csr_rd_cb[mintthresh] = &this_class::read_csr_reg; csr_rd_cb[mintthresh] = &this_class::read_csr_reg;
csr_wr_cb[mintthresh] = &this_class::write_intthresh; 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_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; 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; 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 +1112,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 +1136,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
@ -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 } 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;
} }
@ -1278,8 +1260,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) {

View File

@ -16,8 +16,9 @@ using tgc_b_plat_type = iss::arch::riscv_hart_m_p<iss::arch::tgc_b>;
#endif #endif
#ifdef CORE_TGC_C_XRB_NN #ifdef CORE_TGC_C_XRB_NN
#include "riscv_hart_m_p.h" #include "riscv_hart_m_p.h"
#include "hwl.h"
#include <iss/arch/tgc_c_xrb_nn.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 #endif
#ifdef CORE_TGC_D #ifdef CORE_TGC_D
#include "riscv_hart_mu_p.h" #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 #endif
#ifdef CORE_TGC_D_XRB_NN #ifdef CORE_TGC_D_XRB_NN
#include "riscv_hart_mu_p.h" #include "riscv_hart_mu_p.h"
#include "hwl.h"
#include <iss/arch/tgc_d_xrb_nn.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 #endif
#ifdef CORE_TGC_E #ifdef CORE_TGC_E
#include "riscv_hart_mu_p.h" #include "riscv_hart_mu_p.h"

View File

@ -186,17 +186,17 @@ public:
void local_irq(short id, bool value) { void local_irq(short id, bool value) {
reg_t mask = 0; reg_t mask = 0;
switch (id) { switch (id) {
case 16: // SW case 3: // SW
mask = 1 << 3; mask = 1 << 3;
break; break;
case 17: // timer case 7: // timer
mask = 1 << 7; mask = 1 << 7;
break; break;
case 18: // external case 11: // external
mask = 1 << 11; mask = 1 << 11;
break; break;
default: default:
/* do nothing*/ if(id>15) mask = 1 << id;
break; break;
} }
if (value) { if (value) {
@ -357,8 +357,11 @@ void core_complex::init(){
sensitive << sw_irq_i; sensitive << sw_irq_i;
SC_METHOD(timer_irq_cb); SC_METHOD(timer_irq_cb);
sensitive << timer_irq_i; sensitive << timer_irq_i;
SC_METHOD(global_irq_cb); SC_METHOD(ext_irq_cb);
sensitive << global_irq_i; 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(); trc->m_db=scv_tr_db::get_default_db();
SC_METHOD(forward); SC_METHOD(forward);
@ -480,11 +483,19 @@ void core_complex::rst_cb() {
if (rst_i.read()) cpu->set_interrupt_execution(true); 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() { void core_complex::run() {
wait(SC_ZERO_TIME); // separate from elaboration phase wait(SC_ZERO_TIME); // separate from elaboration phase

View File

@ -73,7 +73,7 @@ public:
sc_core::sc_in<bool> rst_i{"rst_i"}; 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"}; sc_core::sc_in<bool> timer_irq_i{"timer_irq_i"};
@ -181,7 +181,8 @@ protected:
void rst_cb(); void rst_cb();
void sw_irq_cb(); void sw_irq_cb();
void timer_irq_cb(); void timer_irq_cb();
void global_irq_cb(); void ext_irq_cb();
void local_irq_cb();
uint64_t last_sync_cycle = 0; uint64_t last_sync_cycle = 0;
util::range_lut<tlm_dmi_ext> read_lut, write_lut; util::range_lut<tlm_dmi_ext> read_lut, write_lut;
tlm_utils::tlm_quantumkeeper quantum_keeper; tlm_utils::tlm_quantumkeeper quantum_keeper;

View File

@ -86,7 +86,7 @@ protected:
using compile_ret_t = virt_addr_t; using compile_ret_t = virt_addr_t;
using compile_func = compile_ret_t (this_class::*)(virt_addr_t &pc, code_word_t instr); 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); 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; virt_addr_t execute_inst(finish_cond_e cond, virt_addr_t start, uint64_t icount_limit) override;
@ -131,44 +131,6 @@ protected:
using coro_t = boost::coroutines2::coroutine<void>::pull_type; using coro_t = boost::coroutines2::coroutine<void>::pull_type;
std::vector<coro_t> spawn_blocks; 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> template<unsigned W, typename U, typename S = typename std::make_signed<U>::type>
inline S sext(U from) { inline S sext(U from) {
auto mask = (1ULL<<W) - 1; auto mask = (1ULL<<W) - 1;
@ -177,12 +139,15 @@ protected:
} }
inline void process_spawn_blocks() { 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);) for(auto it = std::begin(spawn_blocks); it!=std::end(spawn_blocks);)
if(*it){ if(*it){
(*it)(); (*it)();
++it; ++it;
} else } else
spawn_blocks.erase(it); spawn_blocks.erase(it);
std::swap(super::ex_info.branch_taken, super::ex_info.hw_branch_taken);
} }
private: private:
@ -393,8 +358,13 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
*NEXT_PC = *PC + 4; *NEXT_PC = *PC + 4;
// execute instruction // execute instruction
{ {
if((rd % traits::RFS) != 0) { if(rd >= traits::RFS) {
*(X+rd % traits::RFS) = (int32_t)imm; raise(0, 2);
}
else {
if(rd != 0) {
*(X+rd) = (int32_t)imm;
}
} }
} }
TRAP_LUI:break; TRAP_LUI:break;
@ -414,8 +384,13 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
*NEXT_PC = *PC + 4; *NEXT_PC = *PC + 4;
// execute instruction // execute instruction
{ {
if((rd % traits::RFS) != 0) { if(rd >= traits::RFS) {
*(X+rd % traits::RFS) = *PC + (int32_t)imm; raise(0, 2);
}
else {
if(rd != 0) {
*(X+rd) = *PC + (int32_t)imm;
}
} }
} }
TRAP_AUIPC:break; TRAP_AUIPC:break;
@ -435,17 +410,22 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
*NEXT_PC = *PC + 4; *NEXT_PC = *PC + 4;
// execute instruction // execute instruction
{ {
if(rd >= traits::RFS) {
raise(0, 2);
}
else {
if(imm % traits::INSTR_ALIGNMENT) { if(imm % traits::INSTR_ALIGNMENT) {
raise(0, 0); raise(0, 0);
} }
else { else {
if((rd % traits::RFS) != 0) { if(rd != 0) {
*(X+rd % traits::RFS) = *PC + 4; *(X+rd) = *PC + 4;
} }
*NEXT_PC = *PC + (int32_t)sext<21>(imm); *NEXT_PC = *PC + (int32_t)sext<21>(imm);
super::ex_info.branch_taken=true; super::ex_info.branch_taken=true;
} }
} }
}
TRAP_JAL:break; TRAP_JAL:break;
}// @suppress("No break at end of case") }// @suppress("No break at end of case")
case arch::traits<ARCH>::opcode_e::JALR: { case arch::traits<ARCH>::opcode_e::JALR: {
@ -464,18 +444,23 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
*NEXT_PC = *PC + 4; *NEXT_PC = *PC + 4;
// execute instruction // execute instruction
{ {
if(rd >= traits::RFS || rs1 >= traits::RFS) {
raise(0, 2);
}
else {
uint32_t new_pc = (*(X+rs1 % traits::RFS) + (int16_t)sext<12>(imm)) & ~ 0x1; uint32_t new_pc = (*(X+rs1 % traits::RFS) + (int16_t)sext<12>(imm)) & ~ 0x1;
if(new_pc % traits::INSTR_ALIGNMENT) { if(new_pc % traits::INSTR_ALIGNMENT) {
raise(0, 0); raise(0, 0);
} }
else { else {
if((rd % traits::RFS) != 0) { if(rd != 0) {
*(X+rd % traits::RFS) = *PC + 4; *(X+rd) = *PC + 4;
} }
*NEXT_PC = new_pc & ~ 0x1; *NEXT_PC = new_pc & ~ 0x1;
super::ex_info.branch_taken=true; super::ex_info.branch_taken=true;
} }
} }
}
TRAP_JALR:break; TRAP_JALR:break;
}// @suppress("No break at end of case") }// @suppress("No break at end of case")
case arch::traits<ARCH>::opcode_e::BEQ: { case arch::traits<ARCH>::opcode_e::BEQ: {
@ -494,6 +479,10 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
*NEXT_PC = *PC + 4; *NEXT_PC = *PC + 4;
// execute instruction // execute instruction
{ {
if(rs2 >= traits::RFS || rs1 >= traits::RFS) {
raise(0, 2);
}
else {
if(*(X+rs1 % traits::RFS) == *(X+rs2 % traits::RFS)) { if(*(X+rs1 % traits::RFS) == *(X+rs2 % traits::RFS)) {
if(imm % traits::INSTR_ALIGNMENT) { if(imm % traits::INSTR_ALIGNMENT) {
raise(0, 0); raise(0, 0);
@ -504,6 +493,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
} }
} }
} }
}
TRAP_BEQ:break; TRAP_BEQ:break;
}// @suppress("No break at end of case") }// @suppress("No break at end of case")
case arch::traits<ARCH>::opcode_e::BNE: { case arch::traits<ARCH>::opcode_e::BNE: {
@ -522,6 +512,10 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
*NEXT_PC = *PC + 4; *NEXT_PC = *PC + 4;
// execute instruction // execute instruction
{ {
if(rs2 >= traits::RFS || rs1 >= traits::RFS) {
raise(0, 2);
}
else {
if(*(X+rs1 % traits::RFS) != *(X+rs2 % traits::RFS)) { if(*(X+rs1 % traits::RFS) != *(X+rs2 % traits::RFS)) {
if(imm % traits::INSTR_ALIGNMENT) { if(imm % traits::INSTR_ALIGNMENT) {
raise(0, 0); raise(0, 0);
@ -532,6 +526,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
} }
} }
} }
}
TRAP_BNE:break; TRAP_BNE:break;
}// @suppress("No break at end of case") }// @suppress("No break at end of case")
case arch::traits<ARCH>::opcode_e::BLT: { case arch::traits<ARCH>::opcode_e::BLT: {
@ -550,6 +545,10 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
*NEXT_PC = *PC + 4; *NEXT_PC = *PC + 4;
// execute instruction // execute instruction
{ {
if(rs2 >= traits::RFS || rs1 >= traits::RFS) {
raise(0, 2);
}
else {
if((int32_t)*(X+rs1 % traits::RFS) < (int32_t)*(X+rs2 % traits::RFS)) { if((int32_t)*(X+rs1 % traits::RFS) < (int32_t)*(X+rs2 % traits::RFS)) {
if(imm % traits::INSTR_ALIGNMENT) { if(imm % traits::INSTR_ALIGNMENT) {
raise(0, 0); raise(0, 0);
@ -560,6 +559,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
} }
} }
} }
}
TRAP_BLT:break; TRAP_BLT:break;
}// @suppress("No break at end of case") }// @suppress("No break at end of case")
case arch::traits<ARCH>::opcode_e::BGE: { case arch::traits<ARCH>::opcode_e::BGE: {
@ -578,6 +578,10 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
*NEXT_PC = *PC + 4; *NEXT_PC = *PC + 4;
// execute instruction // execute instruction
{ {
if(rs2 >= traits::RFS || rs1 >= traits::RFS) {
raise(0, 2);
}
else {
if((int32_t)*(X+rs1 % traits::RFS) >= (int32_t)*(X+rs2 % traits::RFS)) { if((int32_t)*(X+rs1 % traits::RFS) >= (int32_t)*(X+rs2 % traits::RFS)) {
if(imm % traits::INSTR_ALIGNMENT) { if(imm % traits::INSTR_ALIGNMENT) {
raise(0, 0); raise(0, 0);
@ -588,6 +592,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
} }
} }
} }
}
TRAP_BGE:break; TRAP_BGE:break;
}// @suppress("No break at end of case") }// @suppress("No break at end of case")
case arch::traits<ARCH>::opcode_e::BLTU: { case arch::traits<ARCH>::opcode_e::BLTU: {
@ -606,6 +611,10 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
*NEXT_PC = *PC + 4; *NEXT_PC = *PC + 4;
// execute instruction // execute instruction
{ {
if(rs2 >= traits::RFS || rs1 >= traits::RFS) {
raise(0, 2);
}
else {
if(*(X+rs1 % traits::RFS) < *(X+rs2 % traits::RFS)) { if(*(X+rs1 % traits::RFS) < *(X+rs2 % traits::RFS)) {
if(imm % traits::INSTR_ALIGNMENT) { if(imm % traits::INSTR_ALIGNMENT) {
raise(0, 0); raise(0, 0);
@ -616,6 +625,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
} }
} }
} }
}
TRAP_BLTU:break; TRAP_BLTU:break;
}// @suppress("No break at end of case") }// @suppress("No break at end of case")
case arch::traits<ARCH>::opcode_e::BGEU: { case arch::traits<ARCH>::opcode_e::BGEU: {
@ -634,6 +644,10 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
*NEXT_PC = *PC + 4; *NEXT_PC = *PC + 4;
// execute instruction // execute instruction
{ {
if(rs2 >= traits::RFS || rs1 >= traits::RFS) {
raise(0, 2);
}
else {
if(*(X+rs1 % traits::RFS) >= *(X+rs2 % traits::RFS)) { if(*(X+rs1 % traits::RFS) >= *(X+rs2 % traits::RFS)) {
if(imm % traits::INSTR_ALIGNMENT) { if(imm % traits::INSTR_ALIGNMENT) {
raise(0, 0); raise(0, 0);
@ -644,6 +658,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
} }
} }
} }
}
TRAP_BGEU:break; TRAP_BGEU:break;
}// @suppress("No break at end of case") }// @suppress("No break at end of case")
case arch::traits<ARCH>::opcode_e::LB: { case arch::traits<ARCH>::opcode_e::LB: {
@ -662,12 +677,17 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
*NEXT_PC = *PC + 4; *NEXT_PC = *PC + 4;
// execute instruction // execute instruction
{ {
if(rd >= traits::RFS || rs1 >= traits::RFS) {
raise(0, 2);
}
else {
uint32_t load_address = *(X+rs1 % traits::RFS) + (int16_t)sext<12>(imm); uint32_t load_address = *(X+rs1 % traits::RFS) + (int16_t)sext<12>(imm);
int8_t read_res = super::template read_mem<int8_t>(traits::MEM, load_address); int8_t read_res = super::template read_mem<int8_t>(traits::MEM, load_address);
if(this->core.trap_state) goto TRAP_LB; if(this->core.trap_state>=0x80000000UL) goto TRAP_LB;
int8_t res = (int8_t)read_res; int8_t res = (int8_t)read_res;
if((rd % traits::RFS) != 0) { if(rd != 0) {
*(X+rd % traits::RFS) = (int32_t)res; *(X+rd) = (int32_t)res;
}
} }
} }
TRAP_LB:break; TRAP_LB:break;
@ -688,12 +708,17 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
*NEXT_PC = *PC + 4; *NEXT_PC = *PC + 4;
// execute instruction // execute instruction
{ {
if(rd >= traits::RFS || rs1 >= traits::RFS) {
raise(0, 2);
}
else {
uint32_t load_address = *(X+rs1 % traits::RFS) + (int16_t)sext<12>(imm); uint32_t load_address = *(X+rs1 % traits::RFS) + (int16_t)sext<12>(imm);
int16_t read_res = super::template read_mem<int16_t>(traits::MEM, load_address); int16_t read_res = super::template read_mem<int16_t>(traits::MEM, load_address);
if(this->core.trap_state) goto TRAP_LH; if(this->core.trap_state>=0x80000000UL) goto TRAP_LH;
int16_t res = (int16_t)read_res; int16_t res = (int16_t)read_res;
if((rd % traits::RFS) != 0) { if(rd != 0) {
*(X+rd % traits::RFS) = (int32_t)res; *(X+rd) = (int32_t)res;
}
} }
} }
TRAP_LH:break; TRAP_LH:break;
@ -714,12 +739,17 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
*NEXT_PC = *PC + 4; *NEXT_PC = *PC + 4;
// execute instruction // execute instruction
{ {
if(rd >= traits::RFS || rs1 >= traits::RFS) {
raise(0, 2);
}
else {
uint32_t load_address = *(X+rs1 % traits::RFS) + (int16_t)sext<12>(imm); uint32_t load_address = *(X+rs1 % traits::RFS) + (int16_t)sext<12>(imm);
int32_t read_res = super::template read_mem<int32_t>(traits::MEM, load_address); int32_t read_res = super::template read_mem<int32_t>(traits::MEM, load_address);
if(this->core.trap_state) goto TRAP_LW; if(this->core.trap_state>=0x80000000UL) goto TRAP_LW;
int32_t res = (int32_t)read_res; int32_t res = (int32_t)read_res;
if((rd % traits::RFS) != 0) { if(rd != 0) {
*(X+rd % traits::RFS) = (int32_t)res; *(X+rd) = (int32_t)res;
}
} }
} }
TRAP_LW:break; TRAP_LW:break;
@ -740,12 +770,17 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
*NEXT_PC = *PC + 4; *NEXT_PC = *PC + 4;
// execute instruction // execute instruction
{ {
if(rd >= traits::RFS || rs1 >= traits::RFS) {
raise(0, 2);
}
else {
uint32_t load_address = *(X+rs1 % traits::RFS) + (int16_t)sext<12>(imm); uint32_t load_address = *(X+rs1 % traits::RFS) + (int16_t)sext<12>(imm);
uint8_t read_res = super::template read_mem<uint8_t>(traits::MEM, load_address); uint8_t read_res = super::template read_mem<uint8_t>(traits::MEM, load_address);
if(this->core.trap_state) goto TRAP_LBU; if(this->core.trap_state>=0x80000000UL) goto TRAP_LBU;
uint8_t res = (uint8_t)read_res; uint8_t res = (uint8_t)read_res;
if((rd % traits::RFS) != 0) { if(rd != 0) {
*(X+rd % traits::RFS) = (uint32_t)res; *(X+rd) = (uint32_t)res;
}
} }
} }
TRAP_LBU:break; TRAP_LBU:break;
@ -766,12 +801,17 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
*NEXT_PC = *PC + 4; *NEXT_PC = *PC + 4;
// execute instruction // execute instruction
{ {
if(rd >= traits::RFS || rs1 >= traits::RFS) {
raise(0, 2);
}
else {
uint32_t load_address = *(X+rs1 % traits::RFS) + (int16_t)sext<12>(imm); uint32_t load_address = *(X+rs1 % traits::RFS) + (int16_t)sext<12>(imm);
uint16_t read_res = super::template read_mem<uint16_t>(traits::MEM, load_address); uint16_t read_res = super::template read_mem<uint16_t>(traits::MEM, load_address);
if(this->core.trap_state) goto TRAP_LHU; if(this->core.trap_state>=0x80000000UL) goto TRAP_LHU;
uint16_t res = (uint16_t)read_res; uint16_t res = (uint16_t)read_res;
if((rd % traits::RFS) != 0) { if(rd != 0) {
*(X+rd % traits::RFS) = (uint32_t)res; *(X+rd) = (uint32_t)res;
}
} }
} }
TRAP_LHU:break; TRAP_LHU:break;
@ -792,9 +832,14 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
*NEXT_PC = *PC + 4; *NEXT_PC = *PC + 4;
// execute instruction // execute instruction
{ {
if(rs2 >= traits::RFS || rs1 >= traits::RFS) {
raise(0, 2);
}
else {
uint32_t store_address = *(X+rs1 % traits::RFS) + (int16_t)sext<12>(imm); uint32_t store_address = *(X+rs1 % traits::RFS) + (int16_t)sext<12>(imm);
super::template write_mem<uint8_t>(traits::MEM, store_address, (int8_t)*(X+rs2 % traits::RFS)); super::template write_mem<uint8_t>(traits::MEM, store_address, (int8_t)*(X+rs2 % traits::RFS));
if(this->core.trap_state) goto TRAP_SB; if(this->core.trap_state>=0x80000000UL) goto TRAP_SB;
}
} }
TRAP_SB:break; TRAP_SB:break;
}// @suppress("No break at end of case") }// @suppress("No break at end of case")
@ -814,9 +859,14 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
*NEXT_PC = *PC + 4; *NEXT_PC = *PC + 4;
// execute instruction // execute instruction
{ {
if(rs2 >= traits::RFS || rs1 >= traits::RFS) {
raise(0, 2);
}
else {
uint32_t store_address = *(X+rs1 % traits::RFS) + (int16_t)sext<12>(imm); uint32_t store_address = *(X+rs1 % traits::RFS) + (int16_t)sext<12>(imm);
super::template write_mem<uint16_t>(traits::MEM, store_address, (int16_t)*(X+rs2 % traits::RFS)); super::template write_mem<uint16_t>(traits::MEM, store_address, (int16_t)*(X+rs2 % traits::RFS));
if(this->core.trap_state) goto TRAP_SH; if(this->core.trap_state>=0x80000000UL) goto TRAP_SH;
}
} }
TRAP_SH:break; TRAP_SH:break;
}// @suppress("No break at end of case") }// @suppress("No break at end of case")
@ -836,9 +886,14 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
*NEXT_PC = *PC + 4; *NEXT_PC = *PC + 4;
// execute instruction // execute instruction
{ {
if(rs2 >= traits::RFS || rs1 >= traits::RFS) {
raise(0, 2);
}
else {
uint32_t store_address = *(X+rs1 % traits::RFS) + (int16_t)sext<12>(imm); uint32_t store_address = *(X+rs1 % traits::RFS) + (int16_t)sext<12>(imm);
super::template write_mem<uint32_t>(traits::MEM, store_address, (int32_t)*(X+rs2 % traits::RFS)); super::template write_mem<uint32_t>(traits::MEM, store_address, (int32_t)*(X+rs2 % traits::RFS));
if(this->core.trap_state) goto TRAP_SW; if(this->core.trap_state>=0x80000000UL) goto TRAP_SW;
}
} }
TRAP_SW:break; TRAP_SW:break;
}// @suppress("No break at end of case") }// @suppress("No break at end of case")
@ -858,8 +913,13 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
*NEXT_PC = *PC + 4; *NEXT_PC = *PC + 4;
// execute instruction // execute instruction
{ {
if((rd % traits::RFS) != 0) { if(rd >= traits::RFS || rs1 >= traits::RFS) {
*(X+rd % traits::RFS) = *(X+rs1 % traits::RFS) + (int16_t)sext<12>(imm); raise(0, 2);
}
else {
if(rd != 0) {
*(X+rd) = *(X+rs1 % traits::RFS) + (int16_t)sext<12>(imm);
}
} }
} }
TRAP_ADDI:break; TRAP_ADDI:break;
@ -880,8 +940,13 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
*NEXT_PC = *PC + 4; *NEXT_PC = *PC + 4;
// execute instruction // execute instruction
{ {
if((rd % traits::RFS) != 0) { if(rd >= traits::RFS || rs1 >= traits::RFS) {
*(X+rd % traits::RFS) = ((int32_t)*(X+rs1 % traits::RFS) < (int16_t)sext<12>(imm))? 1 : 0; raise(0, 2);
}
else {
if(rd != 0) {
*(X+rd) = ((int32_t)*(X+rs1 % traits::RFS) < (int16_t)sext<12>(imm))? 1 : 0;
}
} }
} }
TRAP_SLTI:break; TRAP_SLTI:break;
@ -902,8 +967,13 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
*NEXT_PC = *PC + 4; *NEXT_PC = *PC + 4;
// execute instruction // execute instruction
{ {
if((rd % traits::RFS) != 0) { if(rd >= traits::RFS || rs1 >= traits::RFS) {
*(X+rd % traits::RFS) = (*(X+rs1 % traits::RFS) < (uint32_t)((int16_t)sext<12>(imm)))? 1 : 0; raise(0, 2);
}
else {
if(rd != 0) {
*(X+rd) = (*(X+rs1 % traits::RFS) < (uint32_t)((int16_t)sext<12>(imm)))? 1 : 0;
}
} }
} }
TRAP_SLTIU:break; TRAP_SLTIU:break;
@ -924,8 +994,13 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
*NEXT_PC = *PC + 4; *NEXT_PC = *PC + 4;
// execute instruction // execute instruction
{ {
if((rd % traits::RFS) != 0) { if(rd >= traits::RFS || rs1 >= traits::RFS) {
*(X+rd % traits::RFS) = *(X+rs1 % traits::RFS) ^ (int16_t)sext<12>(imm); raise(0, 2);
}
else {
if(rd != 0) {
*(X+rd) = *(X+rs1 % traits::RFS) ^ (int16_t)sext<12>(imm);
}
} }
} }
TRAP_XORI:break; TRAP_XORI:break;
@ -946,8 +1021,13 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
*NEXT_PC = *PC + 4; *NEXT_PC = *PC + 4;
// execute instruction // execute instruction
{ {
if((rd % traits::RFS) != 0) { if(rd >= traits::RFS || rs1 >= traits::RFS) {
*(X+rd % traits::RFS) = *(X+rs1 % traits::RFS) | (int16_t)sext<12>(imm); raise(0, 2);
}
else {
if(rd != 0) {
*(X+rd) = *(X+rs1 % traits::RFS) | (int16_t)sext<12>(imm);
}
} }
} }
TRAP_ORI:break; TRAP_ORI:break;
@ -968,8 +1048,13 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
*NEXT_PC = *PC + 4; *NEXT_PC = *PC + 4;
// execute instruction // execute instruction
{ {
if((rd % traits::RFS) != 0) { if(rd >= traits::RFS || rs1 >= traits::RFS) {
*(X+rd % traits::RFS) = *(X+rs1 % traits::RFS) & (int16_t)sext<12>(imm); raise(0, 2);
}
else {
if(rd != 0) {
*(X+rd) = *(X+rs1 % traits::RFS) & (int16_t)sext<12>(imm);
}
} }
} }
TRAP_ANDI:break; TRAP_ANDI:break;
@ -990,8 +1075,13 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
*NEXT_PC = *PC + 4; *NEXT_PC = *PC + 4;
// execute instruction // execute instruction
{ {
if((rd % traits::RFS) != 0) { if(rd >= traits::RFS || rs1 >= traits::RFS) {
*(X+rd % traits::RFS) = *(X+rs1 % traits::RFS) << shamt; raise(0, 2);
}
else {
if(rd != 0) {
*(X+rd) = *(X+rs1 % traits::RFS) << shamt;
}
} }
} }
TRAP_SLLI:break; TRAP_SLLI:break;
@ -1012,8 +1102,13 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
*NEXT_PC = *PC + 4; *NEXT_PC = *PC + 4;
// execute instruction // execute instruction
{ {
if((rd % traits::RFS) != 0) { if(rd >= traits::RFS || rs1 >= traits::RFS) {
*(X+rd % traits::RFS) = *(X+rs1 % traits::RFS) >> shamt; raise(0, 2);
}
else {
if(rd != 0) {
*(X+rd) = *(X+rs1 % traits::RFS) >> shamt;
}
} }
} }
TRAP_SRLI:break; TRAP_SRLI:break;
@ -1034,8 +1129,13 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
*NEXT_PC = *PC + 4; *NEXT_PC = *PC + 4;
// execute instruction // execute instruction
{ {
if((rd % traits::RFS) != 0) { if(rd >= traits::RFS || rs1 >= traits::RFS) {
*(X+rd % traits::RFS) = (int32_t)*(X+rs1 % traits::RFS) >> shamt; raise(0, 2);
}
else {
if(rd != 0) {
*(X+rd) = (int32_t)*(X+rs1 % traits::RFS) >> shamt;
}
} }
} }
TRAP_SRAI:break; TRAP_SRAI:break;
@ -1056,8 +1156,13 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
*NEXT_PC = *PC + 4; *NEXT_PC = *PC + 4;
// execute instruction // execute instruction
{ {
if((rd % traits::RFS) != 0) { if(rd >= traits::RFS || rs1 >= traits::RFS || rs2 >= traits::RFS) {
*(X+rd % traits::RFS) = *(X+rs1 % traits::RFS) + *(X+rs2 % traits::RFS); raise(0, 2);
}
else {
if(rd != 0) {
*(X+rd) = *(X+rs1 % traits::RFS) + *(X+rs2 % traits::RFS);
}
} }
} }
TRAP_ADD:break; TRAP_ADD:break;
@ -1078,8 +1183,13 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
*NEXT_PC = *PC + 4; *NEXT_PC = *PC + 4;
// execute instruction // execute instruction
{ {
if((rd % traits::RFS) != 0) { if(rd >= traits::RFS || rs1 >= traits::RFS || rs2 >= traits::RFS) {
*(X+rd % traits::RFS) = *(X+rs1 % traits::RFS) - *(X+rs2 % traits::RFS); raise(0, 2);
}
else {
if(rd != 0) {
*(X+rd) = *(X+rs1 % traits::RFS) - *(X+rs2 % traits::RFS);
}
} }
} }
TRAP_SUB:break; TRAP_SUB:break;
@ -1100,8 +1210,13 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
*NEXT_PC = *PC + 4; *NEXT_PC = *PC + 4;
// execute instruction // execute instruction
{ {
if((rd % traits::RFS) != 0) { if(rd >= traits::RFS || rs1 >= traits::RFS || rs2 >= traits::RFS) {
*(X+rd % traits::RFS) = *(X+rs1 % traits::RFS) << (*(X+rs2 % traits::RFS) & (traits::XLEN - 1)); raise(0, 2);
}
else {
if(rd != 0) {
*(X+rd) = *(X+rs1 % traits::RFS) << (*(X+rs2 % traits::RFS) & (traits::XLEN - 1));
}
} }
} }
TRAP_SLL:break; TRAP_SLL:break;
@ -1122,8 +1237,18 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
*NEXT_PC = *PC + 4; *NEXT_PC = *PC + 4;
// execute instruction // execute instruction
{ {
if((rd % traits::RFS) != 0) { if(rd >= traits::RFS || rs1 >= traits::RFS || rs2 >= traits::RFS) {
*(X+rd % traits::RFS) = (int32_t)*(X+rs1 % traits::RFS) < (int32_t)*(X+rs2 % traits::RFS)? 1 : 0; raise(0, 2);
}
else {
if(rd >= traits::RFS || rs1 >= traits::RFS || rs2 >= traits::RFS) {
raise(0, 2);
}
else {
if(rd != 0) {
*(X+rd) = (int32_t)*(X+rs1 % traits::RFS) < (int32_t)*(X+rs2 % traits::RFS)? 1 : 0;
}
}
} }
} }
TRAP_SLT:break; TRAP_SLT:break;
@ -1144,8 +1269,13 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
*NEXT_PC = *PC + 4; *NEXT_PC = *PC + 4;
// execute instruction // execute instruction
{ {
if((rd % traits::RFS) != 0) { if(rd >= traits::RFS || rs1 >= traits::RFS || rs2 >= traits::RFS) {
*(X+rd % traits::RFS) = (uint32_t)*(X+rs1 % traits::RFS) < (uint32_t)*(X+rs2 % traits::RFS)? 1 : 0; raise(0, 2);
}
else {
if(rd != 0) {
*(X+rd) = (uint32_t)*(X+rs1 % traits::RFS) < (uint32_t)*(X+rs2 % traits::RFS)? 1 : 0;
}
} }
} }
TRAP_SLTU:break; TRAP_SLTU:break;
@ -1166,8 +1296,13 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
*NEXT_PC = *PC + 4; *NEXT_PC = *PC + 4;
// execute instruction // execute instruction
{ {
if((rd % traits::RFS) != 0) { if(rd >= traits::RFS || rs1 >= traits::RFS || rs2 >= traits::RFS) {
*(X+rd % traits::RFS) = *(X+rs1 % traits::RFS) ^ *(X+rs2 % traits::RFS); raise(0, 2);
}
else {
if(rd != 0) {
*(X+rd) = *(X+rs1 % traits::RFS) ^ *(X+rs2 % traits::RFS);
}
} }
} }
TRAP_XOR:break; TRAP_XOR:break;
@ -1188,8 +1323,13 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
*NEXT_PC = *PC + 4; *NEXT_PC = *PC + 4;
// execute instruction // execute instruction
{ {
if((rd % traits::RFS) != 0) { if(rd >= traits::RFS || rs1 >= traits::RFS || rs2 >= traits::RFS) {
*(X+rd % traits::RFS) = *(X+rs1 % traits::RFS) >> (*(X+rs2 % traits::RFS) & (traits::XLEN - 1)); raise(0, 2);
}
else {
if(rd != 0) {
*(X+rd) = *(X+rs1 % traits::RFS) >> (*(X+rs2 % traits::RFS) & (traits::XLEN - 1));
}
} }
} }
TRAP_SRL:break; TRAP_SRL:break;
@ -1210,8 +1350,13 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
*NEXT_PC = *PC + 4; *NEXT_PC = *PC + 4;
// execute instruction // execute instruction
{ {
if((rd % traits::RFS) != 0) { if(rd >= traits::RFS || rs1 >= traits::RFS || rs2 >= traits::RFS) {
*(X+rd % traits::RFS) = (int32_t)*(X+rs1 % traits::RFS) >> (*(X+rs2 % traits::RFS) & (traits::XLEN - 1)); raise(0, 2);
}
else {
if(rd != 0) {
*(X+rd) = (int32_t)*(X+rs1 % traits::RFS) >> (*(X+rs2 % traits::RFS) & (traits::XLEN - 1));
}
} }
} }
TRAP_SRA:break; TRAP_SRA:break;
@ -1232,8 +1377,13 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
*NEXT_PC = *PC + 4; *NEXT_PC = *PC + 4;
// execute instruction // execute instruction
{ {
if((rd % traits::RFS) != 0) { if(rd >= traits::RFS || rs1 >= traits::RFS || rs2 >= traits::RFS) {
*(X+rd % traits::RFS) = *(X+rs1 % traits::RFS) | *(X+rs2 % traits::RFS); raise(0, 2);
}
else {
if(rd != 0) {
*(X+rd) = *(X+rs1 % traits::RFS) | *(X+rs2 % traits::RFS);
}
} }
} }
TRAP_OR:break; TRAP_OR:break;
@ -1254,8 +1404,13 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
*NEXT_PC = *PC + 4; *NEXT_PC = *PC + 4;
// execute instruction // execute instruction
{ {
if((rd % traits::RFS) != 0) { if(rd >= traits::RFS || rs1 >= traits::RFS || rs2 >= traits::RFS) {
*(X+rd % traits::RFS) = *(X+rs1 % traits::RFS) & *(X+rs2 % traits::RFS); raise(0, 2);
}
else {
if(rd != 0) {
*(X+rd) = *(X+rs1 % traits::RFS) & *(X+rs2 % traits::RFS);
}
} }
} }
TRAP_AND:break; TRAP_AND:break;
@ -1278,7 +1433,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
// execute instruction // execute instruction
{ {
super::template write_mem<uint8_t>(traits::FENCE, traits::fence, pred << 4 | succ); super::template write_mem<uint8_t>(traits::FENCE, traits::fence, pred << 4 | succ);
if(this->core.trap_state) goto TRAP_FENCE; if(this->core.trap_state>=0x80000000UL) goto TRAP_FENCE;
} }
TRAP_FENCE:break; TRAP_FENCE:break;
}// @suppress("No break at end of case") }// @suppress("No break at end of case")
@ -1350,18 +1505,23 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
*NEXT_PC = *PC + 4; *NEXT_PC = *PC + 4;
// execute instruction // execute instruction
{ {
if(rd >= traits::RFS || rs1 >= traits::RFS) {
raise(0, 2);
}
else {
uint32_t xrs1 = *(X+rs1 % traits::RFS); uint32_t xrs1 = *(X+rs1 % traits::RFS);
if((rd % traits::RFS) != 0) { if(rd != 0) {
uint32_t read_res = super::template read_mem<uint32_t>(traits::CSR, csr); uint32_t read_res = super::template read_mem<uint32_t>(traits::CSR, csr);
if(this->core.trap_state) goto TRAP_CSRRW; if(this->core.trap_state>=0x80000000UL) goto TRAP_CSRRW;
uint32_t xrd = read_res; uint32_t xrd = read_res;
super::template write_mem<uint32_t>(traits::CSR, csr, xrs1); super::template write_mem<uint32_t>(traits::CSR, csr, xrs1);
if(this->core.trap_state) goto TRAP_CSRRW; if(this->core.trap_state>=0x80000000UL) goto TRAP_CSRRW;
*(X+rd % traits::RFS) = xrd; *(X+rd) = xrd;
} }
else { else {
super::template write_mem<uint32_t>(traits::CSR, csr, xrs1); super::template write_mem<uint32_t>(traits::CSR, csr, xrs1);
if(this->core.trap_state) goto TRAP_CSRRW; if(this->core.trap_state>=0x80000000UL) goto TRAP_CSRRW;
}
} }
} }
TRAP_CSRRW:break; TRAP_CSRRW:break;
@ -1382,16 +1542,21 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
*NEXT_PC = *PC + 4; *NEXT_PC = *PC + 4;
// execute instruction // execute instruction
{ {
if(rd >= traits::RFS || rs1 >= traits::RFS) {
raise(0, 2);
}
else {
uint32_t read_res = super::template read_mem<uint32_t>(traits::CSR, csr); uint32_t read_res = super::template read_mem<uint32_t>(traits::CSR, csr);
if(this->core.trap_state) goto TRAP_CSRRS; if(this->core.trap_state>=0x80000000UL) goto TRAP_CSRRS;
uint32_t xrd = read_res; uint32_t xrd = read_res;
uint32_t xrs1 = *(X+rs1 % traits::RFS); uint32_t xrs1 = *(X+rs1 % traits::RFS);
if(rs1 != 0) { if(rs1 != 0) {
super::template write_mem<uint32_t>(traits::CSR, csr, xrd | xrs1); super::template write_mem<uint32_t>(traits::CSR, csr, xrd | xrs1);
if(this->core.trap_state) goto TRAP_CSRRS; if(this->core.trap_state>=0x80000000UL) goto TRAP_CSRRS;
}
if(rd != 0) {
*(X+rd) = xrd;
} }
if((rd % traits::RFS) != 0) {
*(X+rd % traits::RFS) = xrd;
} }
} }
TRAP_CSRRS:break; TRAP_CSRRS:break;
@ -1412,16 +1577,21 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
*NEXT_PC = *PC + 4; *NEXT_PC = *PC + 4;
// execute instruction // execute instruction
{ {
if(rd >= traits::RFS || rs1 >= traits::RFS) {
raise(0, 2);
}
else {
uint32_t read_res = super::template read_mem<uint32_t>(traits::CSR, csr); uint32_t read_res = super::template read_mem<uint32_t>(traits::CSR, csr);
if(this->core.trap_state) goto TRAP_CSRRC; if(this->core.trap_state>=0x80000000UL) goto TRAP_CSRRC;
uint32_t xrd = read_res; uint32_t xrd = read_res;
uint32_t xrs1 = *(X+rs1 % traits::RFS); uint32_t xrs1 = *(X+rs1 % traits::RFS);
if(rs1 != 0) { if(rs1 != 0) {
super::template write_mem<uint32_t>(traits::CSR, csr, xrd & ~ xrs1); super::template write_mem<uint32_t>(traits::CSR, csr, xrd & ~ xrs1);
if(this->core.trap_state) goto TRAP_CSRRC; if(this->core.trap_state>=0x80000000UL) goto TRAP_CSRRC;
}
if(rd != 0) {
*(X+rd) = xrd;
} }
if((rd % traits::RFS) != 0) {
*(X+rd % traits::RFS) = xrd;
} }
} }
TRAP_CSRRC:break; TRAP_CSRRC:break;
@ -1442,13 +1612,18 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
*NEXT_PC = *PC + 4; *NEXT_PC = *PC + 4;
// execute instruction // execute instruction
{ {
if(rd >= traits::RFS) {
raise(0, 2);
}
else {
uint32_t read_res = super::template read_mem<uint32_t>(traits::CSR, csr); uint32_t read_res = super::template read_mem<uint32_t>(traits::CSR, csr);
if(this->core.trap_state) goto TRAP_CSRRWI; if(this->core.trap_state>=0x80000000UL) goto TRAP_CSRRWI;
uint32_t xrd = read_res; uint32_t xrd = read_res;
super::template write_mem<uint32_t>(traits::CSR, csr, (uint32_t)zimm); super::template write_mem<uint32_t>(traits::CSR, csr, (uint32_t)zimm);
if(this->core.trap_state) goto TRAP_CSRRWI; if(this->core.trap_state>=0x80000000UL) goto TRAP_CSRRWI;
if((rd % traits::RFS) != 0) { if(rd != 0) {
*(X+rd % traits::RFS) = xrd; *(X+rd) = xrd;
}
} }
} }
TRAP_CSRRWI:break; TRAP_CSRRWI:break;
@ -1469,15 +1644,20 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
*NEXT_PC = *PC + 4; *NEXT_PC = *PC + 4;
// execute instruction // execute instruction
{ {
if(rd >= traits::RFS) {
raise(0, 2);
}
else {
uint32_t read_res = super::template read_mem<uint32_t>(traits::CSR, csr); uint32_t read_res = super::template read_mem<uint32_t>(traits::CSR, csr);
if(this->core.trap_state) goto TRAP_CSRRSI; if(this->core.trap_state>=0x80000000UL) goto TRAP_CSRRSI;
uint32_t xrd = read_res; uint32_t xrd = read_res;
if(zimm != 0) { if(zimm != 0) {
super::template write_mem<uint32_t>(traits::CSR, csr, xrd | (uint32_t)zimm); super::template write_mem<uint32_t>(traits::CSR, csr, xrd | (uint32_t)zimm);
if(this->core.trap_state) goto TRAP_CSRRSI; if(this->core.trap_state>=0x80000000UL) goto TRAP_CSRRSI;
}
if(rd != 0) {
*(X+rd) = xrd;
} }
if((rd % traits::RFS) != 0) {
*(X+rd % traits::RFS) = xrd;
} }
} }
TRAP_CSRRSI:break; TRAP_CSRRSI:break;
@ -1498,15 +1678,20 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
*NEXT_PC = *PC + 4; *NEXT_PC = *PC + 4;
// execute instruction // execute instruction
{ {
if(rd >= traits::RFS) {
raise(0, 2);
}
else {
uint32_t read_res = super::template read_mem<uint32_t>(traits::CSR, csr); uint32_t read_res = super::template read_mem<uint32_t>(traits::CSR, csr);
if(this->core.trap_state) goto TRAP_CSRRCI; if(this->core.trap_state>=0x80000000UL) goto TRAP_CSRRCI;
uint32_t xrd = read_res; uint32_t xrd = read_res;
if(zimm != 0) { if(zimm != 0) {
super::template write_mem<uint32_t>(traits::CSR, csr, xrd & ~ ((uint32_t)zimm)); super::template write_mem<uint32_t>(traits::CSR, csr, xrd & ~ ((uint32_t)zimm));
if(this->core.trap_state) goto TRAP_CSRRCI; if(this->core.trap_state>=0x80000000UL) goto TRAP_CSRRCI;
}
if(rd != 0) {
*(X+rd) = xrd;
} }
if((rd % traits::RFS) != 0) {
*(X+rd % traits::RFS) = xrd;
} }
} }
TRAP_CSRRCI:break; TRAP_CSRRCI:break;
@ -1527,7 +1712,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
// execute instruction // execute instruction
{ {
super::template write_mem<uint16_t>(traits::FENCE, traits::fencei, imm); super::template write_mem<uint16_t>(traits::FENCE, traits::fencei, imm);
if(this->core.trap_state) goto TRAP_FENCE_I; if(this->core.trap_state>=0x80000000UL) goto TRAP_FENCE_I;
} }
TRAP_FENCE_I:break; TRAP_FENCE_I:break;
}// @suppress("No break at end of case") }// @suppress("No break at end of case")
@ -1785,7 +1970,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
{ {
uint32_t load_address = *(X+rs1 + 8) + uimm; uint32_t load_address = *(X+rs1 + 8) + uimm;
int32_t read_res = super::template read_mem<int32_t>(traits::MEM, load_address); int32_t read_res = super::template read_mem<int32_t>(traits::MEM, load_address);
if(this->core.trap_state) goto TRAP_CLW; if(this->core.trap_state>=0x80000000UL) goto TRAP_CLW;
*(X+rd + 8) = (int32_t)read_res; *(X+rd + 8) = (int32_t)read_res;
} }
TRAP_CLW:break; TRAP_CLW:break;
@ -1808,7 +1993,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
{ {
uint32_t load_address = *(X+rs1 + 8) + uimm; uint32_t load_address = *(X+rs1 + 8) + uimm;
super::template write_mem<uint32_t>(traits::MEM, load_address, (int32_t)*(X+rs2 + 8)); super::template write_mem<uint32_t>(traits::MEM, load_address, (int32_t)*(X+rs2 + 8));
if(this->core.trap_state) goto TRAP_CSW; if(this->core.trap_state>=0x80000000UL) goto TRAP_CSW;
} }
TRAP_CSW:break; TRAP_CSW:break;
}// @suppress("No break at end of case") }// @suppress("No break at end of case")
@ -2188,7 +2373,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
{ {
if(rd % traits::RFS) { if(rd % traits::RFS) {
int32_t read_res = super::template read_mem<int32_t>(traits::MEM, *(X+2) + uimm); int32_t read_res = super::template read_mem<int32_t>(traits::MEM, *(X+2) + uimm);
if(this->core.trap_state) goto TRAP_CLWSP; if(this->core.trap_state>=0x80000000UL) goto TRAP_CLWSP;
int32_t res = read_res; int32_t res = read_res;
*(X+rd % traits::RFS) = (int32_t)res; *(X+rd % traits::RFS) = (int32_t)res;
} }
@ -2328,7 +2513,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
{ {
uint32_t offs = *(X+2) + uimm; uint32_t offs = *(X+2) + uimm;
super::template write_mem<uint32_t>(traits::MEM, offs, (uint32_t)*(X+rs2 % traits::RFS)); super::template write_mem<uint32_t>(traits::MEM, offs, (uint32_t)*(X+rs2 % traits::RFS));
if(this->core.trap_state) goto TRAP_CSWSP; if(this->core.trap_state>=0x80000000UL) goto TRAP_CSWSP;
} }
TRAP_CSWSP:break; TRAP_CSWSP:break;
}// @suppress("No break at end of case") }// @suppress("No break at end of case")
@ -2353,6 +2538,8 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
// post execution stuff // post execution stuff
process_spawn_blocks(); process_spawn_blocks();
if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, static_cast<unsigned>(inst_id)); 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 // trap check
if(trap_state!=0){ if(trap_state!=0){
super::core.enter_trap(trap_state, pc.val, instr); super::core.enter_trap(trap_state, pc.val, instr);