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