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(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
|
||||||
|
@ -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);
|
||||||
|
@ -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,
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -312,14 +312,6 @@ public:
|
|||||||
|
|
||||||
iss::instrumentation_if *get_instrumentation_if() override { return &instr_if; }
|
iss::instrumentation_if *get_instrumentation_if() override { return &instr_if; }
|
||||||
|
|
||||||
void setMemReadCb(std::function<iss::status(phys_addr_t, unsigned, uint8_t* const)> const& memReadCb) {
|
|
||||||
mem_read_cb = memReadCb;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setMemWriteCb(std::function<iss::status(phys_addr_t, unsigned, const uint8_t* const)> const& memWriteCb) {
|
|
||||||
mem_write_cb = memWriteCb;
|
|
||||||
}
|
|
||||||
|
|
||||||
void set_csr(unsigned addr, reg_t val){
|
void set_csr(unsigned addr, reg_t val){
|
||||||
csr[addr & csr.page_addr_mask] = val;
|
csr[addr & csr.page_addr_mask] = val;
|
||||||
}
|
}
|
||||||
@ -422,8 +414,6 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
reg_t mhartid_reg{0x0};
|
reg_t mhartid_reg{0x0};
|
||||||
std::function<iss::status(phys_addr_t, unsigned, uint8_t *const)>mem_read_cb;
|
|
||||||
std::function<iss::status(phys_addr_t, unsigned, const uint8_t *const)> mem_write_cb;
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void check_interrupt();
|
void check_interrupt();
|
||||||
@ -1031,7 +1021,6 @@ template <typename BASE> iss::status riscv_hart_msu_vp<BASE>::write_fcsr(unsigne
|
|||||||
|
|
||||||
template <typename BASE>
|
template <typename BASE>
|
||||||
iss::status riscv_hart_msu_vp<BASE>::read_mem(phys_addr_t paddr, unsigned length, uint8_t *const data) {
|
iss::status riscv_hart_msu_vp<BASE>::read_mem(phys_addr_t paddr, unsigned length, uint8_t *const data) {
|
||||||
if(mem_read_cb) return mem_read_cb(paddr, length, data);
|
|
||||||
switch (paddr.val) {
|
switch (paddr.val) {
|
||||||
case 0x0200BFF8: { // CLINT base, mtime reg
|
case 0x0200BFF8: { // CLINT base, mtime reg
|
||||||
if (sizeof(reg_t) < length) return iss::Err;
|
if (sizeof(reg_t) < length) return iss::Err;
|
||||||
@ -1056,7 +1045,6 @@ iss::status riscv_hart_msu_vp<BASE>::read_mem(phys_addr_t paddr, unsigned length
|
|||||||
|
|
||||||
template <typename BASE>
|
template <typename BASE>
|
||||||
iss::status riscv_hart_msu_vp<BASE>::write_mem(phys_addr_t paddr, unsigned length, const uint8_t *const data) {
|
iss::status riscv_hart_msu_vp<BASE>::write_mem(phys_addr_t paddr, unsigned length, const uint8_t *const data) {
|
||||||
if(mem_write_cb) return mem_write_cb(paddr, length, data);
|
|
||||||
switch (paddr.val) {
|
switch (paddr.val) {
|
||||||
case 0x10013000: // UART0 base, TXFIFO reg
|
case 0x10013000: // UART0 base, TXFIFO reg
|
||||||
case 0x10023000: // UART1 base, TXFIFO reg
|
case 0x10023000: // UART1 base, TXFIFO reg
|
||||||
|
@ -223,14 +223,6 @@ public:
|
|||||||
|
|
||||||
iss::instrumentation_if *get_instrumentation_if() override { return &instr_if; }
|
iss::instrumentation_if *get_instrumentation_if() override { return &instr_if; }
|
||||||
|
|
||||||
void setMemReadCb(std::function<iss::status(phys_addr_t, unsigned, uint8_t* const)> const& memReadCb) {
|
|
||||||
mem_read_cb = memReadCb;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setMemWriteCb(std::function<iss::status(phys_addr_t, unsigned, const uint8_t* const)> const& memWriteCb) {
|
|
||||||
mem_write_cb = memWriteCb;
|
|
||||||
}
|
|
||||||
|
|
||||||
void set_csr(unsigned addr, reg_t val){
|
void set_csr(unsigned addr, reg_t val){
|
||||||
csr[addr & csr.page_addr_mask] = val;
|
csr[addr & csr.page_addr_mask] = val;
|
||||||
}
|
}
|
||||||
@ -250,26 +242,24 @@ protected:
|
|||||||
*/
|
*/
|
||||||
const std::string core_type_name() const override { return traits<BASE>::core_type; }
|
const std::string core_type_name() const override { return traits<BASE>::core_type; }
|
||||||
|
|
||||||
virtual uint64_t get_pc() { return arch.get_pc(); };
|
uint64_t get_pc() override { return arch.reg.PC; };
|
||||||
|
|
||||||
virtual uint64_t get_next_pc() { return arch.get_next_pc(); };
|
uint64_t get_next_pc() override { return arch.reg.NEXT_PC; };
|
||||||
|
|
||||||
uint64_t get_instr_word() override { return arch.instruction; }
|
uint64_t get_instr_word() override { return arch.instruction; }
|
||||||
|
|
||||||
uint64_t get_instr_count() { return arch.icount; }
|
uint64_t get_instr_count() override { return arch.icount; }
|
||||||
|
|
||||||
uint64_t get_pendig_traps() override { return arch.trap_state; }
|
uint64_t get_pendig_traps() override { return arch.trap_state; }
|
||||||
|
|
||||||
uint64_t get_total_cycles() override { return arch.icount + arch.cycle_offset; }
|
uint64_t get_total_cycles() override { return arch.icount + arch.cycle_offset; }
|
||||||
|
|
||||||
virtual void set_curr_instr_cycles(unsigned cycles) { arch.cycle_offset += cycles - 1; };
|
void set_curr_instr_cycles(unsigned cycles) override { arch.cycle_offset += cycles - 1; };
|
||||||
|
|
||||||
riscv_hart_mu_p<BASE, FEAT> &arch;
|
riscv_hart_mu_p<BASE, FEAT> &arch;
|
||||||
};
|
};
|
||||||
|
|
||||||
friend struct riscv_instrumentation_if;
|
friend struct riscv_instrumentation_if;
|
||||||
addr_t get_pc() { return this->reg.PC; }
|
|
||||||
addr_t get_next_pc() { return this->reg.NEXT_PC; }
|
|
||||||
|
|
||||||
virtual iss::status read_mem(phys_addr_t addr, unsigned length, uint8_t *const data);
|
virtual iss::status read_mem(phys_addr_t addr, unsigned length, uint8_t *const data);
|
||||||
virtual iss::status write_mem(phys_addr_t addr, unsigned length, const uint8_t *const data);
|
virtual iss::status write_mem(phys_addr_t addr, unsigned length, const uint8_t *const data);
|
||||||
@ -357,8 +347,6 @@ protected:
|
|||||||
}
|
}
|
||||||
|
|
||||||
reg_t mhartid_reg{0x0};
|
reg_t mhartid_reg{0x0};
|
||||||
std::function<iss::status(phys_addr_t, unsigned, uint8_t *const)>mem_read_cb;
|
|
||||||
std::function<iss::status(phys_addr_t, unsigned, const uint8_t *const)> mem_write_cb;
|
|
||||||
|
|
||||||
void check_interrupt();
|
void check_interrupt();
|
||||||
bool pmp_check(const access_type type, const uint64_t addr, const unsigned len);
|
bool pmp_check(const access_type type, const uint64_t addr, const unsigned len);
|
||||||
@ -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) {
|
||||||
|
@ -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"
|
||||||
|
@ -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
|
||||||
|
@ -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;
|
||||||
|
@ -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);
|
||||||
|
Reference in New Issue
Block a user