Comparar commits
43 Commits
c376e34b2b
...
feature/ev
Autor | SHA1 | Fecha | |
---|---|---|---|
7ea3a6261d | |||
a6a6f51f0b | |||
21e1f791ad | |||
be6f5791fa | |||
ac818f304d | |||
ad60449073 | |||
b45b3589fa | |||
1fb7e8fcea | |||
5f9d0beafb | |||
4c0d1c75aa | |||
2f3abf2f76 | |||
62768bf81e | |||
f6be8ec006 | |||
a8f56b6e27 | |||
76ea0db25d | |||
ec1b820c18 | |||
64329cf0f6 | |||
9de0aed84d | |||
bb4e2766d1 | |||
0996d15bd4 | |||
6305efa7c2 | |||
de79adc50d | |||
0473aa5344 | |||
a45fcd28db | |||
0f15032210 | |||
efc11d87a5 | |||
4a19e27926 | |||
c15cdb0955 | |||
6609d12582 | |||
b5341700aa | |||
0b5062d21c | |||
fbca690b3b | |||
235a7e6e24 | |||
62d21e1156 | |||
9c51d6eade | |||
2878dca6b5 | |||
c28e8fd00c | |||
b3cc9d2346 | |||
933f08494c | |||
21f8eab432 | |||
6ddb8da07f | |||
edf456c59f | |||
42efced1eb |
@ -20,6 +20,7 @@ set(LIB_SOURCES
|
|||||||
src/iss/arch/tgc5c.cpp
|
src/iss/arch/tgc5c.cpp
|
||||||
src/vm/interp/vm_tgc5c.cpp
|
src/vm/interp/vm_tgc5c.cpp
|
||||||
src/vm/fp_functions.cpp
|
src/vm/fp_functions.cpp
|
||||||
|
src/iss/debugger/csr_names.cpp
|
||||||
src/iss/semihosting/semihosting.cpp
|
src/iss/semihosting/semihosting.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -108,15 +109,14 @@ if(TARGET yaml-cpp::yaml-cpp)
|
|||||||
target_link_libraries(${PROJECT_NAME} PUBLIC yaml-cpp::yaml-cpp)
|
target_link_libraries(${PROJECT_NAME} PUBLIC yaml-cpp::yaml-cpp)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(WITH_LLVM)
|
# if(WITH_LLVM)
|
||||||
find_package(LLVM)
|
# target_compile_definitions(${PROJECT_NAME} PUBLIC ${LLVM_DEFINITIONS})
|
||||||
target_compile_definitions(${PROJECT_NAME} PUBLIC ${LLVM_DEFINITIONS})
|
# target_include_directories(${PROJECT_NAME} PUBLIC ${LLVM_INCLUDE_DIRS})
|
||||||
target_include_directories(${PROJECT_NAME} PUBLIC ${LLVM_INCLUDE_DIRS})
|
|
||||||
|
|
||||||
if(BUILD_SHARED_LIBS)
|
# if(BUILD_SHARED_LIBS)
|
||||||
target_link_libraries(${PROJECT_NAME} PUBLIC ${LLVM_LIBRARIES})
|
# target_link_libraries(${PROJECT_NAME} PUBLIC ${LLVM_LIBRARIES})
|
||||||
endif()
|
# endif()
|
||||||
endif()
|
# endif()
|
||||||
|
|
||||||
set_target_properties(${PROJECT_NAME} PROPERTIES
|
set_target_properties(${PROJECT_NAME} PROPERTIES
|
||||||
VERSION ${PROJECT_VERSION}
|
VERSION ${PROJECT_VERSION}
|
||||||
@ -261,3 +261,9 @@ if(TARGET scc-sysc)
|
|||||||
INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} # headers
|
INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} # headers
|
||||||
)
|
)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
project(elfio-test)
|
||||||
|
find_package(Boost COMPONENTS program_options thread REQUIRED)
|
||||||
|
|
||||||
|
add_executable(${PROJECT_NAME} src/elfio.cpp)
|
||||||
|
target_link_libraries(${PROJECT_NAME} PUBLIC elfio::elfio)
|
||||||
|
@ -131,8 +131,6 @@ struct ${coreDef.name.toLowerCase()}: public arch_if {
|
|||||||
|
|
||||||
uint8_t* get_regs_base_ptr() override;
|
uint8_t* get_regs_base_ptr() override;
|
||||||
|
|
||||||
inline uint64_t get_icount() { return reg.icount; }
|
|
||||||
|
|
||||||
inline bool should_stop() { return interrupt_sim; }
|
inline bool should_stop() { return interrupt_sim; }
|
||||||
|
|
||||||
inline uint64_t stop_code() { return interrupt_sim; }
|
inline uint64_t stop_code() { return interrupt_sim; }
|
||||||
@ -141,8 +139,6 @@ struct ${coreDef.name.toLowerCase()}: public arch_if {
|
|||||||
|
|
||||||
virtual iss::sync_type needed_sync() const { return iss::NO_SYNC; }
|
virtual iss::sync_type needed_sync() const { return iss::NO_SYNC; }
|
||||||
|
|
||||||
inline uint32_t get_last_branch() { return reg.last_branch; }
|
|
||||||
|
|
||||||
|
|
||||||
#pragma pack(push, 1)
|
#pragma pack(push, 1)
|
||||||
struct ${coreDef.name}_regs {<%
|
struct ${coreDef.name}_regs {<%
|
||||||
|
@ -45,17 +45,17 @@ namespace interp {
|
|||||||
using namespace sysc;
|
using namespace sysc;
|
||||||
volatile std::array<bool, ${array_count}> ${coreDef.name.toLowerCase()}_init = {
|
volatile std::array<bool, ${array_count}> ${coreDef.name.toLowerCase()}_init = {
|
||||||
iss_factory::instance().register_creator("${coreDef.name.toLowerCase()}|m_p|interp", [](unsigned gdb_port, void* data) -> iss_factory::base_t {
|
iss_factory::instance().register_creator("${coreDef.name.toLowerCase()}|m_p|interp", [](unsigned gdb_port, void* data) -> iss_factory::base_t {
|
||||||
auto* cc = reinterpret_cast<sysc::tgfs::core_complex*>(data);
|
auto* cc = reinterpret_cast<sysc::tgfs::core_complex_if*>(data);
|
||||||
auto* cpu = new sc_core_adapter<arch::riscv_hart_m_p<arch::${coreDef.name.toLowerCase()}>>(cc);
|
auto* cpu = new sc_core_adapter<arch::riscv_hart_m_p<arch::${coreDef.name.toLowerCase()}>>(cc);
|
||||||
return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast<arch::${coreDef.name.toLowerCase()}*>(cpu), gdb_port)}};
|
return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast<arch::${coreDef.name.toLowerCase()}*>(cpu), gdb_port)}};
|
||||||
}),
|
}),
|
||||||
iss_factory::instance().register_creator("${coreDef.name.toLowerCase()}|mu_p|interp", [](unsigned gdb_port, void* data) -> iss_factory::base_t {
|
iss_factory::instance().register_creator("${coreDef.name.toLowerCase()}|mu_p|interp", [](unsigned gdb_port, void* data) -> iss_factory::base_t {
|
||||||
auto* cc = reinterpret_cast<sysc::tgfs::core_complex*>(data);
|
auto* cc = reinterpret_cast<sysc::tgfs::core_complex_if*>(data);
|
||||||
auto* cpu = new sc_core_adapter<arch::riscv_hart_mu_p<arch::${coreDef.name.toLowerCase()}>>(cc);
|
auto* cpu = new sc_core_adapter<arch::riscv_hart_mu_p<arch::${coreDef.name.toLowerCase()}>>(cc);
|
||||||
return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast<arch::${coreDef.name.toLowerCase()}*>(cpu), gdb_port)}};
|
return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast<arch::${coreDef.name.toLowerCase()}*>(cpu), gdb_port)}};
|
||||||
})<%if(coreDef.name.toLowerCase()=="tgc5d" || coreDef.name.toLowerCase()=="tgc5e") {%>,
|
})<%if(coreDef.name.toLowerCase()=="tgc5d" || coreDef.name.toLowerCase()=="tgc5e") {%>,
|
||||||
iss_factory::instance().register_creator("${coreDef.name.toLowerCase()}|mu_p_clic_pmp|interp", [](unsigned gdb_port, void* data) -> iss_factory::base_t {
|
iss_factory::instance().register_creator("${coreDef.name.toLowerCase()}|mu_p_clic_pmp|interp", [](unsigned gdb_port, void* data) -> iss_factory::base_t {
|
||||||
auto* cc = reinterpret_cast<sysc::tgfs::core_complex*>(data);
|
auto* cc = reinterpret_cast<sysc::tgfs::core_complex_if*>(data);
|
||||||
auto* cpu = new sc_core_adapter<arch::riscv_hart_mu_p<arch::${coreDef.name.toLowerCase()}, (iss::arch::features_e)(iss::arch::FEAT_PMP | iss::arch::FEAT_EXT_N | iss::arch::FEAT_CLIC)>>(cc);
|
auto* cpu = new sc_core_adapter<arch::riscv_hart_mu_p<arch::${coreDef.name.toLowerCase()}, (iss::arch::features_e)(iss::arch::FEAT_PMP | iss::arch::FEAT_EXT_N | iss::arch::FEAT_CLIC)>>(cc);
|
||||||
return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast<arch::${coreDef.name.toLowerCase()}*>(cpu), gdb_port)}};
|
return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast<arch::${coreDef.name.toLowerCase()}*>(cpu), gdb_port)}};
|
||||||
})<%}%>
|
})<%}%>
|
||||||
@ -66,17 +66,17 @@ namespace llvm {
|
|||||||
using namespace sysc;
|
using namespace sysc;
|
||||||
volatile std::array<bool, ${array_count}> ${coreDef.name.toLowerCase()}_init = {
|
volatile std::array<bool, ${array_count}> ${coreDef.name.toLowerCase()}_init = {
|
||||||
iss_factory::instance().register_creator("${coreDef.name.toLowerCase()}|m_p|llvm", [](unsigned gdb_port, void* data) -> iss_factory::base_t {
|
iss_factory::instance().register_creator("${coreDef.name.toLowerCase()}|m_p|llvm", [](unsigned gdb_port, void* data) -> iss_factory::base_t {
|
||||||
auto* cc = reinterpret_cast<sysc::tgfs::core_complex*>(data);
|
auto* cc = reinterpret_cast<sysc::tgfs::core_complex_if*>(data);
|
||||||
auto* cpu = new sc_core_adapter<arch::riscv_hart_m_p<arch::${coreDef.name.toLowerCase()}>>(cc);
|
auto* cpu = new sc_core_adapter<arch::riscv_hart_m_p<arch::${coreDef.name.toLowerCase()}>>(cc);
|
||||||
return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast<arch::${coreDef.name.toLowerCase()}*>(cpu), gdb_port)}};
|
return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast<arch::${coreDef.name.toLowerCase()}*>(cpu), gdb_port)}};
|
||||||
}),
|
}),
|
||||||
iss_factory::instance().register_creator("${coreDef.name.toLowerCase()}|mu_p|llvm", [](unsigned gdb_port, void* data) -> iss_factory::base_t {
|
iss_factory::instance().register_creator("${coreDef.name.toLowerCase()}|mu_p|llvm", [](unsigned gdb_port, void* data) -> iss_factory::base_t {
|
||||||
auto* cc = reinterpret_cast<sysc::tgfs::core_complex*>(data);
|
auto* cc = reinterpret_cast<sysc::tgfs::core_complex_if*>(data);
|
||||||
auto* cpu = new sc_core_adapter<arch::riscv_hart_mu_p<arch::${coreDef.name.toLowerCase()}>>(cc);
|
auto* cpu = new sc_core_adapter<arch::riscv_hart_mu_p<arch::${coreDef.name.toLowerCase()}>>(cc);
|
||||||
return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast<arch::${coreDef.name.toLowerCase()}*>(cpu), gdb_port)}};
|
return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast<arch::${coreDef.name.toLowerCase()}*>(cpu), gdb_port)}};
|
||||||
})<%if(coreDef.name.toLowerCase()=="tgc5d" || coreDef.name.toLowerCase()=="tgc5e") {%>,
|
})<%if(coreDef.name.toLowerCase()=="tgc5d" || coreDef.name.toLowerCase()=="tgc5e") {%>,
|
||||||
iss_factory::instance().register_creator("${coreDef.name.toLowerCase()}|mu_p_clic_pmp|llvm", [](unsigned gdb_port, void* data) -> iss_factory::base_t {
|
iss_factory::instance().register_creator("${coreDef.name.toLowerCase()}|mu_p_clic_pmp|llvm", [](unsigned gdb_port, void* data) -> iss_factory::base_t {
|
||||||
auto* cc = reinterpret_cast<sysc::tgfs::core_complex*>(data);
|
auto* cc = reinterpret_cast<sysc::tgfs::core_complex_if*>(data);
|
||||||
auto* cpu = new sc_core_adapter<arch::riscv_hart_mu_p<arch::${coreDef.name.toLowerCase()}, (iss::arch::features_e)(iss::arch::FEAT_PMP | iss::arch::FEAT_EXT_N | iss::arch::FEAT_CLIC)>>(cc);
|
auto* cpu = new sc_core_adapter<arch::riscv_hart_mu_p<arch::${coreDef.name.toLowerCase()}, (iss::arch::features_e)(iss::arch::FEAT_PMP | iss::arch::FEAT_EXT_N | iss::arch::FEAT_CLIC)>>(cc);
|
||||||
return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast<arch::${coreDef.name.toLowerCase()}*>(cpu), gdb_port)}};
|
return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast<arch::${coreDef.name.toLowerCase()}*>(cpu), gdb_port)}};
|
||||||
})<%}%>
|
})<%}%>
|
||||||
@ -88,17 +88,17 @@ namespace tcc {
|
|||||||
using namespace sysc;
|
using namespace sysc;
|
||||||
volatile std::array<bool, ${array_count}> ${coreDef.name.toLowerCase()}_init = {
|
volatile std::array<bool, ${array_count}> ${coreDef.name.toLowerCase()}_init = {
|
||||||
iss_factory::instance().register_creator("${coreDef.name.toLowerCase()}|m_p|tcc", [](unsigned gdb_port, void* data) -> iss_factory::base_t {
|
iss_factory::instance().register_creator("${coreDef.name.toLowerCase()}|m_p|tcc", [](unsigned gdb_port, void* data) -> iss_factory::base_t {
|
||||||
auto* cc = reinterpret_cast<sysc::tgfs::core_complex*>(data);
|
auto* cc = reinterpret_cast<sysc::tgfs::core_complex_if*>(data);
|
||||||
auto* cpu = new sc_core_adapter<arch::riscv_hart_m_p<arch::${coreDef.name.toLowerCase()}>>(cc);
|
auto* cpu = new sc_core_adapter<arch::riscv_hart_m_p<arch::${coreDef.name.toLowerCase()}>>(cc);
|
||||||
return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast<arch::${coreDef.name.toLowerCase()}*>(cpu), gdb_port)}};
|
return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast<arch::${coreDef.name.toLowerCase()}*>(cpu), gdb_port)}};
|
||||||
}),
|
}),
|
||||||
iss_factory::instance().register_creator("${coreDef.name.toLowerCase()}|mu_p|tcc", [](unsigned gdb_port, void* data) -> iss_factory::base_t {
|
iss_factory::instance().register_creator("${coreDef.name.toLowerCase()}|mu_p|tcc", [](unsigned gdb_port, void* data) -> iss_factory::base_t {
|
||||||
auto* cc = reinterpret_cast<sysc::tgfs::core_complex*>(data);
|
auto* cc = reinterpret_cast<sysc::tgfs::core_complex_if*>(data);
|
||||||
auto* cpu = new sc_core_adapter<arch::riscv_hart_mu_p<arch::${coreDef.name.toLowerCase()}>>(cc);
|
auto* cpu = new sc_core_adapter<arch::riscv_hart_mu_p<arch::${coreDef.name.toLowerCase()}>>(cc);
|
||||||
return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast<arch::${coreDef.name.toLowerCase()}*>(cpu), gdb_port)}};
|
return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast<arch::${coreDef.name.toLowerCase()}*>(cpu), gdb_port)}};
|
||||||
})<%if(coreDef.name.toLowerCase()=="tgc5d" || coreDef.name.toLowerCase()=="tgc5e") {%>,
|
})<%if(coreDef.name.toLowerCase()=="tgc5d" || coreDef.name.toLowerCase()=="tgc5e") {%>,
|
||||||
iss_factory::instance().register_creator("${coreDef.name.toLowerCase()}|mu_p_clic_pmp|tcc", [](unsigned gdb_port, void* data) -> iss_factory::base_t {
|
iss_factory::instance().register_creator("${coreDef.name.toLowerCase()}|mu_p_clic_pmp|tcc", [](unsigned gdb_port, void* data) -> iss_factory::base_t {
|
||||||
auto* cc = reinterpret_cast<sysc::tgfs::core_complex*>(data);
|
auto* cc = reinterpret_cast<sysc::tgfs::core_complex_if*>(data);
|
||||||
auto* cpu = new sc_core_adapter<arch::riscv_hart_mu_p<arch::${coreDef.name.toLowerCase()}, (iss::arch::features_e)(iss::arch::FEAT_PMP | iss::arch::FEAT_EXT_N | iss::arch::FEAT_CLIC)>>(cc);
|
auto* cpu = new sc_core_adapter<arch::riscv_hart_mu_p<arch::${coreDef.name.toLowerCase()}, (iss::arch::features_e)(iss::arch::FEAT_PMP | iss::arch::FEAT_EXT_N | iss::arch::FEAT_CLIC)>>(cc);
|
||||||
return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast<arch::${coreDef.name.toLowerCase()}*>(cpu), gdb_port)}};
|
return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast<arch::${coreDef.name.toLowerCase()}*>(cpu), gdb_port)}};
|
||||||
})<%}%>
|
})<%}%>
|
||||||
@ -110,17 +110,17 @@ namespace asmjit {
|
|||||||
using namespace sysc;
|
using namespace sysc;
|
||||||
volatile std::array<bool, ${array_count}> ${coreDef.name.toLowerCase()}_init = {
|
volatile std::array<bool, ${array_count}> ${coreDef.name.toLowerCase()}_init = {
|
||||||
iss_factory::instance().register_creator("${coreDef.name.toLowerCase()}|m_p|asmjit", [](unsigned gdb_port, void* data) -> iss_factory::base_t {
|
iss_factory::instance().register_creator("${coreDef.name.toLowerCase()}|m_p|asmjit", [](unsigned gdb_port, void* data) -> iss_factory::base_t {
|
||||||
auto* cc = reinterpret_cast<sysc::tgfs::core_complex*>(data);
|
auto* cc = reinterpret_cast<sysc::tgfs::core_complex_if*>(data);
|
||||||
auto* cpu = new sc_core_adapter<arch::riscv_hart_m_p<arch::${coreDef.name.toLowerCase()}>>(cc);
|
auto* cpu = new sc_core_adapter<arch::riscv_hart_m_p<arch::${coreDef.name.toLowerCase()}>>(cc);
|
||||||
return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast<arch::${coreDef.name.toLowerCase()}*>(cpu), gdb_port)}};
|
return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast<arch::${coreDef.name.toLowerCase()}*>(cpu), gdb_port)}};
|
||||||
}),
|
}),
|
||||||
iss_factory::instance().register_creator("${coreDef.name.toLowerCase()}|mu_p|asmjit", [](unsigned gdb_port, void* data) -> iss_factory::base_t {
|
iss_factory::instance().register_creator("${coreDef.name.toLowerCase()}|mu_p|asmjit", [](unsigned gdb_port, void* data) -> iss_factory::base_t {
|
||||||
auto* cc = reinterpret_cast<sysc::tgfs::core_complex*>(data);
|
auto* cc = reinterpret_cast<sysc::tgfs::core_complex_if*>(data);
|
||||||
auto* cpu = new sc_core_adapter<arch::riscv_hart_mu_p<arch::${coreDef.name.toLowerCase()}>>(cc);
|
auto* cpu = new sc_core_adapter<arch::riscv_hart_mu_p<arch::${coreDef.name.toLowerCase()}>>(cc);
|
||||||
return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast<arch::${coreDef.name.toLowerCase()}*>(cpu), gdb_port)}};
|
return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast<arch::${coreDef.name.toLowerCase()}*>(cpu), gdb_port)}};
|
||||||
})<%if(coreDef.name.toLowerCase()=="tgc5d" || coreDef.name.toLowerCase()=="tgc5e") {%>,
|
})<%if(coreDef.name.toLowerCase()=="tgc5d" || coreDef.name.toLowerCase()=="tgc5e") {%>,
|
||||||
iss_factory::instance().register_creator("${coreDef.name.toLowerCase()}|mu_p_clic_pmp|asmjit", [](unsigned gdb_port, void* data) -> iss_factory::base_t {
|
iss_factory::instance().register_creator("${coreDef.name.toLowerCase()}|mu_p_clic_pmp|asmjit", [](unsigned gdb_port, void* data) -> iss_factory::base_t {
|
||||||
auto* cc = reinterpret_cast<sysc::tgfs::core_complex*>(data);
|
auto* cc = reinterpret_cast<sysc::tgfs::core_complex_if*>(data);
|
||||||
auto* cpu = new sc_core_adapter<arch::riscv_hart_mu_p<arch::${coreDef.name.toLowerCase()}, (iss::arch::features_e)(iss::arch::FEAT_PMP | iss::arch::FEAT_EXT_N | iss::arch::FEAT_CLIC)>>(cc);
|
auto* cpu = new sc_core_adapter<arch::riscv_hart_mu_p<arch::${coreDef.name.toLowerCase()}, (iss::arch::features_e)(iss::arch::FEAT_PMP | iss::arch::FEAT_EXT_N | iss::arch::FEAT_CLIC)>>(cc);
|
||||||
return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast<arch::${coreDef.name.toLowerCase()}*>(cpu), gdb_port)}};
|
return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast<arch::${coreDef.name.toLowerCase()}*>(cpu), gdb_port)}};
|
||||||
})<%}%>
|
})<%}%>
|
||||||
|
@ -38,7 +38,9 @@
|
|||||||
#include <asmjit/asmjit.h>
|
#include <asmjit/asmjit.h>
|
||||||
#include <util/logging.h>
|
#include <util/logging.h>
|
||||||
#include <iss/instruction_decoder.h>
|
#include <iss/instruction_decoder.h>
|
||||||
|
<%def fcsr = registers.find {it.name=='FCSR'}
|
||||||
|
if(fcsr != null) {%>
|
||||||
|
#include <vm/fp_functions.h><%}%>
|
||||||
#ifndef FMT_HEADER_ONLY
|
#ifndef FMT_HEADER_ONLY
|
||||||
#define FMT_HEADER_ONLY
|
#define FMT_HEADER_ONLY
|
||||||
#endif
|
#endif
|
||||||
@ -88,7 +90,6 @@ protected:
|
|||||||
using super::write_reg_to_mem;
|
using super::write_reg_to_mem;
|
||||||
using super::gen_read_mem;
|
using super::gen_read_mem;
|
||||||
using super::gen_write_mem;
|
using super::gen_write_mem;
|
||||||
using super::gen_wait;
|
|
||||||
using super::gen_leave;
|
using super::gen_leave;
|
||||||
using super::gen_sync;
|
using super::gen_sync;
|
||||||
|
|
||||||
@ -100,11 +101,13 @@ protected:
|
|||||||
void gen_block_prologue(jit_holder& jh) override;
|
void gen_block_prologue(jit_holder& jh) override;
|
||||||
void gen_block_epilogue(jit_holder& jh) override;
|
void gen_block_epilogue(jit_holder& jh) override;
|
||||||
inline const char *name(size_t index){return traits::reg_aliases.at(index);}
|
inline const char *name(size_t index){return traits::reg_aliases.at(index);}
|
||||||
|
<%if(fcsr != null) {%>
|
||||||
|
inline const char *fname(size_t index){return index < 32?name(index+traits::F0):"illegal";}
|
||||||
|
<%}%>
|
||||||
void gen_instr_prologue(jit_holder& jh);
|
void gen_instr_prologue(jit_holder& jh);
|
||||||
void gen_instr_epilogue(jit_holder& jh);
|
void gen_instr_epilogue(jit_holder& jh);
|
||||||
inline void gen_raise(jit_holder& jh, uint16_t trap_id, uint16_t cause);
|
inline void gen_raise(jit_holder& jh, uint16_t trap_id, uint16_t cause);
|
||||||
template <typename T, typename = std::enable_if_t<std::is_integral_v<T>>> void gen_set_tval(jit_holder& jh, T new_tval) ;
|
template <typename T, typename = typename std::enable_if<std::is_integral<T>::value>::type> void gen_set_tval(jit_holder& jh, T new_tval) ;
|
||||||
void gen_set_tval(jit_holder& jh, x86_reg_t _new_tval) ;
|
void gen_set_tval(jit_holder& jh, x86_reg_t _new_tval) ;
|
||||||
|
|
||||||
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>
|
||||||
@ -113,6 +116,9 @@ protected:
|
|||||||
auto sign_mask = 1ULL<<(W-1);
|
auto sign_mask = 1ULL<<(W-1);
|
||||||
return (from & mask) | ((from & sign_mask) ? ~mask : 0);
|
return (from & mask) | ((from & sign_mask) ? ~mask : 0);
|
||||||
}
|
}
|
||||||
|
<%functions.each{ it.eachLine { %>
|
||||||
|
${it}<%}%>
|
||||||
|
<%}%>
|
||||||
private:
|
private:
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* start opcode definitions
|
* start opcode definitions
|
||||||
@ -195,7 +201,7 @@ private:
|
|||||||
gen_raise(jh, 0, 2);
|
gen_raise(jh, 0, 2);
|
||||||
gen_sync(jh, POST_SYNC, instr_descr.size());
|
gen_sync(jh, POST_SYNC, instr_descr.size());
|
||||||
gen_instr_epilogue(jh);
|
gen_instr_epilogue(jh);
|
||||||
return BRANCH;
|
return ILLEGAL_INSTR;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -224,9 +230,9 @@ continuation_e vm_impl<ARCH>::gen_single_inst_behavior(virt_addr_t &pc, unsigned
|
|||||||
paddr = this->core.virt2phys(pc);
|
paddr = this->core.virt2phys(pc);
|
||||||
auto res = this->core.read(paddr, 4, data);
|
auto res = this->core.read(paddr, 4, data);
|
||||||
if (res != iss::Ok)
|
if (res != iss::Ok)
|
||||||
throw trap_access(TRAP_ID, pc.val);
|
return ILLEGAL_FETCH;
|
||||||
if (instr == 0x0000006f || (instr&0xffff)==0xa001)
|
if (instr == 0x0000006f || (instr&0xffff)==0xa001)
|
||||||
throw simulation_stopped(0); // 'J 0' or 'C.J 0'
|
return JUMP_TO_SELF;
|
||||||
++inst_cnt;
|
++inst_cnt;
|
||||||
uint32_t inst_index = instr_decoder.decode_instr(instr);
|
uint32_t inst_index = instr_decoder.decode_instr(instr);
|
||||||
compile_func f = nullptr;
|
compile_func f = nullptr;
|
||||||
@ -257,6 +263,7 @@ void vm_impl<ARCH>::gen_instr_epilogue(jit_holder& jh) {
|
|||||||
cmp(cc, current_trap_state, 0);
|
cmp(cc, current_trap_state, 0);
|
||||||
cc.jne(jh.trap_entry);
|
cc.jne(jh.trap_entry);
|
||||||
cc.inc(get_ptr_for(jh, traits::ICOUNT));
|
cc.inc(get_ptr_for(jh, traits::ICOUNT));
|
||||||
|
cc.inc(get_ptr_for(jh, traits::CYCLE));
|
||||||
}
|
}
|
||||||
template <typename ARCH>
|
template <typename ARCH>
|
||||||
void vm_impl<ARCH>::gen_block_prologue(jit_holder& jh){
|
void vm_impl<ARCH>::gen_block_prologue(jit_holder& jh){
|
||||||
@ -302,6 +309,7 @@ inline void vm_impl<ARCH>::gen_raise(jit_holder& jh, uint16_t trap_id, uint16_t
|
|||||||
auto tmp1 = get_reg_for(cc, traits::TRAP_STATE);
|
auto tmp1 = get_reg_for(cc, traits::TRAP_STATE);
|
||||||
mov(cc, tmp1, 0x80ULL << 24 | (cause << 16) | trap_id);
|
mov(cc, tmp1, 0x80ULL << 24 | (cause << 16) | trap_id);
|
||||||
mov(cc, get_ptr_for(jh, traits::TRAP_STATE), tmp1);
|
mov(cc, get_ptr_for(jh, traits::TRAP_STATE), tmp1);
|
||||||
|
cc.jmp(jh.trap_entry);
|
||||||
}
|
}
|
||||||
template <typename ARCH>
|
template <typename ARCH>
|
||||||
template <typename T, typename>
|
template <typename T, typename>
|
||||||
@ -310,8 +318,8 @@ void vm_impl<ARCH>::gen_set_tval(jit_holder& jh, T new_tval) {
|
|||||||
}
|
}
|
||||||
template <typename ARCH>
|
template <typename ARCH>
|
||||||
void vm_impl<ARCH>::gen_set_tval(jit_holder& jh, x86_reg_t _new_tval) {
|
void vm_impl<ARCH>::gen_set_tval(jit_holder& jh, x86_reg_t _new_tval) {
|
||||||
if(std::holds_alternative<x86::Gp>(_new_tval)) {
|
if(nonstd::holds_alternative<x86::Gp>(_new_tval)) {
|
||||||
x86::Gp new_tval = std::get<x86::Gp>(_new_tval);
|
x86::Gp new_tval = nonstd::get<x86::Gp>(_new_tval);
|
||||||
if(new_tval.size() < 8)
|
if(new_tval.size() < 8)
|
||||||
new_tval = gen_ext_Gp(jh.cc, new_tval, 64, false);
|
new_tval = gen_ext_Gp(jh.cc, new_tval, 64, false);
|
||||||
mov(jh.cc, jh.globals[TVAL], new_tval);
|
mov(jh.cc, jh.globals[TVAL], new_tval);
|
||||||
|
@ -257,17 +257,21 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
|
|||||||
while(!this->core.should_stop() &&
|
while(!this->core.should_stop() &&
|
||||||
!(is_icount_limit_enabled(cond) && icount >= count_limit) &&
|
!(is_icount_limit_enabled(cond) && icount >= count_limit) &&
|
||||||
!(is_fcount_limit_enabled(cond) && fetch_count >= count_limit)){
|
!(is_fcount_limit_enabled(cond) && fetch_count >= count_limit)){
|
||||||
fetch_count++;
|
if(this->debugging_enabled())
|
||||||
|
this->tgt_adapter->check_continue(*PC);
|
||||||
|
pc.val=*PC;
|
||||||
if(fetch_ins(pc, data)!=iss::Ok){
|
if(fetch_ins(pc, data)!=iss::Ok){
|
||||||
this->do_sync(POST_SYNC, std::numeric_limits<unsigned>::max());
|
if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, std::numeric_limits<unsigned>::max());
|
||||||
pc.val = super::core.enter_trap(std::numeric_limits<uint64_t>::max(), pc.val, 0);
|
process_spawn_blocks();
|
||||||
|
if(this->sync_exec && POST_SYNC) this->do_sync(PRE_SYNC, std::numeric_limits<unsigned>::max());
|
||||||
|
pc.val = super::core.enter_trap(arch::traits<ARCH>::RV_CAUSE_FETCH_ACCESS<<16, pc.val, 0);
|
||||||
} else {
|
} else {
|
||||||
if (is_jump_to_self_enabled(cond) &&
|
if (is_jump_to_self_enabled(cond) &&
|
||||||
(instr == 0x0000006f || (instr&0xffff)==0xa001)) throw simulation_stopped(0); // 'J 0' or 'C.J 0'
|
(instr == 0x0000006f || (instr&0xffff)==0xa001)) throw simulation_stopped(0); // 'J 0' or 'C.J 0'
|
||||||
uint32_t inst_index = instr_decoder.decode_instr(instr);
|
uint32_t inst_index = instr_decoder.decode_instr(instr);
|
||||||
opcode_e inst_id = arch::traits<ARCH>::opcode_e::MAX_OPCODE;;
|
opcode_e inst_id = arch::traits<ARCH>::opcode_e::MAX_OPCODE;;
|
||||||
if(inst_index <instr_descr.size())
|
if(inst_index <instr_descr.size())
|
||||||
inst_id = instr_descr.at(instr_decoder.decode_instr(instr)).op;
|
inst_id = instr_descr[inst_index].op;
|
||||||
|
|
||||||
// pre execution stuff
|
// pre execution stuff
|
||||||
this->core.reg.last_branch = 0;
|
this->core.reg.last_branch = 0;
|
||||||
@ -279,6 +283,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
|
|||||||
<%}%>if(this->disass_enabled){
|
<%}%>if(this->disass_enabled){
|
||||||
/* generate console output when executing the command */<%instr.disass.eachLine{%>
|
/* generate console output when executing the command */<%instr.disass.eachLine{%>
|
||||||
${it}<%}%>
|
${it}<%}%>
|
||||||
|
this->core.disass_output(pc.val, mnemonic);
|
||||||
}
|
}
|
||||||
// used registers<%instr.usedVariables.each{ k,v->
|
// used registers<%instr.usedVariables.each{ k,v->
|
||||||
if(v.isArray) {%>
|
if(v.isArray) {%>
|
||||||
@ -310,11 +315,11 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
|
|||||||
icount++;
|
icount++;
|
||||||
instret++;
|
instret++;
|
||||||
}
|
}
|
||||||
cycle++;
|
*PC = *NEXT_PC;
|
||||||
pc.val=*NEXT_PC;
|
|
||||||
this->core.reg.PC = this->core.reg.NEXT_PC;
|
|
||||||
this->core.reg.trap_state = this->core.reg.pending_trap;
|
this->core.reg.trap_state = this->core.reg.pending_trap;
|
||||||
}
|
}
|
||||||
|
fetch_count++;
|
||||||
|
cycle++;
|
||||||
}
|
}
|
||||||
return pc;
|
return pc;
|
||||||
}
|
}
|
||||||
|
@ -37,7 +37,9 @@
|
|||||||
#include <iss/llvm/vm_base.h>
|
#include <iss/llvm/vm_base.h>
|
||||||
#include <util/logging.h>
|
#include <util/logging.h>
|
||||||
#include <iss/instruction_decoder.h>
|
#include <iss/instruction_decoder.h>
|
||||||
|
<%def fcsr = registers.find {it.name=='FCSR'}
|
||||||
|
if(fcsr != null) {%>
|
||||||
|
#include <vm/fp_functions.h><%}%>
|
||||||
#ifndef FMT_HEADER_ONLY
|
#ifndef FMT_HEADER_ONLY
|
||||||
#define FMT_HEADER_ONLY
|
#define FMT_HEADER_ONLY
|
||||||
#endif
|
#endif
|
||||||
@ -83,7 +85,9 @@ protected:
|
|||||||
using vm_base<ARCH>::get_reg_ptr;
|
using vm_base<ARCH>::get_reg_ptr;
|
||||||
|
|
||||||
inline const char *name(size_t index){return traits::reg_aliases.at(index);}
|
inline const char *name(size_t index){return traits::reg_aliases.at(index);}
|
||||||
|
<%if(fcsr != null) {%>
|
||||||
|
inline const char *fname(size_t index){return index < 32?name(index+traits::F0):"illegal";}
|
||||||
|
<%}%>
|
||||||
template <typename T> inline ConstantInt *size(T type) {
|
template <typename T> inline ConstantInt *size(T type) {
|
||||||
return ConstantInt::get(getContext(), APInt(32, type->getType()->getScalarSizeInBits()));
|
return ConstantInt::get(getContext(), APInt(32, type->getType()->getScalarSizeInBits()));
|
||||||
}
|
}
|
||||||
@ -131,7 +135,9 @@ protected:
|
|||||||
auto sign_mask = 1ULL<<(W-1);
|
auto sign_mask = 1ULL<<(W-1);
|
||||||
return (from & mask) | ((from & sign_mask) ? ~mask : 0);
|
return (from & mask) | ((from & sign_mask) ? ~mask : 0);
|
||||||
}
|
}
|
||||||
|
<%functions.each{ it.eachLine { %>
|
||||||
|
${it}<%}%>
|
||||||
|
<%}%>
|
||||||
private:
|
private:
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* start opcode definitions
|
* start opcode definitions
|
||||||
@ -212,7 +218,7 @@ private:
|
|||||||
bb = this->leave_blk;
|
bb = this->leave_blk;
|
||||||
this->gen_instr_epilogue(bb);
|
this->gen_instr_epilogue(bb);
|
||||||
this->builder.CreateBr(bb);
|
this->builder.CreateBr(bb);
|
||||||
return std::make_tuple(BRANCH, nullptr);
|
return std::make_tuple(ILLEGAL_INSTR, nullptr);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -247,19 +253,11 @@ vm_impl<ARCH>::gen_single_inst_behavior(virt_addr_t &pc, unsigned int &inst_cnt,
|
|||||||
auto *const data = (uint8_t *)&instr;
|
auto *const data = (uint8_t *)&instr;
|
||||||
if(this->core.has_mmu())
|
if(this->core.has_mmu())
|
||||||
paddr = this->core.virt2phys(pc);
|
paddr = this->core.virt2phys(pc);
|
||||||
//TODO: re-add page handling
|
|
||||||
// if ((pc.val & upper_bits) != ((pc.val + 2) & upper_bits)) { // we may cross a page boundary
|
|
||||||
// auto res = this->core.read(paddr, 2, data);
|
|
||||||
// if (res != iss::Ok) throw trap_access(TRAP_ID, pc.val);
|
|
||||||
// if ((instr & 0x3) == 0x3) { // this is a 32bit instruction
|
|
||||||
// res = this->core.read(this->core.v2p(pc + 2), 2, data + 2);
|
|
||||||
// }
|
|
||||||
// } else {
|
|
||||||
auto res = this->core.read(paddr, 4, data);
|
auto res = this->core.read(paddr, 4, data);
|
||||||
if (res != iss::Ok) throw trap_access(TRAP_ID, pc.val);
|
if (res != iss::Ok)
|
||||||
// }
|
return std::make_tuple(ILLEGAL_FETCH, nullptr);
|
||||||
if (instr == 0x0000006f || (instr&0xffff)==0xa001) throw simulation_stopped(0); // 'J 0' or 'C.J 0'
|
if (instr == 0x0000006f || (instr&0xffff)==0xa001)
|
||||||
// curr pc on stack
|
return std::make_tuple(JUMP_TO_SELF, nullptr);
|
||||||
++inst_cnt;
|
++inst_cnt;
|
||||||
uint32_t inst_index = instr_decoder.decode_instr(instr);
|
uint32_t inst_index = instr_decoder.decode_instr(instr);
|
||||||
compile_func f = nullptr;
|
compile_func f = nullptr;
|
||||||
@ -281,6 +279,7 @@ template <typename ARCH>
|
|||||||
void vm_impl<ARCH>::gen_raise_trap(uint16_t trap_id, uint16_t cause) {
|
void vm_impl<ARCH>::gen_raise_trap(uint16_t trap_id, uint16_t cause) {
|
||||||
auto *TRAP_val = this->gen_const(32, 0x80 << 24 | (cause << 16) | trap_id);
|
auto *TRAP_val = this->gen_const(32, 0x80 << 24 | (cause << 16) | trap_id);
|
||||||
this->builder.CreateStore(TRAP_val, get_reg_ptr(traits::TRAP_STATE), true);
|
this->builder.CreateStore(TRAP_val, get_reg_ptr(traits::TRAP_STATE), true);
|
||||||
|
this->builder.CreateBr(this->trap_blk);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename ARCH>
|
template <typename ARCH>
|
||||||
|
@ -38,7 +38,9 @@
|
|||||||
#include <util/logging.h>
|
#include <util/logging.h>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <iss/instruction_decoder.h>
|
#include <iss/instruction_decoder.h>
|
||||||
|
<%def fcsr = registers.find {it.name=='FCSR'}
|
||||||
|
if(fcsr != null) {%>
|
||||||
|
#include <vm/fp_functions.h><%}%>
|
||||||
#ifndef FMT_HEADER_ONLY
|
#ifndef FMT_HEADER_ONLY
|
||||||
#define FMT_HEADER_ONLY
|
#define FMT_HEADER_ONLY
|
||||||
#endif
|
#endif
|
||||||
@ -81,16 +83,21 @@ protected:
|
|||||||
using vm_base<ARCH>::get_reg_ptr;
|
using vm_base<ARCH>::get_reg_ptr;
|
||||||
|
|
||||||
using this_class = vm_impl<ARCH>;
|
using this_class = vm_impl<ARCH>;
|
||||||
using compile_ret_t = std::tuple<continuation_e>;
|
using compile_ret_t = continuation_e;
|
||||||
using compile_func = compile_ret_t (this_class::*)(virt_addr_t &pc, code_word_t instr, tu_builder&);
|
using compile_func = compile_ret_t (this_class::*)(virt_addr_t &pc, code_word_t instr, tu_builder&);
|
||||||
|
|
||||||
inline const char *name(size_t index){return traits::reg_aliases.at(index);}
|
inline const char *name(size_t index){return traits::reg_aliases.at(index);}
|
||||||
|
<%
|
||||||
|
if(fcsr != null) {%>
|
||||||
|
inline const char *fname(size_t index){return index < 32?name(index+traits::F0):"illegal";}
|
||||||
|
<%}%>
|
||||||
|
void add_prologue(tu_builder& tu) override;
|
||||||
|
|
||||||
void setup_module(std::string m) override {
|
void setup_module(std::string m) override {
|
||||||
super::setup_module(m);
|
super::setup_module(m);
|
||||||
}
|
}
|
||||||
|
|
||||||
compile_ret_t gen_single_inst_behavior(virt_addr_t &, unsigned int &, tu_builder&) override;
|
compile_ret_t gen_single_inst_behavior(virt_addr_t &, tu_builder&) override;
|
||||||
|
|
||||||
void gen_trap_behavior(tu_builder& tu) override;
|
void gen_trap_behavior(tu_builder& tu) override;
|
||||||
|
|
||||||
@ -98,8 +105,6 @@ protected:
|
|||||||
|
|
||||||
void gen_leave_trap(tu_builder& tu, unsigned lvl);
|
void gen_leave_trap(tu_builder& tu, unsigned lvl);
|
||||||
|
|
||||||
void gen_wait(tu_builder& tu, unsigned type);
|
|
||||||
|
|
||||||
inline void gen_set_tval(tu_builder& tu, uint64_t new_tval);
|
inline void gen_set_tval(tu_builder& tu, uint64_t new_tval);
|
||||||
|
|
||||||
inline void gen_set_tval(tu_builder& tu, value new_tval);
|
inline void gen_set_tval(tu_builder& tu, value new_tval);
|
||||||
@ -133,6 +138,9 @@ protected:
|
|||||||
return (from & mask) | ((from & sign_mask) ? ~mask : 0);
|
return (from & mask) | ((from & sign_mask) ? ~mask : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
<%functions.each{ it.eachLine { %>
|
||||||
|
${it}<%}%>
|
||||||
|
<%}%>
|
||||||
private:
|
private:
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* start opcode definitions
|
* start opcode definitions
|
||||||
@ -163,6 +171,7 @@ private:
|
|||||||
<%}%>if(this->disass_enabled){
|
<%}%>if(this->disass_enabled){
|
||||||
/* generate console output when executing the command */<%instr.disass.eachLine{%>
|
/* generate console output when executing the command */<%instr.disass.eachLine{%>
|
||||||
${it}<%}%>
|
${it}<%}%>
|
||||||
|
tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic);
|
||||||
}
|
}
|
||||||
auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]);
|
auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]);
|
||||||
pc=pc+ ${instr.length/8};
|
pc=pc+ ${instr.length/8};
|
||||||
@ -187,11 +196,11 @@ private:
|
|||||||
tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, std::string("illegal_instruction"));
|
tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, std::string("illegal_instruction"));
|
||||||
}
|
}
|
||||||
pc = pc + ((instr & 3) == 3 ? 4 : 2);
|
pc = pc + ((instr & 3) == 3 ? 4 : 2);
|
||||||
gen_raise_trap(tu, 0, 2); // illegal instruction trap
|
gen_raise_trap(tu, 0, static_cast<int32_t>(traits:: RV_CAUSE_ILLEGAL_INSTRUCTION));
|
||||||
this->gen_set_tval(tu, instr);
|
this->gen_set_tval(tu, instr);
|
||||||
vm_impl::gen_sync(tu, iss::POST_SYNC, instr_descr.size());
|
vm_impl::gen_sync(tu, iss::POST_SYNC, instr_descr.size());
|
||||||
vm_impl::gen_trap_check(tu);
|
vm_impl::gen_trap_check(tu);
|
||||||
return BRANCH;
|
return ILLEGAL_INSTR;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -216,28 +225,19 @@ vm_impl<ARCH>::vm_impl(ARCH &core, unsigned core_id, unsigned cluster_id)
|
|||||||
}()) {}
|
}()) {}
|
||||||
|
|
||||||
template <typename ARCH>
|
template <typename ARCH>
|
||||||
std::tuple<continuation_e>
|
continuation_e
|
||||||
vm_impl<ARCH>::gen_single_inst_behavior(virt_addr_t &pc, unsigned int &inst_cnt, tu_builder& tu) {
|
vm_impl<ARCH>::gen_single_inst_behavior(virt_addr_t &pc, tu_builder& tu) {
|
||||||
// we fetch at max 4 byte, alignment is 2
|
// we fetch at max 4 byte, alignment is 2
|
||||||
enum {TRAP_ID=1<<16};
|
enum {TRAP_ID=1<<16};
|
||||||
code_word_t instr = 0;
|
code_word_t instr = 0;
|
||||||
phys_addr_t paddr(pc);
|
phys_addr_t paddr(pc);
|
||||||
if(this->core.has_mmu())
|
if(this->core.has_mmu())
|
||||||
paddr = this->core.virt2phys(pc);
|
paddr = this->core.virt2phys(pc);
|
||||||
//TODO: re-add page handling
|
|
||||||
// if ((pc.val & upper_bits) != ((pc.val + 2) & upper_bits)) { // we may cross a page boundary
|
|
||||||
// auto res = this->core.read(paddr, 2, data);
|
|
||||||
// if (res != iss::Ok) throw trap_access(TRAP_ID, pc.val);
|
|
||||||
// if ((insn & 0x3) == 0x3) { // this is a 32bit instruction
|
|
||||||
// res = this->core.read(this->core.v2p(pc + 2), 2, data + 2);
|
|
||||||
// }
|
|
||||||
// } else {
|
|
||||||
auto res = this->core.read(paddr, 4, reinterpret_cast<uint8_t*>(&instr));
|
auto res = this->core.read(paddr, 4, reinterpret_cast<uint8_t*>(&instr));
|
||||||
if (res != iss::Ok) throw trap_access(TRAP_ID, pc.val);
|
if (res != iss::Ok)
|
||||||
// }
|
return ILLEGAL_FETCH;
|
||||||
if (instr == 0x0000006f || (instr&0xffff)==0xa001) throw simulation_stopped(0); // 'J 0' or 'C.J 0'
|
if (instr == 0x0000006f || (instr&0xffff)==0xa001)
|
||||||
// curr pc on stack
|
return JUMP_TO_SELF;
|
||||||
++inst_cnt;
|
|
||||||
uint32_t inst_index = instr_decoder.decode_instr(instr);
|
uint32_t inst_index = instr_decoder.decode_instr(instr);
|
||||||
compile_func f = nullptr;
|
compile_func f = nullptr;
|
||||||
if(inst_index < instr_descr.size())
|
if(inst_index < instr_descr.size())
|
||||||
@ -258,9 +258,6 @@ template <typename ARCH> void vm_impl<ARCH>::gen_leave_trap(tu_builder& tu, unsi
|
|||||||
tu.store(traits::LAST_BRANCH, tu.constant(static_cast<int>(UNKNOWN_JUMP), 32));
|
tu.store(traits::LAST_BRANCH, tu.constant(static_cast<int>(UNKNOWN_JUMP), 32));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename ARCH> void vm_impl<ARCH>::gen_wait(tu_builder& tu, unsigned type) {
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename ARCH> void vm_impl<ARCH>::gen_set_tval(tu_builder& tu, uint64_t new_tval) {
|
template <typename ARCH> void vm_impl<ARCH>::gen_set_tval(tu_builder& tu, uint64_t new_tval) {
|
||||||
tu(fmt::format("tval = {};", new_tval));
|
tu(fmt::format("tval = {};", new_tval));
|
||||||
}
|
}
|
||||||
@ -275,6 +272,43 @@ template <typename ARCH> void vm_impl<ARCH>::gen_trap_behavior(tu_builder& tu) {
|
|||||||
tu.store(traits::LAST_BRANCH, tu.constant(static_cast<int>(UNKNOWN_JUMP),32));
|
tu.store(traits::LAST_BRANCH, tu.constant(static_cast<int>(UNKNOWN_JUMP),32));
|
||||||
tu("return *next_pc;");
|
tu("return *next_pc;");
|
||||||
}
|
}
|
||||||
|
<%
|
||||||
|
|
||||||
|
template <typename ARCH> void vm_impl<ARCH>::add_prologue(tu_builder& tu){
|
||||||
|
std::ostringstream os;
|
||||||
|
os << add_reg_ptr("trap_state", arch::traits<ARCH>::TRAP_STATE);
|
||||||
|
os << add_reg_ptr("pending_trap", arch::traits<ARCH>::PENDING_TRAP);
|
||||||
|
if(fcsr != null) {%>
|
||||||
|
os << "uint32_t (*fget_flags)()=" << (uintptr_t)&fget_flags << ";\\n";
|
||||||
|
os << "uint32_t (*fadd_s)(uint32_t v1, uint32_t v2, uint8_t mode)=" << (uintptr_t)&fadd_s << ";\\n";
|
||||||
|
os << "uint32_t (*fsub_s)(uint32_t v1, uint32_t v2, uint8_t mode)=" << (uintptr_t)&fsub_s << ";\\n";
|
||||||
|
os << "uint32_t (*fmul_s)(uint32_t v1, uint32_t v2, uint8_t mode)=" << (uintptr_t)&fmul_s << ";\\n";
|
||||||
|
os << "uint32_t (*fdiv_s)(uint32_t v1, uint32_t v2, uint8_t mode)=" << (uintptr_t)&fdiv_s << ";\\n";
|
||||||
|
os << "uint32_t (*fsqrt_s)(uint32_t v1, uint8_t mode)=" << (uintptr_t)&fsqrt_s << ";\\n";
|
||||||
|
os << "uint32_t (*fcmp_s)(uint32_t v1, uint32_t v2, uint32_t op)=" << (uintptr_t)&fcmp_s << ";\\n";
|
||||||
|
os << "uint32_t (*fcvt_s)(uint32_t v1, uint32_t op, uint8_t mode)=" << (uintptr_t)&fcvt_s << ";\\n";
|
||||||
|
os << "uint32_t (*fmadd_s)(uint32_t v1, uint32_t v2, uint32_t v3, uint32_t op, uint8_t mode)=" << (uintptr_t)&fmadd_s << ";\\n";
|
||||||
|
os << "uint32_t (*fsel_s)(uint32_t v1, uint32_t v2, uint32_t op)=" << (uintptr_t)&fsel_s << ";\\n";
|
||||||
|
os << "uint32_t (*fclass_s)( uint32_t v1 )=" << (uintptr_t)&fclass_s << ";\\n";
|
||||||
|
os << "uint32_t (*fconv_d2f)(uint64_t v1, uint8_t mode)=" << (uintptr_t)&fconv_d2f << ";\\n";
|
||||||
|
os << "uint64_t (*fconv_f2d)(uint32_t v1, uint8_t mode)=" << (uintptr_t)&fconv_f2d << ";\\n";
|
||||||
|
os << "uint64_t (*fadd_d)(uint64_t v1, uint64_t v2, uint8_t mode)=" << (uintptr_t)&fadd_d << ";\\n";
|
||||||
|
os << "uint64_t (*fsub_d)(uint64_t v1, uint64_t v2, uint8_t mode)=" << (uintptr_t)&fsub_d << ";\\n";
|
||||||
|
os << "uint64_t (*fmul_d)(uint64_t v1, uint64_t v2, uint8_t mode)=" << (uintptr_t)&fmul_d << ";\\n";
|
||||||
|
os << "uint64_t (*fdiv_d)(uint64_t v1, uint64_t v2, uint8_t mode)=" << (uintptr_t)&fdiv_d << ";\\n";
|
||||||
|
os << "uint64_t (*fsqrt_d)(uint64_t v1, uint8_t mode)=" << (uintptr_t)&fsqrt_d << ";\\n";
|
||||||
|
os << "uint64_t (*fcmp_d)(uint64_t v1, uint64_t v2, uint32_t op)=" << (uintptr_t)&fcmp_d << ";\\n";
|
||||||
|
os << "uint64_t (*fcvt_d)(uint64_t v1, uint32_t op, uint8_t mode)=" << (uintptr_t)&fcvt_d << ";\\n";
|
||||||
|
os << "uint64_t (*fmadd_d)(uint64_t v1, uint64_t v2, uint64_t v3, uint32_t op, uint8_t mode)=" << (uintptr_t)&fmadd_d << ";\\n";
|
||||||
|
os << "uint64_t (*fsel_d)(uint64_t v1, uint64_t v2, uint32_t op)=" << (uintptr_t)&fsel_d << ";\\n";
|
||||||
|
os << "uint64_t (*fclass_d)(uint64_t v1 )=" << (uintptr_t)&fclass_d << ";\\n";
|
||||||
|
os << "uint64_t (*fcvt_32_64)(uint32_t v1, uint32_t op, uint8_t mode)=" << (uintptr_t)&fcvt_32_64 << ";\\n";
|
||||||
|
os << "uint32_t (*fcvt_64_32)(uint64_t v1, uint32_t op, uint8_t mode)=" << (uintptr_t)&fcvt_64_32 << ";\\n";
|
||||||
|
os << "uint32_t (*unbox_s)(uint64_t v)=" << (uintptr_t)&unbox_s << ";\\n";
|
||||||
|
<%}%>
|
||||||
|
tu.add_prologue(os.str());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
} // namespace ${coreDef.name.toLowerCase()}
|
} // namespace ${coreDef.name.toLowerCase()}
|
||||||
|
|
||||||
|
35
src/elfio.cpp
Archivo normal
35
src/elfio.cpp
Archivo normal
@ -0,0 +1,35 @@
|
|||||||
|
#ifdef _MSC_VER
|
||||||
|
#define _SCL_SECURE_NO_WARNINGS
|
||||||
|
#define ELFIO_NO_INTTYPES
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <elfio/elfio_dump.hpp>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
using namespace ELFIO;
|
||||||
|
|
||||||
|
int main(int argc, char** argv) {
|
||||||
|
if(argc != 2) {
|
||||||
|
printf("Usage: elfdump <file_name>\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
elfio reader;
|
||||||
|
|
||||||
|
if(!reader.load(argv[1])) {
|
||||||
|
printf("File %s is not found or it is not an ELF file\n", argv[1]);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
dump::header(std::cout, reader);
|
||||||
|
dump::section_headers(std::cout, reader);
|
||||||
|
dump::segment_headers(std::cout, reader);
|
||||||
|
dump::symbol_tables(std::cout, reader);
|
||||||
|
dump::notes(std::cout, reader);
|
||||||
|
dump::modinfo(std::cout, reader);
|
||||||
|
dump::dynamic_tags(std::cout, reader);
|
||||||
|
dump::section_datas(std::cout, reader);
|
||||||
|
dump::segment_datas(std::cout, reader);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
@ -51,8 +51,8 @@ public:
|
|||||||
virtual ~hwl() = default;
|
virtual ~hwl() = default;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
iss::status read_custom_csr_reg(unsigned addr, reg_t& val) override;
|
iss::status read_custom_csr(unsigned addr, reg_t& val) override;
|
||||||
iss::status write_custom_csr_reg(unsigned addr, reg_t val) override;
|
iss::status write_custom_csr(unsigned addr, reg_t val) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename BASE>
|
template <typename BASE>
|
||||||
@ -68,7 +68,7 @@ inline hwl<BASE>::hwl(feature_config cfg)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename BASE> inline iss::status iss::arch::hwl<BASE>::read_custom_csr_reg(unsigned addr, reg_t& val) {
|
template <typename BASE> inline iss::status iss::arch::hwl<BASE>::read_custom_csr(unsigned addr, reg_t& val) {
|
||||||
switch(addr) {
|
switch(addr) {
|
||||||
case 0x800:
|
case 0x800:
|
||||||
val = this->reg.lpstart0;
|
val = this->reg.lpstart0;
|
||||||
@ -92,7 +92,7 @@ template <typename BASE> inline iss::status iss::arch::hwl<BASE>::read_custom_cs
|
|||||||
return iss::Ok;
|
return iss::Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename BASE> inline iss::status iss::arch::hwl<BASE>::write_custom_csr_reg(unsigned addr, reg_t val) {
|
template <typename BASE> inline iss::status iss::arch::hwl<BASE>::write_custom_csr(unsigned addr, reg_t val) {
|
||||||
switch(addr) {
|
switch(addr) {
|
||||||
case 0x800:
|
case 0x800:
|
||||||
this->reg.lpstart0 = val;
|
this->reg.lpstart0 = val;
|
||||||
|
@ -35,6 +35,7 @@
|
|||||||
#ifndef _RISCV_HART_COMMON
|
#ifndef _RISCV_HART_COMMON
|
||||||
#define _RISCV_HART_COMMON
|
#define _RISCV_HART_COMMON
|
||||||
|
|
||||||
|
#include "iss/vm_types.h"
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <elfio/elfio.hpp>
|
#include <elfio/elfio.hpp>
|
||||||
#include <fmt/format.h>
|
#include <fmt/format.h>
|
||||||
@ -314,31 +315,36 @@ struct riscv_hart_common {
|
|||||||
riscv_hart_common(){};
|
riscv_hart_common(){};
|
||||||
~riscv_hart_common(){};
|
~riscv_hart_common(){};
|
||||||
std::unordered_map<std::string, uint64_t> symbol_table;
|
std::unordered_map<std::string, uint64_t> symbol_table;
|
||||||
|
uint64_t entry_address{0};
|
||||||
|
uint64_t tohost = tohost_dflt;
|
||||||
|
uint64_t fromhost = fromhost_dflt;
|
||||||
|
|
||||||
std::unordered_map<std::string, uint64_t> get_sym_table(std::string name) {
|
bool read_elf_file(std::string name, uint8_t expected_elf_class,
|
||||||
if(!symbol_table.empty())
|
std::function<iss::status(uint64_t, uint64_t, const uint8_t* const)> cb) {
|
||||||
return symbol_table;
|
|
||||||
FILE* fp = fopen(name.c_str(), "r");
|
|
||||||
if(fp) {
|
|
||||||
std::array<char, 5> buf;
|
|
||||||
auto n = fread(buf.data(), 1, 4, fp);
|
|
||||||
fclose(fp);
|
|
||||||
if(n != 4)
|
|
||||||
throw std::runtime_error("input file has insufficient size");
|
|
||||||
buf[4] = 0;
|
|
||||||
if(strcmp(buf.data() + 1, "ELF") == 0) {
|
|
||||||
// Create elfio reader
|
// Create elfio reader
|
||||||
ELFIO::elfio reader;
|
ELFIO::elfio reader;
|
||||||
// Load ELF data
|
// Load ELF data
|
||||||
if(!reader.load(name))
|
if(reader.load(name)) {
|
||||||
throw std::runtime_error("could not process elf file");
|
|
||||||
// check elf properties
|
// check elf properties
|
||||||
if(reader.get_type() != ET_EXEC)
|
if(reader.get_class() != expected_elf_class)
|
||||||
throw std::runtime_error("wrong elf type in file");
|
return false;
|
||||||
if(reader.get_machine() != EM_RISCV)
|
if(reader.get_type() != ELFIO::ET_EXEC)
|
||||||
throw std::runtime_error("wrong elf machine in file");
|
return false;
|
||||||
|
if(reader.get_machine() != ELFIO::EM_RISCV)
|
||||||
|
return false;
|
||||||
|
entry_address = reader.get_entry();
|
||||||
|
for(const auto& pseg : reader.segments) {
|
||||||
|
const auto fsize = pseg->get_file_size(); // 0x42c/0x0
|
||||||
|
const auto seg_data = pseg->get_data();
|
||||||
|
const auto type = pseg->get_type();
|
||||||
|
if(type == 1 && fsize > 0) {
|
||||||
|
auto res = cb(pseg->get_physical_address(), fsize, reinterpret_cast<const uint8_t* const>(seg_data));
|
||||||
|
if(res != iss::Ok)
|
||||||
|
CPPLOG(ERR) << "problem writing " << fsize << "bytes to 0x" << std::hex << pseg->get_physical_address();
|
||||||
|
}
|
||||||
|
}
|
||||||
const auto sym_sec = reader.sections[".symtab"];
|
const auto sym_sec = reader.sections[".symtab"];
|
||||||
if(SHT_SYMTAB == sym_sec->get_type() || SHT_DYNSYM == sym_sec->get_type()) {
|
if(ELFIO::SHT_SYMTAB == sym_sec->get_type() || ELFIO::SHT_DYNSYM == sym_sec->get_type()) {
|
||||||
ELFIO::symbol_section_accessor symbols(reader, sym_sec);
|
ELFIO::symbol_section_accessor symbols(reader, sym_sec);
|
||||||
auto sym_no = symbols.get_symbols_num();
|
auto sym_no = symbols.get_symbols_num();
|
||||||
std::string name;
|
std::string name;
|
||||||
@ -357,12 +363,19 @@ struct riscv_hart_common {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
try {
|
||||||
|
tohost = symbol_table.at("tohost");
|
||||||
|
try {
|
||||||
|
fromhost = symbol_table.at("fromhost");
|
||||||
|
} catch(std::out_of_range& e) {
|
||||||
|
fromhost = tohost + 0x40;
|
||||||
}
|
}
|
||||||
return symbol_table;
|
} catch(std::out_of_range& e) {
|
||||||
}
|
}
|
||||||
throw std::runtime_error(fmt::format("memory load file {} is not a valid elf file", name));
|
}
|
||||||
} else
|
return true;
|
||||||
throw std::runtime_error(fmt::format("memory load file not found, check if {} is a valid file", name));
|
}
|
||||||
|
return false;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -41,6 +41,7 @@
|
|||||||
#include "iss/vm_if.h"
|
#include "iss/vm_if.h"
|
||||||
#include "iss/vm_types.h"
|
#include "iss/vm_types.h"
|
||||||
#include "riscv_hart_common.h"
|
#include "riscv_hart_common.h"
|
||||||
|
#include <elfio/elf_types.hpp>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#ifndef FMT_HEADER_ONLY
|
#ifndef FMT_HEADER_ONLY
|
||||||
#define FMT_HEADER_ONLY
|
#define FMT_HEADER_ONLY
|
||||||
@ -278,7 +279,7 @@ public:
|
|||||||
|
|
||||||
void disass_output(uint64_t pc, const std::string instr) override {
|
void disass_output(uint64_t pc, const std::string instr) override {
|
||||||
NSCLOG(INFO, LOGCAT) << fmt::format("0x{:016x} {:40} [s:0x{:x};c:{}]", pc, instr, (reg_t)state.mstatus,
|
NSCLOG(INFO, LOGCAT) << fmt::format("0x{:016x} {:40} [s:0x{:x};c:{}]", pc, instr, (reg_t)state.mstatus,
|
||||||
this->reg.icount + cycle_offset);
|
this->reg.cycle + cycle_offset);
|
||||||
};
|
};
|
||||||
|
|
||||||
iss::instrumentation_if* get_instrumentation_if() override { return &instr_if; }
|
iss::instrumentation_if* get_instrumentation_if() override { return &instr_if; }
|
||||||
@ -311,7 +312,7 @@ protected:
|
|||||||
|
|
||||||
uint64_t get_pendig_traps() override { return arch.reg.trap_state; }
|
uint64_t get_pendig_traps() override { return arch.reg.trap_state; }
|
||||||
|
|
||||||
uint64_t get_total_cycles() override { return arch.reg.icount + arch.cycle_offset; }
|
uint64_t get_total_cycles() override { return arch.reg.cycle + arch.cycle_offset; }
|
||||||
|
|
||||||
void update_last_instr_cycles(unsigned cycles) override { arch.cycle_offset += cycles - 1; }
|
void update_last_instr_cycles(unsigned cycles) override { arch.cycle_offset += cycles - 1; }
|
||||||
|
|
||||||
@ -321,7 +322,7 @@ protected:
|
|||||||
|
|
||||||
unsigned get_reg_size(unsigned num) override { return traits<BASE>::reg_bit_widths[num]; }
|
unsigned get_reg_size(unsigned num) override { return traits<BASE>::reg_bit_widths[num]; }
|
||||||
|
|
||||||
std::unordered_map<std::string, uint64_t> get_symbol_table(std::string name) override { return arch.get_sym_table(name); }
|
std::unordered_map<std::string, uint64_t> const& get_symbol_table(std::string name) override { return arch.symbol_table; }
|
||||||
|
|
||||||
riscv_hart_m_p<BASE, FEAT, LOGCAT>& arch;
|
riscv_hart_m_p<BASE, FEAT, LOGCAT>& arch;
|
||||||
};
|
};
|
||||||
@ -343,8 +344,6 @@ protected:
|
|||||||
int64_t instret_offset{0};
|
int64_t instret_offset{0};
|
||||||
uint64_t minstret_csr{0};
|
uint64_t minstret_csr{0};
|
||||||
reg_t fault_data;
|
reg_t fault_data;
|
||||||
uint64_t tohost = tohost_dflt;
|
|
||||||
uint64_t fromhost = fromhost_dflt;
|
|
||||||
bool tohost_lower_written = false;
|
bool tohost_lower_written = false;
|
||||||
riscv_instrumentation_if instr_if;
|
riscv_instrumentation_if instr_if;
|
||||||
|
|
||||||
@ -377,8 +376,8 @@ protected:
|
|||||||
|
|
||||||
std::vector<uint8_t> tcm;
|
std::vector<uint8_t> tcm;
|
||||||
|
|
||||||
iss::status read_csr_reg(unsigned addr, reg_t& val);
|
iss::status read_plain(unsigned addr, reg_t& val);
|
||||||
iss::status write_csr_reg(unsigned addr, reg_t val);
|
iss::status write_plain(unsigned addr, reg_t val);
|
||||||
iss::status read_null(unsigned addr, reg_t& val);
|
iss::status read_null(unsigned addr, reg_t& val);
|
||||||
iss::status write_null(unsigned addr, reg_t val) { return iss::status::Ok; }
|
iss::status write_null(unsigned addr, reg_t val) { return iss::status::Ok; }
|
||||||
iss::status read_cycle(unsigned addr, reg_t& val);
|
iss::status read_cycle(unsigned addr, reg_t& val);
|
||||||
@ -399,17 +398,19 @@ protected:
|
|||||||
iss::status read_intstatus(unsigned addr, reg_t& val);
|
iss::status read_intstatus(unsigned addr, reg_t& val);
|
||||||
iss::status write_intthresh(unsigned addr, reg_t val);
|
iss::status write_intthresh(unsigned addr, reg_t val);
|
||||||
iss::status write_xtvt(unsigned addr, reg_t val);
|
iss::status write_xtvt(unsigned addr, reg_t val);
|
||||||
iss::status write_dcsr_dcsr(unsigned addr, reg_t val);
|
iss::status write_dcsr(unsigned addr, reg_t val);
|
||||||
iss::status read_dcsr_reg(unsigned addr, reg_t& val);
|
iss::status read_debug(unsigned addr, reg_t& val);
|
||||||
iss::status write_dcsr_reg(unsigned addr, reg_t val);
|
iss::status write_dscratch(unsigned addr, reg_t val);
|
||||||
iss::status read_dpc_reg(unsigned addr, reg_t& val);
|
iss::status read_dpc(unsigned addr, reg_t& val);
|
||||||
iss::status write_dpc_reg(unsigned addr, reg_t val);
|
iss::status write_dpc(unsigned addr, reg_t val);
|
||||||
|
iss::status read_fcsr(unsigned addr, reg_t& val);
|
||||||
|
iss::status write_fcsr(unsigned addr, reg_t val);
|
||||||
|
|
||||||
virtual iss::status read_custom_csr_reg(unsigned addr, reg_t& val) { return iss::status::Err; };
|
virtual iss::status read_custom_csr(unsigned addr, reg_t& val) { return iss::status::Err; };
|
||||||
virtual iss::status write_custom_csr_reg(unsigned addr, reg_t val) { return iss::status::Err; };
|
virtual iss::status write_custom_csr(unsigned addr, reg_t val) { return iss::status::Err; };
|
||||||
|
|
||||||
void register_custom_csr_rd(unsigned addr) { csr_rd_cb[addr] = &this_class::read_custom_csr_reg; }
|
void register_custom_csr_rd(unsigned addr) { csr_rd_cb[addr] = &this_class::read_custom_csr; }
|
||||||
void register_custom_csr_wr(unsigned addr) { csr_wr_cb[addr] = &this_class::write_custom_csr_reg; }
|
void register_custom_csr_wr(unsigned addr) { csr_wr_cb[addr] = &this_class::write_custom_csr; }
|
||||||
|
|
||||||
reg_t mhartid_reg{0x0};
|
reg_t mhartid_reg{0x0};
|
||||||
|
|
||||||
@ -446,18 +447,22 @@ riscv_hart_m_p<BASE, FEAT, LOGCAT>::riscv_hart_m_p(feature_config cfg)
|
|||||||
csr[mimpid] = 1;
|
csr[mimpid] = 1;
|
||||||
|
|
||||||
uart_buf.str("");
|
uart_buf.str("");
|
||||||
|
if(traits<BASE>::FLEN > 0) {
|
||||||
|
csr_rd_cb[fcsr] = &this_class::read_fcsr;
|
||||||
|
csr_wr_cb[fcsr] = &this_class::write_fcsr;
|
||||||
|
}
|
||||||
for(unsigned addr = mhpmcounter3; addr <= mhpmcounter31; ++addr) {
|
for(unsigned addr = mhpmcounter3; addr <= mhpmcounter31; ++addr) {
|
||||||
csr_rd_cb[addr] = &this_class::read_null;
|
csr_rd_cb[addr] = &this_class::read_null;
|
||||||
csr_wr_cb[addr] = &this_class::write_csr_reg;
|
csr_wr_cb[addr] = &this_class::write_plain;
|
||||||
}
|
}
|
||||||
if(traits<BASE>::XLEN == 32)
|
if(traits<BASE>::XLEN == 32)
|
||||||
for(unsigned addr = mhpmcounter3h; addr <= mhpmcounter31h; ++addr) {
|
for(unsigned addr = mhpmcounter3h; addr <= mhpmcounter31h; ++addr) {
|
||||||
csr_rd_cb[addr] = &this_class::read_null;
|
csr_rd_cb[addr] = &this_class::read_null;
|
||||||
csr_wr_cb[addr] = &this_class::write_csr_reg;
|
csr_wr_cb[addr] = &this_class::write_plain;
|
||||||
}
|
}
|
||||||
for(unsigned addr = mhpmevent3; addr <= mhpmevent31; ++addr) {
|
for(unsigned addr = mhpmevent3; addr <= mhpmevent31; ++addr) {
|
||||||
csr_rd_cb[addr] = &this_class::read_null;
|
csr_rd_cb[addr] = &this_class::read_null;
|
||||||
csr_wr_cb[addr] = &this_class::write_csr_reg;
|
csr_wr_cb[addr] = &this_class::write_plain;
|
||||||
}
|
}
|
||||||
for(unsigned addr = hpmcounter3; addr <= hpmcounter31; ++addr) {
|
for(unsigned addr = hpmcounter3; addr <= hpmcounter31; ++addr) {
|
||||||
csr_rd_cb[addr] = &this_class::read_null;
|
csr_rd_cb[addr] = &this_class::read_null;
|
||||||
@ -465,18 +470,17 @@ riscv_hart_m_p<BASE, FEAT, LOGCAT>::riscv_hart_m_p(feature_config cfg)
|
|||||||
if(traits<BASE>::XLEN == 32)
|
if(traits<BASE>::XLEN == 32)
|
||||||
for(unsigned addr = hpmcounter3h; addr <= hpmcounter31h; ++addr) {
|
for(unsigned addr = hpmcounter3h; addr <= hpmcounter31h; ++addr) {
|
||||||
csr_rd_cb[addr] = &this_class::read_null;
|
csr_rd_cb[addr] = &this_class::read_null;
|
||||||
// csr_wr_cb[addr] = &this_class::write_csr_reg;
|
|
||||||
}
|
}
|
||||||
// common regs
|
// common regs
|
||||||
const std::array<unsigned, 4> roaddrs{{misa, mvendorid, marchid, mimpid}};
|
const std::array<unsigned, 4> roaddrs{{misa, mvendorid, marchid, mimpid}};
|
||||||
for(auto addr : roaddrs) {
|
for(auto addr : roaddrs) {
|
||||||
csr_rd_cb[addr] = &this_class::read_csr_reg;
|
csr_rd_cb[addr] = &this_class::read_plain;
|
||||||
csr_wr_cb[addr] = &this_class::write_null;
|
csr_wr_cb[addr] = &this_class::write_null;
|
||||||
}
|
}
|
||||||
const std::array<unsigned, 4> rwaddrs{{mepc, mtvec, mscratch, mtval}};
|
const std::array<unsigned, 4> rwaddrs{{mepc, mtvec, mscratch, mtval}};
|
||||||
for(auto addr : rwaddrs) {
|
for(auto addr : rwaddrs) {
|
||||||
csr_rd_cb[addr] = &this_class::read_csr_reg;
|
csr_rd_cb[addr] = &this_class::read_plain;
|
||||||
csr_wr_cb[addr] = &this_class::write_csr_reg;
|
csr_wr_cb[addr] = &this_class::write_plain;
|
||||||
}
|
}
|
||||||
// special handling & overrides
|
// special handling & overrides
|
||||||
csr_rd_cb[time] = &this_class::read_time;
|
csr_rd_cb[time] = &this_class::read_time;
|
||||||
@ -517,7 +521,7 @@ riscv_hart_m_p<BASE, FEAT, LOGCAT>::riscv_hart_m_p(feature_config cfg)
|
|||||||
csr_wr_cb[marchid] = &this_class::write_null;
|
csr_wr_cb[marchid] = &this_class::write_null;
|
||||||
csr_wr_cb[mimpid] = &this_class::write_null;
|
csr_wr_cb[mimpid] = &this_class::write_null;
|
||||||
if(FEAT & FEAT_CLIC) {
|
if(FEAT & FEAT_CLIC) {
|
||||||
csr_rd_cb[mtvt] = &this_class::read_csr_reg;
|
csr_rd_cb[mtvt] = &this_class::read_plain;
|
||||||
csr_wr_cb[mtvt] = &this_class::write_xtvt;
|
csr_wr_cb[mtvt] = &this_class::write_xtvt;
|
||||||
// csr_rd_cb[mxnti] = &this_class::read_csr_reg;
|
// csr_rd_cb[mxnti] = &this_class::read_csr_reg;
|
||||||
// csr_wr_cb[mxnti] = &this_class::write_csr_reg;
|
// csr_wr_cb[mxnti] = &this_class::write_csr_reg;
|
||||||
@ -527,7 +531,7 @@ riscv_hart_m_p<BASE, FEAT, LOGCAT>::riscv_hart_m_p(feature_config cfg)
|
|||||||
// csr_wr_cb[mscratchcsw] = &this_class::write_csr_reg;
|
// csr_wr_cb[mscratchcsw] = &this_class::write_csr_reg;
|
||||||
// csr_rd_cb[mscratchcswl] = &this_class::read_csr_reg;
|
// csr_rd_cb[mscratchcswl] = &this_class::read_csr_reg;
|
||||||
// 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_plain;
|
||||||
csr_wr_cb[mintthresh] = &this_class::write_intthresh;
|
csr_wr_cb[mintthresh] = &this_class::write_intthresh;
|
||||||
clic_int_reg.resize(cfg.clic_num_irq, clic_int_reg_t{.raw = 0});
|
clic_int_reg.resize(cfg.clic_num_irq, clic_int_reg_t{.raw = 0});
|
||||||
clic_cfg_reg = 0x20;
|
clic_cfg_reg = 0x20;
|
||||||
@ -553,14 +557,14 @@ riscv_hart_m_p<BASE, FEAT, LOGCAT>::riscv_hart_m_p(feature_config cfg)
|
|||||||
insert_mem_range(cfg.tcm_base, cfg.tcm_size, 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_dscratch;
|
||||||
csr_rd_cb[dscratch0] = &this_class::read_dcsr_reg;
|
csr_rd_cb[dscratch0] = &this_class::read_debug;
|
||||||
csr_wr_cb[dscratch1] = &this_class::write_dcsr_reg;
|
csr_wr_cb[dscratch1] = &this_class::write_dscratch;
|
||||||
csr_rd_cb[dscratch1] = &this_class::read_dcsr_reg;
|
csr_rd_cb[dscratch1] = &this_class::read_debug;
|
||||||
csr_wr_cb[dpc] = &this_class::write_dpc_reg;
|
csr_wr_cb[dpc] = &this_class::write_dpc;
|
||||||
csr_rd_cb[dpc] = &this_class::read_dpc_reg;
|
csr_rd_cb[dpc] = &this_class::read_dpc;
|
||||||
csr_wr_cb[dcsr] = &this_class::write_dcsr_dcsr;
|
csr_wr_cb[dcsr] = &this_class::write_dcsr;
|
||||||
csr_rd_cb[dcsr] = &this_class::read_dcsr_reg;
|
csr_rd_cb[dcsr] = &this_class::read_debug;
|
||||||
}
|
}
|
||||||
hart_mem_rd_delegate = [this](phys_addr_t a, unsigned l, uint8_t* const d) -> iss::status { return this->read_mem(a, l, d); };
|
hart_mem_rd_delegate = [this](phys_addr_t a, unsigned l, uint8_t* const d) -> iss::status { return this->read_mem(a, l, d); };
|
||||||
hart_mem_wr_delegate = [this](phys_addr_t a, unsigned l, uint8_t const* const d) -> iss::status { return this->write_mem(a, l, d); };
|
hart_mem_wr_delegate = [this](phys_addr_t a, unsigned l, uint8_t const* const d) -> iss::status { return this->write_mem(a, l, d); };
|
||||||
@ -568,57 +572,14 @@ riscv_hart_m_p<BASE, FEAT, LOGCAT>::riscv_hart_m_p(feature_config cfg)
|
|||||||
|
|
||||||
template <typename BASE, features_e FEAT, typename LOGCAT>
|
template <typename BASE, features_e FEAT, typename LOGCAT>
|
||||||
std::pair<uint64_t, bool> riscv_hart_m_p<BASE, FEAT, LOGCAT>::load_file(std::string name, int type) {
|
std::pair<uint64_t, bool> riscv_hart_m_p<BASE, FEAT, LOGCAT>::load_file(std::string name, int type) {
|
||||||
get_sym_table(name);
|
if(read_elf_file(name, sizeof(reg_t) == 4 ? ELFIO::ELFCLASS32 : ELFIO::ELFCLASS64,
|
||||||
try {
|
[this](uint64_t addr, uint64_t size, const uint8_t* const data) -> iss::status {
|
||||||
tohost = symbol_table.at("tohost");
|
return this->write(iss::address_type::PHYSICAL, iss::access_type::DEBUG_WRITE, traits<BASE>::MEM, addr, size,
|
||||||
fromhost = symbol_table.at("fromhost");
|
data);
|
||||||
} catch(std::out_of_range& e) {
|
})) {
|
||||||
|
return std::make_pair(entry_address, true);
|
||||||
}
|
}
|
||||||
FILE* fp = fopen(name.c_str(), "r");
|
return std::make_pair(entry_address, false);
|
||||||
if(fp) {
|
|
||||||
std::array<char, 5> buf;
|
|
||||||
auto n = fread(buf.data(), 1, 4, fp);
|
|
||||||
fclose(fp);
|
|
||||||
if(n != 4)
|
|
||||||
throw std::runtime_error("input file has insufficient size");
|
|
||||||
buf[4] = 0;
|
|
||||||
if(strcmp(buf.data() + 1, "ELF") == 0) {
|
|
||||||
// Create elfio reader
|
|
||||||
ELFIO::elfio reader;
|
|
||||||
// Load ELF data
|
|
||||||
if(!reader.load(name))
|
|
||||||
throw std::runtime_error("could not process elf file");
|
|
||||||
// check elf properties
|
|
||||||
if(reader.get_class() != ELFCLASS32)
|
|
||||||
if(sizeof(reg_t) == 4)
|
|
||||||
throw std::runtime_error("wrong elf class in file");
|
|
||||||
if(reader.get_type() != ET_EXEC)
|
|
||||||
throw std::runtime_error("wrong elf type in file");
|
|
||||||
if(reader.get_machine() != EM_RISCV)
|
|
||||||
throw std::runtime_error("wrong elf machine in file");
|
|
||||||
auto entry = reader.get_entry();
|
|
||||||
for(const auto pseg : reader.segments) {
|
|
||||||
const auto fsize = pseg->get_file_size(); // 0x42c/0x0
|
|
||||||
const auto seg_data = pseg->get_data();
|
|
||||||
const auto type = pseg->get_type();
|
|
||||||
if(type == 1 && fsize > 0) {
|
|
||||||
auto res = this->write(iss::address_type::PHYSICAL, iss::access_type::DEBUG_WRITE, traits<BASE>::MEM,
|
|
||||||
pseg->get_physical_address(), fsize, reinterpret_cast<const uint8_t* const>(seg_data));
|
|
||||||
if(res != iss::Ok)
|
|
||||||
CPPLOG(ERR) << "problem writing " << fsize << "bytes to 0x" << std::hex << pseg->get_physical_address();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for(const auto sec : reader.sections) {
|
|
||||||
if(sec->get_name() == ".tohost") {
|
|
||||||
tohost = sec->get_address();
|
|
||||||
fromhost = tohost + 0x40;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return std::make_pair(entry, true);
|
|
||||||
}
|
|
||||||
throw std::runtime_error(fmt::format("memory load file {} is not a valid elf file", name));
|
|
||||||
}
|
|
||||||
throw std::runtime_error(fmt::format("memory load file not found, check if {} is a valid file", name));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename BASE, features_e FEAT, typename LOGCAT>
|
template <typename BASE, features_e FEAT, typename LOGCAT>
|
||||||
@ -665,7 +626,7 @@ iss::status riscv_hart_m_p<BASE, FEAT, LOGCAT>::read(const address_type type, co
|
|||||||
}
|
}
|
||||||
phys_addr_t phys_addr{access, space, addr};
|
phys_addr_t phys_addr{access, space, addr};
|
||||||
auto res = iss::Err;
|
auto res = iss::Err;
|
||||||
if(access != access_type::FETCH && memfn_range.size()) {
|
if(!is_fetch(access) && memfn_range.size()) {
|
||||||
auto it =
|
auto it =
|
||||||
std::find_if(std::begin(memfn_range), std::end(memfn_range), [phys_addr](std::tuple<uint64_t, uint64_t> const& a) {
|
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;
|
||||||
@ -684,19 +645,16 @@ iss::status riscv_hart_m_p<BASE, FEAT, LOGCAT>::read(const address_type type, co
|
|||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
} catch(trap_access& ta) {
|
} catch(trap_access& ta) {
|
||||||
|
if((access & access_type::DEBUG) == 0) {
|
||||||
this->reg.trap_state = (1UL << 31) | ta.id;
|
this->reg.trap_state = (1UL << 31) | ta.id;
|
||||||
fault_data = ta.addr;
|
fault_data = ta.addr;
|
||||||
|
}
|
||||||
return iss::Err;
|
return iss::Err;
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
case traits<BASE>::CSR: {
|
case traits<BASE>::CSR: {
|
||||||
if(length != sizeof(reg_t))
|
if(length != sizeof(reg_t))
|
||||||
return iss::Err;
|
return iss::Err;
|
||||||
// We emulate the FCSR in the architectural state
|
|
||||||
if(addr == 3) {
|
|
||||||
*data = this->get_fcsr();
|
|
||||||
return iss::Ok;
|
|
||||||
}
|
|
||||||
return read_csr(addr, *reinterpret_cast<reg_t* const>(data));
|
return read_csr(addr, *reinterpret_cast<reg_t* const>(data));
|
||||||
} break;
|
} break;
|
||||||
case traits<BASE>::FENCE: {
|
case traits<BASE>::FENCE: {
|
||||||
@ -717,8 +675,10 @@ iss::status riscv_hart_m_p<BASE, FEAT, LOGCAT>::read(const address_type type, co
|
|||||||
}
|
}
|
||||||
return iss::Ok;
|
return iss::Ok;
|
||||||
} catch(trap_access& ta) {
|
} catch(trap_access& ta) {
|
||||||
|
if((access & access_type::DEBUG) == 0) {
|
||||||
this->reg.trap_state = (1UL << 31) | ta.id;
|
this->reg.trap_state = (1UL << 31) | ta.id;
|
||||||
fault_data = ta.addr;
|
fault_data = ta.addr;
|
||||||
|
}
|
||||||
return iss::Err;
|
return iss::Err;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -746,7 +706,7 @@ iss::status riscv_hart_m_p<BASE, FEAT, LOGCAT>::write(const address_type type, c
|
|||||||
<< std::hex << addr;
|
<< std::hex << addr;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
CPPLOG(TRACE) << prefix << "write of " << length << " bytes @addr " << addr;
|
CPPLOG(TRACE) << prefix << "write of " << length << " bytes @addr 0x" << std::hex << addr;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
try {
|
try {
|
||||||
@ -767,7 +727,7 @@ iss::status riscv_hart_m_p<BASE, FEAT, LOGCAT>::write(const address_type type, c
|
|||||||
}
|
}
|
||||||
phys_addr_t phys_addr{access, space, addr};
|
phys_addr_t phys_addr{access, space, addr};
|
||||||
auto res = iss::Err;
|
auto res = iss::Err;
|
||||||
if(access != access_type::FETCH && memfn_range.size()) {
|
if(!is_fetch(access) && memfn_range.size()) {
|
||||||
auto it =
|
auto it =
|
||||||
std::find_if(std::begin(memfn_range), std::end(memfn_range), [phys_addr](std::tuple<uint64_t, uint64_t> const& a) {
|
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;
|
||||||
@ -798,8 +758,6 @@ iss::status riscv_hart_m_p<BASE, FEAT, LOGCAT>::write(const address_type type, c
|
|||||||
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) {
|
||||||
// CPPLOG(INFO)<<"UART"<<((paddr.val>>16)&0x3)<<" send
|
|
||||||
// '"<<uart_buf.str()<<"'";
|
|
||||||
std::cout << uart_buf.str();
|
std::cout << uart_buf.str();
|
||||||
uart_buf.str("");
|
uart_buf.str("");
|
||||||
}
|
}
|
||||||
@ -828,11 +786,6 @@ iss::status riscv_hart_m_p<BASE, FEAT, LOGCAT>::write(const address_type type, c
|
|||||||
case traits<BASE>::CSR: {
|
case traits<BASE>::CSR: {
|
||||||
if(length != sizeof(reg_t))
|
if(length != sizeof(reg_t))
|
||||||
return iss::Err;
|
return iss::Err;
|
||||||
// We emulate the FCSR in the architectural state
|
|
||||||
if(addr == 3) {
|
|
||||||
this->set_fcsr(*data);
|
|
||||||
return iss::Ok;
|
|
||||||
}
|
|
||||||
return write_csr(addr, *reinterpret_cast<const reg_t*>(data));
|
return write_csr(addr, *reinterpret_cast<const reg_t*>(data));
|
||||||
} break;
|
} break;
|
||||||
case traits<BASE>::FENCE: {
|
case traits<BASE>::FENCE: {
|
||||||
@ -855,8 +808,10 @@ iss::status riscv_hart_m_p<BASE, FEAT, LOGCAT>::write(const address_type type, c
|
|||||||
}
|
}
|
||||||
return iss::Ok;
|
return iss::Ok;
|
||||||
} catch(trap_access& ta) {
|
} catch(trap_access& ta) {
|
||||||
|
if((access & access_type::DEBUG) == 0) {
|
||||||
this->reg.trap_state = (1UL << 31) | ta.id;
|
this->reg.trap_state = (1UL << 31) | ta.id;
|
||||||
fault_data = ta.addr;
|
fault_data = ta.addr;
|
||||||
|
}
|
||||||
return iss::Err;
|
return iss::Err;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -889,12 +844,6 @@ iss::status riscv_hart_m_p<BASE, FEAT, LOGCAT>::write_csr(unsigned addr, reg_t v
|
|||||||
return (this->*(it->second))(addr, val);
|
return (this->*(it->second))(addr, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename BASE, features_e FEAT, typename LOGCAT>
|
|
||||||
iss::status riscv_hart_m_p<BASE, FEAT, LOGCAT>::read_csr_reg(unsigned addr, reg_t& val) {
|
|
||||||
val = csr[addr];
|
|
||||||
return iss::Ok;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename BASE, features_e FEAT, typename LOGCAT>
|
template <typename BASE, features_e FEAT, typename LOGCAT>
|
||||||
iss::status riscv_hart_m_p<BASE, FEAT, LOGCAT>::read_null(unsigned addr, reg_t& val) {
|
iss::status riscv_hart_m_p<BASE, FEAT, LOGCAT>::read_null(unsigned addr, reg_t& val) {
|
||||||
val = 0;
|
val = 0;
|
||||||
@ -902,14 +851,20 @@ iss::status riscv_hart_m_p<BASE, FEAT, LOGCAT>::read_null(unsigned addr, reg_t&
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename BASE, features_e FEAT, typename LOGCAT>
|
template <typename BASE, features_e FEAT, typename LOGCAT>
|
||||||
iss::status riscv_hart_m_p<BASE, FEAT, LOGCAT>::write_csr_reg(unsigned addr, reg_t val) {
|
iss::status riscv_hart_m_p<BASE, FEAT, LOGCAT>::read_plain(unsigned addr, reg_t& val) {
|
||||||
|
val = csr[addr];
|
||||||
|
return iss::Ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename BASE, features_e FEAT, typename LOGCAT>
|
||||||
|
iss::status riscv_hart_m_p<BASE, FEAT, LOGCAT>::write_plain(unsigned addr, reg_t val) {
|
||||||
csr[addr] = val;
|
csr[addr] = val;
|
||||||
return iss::Ok;
|
return iss::Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename BASE, features_e FEAT, typename LOGCAT>
|
template <typename BASE, features_e FEAT, typename LOGCAT>
|
||||||
iss::status riscv_hart_m_p<BASE, FEAT, LOGCAT>::read_cycle(unsigned addr, reg_t& val) {
|
iss::status riscv_hart_m_p<BASE, FEAT, LOGCAT>::read_cycle(unsigned addr, reg_t& val) {
|
||||||
auto cycle_val = this->reg.icount + cycle_offset;
|
auto cycle_val = this->reg.cycle + cycle_offset;
|
||||||
if(addr == mcycle) {
|
if(addr == mcycle) {
|
||||||
val = static_cast<reg_t>(cycle_val);
|
val = static_cast<reg_t>(cycle_val);
|
||||||
} else if(addr == mcycleh) {
|
} else if(addr == mcycleh) {
|
||||||
@ -929,7 +884,7 @@ iss::status riscv_hart_m_p<BASE, FEAT, LOGCAT>::write_cycle(unsigned addr, reg_t
|
|||||||
mcycle_csr = (static_cast<uint64_t>(val) << 32) + (mcycle_csr & 0xffffffff);
|
mcycle_csr = (static_cast<uint64_t>(val) << 32) + (mcycle_csr & 0xffffffff);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
cycle_offset = mcycle_csr - this->reg.icount; // TODO: relying on wrap-around
|
cycle_offset = mcycle_csr - this->reg.cycle; // TODO: relying on wrap-around
|
||||||
return iss::Ok;
|
return iss::Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -960,7 +915,7 @@ iss::status riscv_hart_m_p<BASE, FEAT, LOGCAT>::write_instret(unsigned addr, reg
|
|||||||
|
|
||||||
template <typename BASE, features_e FEAT, typename LOGCAT>
|
template <typename BASE, features_e FEAT, typename LOGCAT>
|
||||||
iss::status riscv_hart_m_p<BASE, FEAT, LOGCAT>::read_time(unsigned addr, reg_t& val) {
|
iss::status riscv_hart_m_p<BASE, FEAT, LOGCAT>::read_time(unsigned addr, reg_t& val) {
|
||||||
uint64_t time_val = this->reg.icount / (100000000 / 32768 - 1); //-> ~3052;
|
uint64_t time_val = this->reg.cycle / (100000000 / 32768 - 1); //-> ~3052;
|
||||||
if(addr == time) {
|
if(addr == time) {
|
||||||
val = static_cast<reg_t>(time_val);
|
val = static_cast<reg_t>(time_val);
|
||||||
} else if(addr == timeh) {
|
} else if(addr == timeh) {
|
||||||
@ -1052,7 +1007,7 @@ iss::status riscv_hart_m_p<BASE, FEAT, LOGCAT>::write_epc(unsigned addr, reg_t v
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename BASE, features_e FEAT, typename LOGCAT>
|
template <typename BASE, features_e FEAT, typename LOGCAT>
|
||||||
iss::status riscv_hart_m_p<BASE, FEAT, LOGCAT>::write_dcsr_dcsr(unsigned addr, reg_t val) {
|
iss::status riscv_hart_m_p<BASE, FEAT, LOGCAT>::write_dcsr(unsigned addr, reg_t val) {
|
||||||
if(!debug_mode_active())
|
if(!debug_mode_active())
|
||||||
throw illegal_instruction_fault(this->fault_data);
|
throw illegal_instruction_fault(this->fault_data);
|
||||||
// +-------------- ebreakm
|
// +-------------- ebreakm
|
||||||
@ -1064,7 +1019,7 @@ iss::status riscv_hart_m_p<BASE, FEAT, LOGCAT>::write_dcsr_dcsr(unsigned addr, r
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename BASE, features_e FEAT, typename LOGCAT>
|
template <typename BASE, features_e FEAT, typename LOGCAT>
|
||||||
iss::status riscv_hart_m_p<BASE, FEAT, LOGCAT>::read_dcsr_reg(unsigned addr, reg_t& val) {
|
iss::status riscv_hart_m_p<BASE, FEAT, LOGCAT>::read_debug(unsigned addr, reg_t& val) {
|
||||||
if(!debug_mode_active())
|
if(!debug_mode_active())
|
||||||
throw illegal_instruction_fault(this->fault_data);
|
throw illegal_instruction_fault(this->fault_data);
|
||||||
val = csr[addr];
|
val = csr[addr];
|
||||||
@ -1072,7 +1027,7 @@ iss::status riscv_hart_m_p<BASE, FEAT, LOGCAT>::read_dcsr_reg(unsigned addr, reg
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename BASE, features_e FEAT, typename LOGCAT>
|
template <typename BASE, features_e FEAT, typename LOGCAT>
|
||||||
iss::status riscv_hart_m_p<BASE, FEAT, LOGCAT>::write_dcsr_reg(unsigned addr, reg_t val) {
|
iss::status riscv_hart_m_p<BASE, FEAT, LOGCAT>::write_dscratch(unsigned addr, reg_t val) {
|
||||||
if(!debug_mode_active())
|
if(!debug_mode_active())
|
||||||
throw illegal_instruction_fault(this->fault_data);
|
throw illegal_instruction_fault(this->fault_data);
|
||||||
csr[addr] = val;
|
csr[addr] = val;
|
||||||
@ -1080,7 +1035,7 @@ iss::status riscv_hart_m_p<BASE, FEAT, LOGCAT>::write_dcsr_reg(unsigned addr, re
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename BASE, features_e FEAT, typename LOGCAT>
|
template <typename BASE, features_e FEAT, typename LOGCAT>
|
||||||
iss::status riscv_hart_m_p<BASE, FEAT, LOGCAT>::read_dpc_reg(unsigned addr, reg_t& val) {
|
iss::status riscv_hart_m_p<BASE, FEAT, LOGCAT>::read_dpc(unsigned addr, reg_t& val) {
|
||||||
if(!debug_mode_active())
|
if(!debug_mode_active())
|
||||||
throw illegal_instruction_fault(this->fault_data);
|
throw illegal_instruction_fault(this->fault_data);
|
||||||
val = this->reg.DPC;
|
val = this->reg.DPC;
|
||||||
@ -1088,7 +1043,7 @@ iss::status riscv_hart_m_p<BASE, FEAT, LOGCAT>::read_dpc_reg(unsigned addr, reg_
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename BASE, features_e FEAT, typename LOGCAT>
|
template <typename BASE, features_e FEAT, typename LOGCAT>
|
||||||
iss::status riscv_hart_m_p<BASE, FEAT, LOGCAT>::write_dpc_reg(unsigned addr, reg_t val) {
|
iss::status riscv_hart_m_p<BASE, FEAT, LOGCAT>::write_dpc(unsigned addr, reg_t val) {
|
||||||
if(!debug_mode_active())
|
if(!debug_mode_active())
|
||||||
throw illegal_instruction_fault(this->fault_data);
|
throw illegal_instruction_fault(this->fault_data);
|
||||||
this->reg.DPC = val;
|
this->reg.DPC = val;
|
||||||
@ -1101,6 +1056,18 @@ iss::status riscv_hart_m_p<BASE, FEAT, LOGCAT>::read_intstatus(unsigned addr, re
|
|||||||
return iss::Ok;
|
return iss::Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename BASE, features_e FEAT, typename LOGCAT>
|
||||||
|
iss::status riscv_hart_m_p<BASE, FEAT, LOGCAT>::read_fcsr(unsigned addr, reg_t& val) {
|
||||||
|
val = this->get_fcsr();
|
||||||
|
return iss::Ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename BASE, features_e FEAT, typename LOGCAT>
|
||||||
|
iss::status riscv_hart_m_p<BASE, FEAT, LOGCAT>::write_fcsr(unsigned addr, reg_t val) {
|
||||||
|
this->set_fcsr(val);
|
||||||
|
return iss::Ok;
|
||||||
|
}
|
||||||
|
|
||||||
template <typename BASE, features_e FEAT, typename LOGCAT>
|
template <typename BASE, features_e FEAT, typename LOGCAT>
|
||||||
iss::status riscv_hart_m_p<BASE, FEAT, LOGCAT>::write_intthresh(unsigned addr, reg_t val) {
|
iss::status riscv_hart_m_p<BASE, FEAT, LOGCAT>::write_intthresh(unsigned addr, reg_t val) {
|
||||||
csr[addr] = (val & 0xff) | (1 << (cfg.clic_int_ctl_bits)) - 1;
|
csr[addr] = (val & 0xff) | (1 << (cfg.clic_int_ctl_bits)) - 1;
|
||||||
|
@ -39,7 +39,9 @@
|
|||||||
#include "iss/instrumentation_if.h"
|
#include "iss/instrumentation_if.h"
|
||||||
#include "iss/log_categories.h"
|
#include "iss/log_categories.h"
|
||||||
#include "iss/vm_if.h"
|
#include "iss/vm_if.h"
|
||||||
|
#include "iss/vm_types.h"
|
||||||
#include "riscv_hart_common.h"
|
#include "riscv_hart_common.h"
|
||||||
|
#include <stdexcept>
|
||||||
#ifndef FMT_HEADER_ONLY
|
#ifndef FMT_HEADER_ONLY
|
||||||
#define FMT_HEADER_ONLY
|
#define FMT_HEADER_ONLY
|
||||||
#endif
|
#endif
|
||||||
@ -326,7 +328,7 @@ public:
|
|||||||
|
|
||||||
void disass_output(uint64_t pc, const std::string instr) override {
|
void disass_output(uint64_t pc, const std::string instr) override {
|
||||||
CLOG(INFO, disass) << fmt::format("0x{:016x} {:40} [p:{};s:0x{:x};c:{}]", pc, instr, lvl[this->reg.PRIV], (reg_t)state.mstatus,
|
CLOG(INFO, disass) << fmt::format("0x{:016x} {:40} [p:{};s:0x{:x};c:{}]", pc, instr, lvl[this->reg.PRIV], (reg_t)state.mstatus,
|
||||||
this->reg.icount + cycle_offset);
|
this->reg.cycle + cycle_offset);
|
||||||
};
|
};
|
||||||
|
|
||||||
iss::instrumentation_if* get_instrumentation_if() override { return &instr_if; }
|
iss::instrumentation_if* get_instrumentation_if() override { return &instr_if; }
|
||||||
@ -359,7 +361,7 @@ protected:
|
|||||||
|
|
||||||
uint64_t get_pendig_traps() override { return arch.reg.trap_state; }
|
uint64_t get_pendig_traps() override { return arch.reg.trap_state; }
|
||||||
|
|
||||||
uint64_t get_total_cycles() override { return arch.reg.icount + arch.cycle_offset; }
|
uint64_t get_total_cycles() override { return arch.reg.cycle + arch.cycle_offset; }
|
||||||
|
|
||||||
void update_last_instr_cycles(unsigned cycles) override { arch.cycle_offset += cycles - 1; }
|
void update_last_instr_cycles(unsigned cycles) override { arch.cycle_offset += cycles - 1; }
|
||||||
|
|
||||||
@ -369,7 +371,7 @@ protected:
|
|||||||
|
|
||||||
unsigned get_reg_size(unsigned num) override { return traits<BASE>::reg_bit_widths[num]; }
|
unsigned get_reg_size(unsigned num) override { return traits<BASE>::reg_bit_widths[num]; }
|
||||||
|
|
||||||
std::unordered_map<std::string, uint64_t> get_symbol_table(std::string name) override { return arch.get_sym_table(name); }
|
std::unordered_map<std::string, uint64_t> const& get_symbol_table(std::string name) override { return arch.symbol_table; }
|
||||||
|
|
||||||
riscv_hart_msu_vp<BASE>& arch;
|
riscv_hart_msu_vp<BASE>& arch;
|
||||||
};
|
};
|
||||||
@ -391,8 +393,6 @@ protected:
|
|||||||
uint64_t minstret_csr{0};
|
uint64_t minstret_csr{0};
|
||||||
reg_t fault_data;
|
reg_t fault_data;
|
||||||
std::array<vm_info, 2> vm;
|
std::array<vm_info, 2> vm;
|
||||||
uint64_t tohost = tohost_dflt;
|
|
||||||
uint64_t fromhost = fromhost_dflt;
|
|
||||||
bool tohost_lower_written = false;
|
bool tohost_lower_written = false;
|
||||||
riscv_instrumentation_if instr_if;
|
riscv_instrumentation_if instr_if;
|
||||||
|
|
||||||
@ -555,71 +555,14 @@ riscv_hart_msu_vp<BASE>::riscv_hart_msu_vp()
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename BASE> std::pair<uint64_t, bool> riscv_hart_msu_vp<BASE>::load_file(std::string name, int type) {
|
template <typename BASE> std::pair<uint64_t, bool> riscv_hart_msu_vp<BASE>::load_file(std::string name, int type) {
|
||||||
FILE* fp = fopen(name.c_str(), "r");
|
if(read_elf_file(name, sizeof(reg_t) == 4 ? ELFIO::ELFCLASS32 : ELFIO::ELFCLASS64,
|
||||||
if(fp) {
|
[this](uint64_t addr, uint64_t size, const uint8_t* const data) -> iss::status {
|
||||||
std::array<char, 5> buf;
|
return this->write(iss::address_type::PHYSICAL, iss::access_type::DEBUG_WRITE, traits<BASE>::MEM, addr, size,
|
||||||
auto n = fread(buf.data(), 1, 4, fp);
|
data);
|
||||||
fclose(fp);
|
})) {
|
||||||
if(n != 4)
|
return std::make_pair(entry_address, true);
|
||||||
throw std::runtime_error("input file has insufficient size");
|
|
||||||
buf[4] = 0;
|
|
||||||
if(strcmp(buf.data() + 1, "ELF") == 0) {
|
|
||||||
// Create elfio reader
|
|
||||||
ELFIO::elfio reader;
|
|
||||||
// Load ELF data
|
|
||||||
if(!reader.load(name))
|
|
||||||
throw std::runtime_error("could not process elf file");
|
|
||||||
// check elf properties
|
|
||||||
if(reader.get_class() != ELFCLASS32)
|
|
||||||
if(sizeof(reg_t) == 4)
|
|
||||||
throw std::runtime_error("wrong elf class in file");
|
|
||||||
if(reader.get_type() != ET_EXEC)
|
|
||||||
throw std::runtime_error("wrong elf type in file");
|
|
||||||
if(reader.get_machine() != EM_RISCV)
|
|
||||||
throw std::runtime_error("wrong elf machine in file");
|
|
||||||
auto entry = reader.get_entry();
|
|
||||||
for(const auto pseg : reader.segments) {
|
|
||||||
const auto fsize = pseg->get_file_size(); // 0x42c/0x0
|
|
||||||
const auto seg_data = pseg->get_data();
|
|
||||||
const auto type = pseg->get_type();
|
|
||||||
if(type == 1 && fsize > 0) {
|
|
||||||
auto res = this->write(iss::address_type::PHYSICAL, iss::access_type::DEBUG_WRITE, traits<BASE>::MEM,
|
|
||||||
pseg->get_physical_address(), fsize, reinterpret_cast<const uint8_t* const>(seg_data));
|
|
||||||
if(res != iss::Ok)
|
|
||||||
CPPLOG(ERR) << "problem writing " << fsize << "bytes to 0x" << std::hex << pseg->get_physical_address();
|
|
||||||
}
|
}
|
||||||
}
|
return std::make_pair(entry_address, false);
|
||||||
for(const auto sec : reader.sections) {
|
|
||||||
if(sec->get_name() == ".symtab") {
|
|
||||||
if(SHT_SYMTAB == sec->get_type() || SHT_DYNSYM == sec->get_type()) {
|
|
||||||
ELFIO::symbol_section_accessor symbols(reader, sec);
|
|
||||||
auto sym_no = symbols.get_symbols_num();
|
|
||||||
std::string name;
|
|
||||||
ELFIO::Elf64_Addr value = 0;
|
|
||||||
ELFIO::Elf_Xword size = 0;
|
|
||||||
unsigned char bind = 0;
|
|
||||||
unsigned char type = 0;
|
|
||||||
ELFIO::Elf_Half section = 0;
|
|
||||||
unsigned char other = 0;
|
|
||||||
for(auto i = 0U; i < sym_no; ++i) {
|
|
||||||
symbols.get_symbol(i, name, value, size, bind, type, section, other);
|
|
||||||
if(name == "tohost") {
|
|
||||||
tohost = value;
|
|
||||||
} else if(name == "fromhost") {
|
|
||||||
fromhost = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if(sec->get_name() == ".tohost") {
|
|
||||||
tohost = sec->get_address();
|
|
||||||
fromhost = tohost + 0x40;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return std::make_pair(entry, true);
|
|
||||||
}
|
|
||||||
throw std::runtime_error(fmt::format("memory load file {} is not a valid elf file", name));
|
|
||||||
}
|
|
||||||
throw std::runtime_error(fmt::format("memory load file not found, check if {} is a valid file", name));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename BASE>
|
template <typename BASE>
|
||||||
@ -669,8 +612,10 @@ iss::status riscv_hart_msu_vp<BASE>::read(const address_type type, const access_
|
|||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
} catch(trap_access& ta) {
|
} catch(trap_access& ta) {
|
||||||
this->reg.trap_state = (1 << 31) | ta.id;
|
if((access & access_type::DEBUG) == 0) {
|
||||||
|
this->reg.trap_state = (1UL << 31) | ta.id;
|
||||||
fault_data = ta.addr;
|
fault_data = ta.addr;
|
||||||
|
}
|
||||||
return iss::Err;
|
return iss::Err;
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
@ -708,8 +653,10 @@ iss::status riscv_hart_msu_vp<BASE>::read(const address_type type, const access_
|
|||||||
}
|
}
|
||||||
return iss::Ok;
|
return iss::Ok;
|
||||||
} catch(trap_access& ta) {
|
} catch(trap_access& ta) {
|
||||||
|
if((access & access_type::DEBUG) == 0) {
|
||||||
this->reg.trap_state = (1UL << 31) | ta.id;
|
this->reg.trap_state = (1UL << 31) | ta.id;
|
||||||
fault_data = ta.addr;
|
fault_data = ta.addr;
|
||||||
|
}
|
||||||
return iss::Err;
|
return iss::Err;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -839,8 +786,10 @@ iss::status riscv_hart_msu_vp<BASE>::write(const address_type type, const access
|
|||||||
}
|
}
|
||||||
return iss::Ok;
|
return iss::Ok;
|
||||||
} catch(trap_access& ta) {
|
} catch(trap_access& ta) {
|
||||||
|
if((access & access_type::DEBUG) == 0) {
|
||||||
this->reg.trap_state = (1UL << 31) | ta.id;
|
this->reg.trap_state = (1UL << 31) | ta.id;
|
||||||
fault_data = ta.addr;
|
fault_data = ta.addr;
|
||||||
|
}
|
||||||
return iss::Err;
|
return iss::Err;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -887,7 +836,7 @@ template <typename BASE> iss::status riscv_hart_msu_vp<BASE>::write_reg(unsigned
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename BASE> iss::status riscv_hart_msu_vp<BASE>::read_cycle(unsigned addr, reg_t& val) {
|
template <typename BASE> iss::status riscv_hart_msu_vp<BASE>::read_cycle(unsigned addr, reg_t& val) {
|
||||||
auto cycle_val = this->reg.icount + cycle_offset;
|
auto cycle_val = this->reg.cycle + cycle_offset;
|
||||||
if(addr == mcycle) {
|
if(addr == mcycle) {
|
||||||
val = static_cast<reg_t>(cycle_val);
|
val = static_cast<reg_t>(cycle_val);
|
||||||
} else if(addr == mcycleh) {
|
} else if(addr == mcycleh) {
|
||||||
@ -908,7 +857,7 @@ template <typename BASE> iss::status riscv_hart_msu_vp<BASE>::write_cycle(unsign
|
|||||||
mcycle_csr = (static_cast<uint64_t>(val) << 32) + (mcycle_csr & 0xffffffff);
|
mcycle_csr = (static_cast<uint64_t>(val) << 32) + (mcycle_csr & 0xffffffff);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
cycle_offset = mcycle_csr - this->reg.icount; // TODO: relying on wrap-around
|
cycle_offset = mcycle_csr - this->reg.cycle; // TODO: relying on wrap-around
|
||||||
return iss::Ok;
|
return iss::Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -936,7 +885,7 @@ template <typename BASE> iss::status riscv_hart_msu_vp<BASE>::write_instret(unsi
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename BASE> iss::status riscv_hart_msu_vp<BASE>::read_time(unsigned addr, reg_t& val) {
|
template <typename BASE> iss::status riscv_hart_msu_vp<BASE>::read_time(unsigned addr, reg_t& val) {
|
||||||
uint64_t time_val = this->reg.icount / (100000000 / 32768 - 1); //-> ~3052;
|
uint64_t time_val = this->reg.cycle / (100000000 / 32768 - 1); //-> ~3052;
|
||||||
if(addr == time) {
|
if(addr == time) {
|
||||||
val = static_cast<reg_t>(time_val);
|
val = static_cast<reg_t>(time_val);
|
||||||
} else if(addr == timeh) {
|
} else if(addr == timeh) {
|
||||||
|
@ -39,7 +39,9 @@
|
|||||||
#include "iss/instrumentation_if.h"
|
#include "iss/instrumentation_if.h"
|
||||||
#include "iss/log_categories.h"
|
#include "iss/log_categories.h"
|
||||||
#include "iss/vm_if.h"
|
#include "iss/vm_if.h"
|
||||||
|
#include "iss/vm_types.h"
|
||||||
#include "riscv_hart_common.h"
|
#include "riscv_hart_common.h"
|
||||||
|
#include <stdexcept>
|
||||||
#ifndef FMT_HEADER_ONLY
|
#ifndef FMT_HEADER_ONLY
|
||||||
#define FMT_HEADER_ONLY
|
#define FMT_HEADER_ONLY
|
||||||
#endif
|
#endif
|
||||||
@ -302,8 +304,8 @@ public:
|
|||||||
void set_mhartid(reg_t mhartid) { mhartid_reg = mhartid; };
|
void set_mhartid(reg_t mhartid) { mhartid_reg = mhartid; };
|
||||||
|
|
||||||
void disass_output(uint64_t pc, const std::string instr) override {
|
void disass_output(uint64_t pc, const std::string instr) override {
|
||||||
CLOG(INFO, disass) << fmt::format("0x{:016x} {:40} [p:{};s:0x{:x};c:{}]", pc, instr, lvl[this->reg.PRIV], (reg_t)state.mstatus,
|
NSCLOG(INFO, LOGCAT) << fmt::format("0x{:016x} {:40} [p:{};s:0x{:x};c:{}]", pc, instr, lvl[this->reg.PRIV], (reg_t)state.mstatus,
|
||||||
this->reg.icount + cycle_offset);
|
this->reg.cycle + cycle_offset);
|
||||||
};
|
};
|
||||||
|
|
||||||
iss::instrumentation_if* get_instrumentation_if() override { return &instr_if; }
|
iss::instrumentation_if* get_instrumentation_if() override { return &instr_if; }
|
||||||
@ -336,7 +338,7 @@ protected:
|
|||||||
|
|
||||||
uint64_t get_pendig_traps() override { return arch.reg.trap_state; }
|
uint64_t get_pendig_traps() override { return arch.reg.trap_state; }
|
||||||
|
|
||||||
uint64_t get_total_cycles() override { return arch.reg.icount + arch.cycle_offset; }
|
uint64_t get_total_cycles() override { return arch.reg.cycle + arch.cycle_offset; }
|
||||||
|
|
||||||
void update_last_instr_cycles(unsigned cycles) override { arch.cycle_offset += cycles - 1; }
|
void update_last_instr_cycles(unsigned cycles) override { arch.cycle_offset += cycles - 1; }
|
||||||
|
|
||||||
@ -346,7 +348,7 @@ protected:
|
|||||||
|
|
||||||
unsigned get_reg_size(unsigned num) override { return traits<BASE>::reg_bit_widths[num]; }
|
unsigned get_reg_size(unsigned num) override { return traits<BASE>::reg_bit_widths[num]; }
|
||||||
|
|
||||||
std::unordered_map<std::string, uint64_t> get_symbol_table(std::string name) override { return arch.get_sym_table(name); }
|
std::unordered_map<std::string, uint64_t> const& get_symbol_table(std::string name) override { return arch.symbol_table; }
|
||||||
|
|
||||||
riscv_hart_mu_p<BASE, FEAT, LOGCAT>& arch;
|
riscv_hart_mu_p<BASE, FEAT, LOGCAT>& arch;
|
||||||
};
|
};
|
||||||
@ -368,8 +370,6 @@ protected:
|
|||||||
int64_t instret_offset{0};
|
int64_t instret_offset{0};
|
||||||
uint64_t minstret_csr{0};
|
uint64_t minstret_csr{0};
|
||||||
reg_t fault_data;
|
reg_t fault_data;
|
||||||
uint64_t tohost = tohost_dflt;
|
|
||||||
uint64_t fromhost = fromhost_dflt;
|
|
||||||
bool tohost_lower_written = false;
|
bool tohost_lower_written = false;
|
||||||
riscv_instrumentation_if instr_if;
|
riscv_instrumentation_if instr_if;
|
||||||
|
|
||||||
@ -402,8 +402,8 @@ protected:
|
|||||||
|
|
||||||
std::vector<uint8_t> tcm;
|
std::vector<uint8_t> tcm;
|
||||||
|
|
||||||
iss::status read_csr_reg(unsigned addr, reg_t& val);
|
iss::status read_plain(unsigned addr, reg_t& val);
|
||||||
iss::status write_csr_reg(unsigned addr, reg_t val);
|
iss::status write_plain(unsigned addr, reg_t val);
|
||||||
iss::status read_null(unsigned addr, reg_t& val);
|
iss::status read_null(unsigned addr, reg_t& val);
|
||||||
iss::status write_null(unsigned addr, reg_t val) { return iss::status::Ok; }
|
iss::status write_null(unsigned addr, reg_t val) { return iss::status::Ok; }
|
||||||
iss::status read_cycle(unsigned addr, reg_t& val);
|
iss::status read_cycle(unsigned addr, reg_t& val);
|
||||||
@ -426,15 +426,17 @@ protected:
|
|||||||
iss::status read_intstatus(unsigned addr, reg_t& val);
|
iss::status read_intstatus(unsigned addr, reg_t& val);
|
||||||
iss::status write_intthresh(unsigned addr, reg_t val);
|
iss::status write_intthresh(unsigned addr, reg_t val);
|
||||||
iss::status write_xtvt(unsigned addr, reg_t val);
|
iss::status write_xtvt(unsigned addr, reg_t val);
|
||||||
iss::status write_dcsr_dcsr(unsigned addr, reg_t val);
|
iss::status write_dcsr(unsigned addr, reg_t val);
|
||||||
iss::status read_dcsr_reg(unsigned addr, reg_t& val);
|
iss::status read_debug(unsigned addr, reg_t& val);
|
||||||
iss::status write_dcsr_reg(unsigned addr, reg_t val);
|
iss::status write_dscratch(unsigned addr, reg_t val);
|
||||||
iss::status read_dpc_reg(unsigned addr, reg_t& val);
|
iss::status read_dpc(unsigned addr, reg_t& val);
|
||||||
iss::status write_dpc_reg(unsigned addr, reg_t val);
|
iss::status write_dpc(unsigned addr, reg_t val);
|
||||||
iss::status write_pmpcfg_reg(unsigned addr, reg_t val);
|
iss::status read_fcsr(unsigned addr, reg_t& val);
|
||||||
|
iss::status write_fcsr(unsigned addr, reg_t val);
|
||||||
|
iss::status write_pmpcfg(unsigned addr, reg_t val);
|
||||||
|
|
||||||
virtual iss::status read_custom_csr_reg(unsigned addr, reg_t& val) { return iss::status::Err; };
|
virtual iss::status read_custom_csr(unsigned addr, reg_t& val) { return iss::status::Err; };
|
||||||
virtual iss::status write_custom_csr_reg(unsigned addr, reg_t val) { return iss::status::Err; };
|
virtual iss::status write_custom_csr(unsigned addr, reg_t val) { return iss::status::Err; };
|
||||||
|
|
||||||
void register_custom_csr_rd(unsigned addr) { csr_rd_cb[addr] = &this_class::read_custom_csr_reg; }
|
void register_custom_csr_rd(unsigned addr) { csr_rd_cb[addr] = &this_class::read_custom_csr_reg; }
|
||||||
void register_custom_csr_wr(unsigned addr) { csr_wr_cb[addr] = &this_class::write_custom_csr_reg; }
|
void register_custom_csr_wr(unsigned addr) { csr_wr_cb[addr] = &this_class::write_custom_csr_reg; }
|
||||||
@ -474,18 +476,22 @@ riscv_hart_mu_p<BASE, FEAT, LOGCAT>::riscv_hart_mu_p(feature_config cfg)
|
|||||||
csr[mimpid] = 1;
|
csr[mimpid] = 1;
|
||||||
|
|
||||||
uart_buf.str("");
|
uart_buf.str("");
|
||||||
|
if(traits<BASE>::FLEN > 0) {
|
||||||
|
csr_rd_cb[fcsr] = &this_class::read_fcsr;
|
||||||
|
csr_wr_cb[fcsr] = &this_class::write_fcsr;
|
||||||
|
}
|
||||||
for(unsigned addr = mhpmcounter3; addr <= mhpmcounter31; ++addr) {
|
for(unsigned addr = mhpmcounter3; addr <= mhpmcounter31; ++addr) {
|
||||||
csr_rd_cb[addr] = &this_class::read_null;
|
csr_rd_cb[addr] = &this_class::read_null;
|
||||||
csr_wr_cb[addr] = &this_class::write_csr_reg;
|
csr_wr_cb[addr] = &this_class::write_plain;
|
||||||
}
|
}
|
||||||
if(traits<BASE>::XLEN == 32)
|
if(traits<BASE>::XLEN == 32)
|
||||||
for(unsigned addr = mhpmcounter3h; addr <= mhpmcounter31h; ++addr) {
|
for(unsigned addr = mhpmcounter3h; addr <= mhpmcounter31h; ++addr) {
|
||||||
csr_rd_cb[addr] = &this_class::read_null;
|
csr_rd_cb[addr] = &this_class::read_null;
|
||||||
csr_wr_cb[addr] = &this_class::write_csr_reg;
|
csr_wr_cb[addr] = &this_class::write_plain;
|
||||||
}
|
}
|
||||||
for(unsigned addr = mhpmevent3; addr <= mhpmevent31; ++addr) {
|
for(unsigned addr = mhpmevent3; addr <= mhpmevent31; ++addr) {
|
||||||
csr_rd_cb[addr] = &this_class::read_null;
|
csr_rd_cb[addr] = &this_class::read_null;
|
||||||
csr_wr_cb[addr] = &this_class::write_csr_reg;
|
csr_wr_cb[addr] = &this_class::write_plain;
|
||||||
}
|
}
|
||||||
for(unsigned addr = hpmcounter3; addr <= hpmcounter31; ++addr) {
|
for(unsigned addr = hpmcounter3; addr <= hpmcounter31; ++addr) {
|
||||||
csr_rd_cb[addr] = &this_class::read_null;
|
csr_rd_cb[addr] = &this_class::read_null;
|
||||||
@ -493,12 +499,11 @@ riscv_hart_mu_p<BASE, FEAT, LOGCAT>::riscv_hart_mu_p(feature_config cfg)
|
|||||||
if(traits<BASE>::XLEN == 32)
|
if(traits<BASE>::XLEN == 32)
|
||||||
for(unsigned addr = hpmcounter3h; addr <= hpmcounter31h; ++addr) {
|
for(unsigned addr = hpmcounter3h; addr <= hpmcounter31h; ++addr) {
|
||||||
csr_rd_cb[addr] = &this_class::read_null;
|
csr_rd_cb[addr] = &this_class::read_null;
|
||||||
// csr_wr_cb[addr] = &this_class::write_csr_reg;
|
|
||||||
}
|
}
|
||||||
// common regs
|
// common regs
|
||||||
const std::array<unsigned, 4> roaddrs{{misa, mvendorid, marchid, mimpid}};
|
const std::array<unsigned, 4> roaddrs{{misa, mvendorid, marchid, mimpid}};
|
||||||
for(auto addr : roaddrs) {
|
for(auto addr : roaddrs) {
|
||||||
csr_rd_cb[addr] = &this_class::read_csr_reg;
|
csr_rd_cb[addr] = &this_class::read_plain;
|
||||||
csr_wr_cb[addr] = &this_class::write_null;
|
csr_wr_cb[addr] = &this_class::write_null;
|
||||||
}
|
}
|
||||||
const std::array<unsigned, 8> rwaddrs{{
|
const std::array<unsigned, 8> rwaddrs{{
|
||||||
@ -512,8 +517,8 @@ riscv_hart_mu_p<BASE, FEAT, LOGCAT>::riscv_hart_mu_p(feature_config cfg)
|
|||||||
utval,
|
utval,
|
||||||
}};
|
}};
|
||||||
for(auto addr : rwaddrs) {
|
for(auto addr : rwaddrs) {
|
||||||
csr_rd_cb[addr] = &this_class::read_csr_reg;
|
csr_rd_cb[addr] = &this_class::read_plain;
|
||||||
csr_wr_cb[addr] = &this_class::write_csr_reg;
|
csr_wr_cb[addr] = &this_class::write_plain;
|
||||||
}
|
}
|
||||||
// special handling & overrides
|
// special handling & overrides
|
||||||
csr_rd_cb[time] = &this_class::read_time;
|
csr_rd_cb[time] = &this_class::read_time;
|
||||||
@ -558,18 +563,18 @@ riscv_hart_mu_p<BASE, FEAT, LOGCAT>::riscv_hart_mu_p(feature_config cfg)
|
|||||||
|
|
||||||
if(FEAT & FEAT_PMP) {
|
if(FEAT & FEAT_PMP) {
|
||||||
for(size_t i = pmpaddr0; i <= pmpaddr15; ++i) {
|
for(size_t i = pmpaddr0; i <= pmpaddr15; ++i) {
|
||||||
csr_rd_cb[i] = &this_class::read_csr_reg;
|
csr_rd_cb[i] = &this_class::read_plain;
|
||||||
csr_wr_cb[i] = &this_class::write_csr_reg;
|
csr_wr_cb[i] = &this_class::write_plain;
|
||||||
}
|
}
|
||||||
for(size_t i = pmpcfg0; i < pmpcfg0 + 16 / sizeof(reg_t); ++i) {
|
for(size_t i = pmpcfg0; i < pmpcfg0 + 16 / sizeof(reg_t); ++i) {
|
||||||
csr_rd_cb[i] = &this_class::read_csr_reg;
|
csr_rd_cb[i] = &this_class::read_plain;
|
||||||
csr_wr_cb[i] = &this_class::write_pmpcfg_reg;
|
csr_wr_cb[i] = &this_class::write_pmpcfg;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(FEAT & FEAT_EXT_N) {
|
if(FEAT & FEAT_EXT_N) {
|
||||||
csr_rd_cb[mideleg] = &this_class::read_csr_reg;
|
csr_rd_cb[mideleg] = &this_class::read_plain;
|
||||||
csr_wr_cb[mideleg] = &this_class::write_ideleg;
|
csr_wr_cb[mideleg] = &this_class::write_ideleg;
|
||||||
csr_rd_cb[medeleg] = &this_class::read_csr_reg;
|
csr_rd_cb[medeleg] = &this_class::read_plain;
|
||||||
csr_wr_cb[medeleg] = &this_class::write_edeleg;
|
csr_wr_cb[medeleg] = &this_class::write_edeleg;
|
||||||
csr_rd_cb[uie] = &this_class::read_ie;
|
csr_rd_cb[uie] = &this_class::read_ie;
|
||||||
csr_wr_cb[uie] = &this_class::write_ie;
|
csr_wr_cb[uie] = &this_class::write_ie;
|
||||||
@ -583,7 +588,7 @@ riscv_hart_mu_p<BASE, FEAT, LOGCAT>::riscv_hart_mu_p(feature_config cfg)
|
|||||||
csr_rd_cb[utvec] = &this_class::read_tvec;
|
csr_rd_cb[utvec] = &this_class::read_tvec;
|
||||||
}
|
}
|
||||||
if(FEAT & FEAT_CLIC) {
|
if(FEAT & FEAT_CLIC) {
|
||||||
csr_rd_cb[mtvt] = &this_class::read_csr_reg;
|
csr_rd_cb[mtvt] = &this_class::read_plain;
|
||||||
csr_wr_cb[mtvt] = &this_class::write_xtvt;
|
csr_wr_cb[mtvt] = &this_class::write_xtvt;
|
||||||
// csr_rd_cb[mxnti] = &this_class::read_csr_reg;
|
// csr_rd_cb[mxnti] = &this_class::read_csr_reg;
|
||||||
// csr_wr_cb[mxnti] = &this_class::write_csr_reg;
|
// csr_wr_cb[mxnti] = &this_class::write_csr_reg;
|
||||||
@ -593,14 +598,14 @@ riscv_hart_mu_p<BASE, FEAT, LOGCAT>::riscv_hart_mu_p(feature_config cfg)
|
|||||||
// csr_wr_cb[mscratchcsw] = &this_class::write_csr_reg;
|
// csr_wr_cb[mscratchcsw] = &this_class::write_csr_reg;
|
||||||
// csr_rd_cb[mscratchcswl] = &this_class::read_csr_reg;
|
// csr_rd_cb[mscratchcswl] = &this_class::read_csr_reg;
|
||||||
// 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_plain;
|
||||||
csr_wr_cb[mintthresh] = &this_class::write_intthresh;
|
csr_wr_cb[mintthresh] = &this_class::write_intthresh;
|
||||||
if(FEAT & FEAT_EXT_N) {
|
if(FEAT & FEAT_EXT_N) {
|
||||||
csr_rd_cb[utvt] = &this_class::read_csr_reg;
|
csr_rd_cb[utvt] = &this_class::read_plain;
|
||||||
csr_wr_cb[utvt] = &this_class::write_xtvt;
|
csr_wr_cb[utvt] = &this_class::write_xtvt;
|
||||||
csr_rd_cb[uintstatus] = &this_class::read_intstatus;
|
csr_rd_cb[uintstatus] = &this_class::read_intstatus;
|
||||||
csr_wr_cb[uintstatus] = &this_class::write_null;
|
csr_wr_cb[uintstatus] = &this_class::write_null;
|
||||||
csr_rd_cb[uintthresh] = &this_class::read_csr_reg;
|
csr_rd_cb[uintthresh] = &this_class::read_plain;
|
||||||
csr_wr_cb[uintthresh] = &this_class::write_intthresh;
|
csr_wr_cb[uintthresh] = &this_class::write_intthresh;
|
||||||
}
|
}
|
||||||
clic_int_reg.resize(cfg.clic_num_irq, clic_int_reg_t{.raw = 0});
|
clic_int_reg.resize(cfg.clic_num_irq, clic_int_reg_t{.raw = 0});
|
||||||
@ -629,14 +634,14 @@ riscv_hart_mu_p<BASE, FEAT, LOGCAT>::riscv_hart_mu_p(feature_config cfg)
|
|||||||
insert_mem_range(cfg.tcm_base, cfg.tcm_size, 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_dscratch;
|
||||||
csr_rd_cb[dscratch0] = &this_class::read_dcsr_reg;
|
csr_rd_cb[dscratch0] = &this_class::read_debug;
|
||||||
csr_wr_cb[dscratch1] = &this_class::write_dcsr_reg;
|
csr_wr_cb[dscratch1] = &this_class::write_dscratch;
|
||||||
csr_rd_cb[dscratch1] = &this_class::read_dcsr_reg;
|
csr_rd_cb[dscratch1] = &this_class::read_debug;
|
||||||
csr_wr_cb[dpc] = &this_class::write_dpc_reg;
|
csr_wr_cb[dpc] = &this_class::write_dpc;
|
||||||
csr_rd_cb[dpc] = &this_class::read_dpc_reg;
|
csr_rd_cb[dpc] = &this_class::read_dpc;
|
||||||
csr_wr_cb[dcsr] = &this_class::write_dcsr_dcsr;
|
csr_wr_cb[dcsr] = &this_class::write_dcsr;
|
||||||
csr_rd_cb[dcsr] = &this_class::read_dcsr_reg;
|
csr_rd_cb[dcsr] = &this_class::read_debug;
|
||||||
}
|
}
|
||||||
hart_mem_rd_delegate = [this](phys_addr_t a, unsigned l, uint8_t* const d) -> iss::status { return this->read_mem(a, l, d); };
|
hart_mem_rd_delegate = [this](phys_addr_t a, unsigned l, uint8_t* const d) -> iss::status { return this->read_mem(a, l, d); };
|
||||||
hart_mem_wr_delegate = [this](phys_addr_t a, unsigned l, uint8_t const* const d) -> iss::status { return this->write_mem(a, l, d); };
|
hart_mem_wr_delegate = [this](phys_addr_t a, unsigned l, uint8_t const* const d) -> iss::status { return this->write_mem(a, l, d); };
|
||||||
@ -644,71 +649,14 @@ riscv_hart_mu_p<BASE, FEAT, LOGCAT>::riscv_hart_mu_p(feature_config cfg)
|
|||||||
|
|
||||||
template <typename BASE, features_e FEAT, typename LOGCAT>
|
template <typename BASE, features_e FEAT, typename LOGCAT>
|
||||||
std::pair<uint64_t, bool> riscv_hart_mu_p<BASE, FEAT, LOGCAT>::load_file(std::string name, int type) {
|
std::pair<uint64_t, bool> riscv_hart_mu_p<BASE, FEAT, LOGCAT>::load_file(std::string name, int type) {
|
||||||
FILE* fp = fopen(name.c_str(), "r");
|
if(read_elf_file(name, sizeof(reg_t) == 4 ? ELFIO::ELFCLASS32 : ELFIO::ELFCLASS64,
|
||||||
if(fp) {
|
[this](uint64_t addr, uint64_t size, const uint8_t* const data) -> iss::status {
|
||||||
std::array<char, 5> buf;
|
return this->write(iss::address_type::PHYSICAL, iss::access_type::DEBUG_WRITE, traits<BASE>::MEM, addr, size,
|
||||||
auto n = fread(buf.data(), 1, 4, fp);
|
data);
|
||||||
fclose(fp);
|
})) {
|
||||||
if(n != 4)
|
return std::make_pair(entry_address, true);
|
||||||
throw std::runtime_error("input file has insufficient size");
|
|
||||||
buf[4] = 0;
|
|
||||||
if(strcmp(buf.data() + 1, "ELF") == 0) {
|
|
||||||
// Create elfio reader
|
|
||||||
ELFIO::elfio reader;
|
|
||||||
// Load ELF data
|
|
||||||
if(!reader.load(name))
|
|
||||||
throw std::runtime_error("could not process elf file");
|
|
||||||
// check elf properties
|
|
||||||
if(reader.get_class() != ELFCLASS32)
|
|
||||||
if(sizeof(reg_t) == 4)
|
|
||||||
throw std::runtime_error("wrong elf class in file");
|
|
||||||
if(reader.get_type() != ET_EXEC)
|
|
||||||
throw std::runtime_error("wrong elf type in file");
|
|
||||||
if(reader.get_machine() != EM_RISCV)
|
|
||||||
throw std::runtime_error("wrong elf machine in file");
|
|
||||||
auto entry = reader.get_entry();
|
|
||||||
for(const auto pseg : reader.segments) {
|
|
||||||
const auto fsize = pseg->get_file_size(); // 0x42c/0x0
|
|
||||||
const auto seg_data = pseg->get_data();
|
|
||||||
const auto type = pseg->get_type();
|
|
||||||
if(type == 1 && fsize > 0) {
|
|
||||||
auto res = this->write(iss::address_type::PHYSICAL, iss::access_type::DEBUG_WRITE, traits<BASE>::MEM,
|
|
||||||
pseg->get_physical_address(), fsize, reinterpret_cast<const uint8_t* const>(seg_data));
|
|
||||||
if(res != iss::Ok)
|
|
||||||
CPPLOG(ERR) << "problem writing " << fsize << "bytes to 0x" << std::hex << pseg->get_physical_address();
|
|
||||||
}
|
}
|
||||||
}
|
return std::make_pair(entry_address, false);
|
||||||
for(const auto sec : reader.sections) {
|
|
||||||
if(sec->get_name() == ".symtab") {
|
|
||||||
if(SHT_SYMTAB == sec->get_type() || SHT_DYNSYM == sec->get_type()) {
|
|
||||||
ELFIO::symbol_section_accessor symbols(reader, sec);
|
|
||||||
auto sym_no = symbols.get_symbols_num();
|
|
||||||
std::string name;
|
|
||||||
ELFIO::Elf64_Addr value = 0;
|
|
||||||
ELFIO::Elf_Xword size = 0;
|
|
||||||
unsigned char bind = 0;
|
|
||||||
unsigned char type = 0;
|
|
||||||
ELFIO::Elf_Half section = 0;
|
|
||||||
unsigned char other = 0;
|
|
||||||
for(auto i = 0U; i < sym_no; ++i) {
|
|
||||||
symbols.get_symbol(i, name, value, size, bind, type, section, other);
|
|
||||||
if(name == "tohost") {
|
|
||||||
tohost = value;
|
|
||||||
} else if(name == "fromhost") {
|
|
||||||
fromhost = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if(sec->get_name() == ".tohost") {
|
|
||||||
tohost = sec->get_address();
|
|
||||||
fromhost = tohost + 0x40;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return std::make_pair(entry, true);
|
|
||||||
}
|
|
||||||
throw std::runtime_error(fmt::format("memory load file {} is not a valid elf file", name));
|
|
||||||
}
|
|
||||||
throw std::runtime_error(fmt::format("memory load file not found, check if {} is a valid file", name));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename BASE, features_e FEAT, typename LOGCAT>
|
template <typename BASE, features_e FEAT, typename LOGCAT>
|
||||||
@ -725,7 +673,7 @@ inline void riscv_hart_mu_p<BASE, FEAT, LOGCAT>::insert_mem_range(uint64_t base,
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename BASE, features_e FEAT, typename LOGCAT>
|
template <typename BASE, features_e FEAT, typename LOGCAT>
|
||||||
inline iss::status riscv_hart_mu_p<BASE, FEAT, LOGCAT>::write_pmpcfg_reg(unsigned addr, reg_t val) {
|
inline iss::status riscv_hart_mu_p<BASE, FEAT, LOGCAT>::write_pmpcfg(unsigned addr, reg_t val) {
|
||||||
csr[addr] = val & 0x9f9f9f9f;
|
csr[addr] = val & 0x9f9f9f9f;
|
||||||
return iss::Ok;
|
return iss::Ok;
|
||||||
}
|
}
|
||||||
@ -870,8 +818,10 @@ iss::status riscv_hart_mu_p<BASE, FEAT, LOGCAT>::read(const address_type type, c
|
|||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
} catch(trap_access& ta) {
|
} catch(trap_access& ta) {
|
||||||
|
if((access & access_type::DEBUG) == 0) {
|
||||||
this->reg.trap_state = (1UL << 31) | ta.id;
|
this->reg.trap_state = (1UL << 31) | ta.id;
|
||||||
fault_data = ta.addr;
|
fault_data = ta.addr;
|
||||||
|
}
|
||||||
return iss::Err;
|
return iss::Err;
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
@ -898,8 +848,10 @@ iss::status riscv_hart_mu_p<BASE, FEAT, LOGCAT>::read(const address_type type, c
|
|||||||
}
|
}
|
||||||
return iss::Ok;
|
return iss::Ok;
|
||||||
} catch(trap_access& ta) {
|
} catch(trap_access& ta) {
|
||||||
|
if((access & access_type::DEBUG) == 0) {
|
||||||
this->reg.trap_state = (1UL << 31) | ta.id;
|
this->reg.trap_state = (1UL << 31) | ta.id;
|
||||||
fault_data = ta.addr;
|
fault_data = ta.addr;
|
||||||
|
}
|
||||||
return iss::Err;
|
return iss::Err;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -988,8 +940,6 @@ iss::status riscv_hart_mu_p<BASE, FEAT, LOGCAT>::write(const address_type type,
|
|||||||
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) {
|
||||||
// CPPLOG(INFO)<<"UART"<<((addr>>16)&0x3)<<" send
|
|
||||||
// '"<<uart_buf.str()<<"'";
|
|
||||||
std::cout << uart_buf.str();
|
std::cout << uart_buf.str();
|
||||||
uart_buf.str("");
|
uart_buf.str("");
|
||||||
}
|
}
|
||||||
@ -1040,8 +990,10 @@ iss::status riscv_hart_mu_p<BASE, FEAT, LOGCAT>::write(const address_type type,
|
|||||||
}
|
}
|
||||||
return iss::Ok;
|
return iss::Ok;
|
||||||
} catch(trap_access& ta) {
|
} catch(trap_access& ta) {
|
||||||
|
if((access & access_type::DEBUG) == 0) {
|
||||||
this->reg.trap_state = (1UL << 31) | ta.id;
|
this->reg.trap_state = (1UL << 31) | ta.id;
|
||||||
fault_data = ta.addr;
|
fault_data = ta.addr;
|
||||||
|
}
|
||||||
return iss::Err;
|
return iss::Err;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1074,12 +1026,6 @@ iss::status riscv_hart_mu_p<BASE, FEAT, LOGCAT>::write_csr(unsigned addr, reg_t
|
|||||||
return (this->*(it->second))(addr, val);
|
return (this->*(it->second))(addr, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename BASE, features_e FEAT, typename LOGCAT>
|
|
||||||
iss::status riscv_hart_mu_p<BASE, FEAT, LOGCAT>::read_csr_reg(unsigned addr, reg_t& val) {
|
|
||||||
val = csr[addr];
|
|
||||||
return iss::Ok;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename BASE, features_e FEAT, typename LOGCAT>
|
template <typename BASE, features_e FEAT, typename LOGCAT>
|
||||||
iss::status riscv_hart_mu_p<BASE, FEAT, LOGCAT>::read_null(unsigned addr, reg_t& val) {
|
iss::status riscv_hart_mu_p<BASE, FEAT, LOGCAT>::read_null(unsigned addr, reg_t& val) {
|
||||||
val = 0;
|
val = 0;
|
||||||
@ -1087,14 +1033,20 @@ iss::status riscv_hart_mu_p<BASE, FEAT, LOGCAT>::read_null(unsigned addr, reg_t&
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename BASE, features_e FEAT, typename LOGCAT>
|
template <typename BASE, features_e FEAT, typename LOGCAT>
|
||||||
iss::status riscv_hart_mu_p<BASE, FEAT, LOGCAT>::write_csr_reg(unsigned addr, reg_t val) {
|
iss::status riscv_hart_mu_p<BASE, FEAT, LOGCAT>::read_plain(unsigned addr, reg_t& val) {
|
||||||
|
val = csr[addr];
|
||||||
|
return iss::Ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename BASE, features_e FEAT, typename LOGCAT>
|
||||||
|
iss::status riscv_hart_mu_p<BASE, FEAT, LOGCAT>::write_plain(unsigned addr, reg_t val) {
|
||||||
csr[addr] = val;
|
csr[addr] = val;
|
||||||
return iss::Ok;
|
return iss::Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename BASE, features_e FEAT, typename LOGCAT>
|
template <typename BASE, features_e FEAT, typename LOGCAT>
|
||||||
iss::status riscv_hart_mu_p<BASE, FEAT, LOGCAT>::read_cycle(unsigned addr, reg_t& val) {
|
iss::status riscv_hart_mu_p<BASE, FEAT, LOGCAT>::read_cycle(unsigned addr, reg_t& val) {
|
||||||
auto cycle_val = this->reg.icount + cycle_offset;
|
auto cycle_val = this->reg.cycle + cycle_offset;
|
||||||
if(addr == mcycle) {
|
if(addr == mcycle) {
|
||||||
val = static_cast<reg_t>(cycle_val);
|
val = static_cast<reg_t>(cycle_val);
|
||||||
} else if(addr == mcycleh) {
|
} else if(addr == mcycleh) {
|
||||||
@ -1114,7 +1066,7 @@ iss::status riscv_hart_mu_p<BASE, FEAT, LOGCAT>::write_cycle(unsigned addr, reg_
|
|||||||
mcycle_csr = (static_cast<uint64_t>(val) << 32) + (mcycle_csr & 0xffffffff);
|
mcycle_csr = (static_cast<uint64_t>(val) << 32) + (mcycle_csr & 0xffffffff);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
cycle_offset = mcycle_csr - this->reg.icount; // TODO: relying on wrap-around
|
cycle_offset = mcycle_csr - this->reg.cycle; // TODO: relying on wrap-around
|
||||||
return iss::Ok;
|
return iss::Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1145,7 +1097,7 @@ iss::status riscv_hart_mu_p<BASE, FEAT, LOGCAT>::write_instret(unsigned addr, re
|
|||||||
|
|
||||||
template <typename BASE, features_e FEAT, typename LOGCAT>
|
template <typename BASE, features_e FEAT, typename LOGCAT>
|
||||||
iss::status riscv_hart_mu_p<BASE, FEAT, LOGCAT>::read_time(unsigned addr, reg_t& val) {
|
iss::status riscv_hart_mu_p<BASE, FEAT, LOGCAT>::read_time(unsigned addr, reg_t& val) {
|
||||||
uint64_t time_val = this->reg.icount / (100000000 / 32768 - 1); //-> ~3052;
|
uint64_t time_val = this->reg.cycle / (100000000 / 32768 - 1); //-> ~3052;
|
||||||
if(addr == time) {
|
if(addr == time) {
|
||||||
val = static_cast<reg_t>(time_val);
|
val = static_cast<reg_t>(time_val);
|
||||||
} else if(addr == timeh) {
|
} else if(addr == timeh) {
|
||||||
@ -1161,6 +1113,7 @@ iss::status riscv_hart_mu_p<BASE, FEAT, LOGCAT>::read_tvec(unsigned addr, reg_t&
|
|||||||
val = FEAT & features_e::FEAT_CLIC ? csr[addr] : csr[addr] & ~2;
|
val = FEAT & features_e::FEAT_CLIC ? csr[addr] : csr[addr] & ~2;
|
||||||
return iss::Ok;
|
return iss::Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename BASE, features_e FEAT, typename LOGCAT>
|
template <typename BASE, features_e FEAT, typename LOGCAT>
|
||||||
iss::status riscv_hart_mu_p<BASE, FEAT, LOGCAT>::read_status(unsigned addr, reg_t& val) {
|
iss::status riscv_hart_mu_p<BASE, FEAT, LOGCAT>::read_status(unsigned addr, reg_t& val) {
|
||||||
val = state.mstatus & hart_state_type::get_mask((addr >> 8) & 0x3);
|
val = state.mstatus & hart_state_type::get_mask((addr >> 8) & 0x3);
|
||||||
@ -1272,7 +1225,7 @@ iss::status riscv_hart_mu_p<BASE, FEAT, LOGCAT>::write_epc(unsigned addr, reg_t
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename BASE, features_e FEAT, typename LOGCAT>
|
template <typename BASE, features_e FEAT, typename LOGCAT>
|
||||||
iss::status riscv_hart_mu_p<BASE, FEAT, LOGCAT>::write_dcsr_dcsr(unsigned addr, reg_t val) {
|
iss::status riscv_hart_mu_p<BASE, FEAT, LOGCAT>::write_dcsr(unsigned addr, reg_t val) {
|
||||||
if(!debug_mode_active())
|
if(!debug_mode_active())
|
||||||
throw illegal_instruction_fault(this->fault_data);
|
throw illegal_instruction_fault(this->fault_data);
|
||||||
// +-------------- ebreakm
|
// +-------------- ebreakm
|
||||||
@ -1284,7 +1237,7 @@ iss::status riscv_hart_mu_p<BASE, FEAT, LOGCAT>::write_dcsr_dcsr(unsigned addr,
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename BASE, features_e FEAT, typename LOGCAT>
|
template <typename BASE, features_e FEAT, typename LOGCAT>
|
||||||
iss::status riscv_hart_mu_p<BASE, FEAT, LOGCAT>::read_dcsr_reg(unsigned addr, reg_t& val) {
|
iss::status riscv_hart_mu_p<BASE, FEAT, LOGCAT>::read_debug(unsigned addr, reg_t& val) {
|
||||||
if(!debug_mode_active())
|
if(!debug_mode_active())
|
||||||
throw illegal_instruction_fault(this->fault_data);
|
throw illegal_instruction_fault(this->fault_data);
|
||||||
val = csr[addr];
|
val = csr[addr];
|
||||||
@ -1292,7 +1245,7 @@ iss::status riscv_hart_mu_p<BASE, FEAT, LOGCAT>::read_dcsr_reg(unsigned addr, re
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename BASE, features_e FEAT, typename LOGCAT>
|
template <typename BASE, features_e FEAT, typename LOGCAT>
|
||||||
iss::status riscv_hart_mu_p<BASE, FEAT, LOGCAT>::write_dcsr_reg(unsigned addr, reg_t val) {
|
iss::status riscv_hart_mu_p<BASE, FEAT, LOGCAT>::write_dscratch(unsigned addr, reg_t val) {
|
||||||
if(!debug_mode_active())
|
if(!debug_mode_active())
|
||||||
throw illegal_instruction_fault(this->fault_data);
|
throw illegal_instruction_fault(this->fault_data);
|
||||||
csr[addr] = val;
|
csr[addr] = val;
|
||||||
@ -1300,7 +1253,7 @@ iss::status riscv_hart_mu_p<BASE, FEAT, LOGCAT>::write_dcsr_reg(unsigned addr, r
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename BASE, features_e FEAT, typename LOGCAT>
|
template <typename BASE, features_e FEAT, typename LOGCAT>
|
||||||
iss::status riscv_hart_mu_p<BASE, FEAT, LOGCAT>::read_dpc_reg(unsigned addr, reg_t& val) {
|
iss::status riscv_hart_mu_p<BASE, FEAT, LOGCAT>::read_dpc(unsigned addr, reg_t& val) {
|
||||||
if(!debug_mode_active())
|
if(!debug_mode_active())
|
||||||
throw illegal_instruction_fault(this->fault_data);
|
throw illegal_instruction_fault(this->fault_data);
|
||||||
val = this->reg.DPC;
|
val = this->reg.DPC;
|
||||||
@ -1308,7 +1261,7 @@ iss::status riscv_hart_mu_p<BASE, FEAT, LOGCAT>::read_dpc_reg(unsigned addr, reg
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename BASE, features_e FEAT, typename LOGCAT>
|
template <typename BASE, features_e FEAT, typename LOGCAT>
|
||||||
iss::status riscv_hart_mu_p<BASE, FEAT, LOGCAT>::write_dpc_reg(unsigned addr, reg_t val) {
|
iss::status riscv_hart_mu_p<BASE, FEAT, LOGCAT>::write_dpc(unsigned addr, reg_t val) {
|
||||||
if(!debug_mode_active())
|
if(!debug_mode_active())
|
||||||
throw illegal_instruction_fault(this->fault_data);
|
throw illegal_instruction_fault(this->fault_data);
|
||||||
this->reg.DPC = val;
|
this->reg.DPC = val;
|
||||||
@ -1324,6 +1277,18 @@ iss::status riscv_hart_mu_p<BASE, FEAT, LOGCAT>::read_intstatus(unsigned addr, r
|
|||||||
return iss::Ok;
|
return iss::Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename BASE, features_e FEAT, typename LOGCAT>
|
||||||
|
iss::status riscv_hart_mu_p<BASE, FEAT, LOGCAT>::read_fcsr(unsigned addr, reg_t& val) {
|
||||||
|
val = this->get_fcsr();
|
||||||
|
return iss::Ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename BASE, features_e FEAT, typename LOGCAT>
|
||||||
|
iss::status riscv_hart_mu_p<BASE, FEAT, LOGCAT>::write_fcsr(unsigned addr, reg_t val) {
|
||||||
|
this->set_fcsr(val);
|
||||||
|
return iss::Ok;
|
||||||
|
}
|
||||||
|
|
||||||
template <typename BASE, features_e FEAT, typename LOGCAT>
|
template <typename BASE, features_e FEAT, typename LOGCAT>
|
||||||
iss::status riscv_hart_mu_p<BASE, FEAT, LOGCAT>::write_intthresh(unsigned addr, reg_t val) {
|
iss::status riscv_hart_mu_p<BASE, FEAT, LOGCAT>::write_intthresh(unsigned addr, reg_t val) {
|
||||||
csr[addr] = (val & 0xff) | (1 << (cfg.clic_int_ctl_bits)) - 1;
|
csr[addr] = (val & 0xff) | (1 << (cfg.clic_int_ctl_bits)) - 1;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
* Copyright (C) 2017 - 2020 MINRES Technologies GmbH
|
* Copyright (C) 2024 MINRES Technologies GmbH
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
* Copyright (C) 2017 - 2021 MINRES Technologies GmbH
|
* Copyright (C) 2024 MINRES Technologies GmbH
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@ -189,7 +189,7 @@ struct tgc5c: public arch_if {
|
|||||||
|
|
||||||
uint8_t* get_regs_base_ptr() override;
|
uint8_t* get_regs_base_ptr() override;
|
||||||
|
|
||||||
inline uint64_t get_icount() { return reg.icount; }
|
inline uint64_t get_icount() { return reg.icount; } //This should not be accessible, only through the instrumentation_if
|
||||||
|
|
||||||
inline bool should_stop() { return interrupt_sim; }
|
inline bool should_stop() { return interrupt_sim; }
|
||||||
|
|
||||||
@ -199,7 +199,7 @@ struct tgc5c: public arch_if {
|
|||||||
|
|
||||||
virtual iss::sync_type needed_sync() const { return iss::NO_SYNC; }
|
virtual iss::sync_type needed_sync() const { return iss::NO_SYNC; }
|
||||||
|
|
||||||
inline uint32_t get_last_branch() { return reg.last_branch; }
|
inline uint32_t get_last_branch() { return reg.last_branch; } //This should also only be accessible through the instrumentation_if
|
||||||
|
|
||||||
|
|
||||||
#pragma pack(push, 1)
|
#pragma pack(push, 1)
|
||||||
|
4108
src/iss/debugger/csr_names.cpp
Archivo normal
4108
src/iss/debugger/csr_names.cpp
Archivo normal
La diferencia del archivo ha sido suprimido porque es demasiado grande
Cargar Diff
@ -30,8 +30,8 @@
|
|||||||
*
|
*
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
|
|
||||||
#ifndef _ISS_DEBUGGER_RISCV_TARGET_ADAPTER_H_
|
#ifndef _ISS_ARCH_DEBUGGER_RISCV_TARGET_ADAPTER_H_
|
||||||
#define _ISS_DEBUGGER_RISCV_TARGET_ADAPTER_H_
|
#define _ISS_ARCH_DEBUGGER_RISCV_TARGET_ADAPTER_H_
|
||||||
|
|
||||||
#include "iss/arch_if.h"
|
#include "iss/arch_if.h"
|
||||||
#include <iss/arch/traits.h>
|
#include <iss/arch/traits.h>
|
||||||
@ -48,6 +48,10 @@
|
|||||||
|
|
||||||
namespace iss {
|
namespace iss {
|
||||||
namespace debugger {
|
namespace debugger {
|
||||||
|
|
||||||
|
char const* const get_csr_name(unsigned);
|
||||||
|
constexpr auto csr_offset = 100U;
|
||||||
|
|
||||||
using namespace iss::arch;
|
using namespace iss::arch;
|
||||||
using namespace iss::debugger;
|
using namespace iss::debugger;
|
||||||
|
|
||||||
@ -129,11 +133,17 @@ public:
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
static inline constexpr addr_t map_addr(const addr_t& i) { return i; }
|
static inline constexpr addr_t map_addr(const addr_t& i) { return i; }
|
||||||
|
std::string csr_xml;
|
||||||
iss::arch_if* core;
|
iss::arch_if* core;
|
||||||
rp_thread_ref thread_idx;
|
rp_thread_ref thread_idx;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <typename ARCH> typename std::enable_if<iss::arch::traits<ARCH>::FLEN != 0, unsigned>::type get_f0_offset() {
|
||||||
|
return iss::arch::traits<ARCH>::F0;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename ARCH> typename std::enable_if<iss::arch::traits<ARCH>::FLEN == 0, unsigned>::type get_f0_offset() { return 0; }
|
||||||
|
|
||||||
template <typename ARCH> status riscv_target_adapter<ARCH>::set_gen_thread(rp_thread_ref& thread) {
|
template <typename ARCH> status riscv_target_adapter<ARCH>::set_gen_thread(rp_thread_ref& thread) {
|
||||||
thread_idx = thread;
|
thread_idx = thread;
|
||||||
return Ok;
|
return Ok;
|
||||||
@ -175,12 +185,29 @@ template <typename ARCH> status riscv_target_adapter<ARCH>::current_thread_query
|
|||||||
|
|
||||||
template <typename ARCH> status riscv_target_adapter<ARCH>::read_registers(std::vector<uint8_t>& data, std::vector<uint8_t>& avail) {
|
template <typename ARCH> status riscv_target_adapter<ARCH>::read_registers(std::vector<uint8_t>& data, std::vector<uint8_t>& avail) {
|
||||||
CPPLOG(TRACE) << "reading target registers";
|
CPPLOG(TRACE) << "reading target registers";
|
||||||
// return idx<0?:;
|
|
||||||
data.clear();
|
data.clear();
|
||||||
avail.clear();
|
avail.clear();
|
||||||
const uint8_t* reg_base = core->get_regs_base_ptr();
|
const uint8_t* reg_base = core->get_regs_base_ptr();
|
||||||
auto start_reg = arch::traits<ARCH>::X0;
|
auto start_reg = arch::traits<ARCH>::X0;
|
||||||
for(size_t reg_no = start_reg; reg_no < start_reg + 33 /*arch::traits<ARCH>::NUM_REGS*/; ++reg_no) {
|
for(size_t i = 0; i < 33; ++i) {
|
||||||
|
if(i < arch::traits<ARCH>::RFS || i == arch::traits<ARCH>::PC) {
|
||||||
|
auto reg_no = i < 32 ? start_reg + i : arch::traits<ARCH>::PC;
|
||||||
|
unsigned offset = traits<ARCH>::reg_byte_offsets[reg_no];
|
||||||
|
for(size_t j = 0; j < arch::traits<ARCH>::XLEN / 8; ++j) {
|
||||||
|
data.push_back(*(reg_base + offset + j));
|
||||||
|
avail.push_back(0xff);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for(size_t j = 0; j < arch::traits<ARCH>::XLEN / 8; ++j) {
|
||||||
|
data.push_back(0);
|
||||||
|
avail.push_back(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(iss::arch::traits<ARCH>::FLEN > 0) {
|
||||||
|
auto fstart_reg = get_f0_offset<ARCH>();
|
||||||
|
for(size_t i = 0; i < 32; ++i) {
|
||||||
|
auto reg_no = fstart_reg + i;
|
||||||
auto reg_width = arch::traits<ARCH>::reg_bit_widths[reg_no] / 8;
|
auto reg_width = arch::traits<ARCH>::reg_bit_widths[reg_no] / 8;
|
||||||
unsigned offset = traits<ARCH>::reg_byte_offsets[reg_no];
|
unsigned offset = traits<ARCH>::reg_byte_offsets[reg_no];
|
||||||
for(size_t j = 0; j < reg_width; ++j) {
|
for(size_t j = 0; j < reg_width; ++j) {
|
||||||
@ -188,21 +215,7 @@ template <typename ARCH> status riscv_target_adapter<ARCH>::read_registers(std::
|
|||||||
avail.push_back(0xff);
|
avail.push_back(0xff);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// work around fill with F type registers
|
}
|
||||||
// if (arch::traits<ARCH>::NUM_REGS < 65) {
|
|
||||||
// auto reg_width = sizeof(typename arch::traits<ARCH>::reg_t);
|
|
||||||
// for (size_t reg_no = 0; reg_no < 33; ++reg_no) {
|
|
||||||
// for (size_t j = 0; j < reg_width; ++j) {
|
|
||||||
// data.push_back(0x0);
|
|
||||||
// avail.push_back(0x00);
|
|
||||||
// }
|
|
||||||
// // if(arch::traits<ARCH>::XLEN < 64)
|
|
||||||
// // for(unsigned j=0; j<4; ++j){
|
|
||||||
// // data.push_back(0x0);
|
|
||||||
// // avail.push_back(0x00);
|
|
||||||
// // }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
return Ok;
|
return Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -210,25 +223,25 @@ template <typename ARCH> status riscv_target_adapter<ARCH>::write_registers(cons
|
|||||||
auto start_reg = arch::traits<ARCH>::X0;
|
auto start_reg = arch::traits<ARCH>::X0;
|
||||||
auto* reg_base = core->get_regs_base_ptr();
|
auto* reg_base = core->get_regs_base_ptr();
|
||||||
auto iter = data.data();
|
auto iter = data.data();
|
||||||
bool e_ext = arch::traits<ARCH>::PC < 32;
|
auto iter_end = data.data() + data.size();
|
||||||
for(size_t reg_no = 0; reg_no < start_reg + 33 /*arch::traits<ARCH>::NUM_REGS*/; ++reg_no) {
|
for(size_t i = 0; i < 33 && iter < iter_end; ++i) {
|
||||||
if(e_ext && reg_no > 15) {
|
auto reg_width = arch::traits<ARCH>::XLEN / 8;
|
||||||
if(reg_no == 32) {
|
if(i < arch::traits<ARCH>::RFS) {
|
||||||
auto reg_width = arch::traits<ARCH>::reg_bit_widths[arch::traits<ARCH>::PC] / 8;
|
auto offset = traits<ARCH>::reg_byte_offsets[start_reg + i];
|
||||||
|
std::copy(iter, iter + reg_width, reg_base + offset);
|
||||||
|
} else if(i == 32) {
|
||||||
auto offset = traits<ARCH>::reg_byte_offsets[arch::traits<ARCH>::PC];
|
auto offset = traits<ARCH>::reg_byte_offsets[arch::traits<ARCH>::PC];
|
||||||
std::copy(iter, iter + reg_width, reg_base);
|
std::copy(iter, iter + reg_width, reg_base + offset);
|
||||||
} else {
|
|
||||||
const uint64_t zero_val = 0;
|
|
||||||
auto reg_width = arch::traits<ARCH>::reg_bit_widths[15] / 8;
|
|
||||||
auto iter = (uint8_t*)&zero_val;
|
|
||||||
std::copy(iter, iter + reg_width, reg_base);
|
|
||||||
}
|
}
|
||||||
} else {
|
iter += reg_width;
|
||||||
auto reg_width = arch::traits<ARCH>::reg_bit_widths[reg_no] / 8;
|
}
|
||||||
auto offset = traits<ARCH>::reg_byte_offsets[reg_no];
|
if(iss::arch::traits<ARCH>::FLEN > 0) {
|
||||||
std::copy(iter, iter + reg_width, reg_base);
|
auto fstart_reg = get_f0_offset<ARCH>();
|
||||||
iter += 4;
|
auto reg_width = arch::traits<ARCH>::FLEN / 8;
|
||||||
reg_base += offset;
|
for(size_t i = 0; i < 32 && iter < iter_end; ++i) {
|
||||||
|
unsigned offset = traits<ARCH>::reg_byte_offsets[fstart_reg + i];
|
||||||
|
std::copy(iter, iter + reg_width, reg_base + offset);
|
||||||
|
iter += reg_width;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Ok;
|
return Ok;
|
||||||
@ -236,7 +249,7 @@ template <typename ARCH> status riscv_target_adapter<ARCH>::write_registers(cons
|
|||||||
|
|
||||||
template <typename ARCH>
|
template <typename ARCH>
|
||||||
status riscv_target_adapter<ARCH>::read_single_register(unsigned int reg_no, std::vector<uint8_t>& data, std::vector<uint8_t>& avail) {
|
status riscv_target_adapter<ARCH>::read_single_register(unsigned int reg_no, std::vector<uint8_t>& data, std::vector<uint8_t>& avail) {
|
||||||
if(reg_no < 65) {
|
if(reg_no < csr_offset) {
|
||||||
// auto reg_size = arch::traits<ARCH>::reg_bit_width(static_cast<typename
|
// auto reg_size = arch::traits<ARCH>::reg_bit_width(static_cast<typename
|
||||||
// arch::traits<ARCH>::reg_e>(reg_no))/8;
|
// arch::traits<ARCH>::reg_e>(reg_no))/8;
|
||||||
auto* reg_base = core->get_regs_base_ptr();
|
auto* reg_base = core->get_regs_base_ptr();
|
||||||
@ -247,23 +260,24 @@ status riscv_target_adapter<ARCH>::read_single_register(unsigned int reg_no, std
|
|||||||
std::copy(reg_base + offset, reg_base + offset + reg_width, data.begin());
|
std::copy(reg_base + offset, reg_base + offset + reg_width, data.begin());
|
||||||
std::fill(avail.begin(), avail.end(), 0xff);
|
std::fill(avail.begin(), avail.end(), 0xff);
|
||||||
} else {
|
} else {
|
||||||
typed_addr_t<iss::address_type::PHYSICAL> a(iss::access_type::DEBUG_READ, traits<ARCH>::CSR, reg_no - 65);
|
typed_addr_t<iss::address_type::PHYSICAL> a(iss::access_type::DEBUG_READ, traits<ARCH>::CSR, reg_no - csr_offset);
|
||||||
data.resize(sizeof(typename traits<ARCH>::reg_t));
|
data.resize(sizeof(typename traits<ARCH>::reg_t));
|
||||||
avail.resize(sizeof(typename traits<ARCH>::reg_t));
|
avail.resize(sizeof(typename traits<ARCH>::reg_t));
|
||||||
std::fill(avail.begin(), avail.end(), 0xff);
|
std::fill(avail.begin(), avail.end(), 0xff);
|
||||||
core->read(a, data.size(), data.data());
|
core->read(a, data.size(), data.data());
|
||||||
|
std::fill(avail.begin(), avail.end(), 0xff);
|
||||||
}
|
}
|
||||||
return data.size() > 0 ? Ok : Err;
|
return data.size() > 0 ? Ok : Err;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename ARCH> status riscv_target_adapter<ARCH>::write_single_register(unsigned int reg_no, const std::vector<uint8_t>& data) {
|
template <typename ARCH> status riscv_target_adapter<ARCH>::write_single_register(unsigned int reg_no, const std::vector<uint8_t>& data) {
|
||||||
if(reg_no < 65) {
|
if(reg_no < csr_offset) {
|
||||||
auto* reg_base = core->get_regs_base_ptr();
|
auto* reg_base = core->get_regs_base_ptr();
|
||||||
auto reg_width = arch::traits<ARCH>::reg_bit_widths[static_cast<typename arch::traits<ARCH>::reg_e>(reg_no)] / 8;
|
auto reg_width = arch::traits<ARCH>::reg_bit_widths[static_cast<typename arch::traits<ARCH>::reg_e>(reg_no)] / 8;
|
||||||
auto offset = traits<ARCH>::reg_byte_offsets[reg_no];
|
auto offset = traits<ARCH>::reg_byte_offsets[reg_no];
|
||||||
std::copy(data.begin(), data.begin() + reg_width, reg_base + offset);
|
std::copy(data.begin(), data.begin() + reg_width, reg_base + offset);
|
||||||
} else {
|
} else {
|
||||||
typed_addr_t<iss::address_type::PHYSICAL> a(iss::access_type::DEBUG_WRITE, traits<ARCH>::CSR, reg_no - 65);
|
typed_addr_t<iss::address_type::PHYSICAL> a(iss::access_type::DEBUG_WRITE, traits<ARCH>::CSR, reg_no - csr_offset);
|
||||||
core->write(a, data.size(), data.data());
|
core->write(a, data.size(), data.data());
|
||||||
}
|
}
|
||||||
return Ok;
|
return Ok;
|
||||||
@ -276,7 +290,7 @@ template <typename ARCH> status riscv_target_adapter<ARCH>::read_mem(uint64_t ad
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename ARCH> status riscv_target_adapter<ARCH>::write_mem(uint64_t addr, const std::vector<uint8_t>& data) {
|
template <typename ARCH> status riscv_target_adapter<ARCH>::write_mem(uint64_t addr, const std::vector<uint8_t>& data) {
|
||||||
auto a = map_addr({iss::access_type::DEBUG_READ, iss::address_type::VIRTUAL, 0, addr});
|
auto a = map_addr({iss::access_type::DEBUG_WRITE, iss::address_type::VIRTUAL, 0, addr});
|
||||||
auto f = [&]() -> status { return core->write(a, data.size(), data.data()); };
|
auto f = [&]() -> status { return core->write(a, data.size(), data.data()); };
|
||||||
return srv->execute_syncronized(f);
|
return srv->execute_syncronized(f);
|
||||||
}
|
}
|
||||||
@ -369,93 +383,57 @@ status riscv_target_adapter<ARCH>::resume_from_addr(bool step, int sig, uint64_t
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename ARCH> status riscv_target_adapter<ARCH>::target_xml_query(std::string& out_buf) {
|
template <typename ARCH> status riscv_target_adapter<ARCH>::target_xml_query(std::string& out_buf) {
|
||||||
const std::string res{"<?xml version=\"1.0\"?><!DOCTYPE target SYSTEM \"gdb-target.dtd\">"
|
if(!csr_xml.size()) {
|
||||||
"<target><architecture>riscv:rv32</architecture>"
|
std::ostringstream oss;
|
||||||
//" <feature name=\"org.gnu.gdb.riscv.rv32i\">\n"
|
oss << "<?xml version=\"1.0\"?><!DOCTYPE feature SYSTEM \"gdb-target.dtd\"><target version=\"1.0\">\n";
|
||||||
//" <reg name=\"x0\" bitsize=\"32\" group=\"general\"/>\n"
|
if(iss::arch::traits<ARCH>::XLEN == 32)
|
||||||
//" <reg name=\"x1\" bitsize=\"32\" group=\"general\"/>\n"
|
oss << "<architecture>riscv:rv32</architecture>\n";
|
||||||
//" <reg name=\"x2\" bitsize=\"32\" group=\"general\"/>\n"
|
else if(iss::arch::traits<ARCH>::XLEN == 64)
|
||||||
//" <reg name=\"x3\" bitsize=\"32\" group=\"general\"/>\n"
|
oss << " <architectureriscv:rv64</architecture>\n";
|
||||||
//" <reg name=\"x4\" bitsize=\"32\" group=\"general\"/>\n"
|
oss << " <feature name=\"org.gnu.gdb.riscv.cpu\">\n";
|
||||||
//" <reg name=\"x5\" bitsize=\"32\" group=\"general\"/>\n"
|
auto reg_base_num = iss::arch::traits<ARCH>::X0;
|
||||||
//" <reg name=\"x6\" bitsize=\"32\" group=\"general\"/>\n"
|
for(auto i = 0U; i < iss::arch::traits<ARCH>::RFS; ++i) {
|
||||||
//" <reg name=\"x7\" bitsize=\"32\" group=\"general\"/>\n"
|
oss << " <reg name=\"x" << i << "\" bitsize=\"" << iss::arch::traits<ARCH>::reg_bit_widths[reg_base_num + i]
|
||||||
//" <reg name=\"x8\" bitsize=\"32\" group=\"general\"/>\n"
|
<< "\" type=\"int\" regnum=\"" << i << "\"/>\n";
|
||||||
//" <reg name=\"x9\" bitsize=\"32\" group=\"general\"/>\n"
|
}
|
||||||
//" <reg name=\"x10\" bitsize=\"32\" group=\"general\"/>\n"
|
oss << " <reg name=\"pc\" bitsize=\"" << iss::arch::traits<ARCH>::reg_bit_widths[iss::arch::traits<ARCH>::PC]
|
||||||
//" <reg name=\"x11\" bitsize=\"32\" group=\"general\"/>\n"
|
<< "\" type=\"code_ptr\" regnum=\"" << 32U << "\"/>\n";
|
||||||
//" <reg name=\"x12\" bitsize=\"32\" group=\"general\"/>\n"
|
oss << " </feature>\n";
|
||||||
//" <reg name=\"x13\" bitsize=\"32\" group=\"general\"/>\n"
|
if(iss::arch::traits<ARCH>::FLEN > 0) {
|
||||||
//" <reg name=\"x14\" bitsize=\"32\" group=\"general\"/>\n"
|
oss << " <feature name=\"org.gnu.gdb.riscv.fpu\">\n";
|
||||||
//" <reg name=\"x15\" bitsize=\"32\" group=\"general\"/>\n"
|
auto reg_base_num = get_f0_offset<ARCH>();
|
||||||
//" <reg name=\"x16\" bitsize=\"32\" group=\"general\"/>\n"
|
auto type = iss::arch::traits<ARCH>::FLEN == 32 ? "ieee_single" : "riscv_double";
|
||||||
//" <reg name=\"x17\" bitsize=\"32\" group=\"general\"/>\n"
|
for(auto i = 0U; i < 32; ++i) {
|
||||||
//" <reg name=\"x18\" bitsize=\"32\" group=\"general\"/>\n"
|
oss << " <reg name=\"f" << i << "\" bitsize=\"" << iss::arch::traits<ARCH>::reg_bit_widths[reg_base_num + i]
|
||||||
//" <reg name=\"x19\" bitsize=\"32\" group=\"general\"/>\n"
|
<< "\" type=\"" << type << "\" regnum=\"" << i + 33 << "\"/>\n";
|
||||||
//" <reg name=\"x20\" bitsize=\"32\" group=\"general\"/>\n"
|
}
|
||||||
//" <reg name=\"x21\" bitsize=\"32\" group=\"general\"/>\n"
|
oss << " <reg name=\"fcsr\" bitsize=\"" << iss::arch::traits<ARCH>::XLEN << "\" regnum=\"103\" type int/>\n";
|
||||||
//" <reg name=\"x22\" bitsize=\"32\" group=\"general\"/>\n"
|
oss << " <reg name=\"fflags\" bitsize=\"" << iss::arch::traits<ARCH>::XLEN << "\" regnum=\"101\" type int/>\n";
|
||||||
//" <reg name=\"x23\" bitsize=\"32\" group=\"general\"/>\n"
|
oss << " <reg name=\"frm\" bitsize=\"" << iss::arch::traits<ARCH>::XLEN << "\" regnum=\"102\" type int/>\n";
|
||||||
//" <reg name=\"x24\" bitsize=\"32\" group=\"general\"/>\n"
|
oss << " </feature>\n";
|
||||||
//" <reg name=\"x25\" bitsize=\"32\" group=\"general\"/>\n"
|
}
|
||||||
//" <reg name=\"x26\" bitsize=\"32\" group=\"general\"/>\n"
|
oss << " <feature name=\"org.gnu.gdb.riscv.csr\">\n";
|
||||||
//" <reg name=\"x27\" bitsize=\"32\" group=\"general\"/>\n"
|
std::vector<uint8_t> data;
|
||||||
//" <reg name=\"x28\" bitsize=\"32\" group=\"general\"/>\n"
|
std::vector<uint8_t> avail;
|
||||||
//" <reg name=\"x29\" bitsize=\"32\" group=\"general\"/>\n"
|
data.resize(sizeof(typename traits<ARCH>::reg_t));
|
||||||
//" <reg name=\"x30\" bitsize=\"32\" group=\"general\"/>\n"
|
avail.resize(sizeof(typename traits<ARCH>::reg_t));
|
||||||
//" <reg name=\"x31\" bitsize=\"32\" group=\"general\"/>\n"
|
for(auto i = 0U; i < 4096; ++i) {
|
||||||
//" </feature>\n"
|
typed_addr_t<iss::address_type::PHYSICAL> a(iss::access_type::DEBUG_READ, traits<ARCH>::CSR, i);
|
||||||
"</target>"};
|
std::fill(avail.begin(), avail.end(), 0xff);
|
||||||
out_buf = res;
|
auto res = core->read(a, data.size(), data.data());
|
||||||
|
if(res == iss::Ok) {
|
||||||
|
oss << " <reg name=\"" << get_csr_name(i) << "\" bitsize=\"" << iss::arch::traits<ARCH>::XLEN
|
||||||
|
<< "\" type=\"int\" regnum=\"" << (i + csr_offset) << "\"/>\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
oss << " </feature>\n";
|
||||||
|
oss << "</target>\n";
|
||||||
|
csr_xml = oss.str();
|
||||||
|
}
|
||||||
|
out_buf = csr_xml;
|
||||||
return Ok;
|
return Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
*
|
|
||||||
<?xml version="1.0"?>
|
|
||||||
<!DOCTYPE target SYSTEM "gdb-target.dtd">
|
|
||||||
<target>
|
|
||||||
<architecture>riscv:rv32</architecture>
|
|
||||||
|
|
||||||
<feature name="org.gnu.gdb.riscv.rv32i">
|
|
||||||
<reg name="x0" bitsize="32" group="general"/>
|
|
||||||
<reg name="x1" bitsize="32" group="general"/>
|
|
||||||
<reg name="x2" bitsize="32" group="general"/>
|
|
||||||
<reg name="x3" bitsize="32" group="general"/>
|
|
||||||
<reg name="x4" bitsize="32" group="general"/>
|
|
||||||
<reg name="x5" bitsize="32" group="general"/>
|
|
||||||
<reg name="x6" bitsize="32" group="general"/>
|
|
||||||
<reg name="x7" bitsize="32" group="general"/>
|
|
||||||
<reg name="x8" bitsize="32" group="general"/>
|
|
||||||
<reg name="x9" bitsize="32" group="general"/>
|
|
||||||
<reg name="x10" bitsize="32" group="general"/>
|
|
||||||
<reg name="x11" bitsize="32" group="general"/>
|
|
||||||
<reg name="x12" bitsize="32" group="general"/>
|
|
||||||
<reg name="x13" bitsize="32" group="general"/>
|
|
||||||
<reg name="x14" bitsize="32" group="general"/>
|
|
||||||
<reg name="x15" bitsize="32" group="general"/>
|
|
||||||
<reg name="x16" bitsize="32" group="general"/>
|
|
||||||
<reg name="x17" bitsize="32" group="general"/>
|
|
||||||
<reg name="x18" bitsize="32" group="general"/>
|
|
||||||
<reg name="x19" bitsize="32" group="general"/>
|
|
||||||
<reg name="x20" bitsize="32" group="general"/>
|
|
||||||
<reg name="x21" bitsize="32" group="general"/>
|
|
||||||
<reg name="x22" bitsize="32" group="general"/>
|
|
||||||
<reg name="x23" bitsize="32" group="general"/>
|
|
||||||
<reg name="x24" bitsize="32" group="general"/>
|
|
||||||
<reg name="x25" bitsize="32" group="general"/>
|
|
||||||
<reg name="x26" bitsize="32" group="general"/>
|
|
||||||
<reg name="x27" bitsize="32" group="general"/>
|
|
||||||
<reg name="x28" bitsize="32" group="general"/>
|
|
||||||
<reg name="x29" bitsize="32" group="general"/>
|
|
||||||
<reg name="x30" bitsize="32" group="general"/>
|
|
||||||
<reg name="x31" bitsize="32" group="general"/>
|
|
||||||
</feature>
|
|
||||||
|
|
||||||
</target>
|
|
||||||
|
|
||||||
*/
|
|
||||||
} // namespace debugger
|
} // namespace debugger
|
||||||
} // namespace iss
|
} // namespace iss
|
||||||
|
|
||||||
#endif /* _ISS_DEBUGGER_RISCV_TARGET_ADAPTER_H_ */
|
#endif /* _ISS_ARCH_DEBUGGER_RISCV_TARGET_ADAPTER_H_ */
|
||||||
|
31
src/main.cpp
31
src/main.cpp
@ -69,7 +69,8 @@ int main(int argc, char* argv[]) {
|
|||||||
("logfile,l", po::value<std::string>(), "Sets default log file.")
|
("logfile,l", po::value<std::string>(), "Sets default log file.")
|
||||||
("disass,d", po::value<std::string>()->implicit_value(""), "Enables disassembly")
|
("disass,d", po::value<std::string>()->implicit_value(""), "Enables disassembly")
|
||||||
("gdb-port,g", po::value<unsigned>()->default_value(0), "enable gdb server and specify port to use")
|
("gdb-port,g", po::value<unsigned>()->default_value(0), "enable gdb server and specify port to use")
|
||||||
("instructions,i", po::value<uint64_t>()->default_value(std::numeric_limits<uint64_t>::max()), "max. number of instructions to simulate")
|
("ilimit,i", po::value<uint64_t>()->default_value(std::numeric_limits<uint64_t>::max()), "max. number of instructions to simulate")
|
||||||
|
("flimit", po::value<uint64_t>()->default_value(std::numeric_limits<uint64_t>::max()), "max. number of fetches to simulate")
|
||||||
("reset,r", po::value<std::string>(), "reset address")
|
("reset,r", po::value<std::string>(), "reset address")
|
||||||
("dump-ir", "dump the intermediate representation")
|
("dump-ir", "dump the intermediate representation")
|
||||||
("elf,f", po::value<std::vector<std::string>>(), "ELF file(s) to load")
|
("elf,f", po::value<std::vector<std::string>>(), "ELF file(s) to load")
|
||||||
@ -140,7 +141,10 @@ int main(int argc, char* argv[]) {
|
|||||||
std::tie(cpu, vm) = f.create(isa_opt, clim["gdb-port"].as<unsigned>(), &semihosting_cb);
|
std::tie(cpu, vm) = f.create(isa_opt, clim["gdb-port"].as<unsigned>(), &semihosting_cb);
|
||||||
}
|
}
|
||||||
if(!cpu) {
|
if(!cpu) {
|
||||||
CPPLOG(ERR) << "Could not create cpu for isa " << isa_opt << " and backend " << clim["backend"].as<std::string>() << std::endl;
|
auto list = f.get_names();
|
||||||
|
std::sort(std::begin(list), std::end(list));
|
||||||
|
CPPLOG(ERR) << "Could not create cpu for isa " << isa_opt << " and backend " << clim["backend"].as<std::string>() << "\n"
|
||||||
|
<< "Available implementations (core|platform|backend):\n - " << util::join(list, "\n - ") << std::endl;
|
||||||
return 127;
|
return 127;
|
||||||
}
|
}
|
||||||
if(!vm) {
|
if(!vm) {
|
||||||
@ -202,21 +206,36 @@ int main(int argc, char* argv[]) {
|
|||||||
if(clim.count("elf"))
|
if(clim.count("elf"))
|
||||||
for(std::string input : clim["elf"].as<std::vector<std::string>>()) {
|
for(std::string input : clim["elf"].as<std::vector<std::string>>()) {
|
||||||
auto start_addr = vm->get_arch()->load_file(input);
|
auto start_addr = vm->get_arch()->load_file(input);
|
||||||
if(start_addr.second) // FIXME: this always evaluates to true as load file always returns <sth, true>
|
if(start_addr.second)
|
||||||
start_address = start_addr.first;
|
start_address = start_addr.first;
|
||||||
|
else {
|
||||||
|
LOG(ERR) << "Error occured while loading file " << input << std::endl;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
for(std::string input : args) {
|
for(std::string input : args) {
|
||||||
auto start_addr = vm->get_arch()->load_file(input); // treat remaining arguments as elf files
|
auto start_addr = vm->get_arch()->load_file(input); // treat remaining arguments as elf files
|
||||||
if(start_addr.second) // FIXME: this always evaluates to true as load file always returns <sth, true>
|
if(start_addr.second)
|
||||||
start_address = start_addr.first;
|
start_address = start_addr.first;
|
||||||
|
else {
|
||||||
|
LOG(ERR) << "Error occured while loading file " << input << std::endl;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if(clim.count("reset")) {
|
if(clim.count("reset")) {
|
||||||
auto str = clim["reset"].as<std::string>();
|
auto str = clim["reset"].as<std::string>();
|
||||||
start_address = str.find("0x") == 0 ? std::stoull(str.substr(2), nullptr, 16) : std::stoull(str, nullptr, 10);
|
start_address = str.find("0x") == 0 ? std::stoull(str.substr(2), nullptr, 16) : std::stoull(str, nullptr, 10);
|
||||||
}
|
}
|
||||||
vm->reset(start_address);
|
vm->reset(start_address);
|
||||||
auto cycles = clim["instructions"].as<uint64_t>();
|
auto limit = clim["ilimit"].as<uint64_t>();
|
||||||
res = vm->start(cycles, dump);
|
auto cond = iss::finish_cond_e::JUMP_TO_SELF;
|
||||||
|
if(clim.count("flimit")) {
|
||||||
|
cond = cond | iss::finish_cond_e::FCOUNT_LIMIT;
|
||||||
|
limit = clim["flimit"].as<uint64_t>();
|
||||||
|
} else {
|
||||||
|
cond = cond | iss::finish_cond_e::ICOUNT_LIMIT;
|
||||||
|
}
|
||||||
|
res = vm->start(limit, dump, cond);
|
||||||
|
|
||||||
auto instr_if = vm->get_arch()->get_instrumentation_if();
|
auto instr_if = vm->get_arch()->get_instrumentation_if();
|
||||||
// this assumes a single input file
|
// this assumes a single input file
|
||||||
|
@ -42,7 +42,6 @@
|
|||||||
#include <iss/plugin/loader.h>
|
#include <iss/plugin/loader.h>
|
||||||
#endif
|
#endif
|
||||||
#include "sc_core_adapter_if.h"
|
#include "sc_core_adapter_if.h"
|
||||||
#include <iss/arch/tgc_mapper.h>
|
|
||||||
#include <scc/report.h>
|
#include <scc/report.h>
|
||||||
#include <util/ities.h>
|
#include <util/ities.h>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
@ -125,7 +124,7 @@ using vm_ptr = std::unique_ptr<iss::vm_if>;
|
|||||||
|
|
||||||
class core_wrapper {
|
class core_wrapper {
|
||||||
public:
|
public:
|
||||||
core_wrapper(core_complex* owner)
|
core_wrapper(core_complex_if* owner)
|
||||||
: owner(owner) {}
|
: owner(owner) {}
|
||||||
|
|
||||||
void reset(uint64_t addr) { vm->reset(addr); }
|
void reset(uint64_t addr) { vm->reset(addr); }
|
||||||
@ -181,7 +180,7 @@ public:
|
|||||||
"SystemC sub-commands: break <time>, print_time"});
|
"SystemC sub-commands: break <time>, print_time"});
|
||||||
}
|
}
|
||||||
|
|
||||||
core_complex* const owner;
|
core_complex_if* const owner;
|
||||||
vm_ptr vm{nullptr};
|
vm_ptr vm{nullptr};
|
||||||
sc_cpu_ptr cpu{nullptr};
|
sc_cpu_ptr cpu{nullptr};
|
||||||
iss::debugger::target_adapter_if* tgt_adapter{nullptr};
|
iss::debugger::target_adapter_if* tgt_adapter{nullptr};
|
||||||
@ -197,9 +196,9 @@ struct core_trace {
|
|||||||
scv_tr_handle tr_handle;
|
scv_tr_handle tr_handle;
|
||||||
};
|
};
|
||||||
|
|
||||||
SC_HAS_PROCESS(core_complex); // NOLINT
|
|
||||||
#ifndef CWR_SYSTEMC
|
#ifndef CWR_SYSTEMC
|
||||||
core_complex::core_complex(sc_module_name const& name)
|
template <unsigned int BUSWIDTH>
|
||||||
|
core_complex<BUSWIDTH>::core_complex(sc_module_name const& name)
|
||||||
: sc_module(name)
|
: sc_module(name)
|
||||||
, fetch_lut(tlm_dmi_ext())
|
, fetch_lut(tlm_dmi_ext())
|
||||||
, read_lut(tlm_dmi_ext())
|
, read_lut(tlm_dmi_ext())
|
||||||
@ -208,7 +207,7 @@ core_complex::core_complex(sc_module_name const& name)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void core_complex::init() {
|
template <unsigned int BUSWIDTH> void core_complex<BUSWIDTH>::init() {
|
||||||
trc = new core_trace();
|
trc = new core_trace();
|
||||||
ibus.register_invalidate_direct_mem_ptr([=](uint64_t start, uint64_t end) -> void {
|
ibus.register_invalidate_direct_mem_ptr([=](uint64_t start, uint64_t end) -> void {
|
||||||
auto lut_entry = fetch_lut.getEntry(start);
|
auto lut_entry = fetch_lut.getEntry(start);
|
||||||
@ -227,6 +226,7 @@ void core_complex::init() {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
SC_HAS_PROCESS(core_complex<BUSWIDTH>); // NOLINT
|
||||||
SC_THREAD(run);
|
SC_THREAD(run);
|
||||||
SC_METHOD(rst_cb);
|
SC_METHOD(rst_cb);
|
||||||
sensitive << rst_i;
|
sensitive << rst_i;
|
||||||
@ -252,16 +252,16 @@ void core_complex::init() {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
core_complex::~core_complex() {
|
template <unsigned int BUSWIDTH> core_complex<BUSWIDTH>::~core_complex() {
|
||||||
delete cpu;
|
delete cpu;
|
||||||
delete trc;
|
delete trc;
|
||||||
for(auto* p : plugin_list)
|
for(auto* p : plugin_list)
|
||||||
delete p;
|
delete p;
|
||||||
}
|
}
|
||||||
|
|
||||||
void core_complex::trace(sc_trace_file* trf) const {}
|
template <unsigned int BUSWIDTH> void core_complex<BUSWIDTH>::trace(sc_trace_file* trf) const {}
|
||||||
|
|
||||||
void core_complex::before_end_of_elaboration() {
|
template <unsigned int BUSWIDTH> void core_complex<BUSWIDTH>::before_end_of_elaboration() {
|
||||||
SCCDEBUG(SCMOD) << "instantiating iss::arch::tgf with " << GET_PROP_VALUE(backend) << " backend";
|
SCCDEBUG(SCMOD) << "instantiating iss::arch::tgf with " << GET_PROP_VALUE(backend) << " backend";
|
||||||
// cpu = scc::make_unique<core_wrapper>(this);
|
// cpu = scc::make_unique<core_wrapper>(this);
|
||||||
cpu = new core_wrapper(this);
|
cpu = new core_wrapper(this);
|
||||||
@ -302,7 +302,7 @@ void core_complex::before_end_of_elaboration() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void core_complex::start_of_simulation() {
|
template <unsigned int BUSWIDTH> void core_complex<BUSWIDTH>::start_of_simulation() {
|
||||||
// quantum_keeper.reset();
|
// quantum_keeper.reset();
|
||||||
if(GET_PROP_VALUE(elf_file).size() > 0) {
|
if(GET_PROP_VALUE(elf_file).size() > 0) {
|
||||||
istringstream is(GET_PROP_VALUE(elf_file));
|
istringstream is(GET_PROP_VALUE(elf_file));
|
||||||
@ -325,7 +325,7 @@ void core_complex::start_of_simulation() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool core_complex::disass_output(uint64_t pc, const std::string instr_str) {
|
template <unsigned int BUSWIDTH> bool core_complex<BUSWIDTH>::disass_output(uint64_t pc, const std::string instr_str) {
|
||||||
if(trc->m_db == nullptr)
|
if(trc->m_db == nullptr)
|
||||||
return false;
|
return false;
|
||||||
if(trc->tr_handle.is_active())
|
if(trc->tr_handle.is_active())
|
||||||
@ -339,7 +339,7 @@ bool core_complex::disass_output(uint64_t pc, const std::string instr_str) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void core_complex::forward() {
|
template <unsigned int BUSWIDTH> void core_complex<BUSWIDTH>::forward() {
|
||||||
#ifndef CWR_SYSTEMC
|
#ifndef CWR_SYSTEMC
|
||||||
set_clock_period(clk_i.read());
|
set_clock_period(clk_i.read());
|
||||||
#else
|
#else
|
||||||
@ -348,24 +348,24 @@ void core_complex::forward() {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void core_complex::set_clock_period(sc_core::sc_time period) {
|
template <unsigned int BUSWIDTH> void core_complex<BUSWIDTH>::set_clock_period(sc_core::sc_time period) {
|
||||||
curr_clk = period;
|
curr_clk = period;
|
||||||
if(period == SC_ZERO_TIME)
|
if(period == SC_ZERO_TIME)
|
||||||
cpu->set_interrupt_execution(true);
|
cpu->set_interrupt_execution(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void core_complex::rst_cb() {
|
template <unsigned int BUSWIDTH> void core_complex<BUSWIDTH>::rst_cb() {
|
||||||
if(rst_i.read())
|
if(rst_i.read())
|
||||||
cpu->set_interrupt_execution(true);
|
cpu->set_interrupt_execution(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void core_complex::sw_irq_cb() { cpu->local_irq(3, sw_irq_i.read()); }
|
template <unsigned int BUSWIDTH> void core_complex<BUSWIDTH>::sw_irq_cb() { cpu->local_irq(3, sw_irq_i.read()); }
|
||||||
|
|
||||||
void core_complex::timer_irq_cb() { cpu->local_irq(7, timer_irq_i.read()); }
|
template <unsigned int BUSWIDTH> void core_complex<BUSWIDTH>::timer_irq_cb() { cpu->local_irq(7, timer_irq_i.read()); }
|
||||||
|
|
||||||
void core_complex::ext_irq_cb() { cpu->local_irq(11, ext_irq_i.read()); }
|
template <unsigned int BUSWIDTH> void core_complex<BUSWIDTH>::ext_irq_cb() { cpu->local_irq(11, ext_irq_i.read()); }
|
||||||
|
|
||||||
void core_complex::local_irq_cb() {
|
template <unsigned int BUSWIDTH> void core_complex<BUSWIDTH>::local_irq_cb() {
|
||||||
for(auto i = 0U; i < local_irq_i.size(); ++i) {
|
for(auto i = 0U; i < local_irq_i.size(); ++i) {
|
||||||
if(local_irq_i[i].event()) {
|
if(local_irq_i[i].event()) {
|
||||||
cpu->local_irq(16 + i, local_irq_i[i].read());
|
cpu->local_irq(16 + i, local_irq_i[i].read());
|
||||||
@ -373,7 +373,7 @@ void core_complex::local_irq_cb() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void core_complex::run() {
|
template <unsigned int BUSWIDTH> void core_complex<BUSWIDTH>::run() {
|
||||||
wait(SC_ZERO_TIME); // separate from elaboration phase
|
wait(SC_ZERO_TIME); // separate from elaboration phase
|
||||||
do {
|
do {
|
||||||
wait(SC_ZERO_TIME);
|
wait(SC_ZERO_TIME);
|
||||||
@ -391,7 +391,7 @@ void core_complex::run() {
|
|||||||
sc_stop();
|
sc_stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool core_complex::read_mem(uint64_t addr, unsigned length, uint8_t* const data, bool is_fetch) {
|
template <unsigned int BUSWIDTH> bool core_complex<BUSWIDTH>::read_mem(uint64_t addr, unsigned length, uint8_t* const data, bool is_fetch) {
|
||||||
auto& dmi_lut = is_fetch ? fetch_lut : read_lut;
|
auto& dmi_lut = is_fetch ? fetch_lut : read_lut;
|
||||||
auto lut_entry = dmi_lut.getEntry(addr);
|
auto lut_entry = dmi_lut.getEntry(addr);
|
||||||
if(lut_entry.get_granted_access() != tlm::tlm_dmi::DMI_ACCESS_NONE && addr + length <= lut_entry.get_end_address() + 1) {
|
if(lut_entry.get_granted_access() != tlm::tlm_dmi::DMI_ACCESS_NONE && addr + length <= lut_entry.get_end_address() + 1) {
|
||||||
@ -449,7 +449,7 @@ bool core_complex::read_mem(uint64_t addr, unsigned length, uint8_t* const data,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool core_complex::write_mem(uint64_t addr, unsigned length, const uint8_t* const data) {
|
template <unsigned int BUSWIDTH> bool core_complex<BUSWIDTH>::write_mem(uint64_t addr, unsigned length, const uint8_t* const data) {
|
||||||
auto lut_entry = write_lut.getEntry(addr);
|
auto lut_entry = write_lut.getEntry(addr);
|
||||||
if(lut_entry.get_granted_access() != tlm::tlm_dmi::DMI_ACCESS_NONE && addr + length <= lut_entry.get_end_address() + 1) {
|
if(lut_entry.get_granted_access() != tlm::tlm_dmi::DMI_ACCESS_NONE && addr + length <= lut_entry.get_end_address() + 1) {
|
||||||
auto offset = addr - lut_entry.get_start_address();
|
auto offset = addr - lut_entry.get_start_address();
|
||||||
@ -497,7 +497,7 @@ bool core_complex::write_mem(uint64_t addr, unsigned length, const uint8_t* cons
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool core_complex::read_mem_dbg(uint64_t addr, unsigned length, uint8_t* const data) {
|
template <unsigned int BUSWIDTH> bool core_complex<BUSWIDTH>::read_mem_dbg(uint64_t addr, unsigned length, uint8_t* const data) {
|
||||||
tlm::tlm_generic_payload gp;
|
tlm::tlm_generic_payload gp;
|
||||||
gp.set_command(tlm::TLM_READ_COMMAND);
|
gp.set_command(tlm::TLM_READ_COMMAND);
|
||||||
gp.set_address(addr);
|
gp.set_address(addr);
|
||||||
@ -507,7 +507,7 @@ bool core_complex::read_mem_dbg(uint64_t addr, unsigned length, uint8_t* const d
|
|||||||
return dbus->transport_dbg(gp) == length;
|
return dbus->transport_dbg(gp) == length;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool core_complex::write_mem_dbg(uint64_t addr, unsigned length, const uint8_t* const data) {
|
template <unsigned int BUSWIDTH> bool core_complex<BUSWIDTH>::write_mem_dbg(uint64_t addr, unsigned length, const uint8_t* const data) {
|
||||||
write_buf.resize(length);
|
write_buf.resize(length);
|
||||||
std::copy(data, data + length, write_buf.begin()); // need to copy as TLM does not guarantee data integrity
|
std::copy(data, data + length, write_buf.begin()); // need to copy as TLM does not guarantee data integrity
|
||||||
tlm::tlm_generic_payload gp;
|
tlm::tlm_generic_payload gp;
|
||||||
@ -518,5 +518,10 @@ bool core_complex::write_mem_dbg(uint64_t addr, unsigned length, const uint8_t*
|
|||||||
gp.set_streaming_width(length);
|
gp.set_streaming_width(length);
|
||||||
return dbus->transport_dbg(gp) == length;
|
return dbus->transport_dbg(gp) == length;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template class core_complex<scc::LT>;
|
||||||
|
template class core_complex<32>;
|
||||||
|
template class core_complex<64>;
|
||||||
|
|
||||||
} /* namespace tgfs */
|
} /* namespace tgfs */
|
||||||
} /* namespace sysc */
|
} /* namespace sysc */
|
||||||
|
@ -33,6 +33,7 @@
|
|||||||
#ifndef _SYSC_CORE_COMPLEX_H_
|
#ifndef _SYSC_CORE_COMPLEX_H_
|
||||||
#define _SYSC_CORE_COMPLEX_H_
|
#define _SYSC_CORE_COMPLEX_H_
|
||||||
|
|
||||||
|
#include <scc/signal_opt_ports.h>
|
||||||
#include <scc/tick2time.h>
|
#include <scc/tick2time.h>
|
||||||
#include <scc/traceable.h>
|
#include <scc/traceable.h>
|
||||||
#include <scc/utilities.h>
|
#include <scc/utilities.h>
|
||||||
@ -40,10 +41,8 @@
|
|||||||
#include <tlm/scc/scv/tlm_rec_initiator_socket.h>
|
#include <tlm/scc/scv/tlm_rec_initiator_socket.h>
|
||||||
#ifdef CWR_SYSTEMC
|
#ifdef CWR_SYSTEMC
|
||||||
#include <scmlinc/scml_property.h>
|
#include <scmlinc/scml_property.h>
|
||||||
#define SOCKET_WIDTH 32
|
|
||||||
#else
|
#else
|
||||||
#include <cci_configuration>
|
#include <cci_configuration>
|
||||||
#define SOCKET_WIDTH scc::LT
|
|
||||||
#endif
|
#endif
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <tlm>
|
#include <tlm>
|
||||||
@ -68,12 +67,35 @@ public:
|
|||||||
namespace tgfs {
|
namespace tgfs {
|
||||||
class core_wrapper;
|
class core_wrapper;
|
||||||
struct core_trace;
|
struct core_trace;
|
||||||
|
struct core_complex_if {
|
||||||
|
|
||||||
class core_complex : public sc_core::sc_module, public scc::traceable {
|
virtual ~core_complex_if() = default;
|
||||||
|
|
||||||
|
virtual bool read_mem(uint64_t addr, unsigned length, uint8_t* const data, bool is_fetch) = 0;
|
||||||
|
|
||||||
|
virtual bool write_mem(uint64_t addr, unsigned length, const uint8_t* const data) = 0;
|
||||||
|
|
||||||
|
virtual bool read_mem_dbg(uint64_t addr, unsigned length, uint8_t* const data) = 0;
|
||||||
|
|
||||||
|
virtual bool write_mem_dbg(uint64_t addr, unsigned length, const uint8_t* const data) = 0;
|
||||||
|
|
||||||
|
virtual bool disass_output(uint64_t pc, const std::string instr) = 0;
|
||||||
|
|
||||||
|
virtual unsigned get_last_bus_cycles() = 0;
|
||||||
|
|
||||||
|
//! Allow quantum keeper handling
|
||||||
|
virtual void sync(uint64_t) = 0;
|
||||||
|
|
||||||
|
virtual char const* hier_name() = 0;
|
||||||
|
|
||||||
|
scc::sc_in_opt<uint64_t> mtime_i{"mtime_i"};
|
||||||
|
};
|
||||||
|
|
||||||
|
template <unsigned int BUSWIDTH = scc::LT> class core_complex : public sc_core::sc_module, public scc::traceable, public core_complex_if {
|
||||||
public:
|
public:
|
||||||
tlm::scc::initiator_mixin<tlm::tlm_initiator_socket<SOCKET_WIDTH>> ibus{"ibus"};
|
tlm::scc::initiator_mixin<tlm::tlm_initiator_socket<BUSWIDTH>> ibus{"ibus"};
|
||||||
|
|
||||||
tlm::scc::initiator_mixin<tlm::tlm_initiator_socket<SOCKET_WIDTH>> dbus{"dbus"};
|
tlm::scc::initiator_mixin<tlm::tlm_initiator_socket<BUSWIDTH>> dbus{"dbus"};
|
||||||
|
|
||||||
sc_core::sc_in<bool> rst_i{"rst_i"};
|
sc_core::sc_in<bool> rst_i{"rst_i"};
|
||||||
|
|
||||||
@ -88,8 +110,6 @@ public:
|
|||||||
#ifndef CWR_SYSTEMC
|
#ifndef CWR_SYSTEMC
|
||||||
sc_core::sc_in<sc_core::sc_time> clk_i{"clk_i"};
|
sc_core::sc_in<sc_core::sc_time> clk_i{"clk_i"};
|
||||||
|
|
||||||
sc_core::sc_port<tlm::tlm_peek_if<uint64_t>, 1, sc_core::SC_ZERO_OR_MORE_BOUND> mtime_o{"mtime_o"};
|
|
||||||
|
|
||||||
cci::cci_param<std::string> elf_file{"elf_file", ""};
|
cci::cci_param<std::string> elf_file{"elf_file", ""};
|
||||||
|
|
||||||
cci::cci_param<bool> enable_disass{"enable_disass", false};
|
cci::cci_param<bool> enable_disass{"enable_disass", false};
|
||||||
@ -115,8 +135,6 @@ public:
|
|||||||
#else
|
#else
|
||||||
sc_core::sc_in<bool> clk_i{"clk_i"};
|
sc_core::sc_in<bool> clk_i{"clk_i"};
|
||||||
|
|
||||||
sc_core::sc_in<uint64_t> mtime_i{"mtime_i"};
|
|
||||||
|
|
||||||
scml_property<std::string> elf_file{"elf_file", ""};
|
scml_property<std::string> elf_file{"elf_file", ""};
|
||||||
|
|
||||||
scml_property<bool> enable_disass{"enable_disass", false};
|
scml_property<bool> enable_disass{"enable_disass", false};
|
||||||
@ -159,13 +177,13 @@ public:
|
|||||||
|
|
||||||
~core_complex();
|
~core_complex();
|
||||||
|
|
||||||
inline unsigned get_last_bus_cycles() {
|
unsigned get_last_bus_cycles() override {
|
||||||
auto mem_incr = std::max(ibus_inc, dbus_inc);
|
auto mem_incr = std::max(ibus_inc, dbus_inc);
|
||||||
ibus_inc = dbus_inc = 0;
|
ibus_inc = dbus_inc = 0;
|
||||||
return mem_incr > 1 ? mem_incr : 1;
|
return mem_incr > 1 ? mem_incr : 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void sync(uint64_t cycle) {
|
void sync(uint64_t cycle) override {
|
||||||
auto core_inc = curr_clk * (cycle - last_sync_cycle);
|
auto core_inc = curr_clk * (cycle - last_sync_cycle);
|
||||||
quantum_keeper.inc(core_inc);
|
quantum_keeper.inc(core_inc);
|
||||||
if(quantum_keeper.need_sync()) {
|
if(quantum_keeper.need_sync()) {
|
||||||
@ -175,20 +193,22 @@ public:
|
|||||||
last_sync_cycle = cycle;
|
last_sync_cycle = cycle;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool read_mem(uint64_t addr, unsigned length, uint8_t* const data, bool is_fetch);
|
bool read_mem(uint64_t addr, unsigned length, uint8_t* const data, bool is_fetch) override;
|
||||||
|
|
||||||
bool write_mem(uint64_t addr, unsigned length, const uint8_t* const data);
|
bool write_mem(uint64_t addr, unsigned length, const uint8_t* const data) override;
|
||||||
|
|
||||||
bool read_mem_dbg(uint64_t addr, unsigned length, uint8_t* const data);
|
bool read_mem_dbg(uint64_t addr, unsigned length, uint8_t* const data) override;
|
||||||
|
|
||||||
bool write_mem_dbg(uint64_t addr, unsigned length, const uint8_t* const data);
|
bool write_mem_dbg(uint64_t addr, unsigned length, const uint8_t* const data) override;
|
||||||
|
|
||||||
void trace(sc_core::sc_trace_file* trf) const override;
|
void trace(sc_core::sc_trace_file* trf) const override;
|
||||||
|
|
||||||
bool disass_output(uint64_t pc, const std::string instr);
|
bool disass_output(uint64_t pc, const std::string instr) override;
|
||||||
|
|
||||||
void set_clock_period(sc_core::sc_time period);
|
void set_clock_period(sc_core::sc_time period);
|
||||||
|
|
||||||
|
char const* hier_name() override { return name(); }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void before_end_of_elaboration() override;
|
void before_end_of_elaboration() override;
|
||||||
void start_of_simulation() override;
|
void start_of_simulation() override;
|
||||||
|
@ -46,12 +46,12 @@ using namespace sysc;
|
|||||||
volatile std::array<bool, 2> tgc_init = {
|
volatile std::array<bool, 2> tgc_init = {
|
||||||
iss_factory::instance().register_creator("tgc5c|m_p|interp",
|
iss_factory::instance().register_creator("tgc5c|m_p|interp",
|
||||||
[](unsigned gdb_port, void* data) -> iss_factory::base_t {
|
[](unsigned gdb_port, void* data) -> iss_factory::base_t {
|
||||||
auto cc = reinterpret_cast<sysc::tgfs::core_complex*>(data);
|
auto cc = reinterpret_cast<sysc::tgfs::core_complex_if*>(data);
|
||||||
auto* cpu = new sc_core_adapter<arch::riscv_hart_m_p<arch::tgc5c>>(cc);
|
auto* cpu = new sc_core_adapter<arch::riscv_hart_m_p<arch::tgc5c>>(cc);
|
||||||
return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast<arch::tgc5c*>(cpu), gdb_port)}};
|
return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast<arch::tgc5c*>(cpu), gdb_port)}};
|
||||||
}),
|
}),
|
||||||
iss_factory::instance().register_creator("tgc5c|mu_p|interp", [](unsigned gdb_port, void* data) -> iss_factory::base_t {
|
iss_factory::instance().register_creator("tgc5c|mu_p|interp", [](unsigned gdb_port, void* data) -> iss_factory::base_t {
|
||||||
auto cc = reinterpret_cast<sysc::tgfs::core_complex*>(data);
|
auto cc = reinterpret_cast<sysc::tgfs::core_complex_if*>(data);
|
||||||
auto* cpu = new sc_core_adapter<arch::riscv_hart_mu_p<arch::tgc5c>>(cc);
|
auto* cpu = new sc_core_adapter<arch::riscv_hart_mu_p<arch::tgc5c>>(cc);
|
||||||
return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast<arch::tgc5c*>(cpu), gdb_port)}};
|
return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast<arch::tgc5c*>(cpu), gdb_port)}};
|
||||||
})};
|
})};
|
||||||
@ -62,12 +62,12 @@ using namespace sysc;
|
|||||||
volatile std::array<bool, 2> tgc_init = {
|
volatile std::array<bool, 2> tgc_init = {
|
||||||
iss_factory::instance().register_creator("tgc5c|m_p|llvm",
|
iss_factory::instance().register_creator("tgc5c|m_p|llvm",
|
||||||
[](unsigned gdb_port, void* data) -> iss_factory::base_t {
|
[](unsigned gdb_port, void* data) -> iss_factory::base_t {
|
||||||
auto cc = reinterpret_cast<sysc::tgfs::core_complex*>(data);
|
auto cc = reinterpret_cast<sysc::tgfs::core_complex_if*>(data);
|
||||||
auto* cpu = new sc_core_adapter<arch::riscv_hart_m_p<arch::tgc5c>>(cc);
|
auto* cpu = new sc_core_adapter<arch::riscv_hart_m_p<arch::tgc5c>>(cc);
|
||||||
return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast<arch::tgc5c*>(cpu), gdb_port)}};
|
return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast<arch::tgc5c*>(cpu), gdb_port)}};
|
||||||
}),
|
}),
|
||||||
iss_factory::instance().register_creator("tgc5c|mu_p|llvm", [](unsigned gdb_port, void* data) -> iss_factory::base_t {
|
iss_factory::instance().register_creator("tgc5c|mu_p|llvm", [](unsigned gdb_port, void* data) -> iss_factory::base_t {
|
||||||
auto cc = reinterpret_cast<sysc::tgfs::core_complex*>(data);
|
auto cc = reinterpret_cast<sysc::tgfs::core_complex_if*>(data);
|
||||||
auto* cpu = new sc_core_adapter<arch::riscv_hart_mu_p<arch::tgc5c>>(cc);
|
auto* cpu = new sc_core_adapter<arch::riscv_hart_mu_p<arch::tgc5c>>(cc);
|
||||||
return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast<arch::tgc5c*>(cpu), gdb_port)}};
|
return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast<arch::tgc5c*>(cpu), gdb_port)}};
|
||||||
})};
|
})};
|
||||||
@ -79,12 +79,12 @@ using namespace sysc;
|
|||||||
volatile std::array<bool, 2> tgc_init = {
|
volatile std::array<bool, 2> tgc_init = {
|
||||||
iss_factory::instance().register_creator("tgc5c|m_p|tcc",
|
iss_factory::instance().register_creator("tgc5c|m_p|tcc",
|
||||||
[](unsigned gdb_port, void* data) -> iss_factory::base_t {
|
[](unsigned gdb_port, void* data) -> iss_factory::base_t {
|
||||||
auto cc = reinterpret_cast<sysc::tgfs::core_complex*>(data);
|
auto cc = reinterpret_cast<sysc::tgfs::core_complex_if*>(data);
|
||||||
auto* cpu = new sc_core_adapter<arch::riscv_hart_m_p<arch::tgc5c>>(cc);
|
auto* cpu = new sc_core_adapter<arch::riscv_hart_m_p<arch::tgc5c>>(cc);
|
||||||
return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast<arch::tgc5c*>(cpu), gdb_port)}};
|
return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast<arch::tgc5c*>(cpu), gdb_port)}};
|
||||||
}),
|
}),
|
||||||
iss_factory::instance().register_creator("tgc5c|mu_p|tcc", [](unsigned gdb_port, void* data) -> iss_factory::base_t {
|
iss_factory::instance().register_creator("tgc5c|mu_p|tcc", [](unsigned gdb_port, void* data) -> iss_factory::base_t {
|
||||||
auto cc = reinterpret_cast<sysc::tgfs::core_complex*>(data);
|
auto cc = reinterpret_cast<sysc::tgfs::core_complex_if*>(data);
|
||||||
auto* cpu = new sc_core_adapter<arch::riscv_hart_mu_p<arch::tgc5c>>(cc);
|
auto* cpu = new sc_core_adapter<arch::riscv_hart_mu_p<arch::tgc5c>>(cc);
|
||||||
return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast<arch::tgc5c*>(cpu), gdb_port)}};
|
return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast<arch::tgc5c*>(cpu), gdb_port)}};
|
||||||
})};
|
})};
|
||||||
@ -96,12 +96,12 @@ using namespace sysc;
|
|||||||
volatile std::array<bool, 2> tgc_init = {
|
volatile std::array<bool, 2> tgc_init = {
|
||||||
iss_factory::instance().register_creator("tgc5c|m_p|asmjit",
|
iss_factory::instance().register_creator("tgc5c|m_p|asmjit",
|
||||||
[](unsigned gdb_port, void* data) -> iss_factory::base_t {
|
[](unsigned gdb_port, void* data) -> iss_factory::base_t {
|
||||||
auto cc = reinterpret_cast<sysc::tgfs::core_complex*>(data);
|
auto cc = reinterpret_cast<sysc::tgfs::core_complex_if*>(data);
|
||||||
auto* cpu = new sc_core_adapter<arch::riscv_hart_m_p<arch::tgc5c>>(cc);
|
auto* cpu = new sc_core_adapter<arch::riscv_hart_m_p<arch::tgc5c>>(cc);
|
||||||
return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast<arch::tgc5c*>(cpu), gdb_port)}};
|
return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast<arch::tgc5c*>(cpu), gdb_port)}};
|
||||||
}),
|
}),
|
||||||
iss_factory::instance().register_creator("tgc5c|mu_p|asmjit", [](unsigned gdb_port, void* data) -> iss_factory::base_t {
|
iss_factory::instance().register_creator("tgc5c|mu_p|asmjit", [](unsigned gdb_port, void* data) -> iss_factory::base_t {
|
||||||
auto cc = reinterpret_cast<sysc::tgfs::core_complex*>(data);
|
auto cc = reinterpret_cast<sysc::tgfs::core_complex_if*>(data);
|
||||||
auto* cpu = new sc_core_adapter<arch::riscv_hart_mu_p<arch::tgc5c>>(cc);
|
auto* cpu = new sc_core_adapter<arch::riscv_hart_mu_p<arch::tgc5c>>(cc);
|
||||||
return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast<arch::tgc5c*>(cpu), gdb_port)}};
|
return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast<arch::tgc5c*>(cpu), gdb_port)}};
|
||||||
})};
|
})};
|
||||||
|
@ -21,7 +21,7 @@ public:
|
|||||||
using reg_t = typename iss::arch::traits<typename PLAT::core>::reg_t;
|
using reg_t = typename iss::arch::traits<typename PLAT::core>::reg_t;
|
||||||
using phys_addr_t = typename iss::arch::traits<typename PLAT::core>::phys_addr_t;
|
using phys_addr_t = typename iss::arch::traits<typename PLAT::core>::phys_addr_t;
|
||||||
using heart_state_t = typename PLAT::hart_state_type;
|
using heart_state_t = typename PLAT::hart_state_type;
|
||||||
sc_core_adapter(sysc::tgfs::core_complex* owner)
|
sc_core_adapter(sysc::tgfs::core_complex_if* owner)
|
||||||
: owner(owner) {}
|
: owner(owner) {}
|
||||||
|
|
||||||
iss::arch_if* get_arch_if() override { return this; }
|
iss::arch_if* get_arch_if() override { return this; }
|
||||||
@ -54,9 +54,9 @@ public:
|
|||||||
std::stringstream s;
|
std::stringstream s;
|
||||||
s << "[p:" << lvl[this->reg.PRIV] << ";s:0x" << std::hex << std::setfill('0') << std::setw(sizeof(reg_t) * 2)
|
s << "[p:" << lvl[this->reg.PRIV] << ";s:0x" << std::hex << std::setfill('0') << std::setw(sizeof(reg_t) * 2)
|
||||||
<< (reg_t)this->state.mstatus << std::dec << ";c:" << this->reg.icount + this->cycle_offset << "]";
|
<< (reg_t)this->state.mstatus << std::dec << ";c:" << this->reg.icount + this->cycle_offset << "]";
|
||||||
SCCDEBUG(owner->name()) << "disass: "
|
SCCDEBUG(owner->hier_name()) << "disass: "
|
||||||
<< "0x" << std::setw(16) << std::right << std::setfill('0') << std::hex << pc << "\t\t" << std::setw(40)
|
<< "0x" << std::setw(16) << std::right << std::setfill('0') << std::hex << pc << "\t\t"
|
||||||
<< std::setfill(' ') << std::left << instr << s.str();
|
<< std::setw(40) << std::setfill(' ') << std::left << instr << s.str();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -79,10 +79,10 @@ public:
|
|||||||
switch(hostvar >> 48) {
|
switch(hostvar >> 48) {
|
||||||
case 0:
|
case 0:
|
||||||
if(hostvar != 0x1) {
|
if(hostvar != 0x1) {
|
||||||
SCCINFO(owner->name())
|
SCCINFO(owner->hier_name())
|
||||||
<< "tohost value is 0x" << std::hex << hostvar << std::dec << " (" << hostvar << "), stopping simulation";
|
<< "tohost value is 0x" << std::hex << hostvar << std::dec << " (" << hostvar << "), stopping simulation";
|
||||||
} else {
|
} else {
|
||||||
SCCINFO(owner->name())
|
SCCINFO(owner->hier_name())
|
||||||
<< "tohost value is 0x" << std::hex << hostvar << std::dec << " (" << hostvar << "), stopping simulation";
|
<< "tohost value is 0x" << std::hex << hostvar << std::dec << " (" << hostvar << "), stopping simulation";
|
||||||
}
|
}
|
||||||
this->reg.trap_state = std::numeric_limits<uint32_t>::max();
|
this->reg.trap_state = std::numeric_limits<uint32_t>::max();
|
||||||
@ -112,21 +112,8 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
iss::status read_csr(unsigned addr, reg_t& val) override {
|
iss::status read_csr(unsigned addr, reg_t& val) override {
|
||||||
#ifndef CWR_SYSTEMC
|
|
||||||
if((addr == iss::arch::time || addr == iss::arch::timeh) && owner->mtime_o.get_interface(0)) {
|
|
||||||
uint64_t time_val;
|
|
||||||
bool ret = owner->mtime_o->nb_peek(time_val);
|
|
||||||
if(addr == iss::arch::time) {
|
|
||||||
val = static_cast<reg_t>(time_val);
|
|
||||||
} else if(addr == iss::arch::timeh) {
|
|
||||||
if(sizeof(reg_t) != 4)
|
|
||||||
return iss::Err;
|
|
||||||
val = static_cast<reg_t>(time_val >> 32);
|
|
||||||
}
|
|
||||||
return ret ? iss::Ok : iss::Err;
|
|
||||||
#else
|
|
||||||
if((addr == iss::arch::time || addr == iss::arch::timeh)) {
|
if((addr == iss::arch::time || addr == iss::arch::timeh)) {
|
||||||
uint64_t time_val = owner->mtime_i.read();
|
uint64_t time_val = owner->mtime_i.get_interface() ? owner->mtime_i.read() : 0;
|
||||||
if(addr == iss::arch::time) {
|
if(addr == iss::arch::time) {
|
||||||
val = static_cast<reg_t>(time_val);
|
val = static_cast<reg_t>(time_val);
|
||||||
} else if(addr == iss::arch::timeh) {
|
} else if(addr == iss::arch::timeh) {
|
||||||
@ -135,14 +122,13 @@ public:
|
|||||||
val = static_cast<reg_t>(time_val >> 32);
|
val = static_cast<reg_t>(time_val >> 32);
|
||||||
}
|
}
|
||||||
return iss::Ok;
|
return iss::Ok;
|
||||||
#endif
|
|
||||||
} else {
|
} else {
|
||||||
return PLAT::read_csr(addr, val);
|
return PLAT::read_csr(addr, val);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void wait_until(uint64_t flags) override {
|
void wait_until(uint64_t flags) override {
|
||||||
SCCDEBUG(owner->name()) << "Sleeping until interrupt";
|
SCCDEBUG(owner->hier_name()) << "Sleeping until interrupt";
|
||||||
while(this->reg.pending_trap == 0 && (this->csr[iss::arch::mip] & this->csr[iss::arch::mie]) == 0) {
|
while(this->reg.pending_trap == 0 && (this->csr[iss::arch::mip] & this->csr[iss::arch::mie]) == 0) {
|
||||||
sc_core::wait(wfi_evt);
|
sc_core::wait(wfi_evt);
|
||||||
}
|
}
|
||||||
@ -173,11 +159,11 @@ public:
|
|||||||
this->csr[iss::arch::mip] &= ~mask;
|
this->csr[iss::arch::mip] &= ~mask;
|
||||||
this->check_interrupt();
|
this->check_interrupt();
|
||||||
if(value)
|
if(value)
|
||||||
SCCTRACE(owner->name()) << "Triggering interrupt " << id << " Pending trap: " << this->reg.pending_trap;
|
SCCTRACE(owner->hier_name()) << "Triggering interrupt " << id << " Pending trap: " << this->reg.pending_trap;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
sysc::tgfs::core_complex* const owner;
|
sysc::tgfs::core_complex_if* const owner{nullptr};
|
||||||
sc_core::sc_event wfi_evt;
|
sc_core::sc_event wfi_evt;
|
||||||
uint64_t hostvar{std::numeric_limits<uint64_t>::max()};
|
uint64_t hostvar{std::numeric_limits<uint64_t>::max()};
|
||||||
unsigned to_host_wr_cnt = 0;
|
unsigned to_host_wr_cnt = 0;
|
||||||
|
@ -88,7 +88,6 @@ protected:
|
|||||||
using super::write_reg_to_mem;
|
using super::write_reg_to_mem;
|
||||||
using super::gen_read_mem;
|
using super::gen_read_mem;
|
||||||
using super::gen_write_mem;
|
using super::gen_write_mem;
|
||||||
using super::gen_wait;
|
|
||||||
using super::gen_leave;
|
using super::gen_leave;
|
||||||
using super::gen_sync;
|
using super::gen_sync;
|
||||||
|
|
||||||
@ -104,7 +103,7 @@ protected:
|
|||||||
void gen_instr_prologue(jit_holder& jh);
|
void gen_instr_prologue(jit_holder& jh);
|
||||||
void gen_instr_epilogue(jit_holder& jh);
|
void gen_instr_epilogue(jit_holder& jh);
|
||||||
inline void gen_raise(jit_holder& jh, uint16_t trap_id, uint16_t cause);
|
inline void gen_raise(jit_holder& jh, uint16_t trap_id, uint16_t cause);
|
||||||
template <typename T, typename = std::enable_if_t<std::is_integral_v<T>>> void gen_set_tval(jit_holder& jh, T new_tval) ;
|
template <typename T, typename = typename std::enable_if<std::is_integral<T>::value>::type> void gen_set_tval(jit_holder& jh, T new_tval) ;
|
||||||
void gen_set_tval(jit_holder& jh, x86_reg_t _new_tval) ;
|
void gen_set_tval(jit_holder& jh, x86_reg_t _new_tval) ;
|
||||||
|
|
||||||
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>
|
||||||
@ -113,6 +112,7 @@ protected:
|
|||||||
auto sign_mask = 1ULL<<(W-1);
|
auto sign_mask = 1ULL<<(W-1);
|
||||||
return (from & mask) | ((from & sign_mask) ? ~mask : 0);
|
return (from & mask) | ((from & sign_mask) ? ~mask : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* start opcode definitions
|
* start opcode definitions
|
||||||
@ -500,6 +500,7 @@ private:
|
|||||||
(gen_operation(cc, band, (gen_operation(cc, add, load_reg_from_mem(jh, traits::X0 + rs1), (int16_t)sext<12>(imm))
|
(gen_operation(cc, band, (gen_operation(cc, add, load_reg_from_mem(jh, traits::X0 + rs1), (int16_t)sext<12>(imm))
|
||||||
), addr_mask)
|
), addr_mask)
|
||||||
), 32, true);
|
), 32, true);
|
||||||
|
{
|
||||||
auto label_merge = cc.newLabel();
|
auto label_merge = cc.newLabel();
|
||||||
cmp(cc, gen_operation(cc, urem, new_pc, static_cast<uint32_t>(traits::INSTR_ALIGNMENT))
|
cmp(cc, gen_operation(cc, urem, new_pc, static_cast<uint32_t>(traits::INSTR_ALIGNMENT))
|
||||||
,0);
|
,0);
|
||||||
@ -522,6 +523,7 @@ private:
|
|||||||
}
|
}
|
||||||
cc.bind(label_merge);
|
cc.bind(label_merge);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
auto returnValue = BRANCH;
|
auto returnValue = BRANCH;
|
||||||
|
|
||||||
gen_sync(jh, POST_SYNC, 3);
|
gen_sync(jh, POST_SYNC, 3);
|
||||||
@ -566,6 +568,7 @@ private:
|
|||||||
gen_raise(jh, 0, static_cast<int32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
|
gen_raise(jh, 0, static_cast<int32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
|
{
|
||||||
auto label_merge = cc.newLabel();
|
auto label_merge = cc.newLabel();
|
||||||
cmp(cc, gen_operation(cc, eq, load_reg_from_mem(jh, traits::X0 + rs1), load_reg_from_mem(jh, traits::X0 + rs2))
|
cmp(cc, gen_operation(cc, eq, load_reg_from_mem(jh, traits::X0 + rs1), load_reg_from_mem(jh, traits::X0 + rs2))
|
||||||
,0);
|
,0);
|
||||||
@ -584,6 +587,7 @@ private:
|
|||||||
}
|
}
|
||||||
cc.bind(label_merge);
|
cc.bind(label_merge);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
auto returnValue = BRANCH;
|
auto returnValue = BRANCH;
|
||||||
|
|
||||||
gen_sync(jh, POST_SYNC, 4);
|
gen_sync(jh, POST_SYNC, 4);
|
||||||
@ -628,6 +632,7 @@ private:
|
|||||||
gen_raise(jh, 0, static_cast<int32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
|
gen_raise(jh, 0, static_cast<int32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
|
{
|
||||||
auto label_merge = cc.newLabel();
|
auto label_merge = cc.newLabel();
|
||||||
cmp(cc, gen_operation(cc, ne, load_reg_from_mem(jh, traits::X0 + rs1), load_reg_from_mem(jh, traits::X0 + rs2))
|
cmp(cc, gen_operation(cc, ne, load_reg_from_mem(jh, traits::X0 + rs1), load_reg_from_mem(jh, traits::X0 + rs2))
|
||||||
,0);
|
,0);
|
||||||
@ -646,6 +651,7 @@ private:
|
|||||||
}
|
}
|
||||||
cc.bind(label_merge);
|
cc.bind(label_merge);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
auto returnValue = BRANCH;
|
auto returnValue = BRANCH;
|
||||||
|
|
||||||
gen_sync(jh, POST_SYNC, 5);
|
gen_sync(jh, POST_SYNC, 5);
|
||||||
@ -690,6 +696,7 @@ private:
|
|||||||
gen_raise(jh, 0, static_cast<int32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
|
gen_raise(jh, 0, static_cast<int32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
|
{
|
||||||
auto label_merge = cc.newLabel();
|
auto label_merge = cc.newLabel();
|
||||||
cmp(cc, gen_operation(cc, lt, gen_ext(cc,
|
cmp(cc, gen_operation(cc, lt, gen_ext(cc,
|
||||||
load_reg_from_mem(jh, traits::X0 + rs1), 32, false), gen_ext(cc,
|
load_reg_from_mem(jh, traits::X0 + rs1), 32, false), gen_ext(cc,
|
||||||
@ -710,6 +717,7 @@ private:
|
|||||||
}
|
}
|
||||||
cc.bind(label_merge);
|
cc.bind(label_merge);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
auto returnValue = BRANCH;
|
auto returnValue = BRANCH;
|
||||||
|
|
||||||
gen_sync(jh, POST_SYNC, 6);
|
gen_sync(jh, POST_SYNC, 6);
|
||||||
@ -754,6 +762,7 @@ private:
|
|||||||
gen_raise(jh, 0, static_cast<int32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
|
gen_raise(jh, 0, static_cast<int32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
|
{
|
||||||
auto label_merge = cc.newLabel();
|
auto label_merge = cc.newLabel();
|
||||||
cmp(cc, gen_operation(cc, gte, gen_ext(cc,
|
cmp(cc, gen_operation(cc, gte, gen_ext(cc,
|
||||||
load_reg_from_mem(jh, traits::X0 + rs1), 32, false), gen_ext(cc,
|
load_reg_from_mem(jh, traits::X0 + rs1), 32, false), gen_ext(cc,
|
||||||
@ -774,6 +783,7 @@ private:
|
|||||||
}
|
}
|
||||||
cc.bind(label_merge);
|
cc.bind(label_merge);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
auto returnValue = BRANCH;
|
auto returnValue = BRANCH;
|
||||||
|
|
||||||
gen_sync(jh, POST_SYNC, 7);
|
gen_sync(jh, POST_SYNC, 7);
|
||||||
@ -818,6 +828,7 @@ private:
|
|||||||
gen_raise(jh, 0, static_cast<int32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
|
gen_raise(jh, 0, static_cast<int32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
|
{
|
||||||
auto label_merge = cc.newLabel();
|
auto label_merge = cc.newLabel();
|
||||||
cmp(cc, gen_operation(cc, ltu, load_reg_from_mem(jh, traits::X0 + rs1), load_reg_from_mem(jh, traits::X0 + rs2))
|
cmp(cc, gen_operation(cc, ltu, load_reg_from_mem(jh, traits::X0 + rs1), load_reg_from_mem(jh, traits::X0 + rs2))
|
||||||
,0);
|
,0);
|
||||||
@ -836,6 +847,7 @@ private:
|
|||||||
}
|
}
|
||||||
cc.bind(label_merge);
|
cc.bind(label_merge);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
auto returnValue = BRANCH;
|
auto returnValue = BRANCH;
|
||||||
|
|
||||||
gen_sync(jh, POST_SYNC, 8);
|
gen_sync(jh, POST_SYNC, 8);
|
||||||
@ -880,6 +892,7 @@ private:
|
|||||||
gen_raise(jh, 0, static_cast<int32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
|
gen_raise(jh, 0, static_cast<int32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
|
{
|
||||||
auto label_merge = cc.newLabel();
|
auto label_merge = cc.newLabel();
|
||||||
cmp(cc, gen_operation(cc, gteu, load_reg_from_mem(jh, traits::X0 + rs1), load_reg_from_mem(jh, traits::X0 + rs2))
|
cmp(cc, gen_operation(cc, gteu, load_reg_from_mem(jh, traits::X0 + rs1), load_reg_from_mem(jh, traits::X0 + rs2))
|
||||||
,0);
|
,0);
|
||||||
@ -898,6 +911,7 @@ private:
|
|||||||
}
|
}
|
||||||
cc.bind(label_merge);
|
cc.bind(label_merge);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
auto returnValue = BRANCH;
|
auto returnValue = BRANCH;
|
||||||
|
|
||||||
gen_sync(jh, POST_SYNC, 9);
|
gen_sync(jh, POST_SYNC, 9);
|
||||||
@ -1407,25 +1421,23 @@ private:
|
|||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
if(rd!=0){
|
if(rd!=0){
|
||||||
{
|
auto label_then11 = cc.newLabel();
|
||||||
auto label_then = cc.newLabel();
|
auto label_merge11 = cc.newLabel();
|
||||||
auto label_merge = cc.newLabel();
|
auto tmp_reg11 = get_reg(cc, 8, false);
|
||||||
auto tmp_reg = get_reg_for(cc, 1);
|
|
||||||
cmp(cc, gen_ext(cc,
|
cmp(cc, gen_ext(cc,
|
||||||
load_reg_from_mem(jh, traits::X0 + rs1), 32, true), (int16_t)sext<12>(imm));
|
load_reg_from_mem(jh, traits::X0 + rs1), 32, true), (int16_t)sext<12>(imm));
|
||||||
cc.jl(label_then);
|
cc.jl(label_then11);
|
||||||
mov(cc, tmp_reg,0);
|
mov(cc, tmp_reg11,0);
|
||||||
cc.jmp(label_merge);
|
cc.jmp(label_merge11);
|
||||||
cc.bind(label_then);
|
cc.bind(label_then11);
|
||||||
mov(cc, tmp_reg,1);
|
mov(cc, tmp_reg11, 1);
|
||||||
cc.bind(label_merge);
|
cc.bind(label_merge11);
|
||||||
mov(cc, get_ptr_for(jh, traits::X0+ rd),
|
mov(cc, get_ptr_for(jh, traits::X0+ rd),
|
||||||
gen_ext(cc, tmp_reg
|
gen_ext(cc, tmp_reg11
|
||||||
, 32, false)
|
, 32, false)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
auto returnValue = CONT;
|
auto returnValue = CONT;
|
||||||
|
|
||||||
gen_sync(jh, POST_SYNC, 19);
|
gen_sync(jh, POST_SYNC, 19);
|
||||||
@ -1470,24 +1482,22 @@ private:
|
|||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
if(rd!=0){
|
if(rd!=0){
|
||||||
{
|
auto label_then12 = cc.newLabel();
|
||||||
auto label_then = cc.newLabel();
|
auto label_merge12 = cc.newLabel();
|
||||||
auto label_merge = cc.newLabel();
|
auto tmp_reg12 = get_reg(cc, 8, false);
|
||||||
auto tmp_reg = get_reg_for(cc, 1);
|
|
||||||
cmp(cc, load_reg_from_mem(jh, traits::X0 + rs1), (uint32_t)((int16_t)sext<12>(imm)));
|
cmp(cc, load_reg_from_mem(jh, traits::X0 + rs1), (uint32_t)((int16_t)sext<12>(imm)));
|
||||||
cc.jb(label_then);
|
cc.jb(label_then12);
|
||||||
mov(cc, tmp_reg,0);
|
mov(cc, tmp_reg12,0);
|
||||||
cc.jmp(label_merge);
|
cc.jmp(label_merge12);
|
||||||
cc.bind(label_then);
|
cc.bind(label_then12);
|
||||||
mov(cc, tmp_reg,1);
|
mov(cc, tmp_reg12, 1);
|
||||||
cc.bind(label_merge);
|
cc.bind(label_merge12);
|
||||||
mov(cc, get_ptr_for(jh, traits::X0+ rd),
|
mov(cc, get_ptr_for(jh, traits::X0+ rd),
|
||||||
gen_ext(cc, tmp_reg
|
gen_ext(cc, tmp_reg12
|
||||||
, 32, false)
|
, 32, false)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
auto returnValue = CONT;
|
auto returnValue = CONT;
|
||||||
|
|
||||||
gen_sync(jh, POST_SYNC, 20);
|
gen_sync(jh, POST_SYNC, 20);
|
||||||
@ -1978,26 +1988,24 @@ private:
|
|||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
if(rd!=0){
|
if(rd!=0){
|
||||||
{
|
auto label_then13 = cc.newLabel();
|
||||||
auto label_then = cc.newLabel();
|
auto label_merge13 = cc.newLabel();
|
||||||
auto label_merge = cc.newLabel();
|
auto tmp_reg13 = get_reg(cc, 8, false);
|
||||||
auto tmp_reg = get_reg_for(cc, 1);
|
|
||||||
cmp(cc, gen_ext(cc,
|
cmp(cc, gen_ext(cc,
|
||||||
load_reg_from_mem(jh, traits::X0 + rs1), 32, true), gen_ext(cc,
|
load_reg_from_mem(jh, traits::X0 + rs1), 32, true), gen_ext(cc,
|
||||||
load_reg_from_mem(jh, traits::X0 + rs2), 32, true));
|
load_reg_from_mem(jh, traits::X0 + rs2), 32, true));
|
||||||
cc.jl(label_then);
|
cc.jl(label_then13);
|
||||||
mov(cc, tmp_reg,0);
|
mov(cc, tmp_reg13,0);
|
||||||
cc.jmp(label_merge);
|
cc.jmp(label_merge13);
|
||||||
cc.bind(label_then);
|
cc.bind(label_then13);
|
||||||
mov(cc, tmp_reg,1);
|
mov(cc, tmp_reg13, 1);
|
||||||
cc.bind(label_merge);
|
cc.bind(label_merge13);
|
||||||
mov(cc, get_ptr_for(jh, traits::X0+ rd),
|
mov(cc, get_ptr_for(jh, traits::X0+ rd),
|
||||||
gen_ext(cc, tmp_reg
|
gen_ext(cc, tmp_reg13
|
||||||
, 32, false)
|
, 32, false)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
auto returnValue = CONT;
|
auto returnValue = CONT;
|
||||||
|
|
||||||
gen_sync(jh, POST_SYNC, 30);
|
gen_sync(jh, POST_SYNC, 30);
|
||||||
@ -2042,24 +2050,22 @@ private:
|
|||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
if(rd!=0){
|
if(rd!=0){
|
||||||
{
|
auto label_then14 = cc.newLabel();
|
||||||
auto label_then = cc.newLabel();
|
auto label_merge14 = cc.newLabel();
|
||||||
auto label_merge = cc.newLabel();
|
auto tmp_reg14 = get_reg(cc, 8, false);
|
||||||
auto tmp_reg = get_reg_for(cc, 1);
|
|
||||||
cmp(cc, load_reg_from_mem(jh, traits::X0 + rs1), load_reg_from_mem(jh, traits::X0 + rs2));
|
cmp(cc, load_reg_from_mem(jh, traits::X0 + rs1), load_reg_from_mem(jh, traits::X0 + rs2));
|
||||||
cc.jb(label_then);
|
cc.jb(label_then14);
|
||||||
mov(cc, tmp_reg,0);
|
mov(cc, tmp_reg14,0);
|
||||||
cc.jmp(label_merge);
|
cc.jmp(label_merge14);
|
||||||
cc.bind(label_then);
|
cc.bind(label_then14);
|
||||||
mov(cc, tmp_reg,1);
|
mov(cc, tmp_reg14, 1);
|
||||||
cc.bind(label_merge);
|
cc.bind(label_merge14);
|
||||||
mov(cc, get_ptr_for(jh, traits::X0+ rd),
|
mov(cc, get_ptr_for(jh, traits::X0+ rd),
|
||||||
gen_ext(cc, tmp_reg
|
gen_ext(cc, tmp_reg14
|
||||||
, 32, false)
|
, 32, false)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
auto returnValue = CONT;
|
auto returnValue = CONT;
|
||||||
|
|
||||||
gen_sync(jh, POST_SYNC, 31);
|
gen_sync(jh, POST_SYNC, 31);
|
||||||
@ -2364,7 +2370,7 @@ private:
|
|||||||
if(this->disass_enabled){
|
if(this->disass_enabled){
|
||||||
/* generate disass */
|
/* generate disass */
|
||||||
|
|
||||||
//This disass is not yet implemented
|
//No disass specified, using instruction name
|
||||||
std::string mnemonic = "ecall";
|
std::string mnemonic = "ecall";
|
||||||
InvokeNode* call_print_disass;
|
InvokeNode* call_print_disass;
|
||||||
char* mnemonic_ptr = strdup(mnemonic.c_str());
|
char* mnemonic_ptr = strdup(mnemonic.c_str());
|
||||||
@ -2401,7 +2407,7 @@ private:
|
|||||||
if(this->disass_enabled){
|
if(this->disass_enabled){
|
||||||
/* generate disass */
|
/* generate disass */
|
||||||
|
|
||||||
//This disass is not yet implemented
|
//No disass specified, using instruction name
|
||||||
std::string mnemonic = "ebreak";
|
std::string mnemonic = "ebreak";
|
||||||
InvokeNode* call_print_disass;
|
InvokeNode* call_print_disass;
|
||||||
char* mnemonic_ptr = strdup(mnemonic.c_str());
|
char* mnemonic_ptr = strdup(mnemonic.c_str());
|
||||||
@ -2438,7 +2444,7 @@ private:
|
|||||||
if(this->disass_enabled){
|
if(this->disass_enabled){
|
||||||
/* generate disass */
|
/* generate disass */
|
||||||
|
|
||||||
//This disass is not yet implemented
|
//No disass specified, using instruction name
|
||||||
std::string mnemonic = "mret";
|
std::string mnemonic = "mret";
|
||||||
InvokeNode* call_print_disass;
|
InvokeNode* call_print_disass;
|
||||||
char* mnemonic_ptr = strdup(mnemonic.c_str());
|
char* mnemonic_ptr = strdup(mnemonic.c_str());
|
||||||
@ -2475,7 +2481,7 @@ private:
|
|||||||
if(this->disass_enabled){
|
if(this->disass_enabled){
|
||||||
/* generate disass */
|
/* generate disass */
|
||||||
|
|
||||||
//This disass is not yet implemented
|
//No disass specified, using instruction name
|
||||||
std::string mnemonic = "wfi";
|
std::string mnemonic = "wfi";
|
||||||
InvokeNode* call_print_disass;
|
InvokeNode* call_print_disass;
|
||||||
char* mnemonic_ptr = strdup(mnemonic.c_str());
|
char* mnemonic_ptr = strdup(mnemonic.c_str());
|
||||||
@ -2497,7 +2503,10 @@ private:
|
|||||||
gen_instr_prologue(jh);
|
gen_instr_prologue(jh);
|
||||||
cc.comment("//behavior:");
|
cc.comment("//behavior:");
|
||||||
/*generate behavior*/
|
/*generate behavior*/
|
||||||
gen_wait(jh, 1);
|
InvokeNode* call_wait_15;
|
||||||
|
jh.cc.comment("//call_wait");
|
||||||
|
jh.cc.invoke(&call_wait_15, &wait, FuncSignature::build<void, int32_t>());
|
||||||
|
setArg(call_wait_15, 0, 1);
|
||||||
auto returnValue = CONT;
|
auto returnValue = CONT;
|
||||||
|
|
||||||
gen_sync(jh, POST_SYNC, 41);
|
gen_sync(jh, POST_SYNC, 41);
|
||||||
@ -3116,6 +3125,7 @@ private:
|
|||||||
auto divisor = gen_ext(cc,
|
auto divisor = gen_ext(cc,
|
||||||
load_reg_from_mem(jh, traits::X0 + rs2), 32, true);
|
load_reg_from_mem(jh, traits::X0 + rs2), 32, true);
|
||||||
if(rd!=0){
|
if(rd!=0){
|
||||||
|
{
|
||||||
auto label_merge = cc.newLabel();
|
auto label_merge = cc.newLabel();
|
||||||
cmp(cc, gen_operation(cc, ne, divisor, 0)
|
cmp(cc, gen_operation(cc, ne, divisor, 0)
|
||||||
,0);
|
,0);
|
||||||
@ -3123,6 +3133,7 @@ private:
|
|||||||
cc.je(label_else);
|
cc.je(label_else);
|
||||||
{
|
{
|
||||||
auto MMIN = ((uint32_t)1)<<(static_cast<uint32_t>(traits::XLEN)-1);
|
auto MMIN = ((uint32_t)1)<<(static_cast<uint32_t>(traits::XLEN)-1);
|
||||||
|
{
|
||||||
auto label_merge = cc.newLabel();
|
auto label_merge = cc.newLabel();
|
||||||
cmp(cc, gen_operation(cc, land, gen_operation(cc, eq, load_reg_from_mem(jh, traits::X0 + rs1), MMIN)
|
cmp(cc, gen_operation(cc, land, gen_operation(cc, eq, load_reg_from_mem(jh, traits::X0 + rs1), MMIN)
|
||||||
, gen_operation(cc, eq, divisor, - 1)
|
, gen_operation(cc, eq, divisor, - 1)
|
||||||
@ -3144,6 +3155,7 @@ private:
|
|||||||
}
|
}
|
||||||
cc.bind(label_merge);
|
cc.bind(label_merge);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
cc.jmp(label_merge);
|
cc.jmp(label_merge);
|
||||||
cc.bind(label_else);
|
cc.bind(label_else);
|
||||||
{
|
{
|
||||||
@ -3153,6 +3165,7 @@ private:
|
|||||||
cc.bind(label_merge);
|
cc.bind(label_merge);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
auto returnValue = CONT;
|
auto returnValue = CONT;
|
||||||
|
|
||||||
gen_sync(jh, POST_SYNC, 53);
|
gen_sync(jh, POST_SYNC, 53);
|
||||||
@ -3196,6 +3209,7 @@ private:
|
|||||||
gen_raise(jh, 0, static_cast<int32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
|
gen_raise(jh, 0, static_cast<int32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
|
{
|
||||||
auto label_merge = cc.newLabel();
|
auto label_merge = cc.newLabel();
|
||||||
cmp(cc, gen_operation(cc, ne, load_reg_from_mem(jh, traits::X0 + rs2), 0)
|
cmp(cc, gen_operation(cc, ne, load_reg_from_mem(jh, traits::X0 + rs2), 0)
|
||||||
,0);
|
,0);
|
||||||
@ -3218,6 +3232,7 @@ private:
|
|||||||
}
|
}
|
||||||
cc.bind(label_merge);
|
cc.bind(label_merge);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
auto returnValue = CONT;
|
auto returnValue = CONT;
|
||||||
|
|
||||||
gen_sync(jh, POST_SYNC, 54);
|
gen_sync(jh, POST_SYNC, 54);
|
||||||
@ -3261,6 +3276,7 @@ private:
|
|||||||
gen_raise(jh, 0, static_cast<int32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
|
gen_raise(jh, 0, static_cast<int32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
|
{
|
||||||
auto label_merge = cc.newLabel();
|
auto label_merge = cc.newLabel();
|
||||||
cmp(cc, gen_operation(cc, ne, load_reg_from_mem(jh, traits::X0 + rs2), 0)
|
cmp(cc, gen_operation(cc, ne, load_reg_from_mem(jh, traits::X0 + rs2), 0)
|
||||||
,0);
|
,0);
|
||||||
@ -3268,6 +3284,7 @@ private:
|
|||||||
cc.je(label_else);
|
cc.je(label_else);
|
||||||
{
|
{
|
||||||
auto MMIN = (uint32_t)1<<(static_cast<uint32_t>(traits::XLEN)-1);
|
auto MMIN = (uint32_t)1<<(static_cast<uint32_t>(traits::XLEN)-1);
|
||||||
|
{
|
||||||
auto label_merge = cc.newLabel();
|
auto label_merge = cc.newLabel();
|
||||||
cmp(cc, gen_operation(cc, land, gen_operation(cc, eq, load_reg_from_mem(jh, traits::X0 + rs1), MMIN)
|
cmp(cc, gen_operation(cc, land, gen_operation(cc, eq, load_reg_from_mem(jh, traits::X0 + rs1), MMIN)
|
||||||
, gen_operation(cc, eq, gen_ext(cc,
|
, gen_operation(cc, eq, gen_ext(cc,
|
||||||
@ -3297,6 +3314,7 @@ private:
|
|||||||
}
|
}
|
||||||
cc.bind(label_merge);
|
cc.bind(label_merge);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
cc.jmp(label_merge);
|
cc.jmp(label_merge);
|
||||||
cc.bind(label_else);
|
cc.bind(label_else);
|
||||||
{
|
{
|
||||||
@ -3307,6 +3325,7 @@ private:
|
|||||||
}
|
}
|
||||||
cc.bind(label_merge);
|
cc.bind(label_merge);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
auto returnValue = CONT;
|
auto returnValue = CONT;
|
||||||
|
|
||||||
gen_sync(jh, POST_SYNC, 55);
|
gen_sync(jh, POST_SYNC, 55);
|
||||||
@ -3350,6 +3369,7 @@ private:
|
|||||||
gen_raise(jh, 0, static_cast<int32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
|
gen_raise(jh, 0, static_cast<int32_t>(traits::RV_CAUSE_ILLEGAL_INSTRUCTION));
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
|
{
|
||||||
auto label_merge = cc.newLabel();
|
auto label_merge = cc.newLabel();
|
||||||
cmp(cc, gen_operation(cc, ne, load_reg_from_mem(jh, traits::X0 + rs2), 0)
|
cmp(cc, gen_operation(cc, ne, load_reg_from_mem(jh, traits::X0 + rs2), 0)
|
||||||
,0);
|
,0);
|
||||||
@ -3372,6 +3392,7 @@ private:
|
|||||||
}
|
}
|
||||||
cc.bind(label_merge);
|
cc.bind(label_merge);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
auto returnValue = CONT;
|
auto returnValue = CONT;
|
||||||
|
|
||||||
gen_sync(jh, POST_SYNC, 56);
|
gen_sync(jh, POST_SYNC, 56);
|
||||||
@ -3388,7 +3409,7 @@ private:
|
|||||||
/* generate disass */
|
/* generate disass */
|
||||||
|
|
||||||
auto mnemonic = fmt::format(
|
auto mnemonic = fmt::format(
|
||||||
"{mnemonic:10} {rd}, {imm:#05x}", fmt::arg("mnemonic", "c__addi4spn"),
|
"{mnemonic:10} {rd}, {imm:#05x}", fmt::arg("mnemonic", "c.addi4spn"),
|
||||||
fmt::arg("rd", name(8+rd)), fmt::arg("imm", imm));
|
fmt::arg("rd", name(8+rd)), fmt::arg("imm", imm));
|
||||||
InvokeNode* call_print_disass;
|
InvokeNode* call_print_disass;
|
||||||
char* mnemonic_ptr = strdup(mnemonic.c_str());
|
char* mnemonic_ptr = strdup(mnemonic.c_str());
|
||||||
@ -3436,7 +3457,7 @@ private:
|
|||||||
/* generate disass */
|
/* generate disass */
|
||||||
|
|
||||||
auto mnemonic = fmt::format(
|
auto mnemonic = fmt::format(
|
||||||
"{mnemonic:10} {rd}, {uimm:#05x}({rs1})", fmt::arg("mnemonic", "c__lw"),
|
"{mnemonic:10} {rd}, {uimm:#05x}({rs1})", fmt::arg("mnemonic", "c.lw"),
|
||||||
fmt::arg("rd", name(8+rd)), fmt::arg("uimm", uimm), fmt::arg("rs1", name(8+rs1)));
|
fmt::arg("rd", name(8+rd)), fmt::arg("uimm", uimm), fmt::arg("rs1", name(8+rs1)));
|
||||||
InvokeNode* call_print_disass;
|
InvokeNode* call_print_disass;
|
||||||
char* mnemonic_ptr = strdup(mnemonic.c_str());
|
char* mnemonic_ptr = strdup(mnemonic.c_str());
|
||||||
@ -3482,7 +3503,7 @@ private:
|
|||||||
/* generate disass */
|
/* generate disass */
|
||||||
|
|
||||||
auto mnemonic = fmt::format(
|
auto mnemonic = fmt::format(
|
||||||
"{mnemonic:10} {rs2}, {uimm:#05x}({rs1})", fmt::arg("mnemonic", "c__sw"),
|
"{mnemonic:10} {rs2}, {uimm:#05x}({rs1})", fmt::arg("mnemonic", "c.sw"),
|
||||||
fmt::arg("rs2", name(8+rs2)), fmt::arg("uimm", uimm), fmt::arg("rs1", name(8+rs1)));
|
fmt::arg("rs2", name(8+rs2)), fmt::arg("uimm", uimm), fmt::arg("rs1", name(8+rs1)));
|
||||||
InvokeNode* call_print_disass;
|
InvokeNode* call_print_disass;
|
||||||
char* mnemonic_ptr = strdup(mnemonic.c_str());
|
char* mnemonic_ptr = strdup(mnemonic.c_str());
|
||||||
@ -3525,7 +3546,7 @@ private:
|
|||||||
/* generate disass */
|
/* generate disass */
|
||||||
|
|
||||||
auto mnemonic = fmt::format(
|
auto mnemonic = fmt::format(
|
||||||
"{mnemonic:10} {rs1}, {imm:#05x}", fmt::arg("mnemonic", "c__addi"),
|
"{mnemonic:10} {rs1}, {imm:#05x}", fmt::arg("mnemonic", "c.addi"),
|
||||||
fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm));
|
fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm));
|
||||||
InvokeNode* call_print_disass;
|
InvokeNode* call_print_disass;
|
||||||
char* mnemonic_ptr = strdup(mnemonic.c_str());
|
char* mnemonic_ptr = strdup(mnemonic.c_str());
|
||||||
@ -3572,8 +3593,8 @@ private:
|
|||||||
if(this->disass_enabled){
|
if(this->disass_enabled){
|
||||||
/* generate disass */
|
/* generate disass */
|
||||||
|
|
||||||
//This disass is not yet implemented
|
//No disass specified, using instruction name
|
||||||
std::string mnemonic = "c__nop";
|
std::string mnemonic = "c.nop";
|
||||||
InvokeNode* call_print_disass;
|
InvokeNode* call_print_disass;
|
||||||
char* mnemonic_ptr = strdup(mnemonic.c_str());
|
char* mnemonic_ptr = strdup(mnemonic.c_str());
|
||||||
jh.disass_collection.push_back(mnemonic_ptr);
|
jh.disass_collection.push_back(mnemonic_ptr);
|
||||||
@ -3609,7 +3630,7 @@ private:
|
|||||||
/* generate disass */
|
/* generate disass */
|
||||||
|
|
||||||
auto mnemonic = fmt::format(
|
auto mnemonic = fmt::format(
|
||||||
"{mnemonic:10} {imm:#05x}", fmt::arg("mnemonic", "c__jal"),
|
"{mnemonic:10} {imm:#05x}", fmt::arg("mnemonic", "c.jal"),
|
||||||
fmt::arg("imm", imm));
|
fmt::arg("imm", imm));
|
||||||
InvokeNode* call_print_disass;
|
InvokeNode* call_print_disass;
|
||||||
char* mnemonic_ptr = strdup(mnemonic.c_str());
|
char* mnemonic_ptr = strdup(mnemonic.c_str());
|
||||||
@ -3653,7 +3674,7 @@ private:
|
|||||||
/* generate disass */
|
/* generate disass */
|
||||||
|
|
||||||
auto mnemonic = fmt::format(
|
auto mnemonic = fmt::format(
|
||||||
"{mnemonic:10} {rd}, {imm:#05x}", fmt::arg("mnemonic", "c__li"),
|
"{mnemonic:10} {rd}, {imm:#05x}", fmt::arg("mnemonic", "c.li"),
|
||||||
fmt::arg("rd", name(rd)), fmt::arg("imm", imm));
|
fmt::arg("rd", name(rd)), fmt::arg("imm", imm));
|
||||||
InvokeNode* call_print_disass;
|
InvokeNode* call_print_disass;
|
||||||
char* mnemonic_ptr = strdup(mnemonic.c_str());
|
char* mnemonic_ptr = strdup(mnemonic.c_str());
|
||||||
@ -3700,7 +3721,7 @@ private:
|
|||||||
/* generate disass */
|
/* generate disass */
|
||||||
|
|
||||||
auto mnemonic = fmt::format(
|
auto mnemonic = fmt::format(
|
||||||
"{mnemonic:10} {rd}, {imm:#05x}", fmt::arg("mnemonic", "c__lui"),
|
"{mnemonic:10} {rd}, {imm:#05x}", fmt::arg("mnemonic", "c.lui"),
|
||||||
fmt::arg("rd", name(rd)), fmt::arg("imm", imm));
|
fmt::arg("rd", name(rd)), fmt::arg("imm", imm));
|
||||||
InvokeNode* call_print_disass;
|
InvokeNode* call_print_disass;
|
||||||
char* mnemonic_ptr = strdup(mnemonic.c_str());
|
char* mnemonic_ptr = strdup(mnemonic.c_str());
|
||||||
@ -3744,7 +3765,7 @@ private:
|
|||||||
/* generate disass */
|
/* generate disass */
|
||||||
|
|
||||||
auto mnemonic = fmt::format(
|
auto mnemonic = fmt::format(
|
||||||
"{mnemonic:10} {nzimm:#05x}", fmt::arg("mnemonic", "c__addi16sp"),
|
"{mnemonic:10} {nzimm:#05x}", fmt::arg("mnemonic", "c.addi16sp"),
|
||||||
fmt::arg("nzimm", nzimm));
|
fmt::arg("nzimm", nzimm));
|
||||||
InvokeNode* call_print_disass;
|
InvokeNode* call_print_disass;
|
||||||
char* mnemonic_ptr = strdup(mnemonic.c_str());
|
char* mnemonic_ptr = strdup(mnemonic.c_str());
|
||||||
@ -3789,8 +3810,8 @@ private:
|
|||||||
if(this->disass_enabled){
|
if(this->disass_enabled){
|
||||||
/* generate disass */
|
/* generate disass */
|
||||||
|
|
||||||
//This disass is not yet implemented
|
//No disass specified, using instruction name
|
||||||
std::string mnemonic = "__reserved_clui";
|
std::string mnemonic = ".reserved_clui";
|
||||||
InvokeNode* call_print_disass;
|
InvokeNode* call_print_disass;
|
||||||
char* mnemonic_ptr = strdup(mnemonic.c_str());
|
char* mnemonic_ptr = strdup(mnemonic.c_str());
|
||||||
jh.disass_collection.push_back(mnemonic_ptr);
|
jh.disass_collection.push_back(mnemonic_ptr);
|
||||||
@ -3828,7 +3849,7 @@ private:
|
|||||||
/* generate disass */
|
/* generate disass */
|
||||||
|
|
||||||
auto mnemonic = fmt::format(
|
auto mnemonic = fmt::format(
|
||||||
"{mnemonic:10} {rs1}, {shamt}", fmt::arg("mnemonic", "c__srli"),
|
"{mnemonic:10} {rs1}, {shamt}", fmt::arg("mnemonic", "c.srli"),
|
||||||
fmt::arg("rs1", name(8+rs1)), fmt::arg("shamt", shamt));
|
fmt::arg("rs1", name(8+rs1)), fmt::arg("shamt", shamt));
|
||||||
InvokeNode* call_print_disass;
|
InvokeNode* call_print_disass;
|
||||||
char* mnemonic_ptr = strdup(mnemonic.c_str());
|
char* mnemonic_ptr = strdup(mnemonic.c_str());
|
||||||
@ -3869,7 +3890,7 @@ private:
|
|||||||
/* generate disass */
|
/* generate disass */
|
||||||
|
|
||||||
auto mnemonic = fmt::format(
|
auto mnemonic = fmt::format(
|
||||||
"{mnemonic:10} {rs1}, {shamt}", fmt::arg("mnemonic", "c__srai"),
|
"{mnemonic:10} {rs1}, {shamt}", fmt::arg("mnemonic", "c.srai"),
|
||||||
fmt::arg("rs1", name(8+rs1)), fmt::arg("shamt", shamt));
|
fmt::arg("rs1", name(8+rs1)), fmt::arg("shamt", shamt));
|
||||||
InvokeNode* call_print_disass;
|
InvokeNode* call_print_disass;
|
||||||
char* mnemonic_ptr = strdup(mnemonic.c_str());
|
char* mnemonic_ptr = strdup(mnemonic.c_str());
|
||||||
@ -3923,7 +3944,7 @@ private:
|
|||||||
/* generate disass */
|
/* generate disass */
|
||||||
|
|
||||||
auto mnemonic = fmt::format(
|
auto mnemonic = fmt::format(
|
||||||
"{mnemonic:10} {rs1}, {imm:#05x}", fmt::arg("mnemonic", "c__andi"),
|
"{mnemonic:10} {rs1}, {imm:#05x}", fmt::arg("mnemonic", "c.andi"),
|
||||||
fmt::arg("rs1", name(8+rs1)), fmt::arg("imm", imm));
|
fmt::arg("rs1", name(8+rs1)), fmt::arg("imm", imm));
|
||||||
InvokeNode* call_print_disass;
|
InvokeNode* call_print_disass;
|
||||||
char* mnemonic_ptr = strdup(mnemonic.c_str());
|
char* mnemonic_ptr = strdup(mnemonic.c_str());
|
||||||
@ -3965,7 +3986,7 @@ private:
|
|||||||
/* generate disass */
|
/* generate disass */
|
||||||
|
|
||||||
auto mnemonic = fmt::format(
|
auto mnemonic = fmt::format(
|
||||||
"{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "c__sub"),
|
"{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "c.sub"),
|
||||||
fmt::arg("rd", name(8+rd)), fmt::arg("rs2", name(8+rs2)));
|
fmt::arg("rd", name(8+rd)), fmt::arg("rs2", name(8+rs2)));
|
||||||
InvokeNode* call_print_disass;
|
InvokeNode* call_print_disass;
|
||||||
char* mnemonic_ptr = strdup(mnemonic.c_str());
|
char* mnemonic_ptr = strdup(mnemonic.c_str());
|
||||||
@ -4007,7 +4028,7 @@ private:
|
|||||||
/* generate disass */
|
/* generate disass */
|
||||||
|
|
||||||
auto mnemonic = fmt::format(
|
auto mnemonic = fmt::format(
|
||||||
"{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "c__xor"),
|
"{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "c.xor"),
|
||||||
fmt::arg("rd", name(8+rd)), fmt::arg("rs2", name(8+rs2)));
|
fmt::arg("rd", name(8+rd)), fmt::arg("rs2", name(8+rs2)));
|
||||||
InvokeNode* call_print_disass;
|
InvokeNode* call_print_disass;
|
||||||
char* mnemonic_ptr = strdup(mnemonic.c_str());
|
char* mnemonic_ptr = strdup(mnemonic.c_str());
|
||||||
@ -4048,7 +4069,7 @@ private:
|
|||||||
/* generate disass */
|
/* generate disass */
|
||||||
|
|
||||||
auto mnemonic = fmt::format(
|
auto mnemonic = fmt::format(
|
||||||
"{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "c__or"),
|
"{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "c.or"),
|
||||||
fmt::arg("rd", name(8+rd)), fmt::arg("rs2", name(8+rs2)));
|
fmt::arg("rd", name(8+rd)), fmt::arg("rs2", name(8+rs2)));
|
||||||
InvokeNode* call_print_disass;
|
InvokeNode* call_print_disass;
|
||||||
char* mnemonic_ptr = strdup(mnemonic.c_str());
|
char* mnemonic_ptr = strdup(mnemonic.c_str());
|
||||||
@ -4089,7 +4110,7 @@ private:
|
|||||||
/* generate disass */
|
/* generate disass */
|
||||||
|
|
||||||
auto mnemonic = fmt::format(
|
auto mnemonic = fmt::format(
|
||||||
"{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "c__and"),
|
"{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "c.and"),
|
||||||
fmt::arg("rd", name(8+rd)), fmt::arg("rs2", name(8+rs2)));
|
fmt::arg("rd", name(8+rd)), fmt::arg("rs2", name(8+rs2)));
|
||||||
InvokeNode* call_print_disass;
|
InvokeNode* call_print_disass;
|
||||||
char* mnemonic_ptr = strdup(mnemonic.c_str());
|
char* mnemonic_ptr = strdup(mnemonic.c_str());
|
||||||
@ -4129,7 +4150,7 @@ private:
|
|||||||
/* generate disass */
|
/* generate disass */
|
||||||
|
|
||||||
auto mnemonic = fmt::format(
|
auto mnemonic = fmt::format(
|
||||||
"{mnemonic:10} {imm:#05x}", fmt::arg("mnemonic", "c__j"),
|
"{mnemonic:10} {imm:#05x}", fmt::arg("mnemonic", "c.j"),
|
||||||
fmt::arg("imm", imm));
|
fmt::arg("imm", imm));
|
||||||
InvokeNode* call_print_disass;
|
InvokeNode* call_print_disass;
|
||||||
char* mnemonic_ptr = strdup(mnemonic.c_str());
|
char* mnemonic_ptr = strdup(mnemonic.c_str());
|
||||||
@ -4171,7 +4192,7 @@ private:
|
|||||||
/* generate disass */
|
/* generate disass */
|
||||||
|
|
||||||
auto mnemonic = fmt::format(
|
auto mnemonic = fmt::format(
|
||||||
"{mnemonic:10} {rs1}, {imm:#05x}", fmt::arg("mnemonic", "c__beqz"),
|
"{mnemonic:10} {rs1}, {imm:#05x}", fmt::arg("mnemonic", "c.beqz"),
|
||||||
fmt::arg("rs1", name(8+rs1)), fmt::arg("imm", imm));
|
fmt::arg("rs1", name(8+rs1)), fmt::arg("imm", imm));
|
||||||
InvokeNode* call_print_disass;
|
InvokeNode* call_print_disass;
|
||||||
char* mnemonic_ptr = strdup(mnemonic.c_str());
|
char* mnemonic_ptr = strdup(mnemonic.c_str());
|
||||||
@ -4194,6 +4215,7 @@ private:
|
|||||||
cc.comment("//behavior:");
|
cc.comment("//behavior:");
|
||||||
/*generate behavior*/
|
/*generate behavior*/
|
||||||
mov(jh.cc, get_ptr_for(jh, traits::LAST_BRANCH), static_cast<int>(NO_JUMP));
|
mov(jh.cc, get_ptr_for(jh, traits::LAST_BRANCH), static_cast<int>(NO_JUMP));
|
||||||
|
{
|
||||||
auto label_merge = cc.newLabel();
|
auto label_merge = cc.newLabel();
|
||||||
cmp(cc, gen_operation(cc, eq, load_reg_from_mem(jh, traits::X0 + rs1+8), 0)
|
cmp(cc, gen_operation(cc, eq, load_reg_from_mem(jh, traits::X0 + rs1+8), 0)
|
||||||
,0);
|
,0);
|
||||||
@ -4204,6 +4226,7 @@ private:
|
|||||||
mov(cc, get_ptr_for(jh, traits::LAST_BRANCH), static_cast<int>(KNOWN_JUMP));
|
mov(cc, get_ptr_for(jh, traits::LAST_BRANCH), static_cast<int>(KNOWN_JUMP));
|
||||||
}
|
}
|
||||||
cc.bind(label_merge);
|
cc.bind(label_merge);
|
||||||
|
}
|
||||||
auto returnValue = BRANCH;
|
auto returnValue = BRANCH;
|
||||||
|
|
||||||
gen_sync(jh, POST_SYNC, 75);
|
gen_sync(jh, POST_SYNC, 75);
|
||||||
@ -4220,7 +4243,7 @@ private:
|
|||||||
/* generate disass */
|
/* generate disass */
|
||||||
|
|
||||||
auto mnemonic = fmt::format(
|
auto mnemonic = fmt::format(
|
||||||
"{mnemonic:10} {rs1}, {imm:#05x}", fmt::arg("mnemonic", "c__bnez"),
|
"{mnemonic:10} {rs1}, {imm:#05x}", fmt::arg("mnemonic", "c.bnez"),
|
||||||
fmt::arg("rs1", name(8+rs1)), fmt::arg("imm", imm));
|
fmt::arg("rs1", name(8+rs1)), fmt::arg("imm", imm));
|
||||||
InvokeNode* call_print_disass;
|
InvokeNode* call_print_disass;
|
||||||
char* mnemonic_ptr = strdup(mnemonic.c_str());
|
char* mnemonic_ptr = strdup(mnemonic.c_str());
|
||||||
@ -4243,6 +4266,7 @@ private:
|
|||||||
cc.comment("//behavior:");
|
cc.comment("//behavior:");
|
||||||
/*generate behavior*/
|
/*generate behavior*/
|
||||||
mov(jh.cc, get_ptr_for(jh, traits::LAST_BRANCH), static_cast<int>(NO_JUMP));
|
mov(jh.cc, get_ptr_for(jh, traits::LAST_BRANCH), static_cast<int>(NO_JUMP));
|
||||||
|
{
|
||||||
auto label_merge = cc.newLabel();
|
auto label_merge = cc.newLabel();
|
||||||
cmp(cc, gen_operation(cc, ne, load_reg_from_mem(jh, traits::X0 + rs1+8), 0)
|
cmp(cc, gen_operation(cc, ne, load_reg_from_mem(jh, traits::X0 + rs1+8), 0)
|
||||||
,0);
|
,0);
|
||||||
@ -4253,6 +4277,7 @@ private:
|
|||||||
mov(cc, get_ptr_for(jh, traits::LAST_BRANCH), static_cast<int>(KNOWN_JUMP));
|
mov(cc, get_ptr_for(jh, traits::LAST_BRANCH), static_cast<int>(KNOWN_JUMP));
|
||||||
}
|
}
|
||||||
cc.bind(label_merge);
|
cc.bind(label_merge);
|
||||||
|
}
|
||||||
auto returnValue = BRANCH;
|
auto returnValue = BRANCH;
|
||||||
|
|
||||||
gen_sync(jh, POST_SYNC, 76);
|
gen_sync(jh, POST_SYNC, 76);
|
||||||
@ -4269,7 +4294,7 @@ private:
|
|||||||
/* generate disass */
|
/* generate disass */
|
||||||
|
|
||||||
auto mnemonic = fmt::format(
|
auto mnemonic = fmt::format(
|
||||||
"{mnemonic:10} {rs1}, {nzuimm}", fmt::arg("mnemonic", "c__slli"),
|
"{mnemonic:10} {rs1}, {nzuimm}", fmt::arg("mnemonic", "c.slli"),
|
||||||
fmt::arg("rs1", name(rs1)), fmt::arg("nzuimm", nzuimm));
|
fmt::arg("rs1", name(rs1)), fmt::arg("nzuimm", nzuimm));
|
||||||
InvokeNode* call_print_disass;
|
InvokeNode* call_print_disass;
|
||||||
char* mnemonic_ptr = strdup(mnemonic.c_str());
|
char* mnemonic_ptr = strdup(mnemonic.c_str());
|
||||||
@ -4317,7 +4342,7 @@ private:
|
|||||||
/* generate disass */
|
/* generate disass */
|
||||||
|
|
||||||
auto mnemonic = fmt::format(
|
auto mnemonic = fmt::format(
|
||||||
"{mnemonic:10} {rd}, sp, {uimm:#05x}", fmt::arg("mnemonic", "c__lwsp"),
|
"{mnemonic:10} {rd}, sp, {uimm:#05x}", fmt::arg("mnemonic", "c.lwsp"),
|
||||||
fmt::arg("rd", name(rd)), fmt::arg("uimm", uimm));
|
fmt::arg("rd", name(rd)), fmt::arg("uimm", uimm));
|
||||||
InvokeNode* call_print_disass;
|
InvokeNode* call_print_disass;
|
||||||
char* mnemonic_ptr = strdup(mnemonic.c_str());
|
char* mnemonic_ptr = strdup(mnemonic.c_str());
|
||||||
@ -4367,7 +4392,7 @@ private:
|
|||||||
/* generate disass */
|
/* generate disass */
|
||||||
|
|
||||||
auto mnemonic = fmt::format(
|
auto mnemonic = fmt::format(
|
||||||
"{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "c__mv"),
|
"{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "c.mv"),
|
||||||
fmt::arg("rd", name(rd)), fmt::arg("rs2", name(rs2)));
|
fmt::arg("rd", name(rd)), fmt::arg("rs2", name(rs2)));
|
||||||
InvokeNode* call_print_disass;
|
InvokeNode* call_print_disass;
|
||||||
char* mnemonic_ptr = strdup(mnemonic.c_str());
|
char* mnemonic_ptr = strdup(mnemonic.c_str());
|
||||||
@ -4413,7 +4438,7 @@ private:
|
|||||||
/* generate disass */
|
/* generate disass */
|
||||||
|
|
||||||
auto mnemonic = fmt::format(
|
auto mnemonic = fmt::format(
|
||||||
"{mnemonic:10} {rs1}", fmt::arg("mnemonic", "c__jr"),
|
"{mnemonic:10} {rs1}", fmt::arg("mnemonic", "c.jr"),
|
||||||
fmt::arg("rs1", name(rs1)));
|
fmt::arg("rs1", name(rs1)));
|
||||||
InvokeNode* call_print_disass;
|
InvokeNode* call_print_disass;
|
||||||
char* mnemonic_ptr = strdup(mnemonic.c_str());
|
char* mnemonic_ptr = strdup(mnemonic.c_str());
|
||||||
@ -4459,8 +4484,8 @@ private:
|
|||||||
if(this->disass_enabled){
|
if(this->disass_enabled){
|
||||||
/* generate disass */
|
/* generate disass */
|
||||||
|
|
||||||
//This disass is not yet implemented
|
//No disass specified, using instruction name
|
||||||
std::string mnemonic = "__reserved_cmv";
|
std::string mnemonic = ".reserved_cmv";
|
||||||
InvokeNode* call_print_disass;
|
InvokeNode* call_print_disass;
|
||||||
char* mnemonic_ptr = strdup(mnemonic.c_str());
|
char* mnemonic_ptr = strdup(mnemonic.c_str());
|
||||||
jh.disass_collection.push_back(mnemonic_ptr);
|
jh.disass_collection.push_back(mnemonic_ptr);
|
||||||
@ -4498,7 +4523,7 @@ private:
|
|||||||
/* generate disass */
|
/* generate disass */
|
||||||
|
|
||||||
auto mnemonic = fmt::format(
|
auto mnemonic = fmt::format(
|
||||||
"{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "c__add"),
|
"{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "c.add"),
|
||||||
fmt::arg("rd", name(rd)), fmt::arg("rs2", name(rs2)));
|
fmt::arg("rd", name(rd)), fmt::arg("rs2", name(rs2)));
|
||||||
InvokeNode* call_print_disass;
|
InvokeNode* call_print_disass;
|
||||||
char* mnemonic_ptr = strdup(mnemonic.c_str());
|
char* mnemonic_ptr = strdup(mnemonic.c_str());
|
||||||
@ -4546,7 +4571,7 @@ private:
|
|||||||
/* generate disass */
|
/* generate disass */
|
||||||
|
|
||||||
auto mnemonic = fmt::format(
|
auto mnemonic = fmt::format(
|
||||||
"{mnemonic:10} {rs1}", fmt::arg("mnemonic", "c__jalr"),
|
"{mnemonic:10} {rs1}", fmt::arg("mnemonic", "c.jalr"),
|
||||||
fmt::arg("rs1", name(rs1)));
|
fmt::arg("rs1", name(rs1)));
|
||||||
InvokeNode* call_print_disass;
|
InvokeNode* call_print_disass;
|
||||||
char* mnemonic_ptr = strdup(mnemonic.c_str());
|
char* mnemonic_ptr = strdup(mnemonic.c_str());
|
||||||
@ -4595,8 +4620,8 @@ private:
|
|||||||
if(this->disass_enabled){
|
if(this->disass_enabled){
|
||||||
/* generate disass */
|
/* generate disass */
|
||||||
|
|
||||||
//This disass is not yet implemented
|
//No disass specified, using instruction name
|
||||||
std::string mnemonic = "c__ebreak";
|
std::string mnemonic = "c.ebreak";
|
||||||
InvokeNode* call_print_disass;
|
InvokeNode* call_print_disass;
|
||||||
char* mnemonic_ptr = strdup(mnemonic.c_str());
|
char* mnemonic_ptr = strdup(mnemonic.c_str());
|
||||||
jh.disass_collection.push_back(mnemonic_ptr);
|
jh.disass_collection.push_back(mnemonic_ptr);
|
||||||
@ -4634,7 +4659,7 @@ private:
|
|||||||
/* generate disass */
|
/* generate disass */
|
||||||
|
|
||||||
auto mnemonic = fmt::format(
|
auto mnemonic = fmt::format(
|
||||||
"{mnemonic:10} {rs2}, {uimm:#05x}(sp)", fmt::arg("mnemonic", "c__swsp"),
|
"{mnemonic:10} {rs2}, {uimm:#05x}(sp)", fmt::arg("mnemonic", "c.swsp"),
|
||||||
fmt::arg("rs2", name(rs2)), fmt::arg("uimm", uimm));
|
fmt::arg("rs2", name(rs2)), fmt::arg("uimm", uimm));
|
||||||
InvokeNode* call_print_disass;
|
InvokeNode* call_print_disass;
|
||||||
char* mnemonic_ptr = strdup(mnemonic.c_str());
|
char* mnemonic_ptr = strdup(mnemonic.c_str());
|
||||||
@ -4679,7 +4704,7 @@ private:
|
|||||||
if(this->disass_enabled){
|
if(this->disass_enabled){
|
||||||
/* generate disass */
|
/* generate disass */
|
||||||
|
|
||||||
//This disass is not yet implemented
|
//No disass specified, using instruction name
|
||||||
std::string mnemonic = "dii";
|
std::string mnemonic = "dii";
|
||||||
InvokeNode* call_print_disass;
|
InvokeNode* call_print_disass;
|
||||||
char* mnemonic_ptr = strdup(mnemonic.c_str());
|
char* mnemonic_ptr = strdup(mnemonic.c_str());
|
||||||
@ -4735,7 +4760,7 @@ private:
|
|||||||
gen_raise(jh, 0, 2);
|
gen_raise(jh, 0, 2);
|
||||||
gen_sync(jh, POST_SYNC, instr_descr.size());
|
gen_sync(jh, POST_SYNC, instr_descr.size());
|
||||||
gen_instr_epilogue(jh);
|
gen_instr_epilogue(jh);
|
||||||
return BRANCH;
|
return ILLEGAL_INSTR;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -4764,9 +4789,9 @@ continuation_e vm_impl<ARCH>::gen_single_inst_behavior(virt_addr_t &pc, unsigned
|
|||||||
paddr = this->core.virt2phys(pc);
|
paddr = this->core.virt2phys(pc);
|
||||||
auto res = this->core.read(paddr, 4, data);
|
auto res = this->core.read(paddr, 4, data);
|
||||||
if (res != iss::Ok)
|
if (res != iss::Ok)
|
||||||
throw trap_access(TRAP_ID, pc.val);
|
return ILLEGAL_FETCH;
|
||||||
if (instr == 0x0000006f || (instr&0xffff)==0xa001)
|
if (instr == 0x0000006f || (instr&0xffff)==0xa001)
|
||||||
throw simulation_stopped(0); // 'J 0' or 'C.J 0'
|
return JUMP_TO_SELF;
|
||||||
++inst_cnt;
|
++inst_cnt;
|
||||||
uint32_t inst_index = instr_decoder.decode_instr(instr);
|
uint32_t inst_index = instr_decoder.decode_instr(instr);
|
||||||
compile_func f = nullptr;
|
compile_func f = nullptr;
|
||||||
@ -4797,6 +4822,7 @@ void vm_impl<ARCH>::gen_instr_epilogue(jit_holder& jh) {
|
|||||||
cmp(cc, current_trap_state, 0);
|
cmp(cc, current_trap_state, 0);
|
||||||
cc.jne(jh.trap_entry);
|
cc.jne(jh.trap_entry);
|
||||||
cc.inc(get_ptr_for(jh, traits::ICOUNT));
|
cc.inc(get_ptr_for(jh, traits::ICOUNT));
|
||||||
|
cc.inc(get_ptr_for(jh, traits::CYCLE));
|
||||||
}
|
}
|
||||||
template <typename ARCH>
|
template <typename ARCH>
|
||||||
void vm_impl<ARCH>::gen_block_prologue(jit_holder& jh){
|
void vm_impl<ARCH>::gen_block_prologue(jit_holder& jh){
|
||||||
@ -4842,6 +4868,7 @@ inline void vm_impl<ARCH>::gen_raise(jit_holder& jh, uint16_t trap_id, uint16_t
|
|||||||
auto tmp1 = get_reg_for(cc, traits::TRAP_STATE);
|
auto tmp1 = get_reg_for(cc, traits::TRAP_STATE);
|
||||||
mov(cc, tmp1, 0x80ULL << 24 | (cause << 16) | trap_id);
|
mov(cc, tmp1, 0x80ULL << 24 | (cause << 16) | trap_id);
|
||||||
mov(cc, get_ptr_for(jh, traits::TRAP_STATE), tmp1);
|
mov(cc, get_ptr_for(jh, traits::TRAP_STATE), tmp1);
|
||||||
|
cc.jmp(jh.trap_entry);
|
||||||
}
|
}
|
||||||
template <typename ARCH>
|
template <typename ARCH>
|
||||||
template <typename T, typename>
|
template <typename T, typename>
|
||||||
@ -4850,8 +4877,8 @@ void vm_impl<ARCH>::gen_set_tval(jit_holder& jh, T new_tval) {
|
|||||||
}
|
}
|
||||||
template <typename ARCH>
|
template <typename ARCH>
|
||||||
void vm_impl<ARCH>::gen_set_tval(jit_holder& jh, x86_reg_t _new_tval) {
|
void vm_impl<ARCH>::gen_set_tval(jit_holder& jh, x86_reg_t _new_tval) {
|
||||||
if(std::holds_alternative<x86::Gp>(_new_tval)) {
|
if(nonstd::holds_alternative<x86::Gp>(_new_tval)) {
|
||||||
x86::Gp new_tval = std::get<x86::Gp>(_new_tval);
|
x86::Gp new_tval = nonstd::get<x86::Gp>(_new_tval);
|
||||||
if(new_tval.size() < 8)
|
if(new_tval.size() < 8)
|
||||||
new_tval = gen_ext_Gp(jh.cc, new_tval, 64, false);
|
new_tval = gen_ext_Gp(jh.cc, new_tval, 64, false);
|
||||||
mov(jh.cc, jh.globals[TVAL], new_tval);
|
mov(jh.cc, jh.globals[TVAL], new_tval);
|
||||||
|
@ -128,7 +128,6 @@ uint32_t fcmp_s(uint32_t v1, uint32_t v2, uint32_t op) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
uint32_t fcvt_s(uint32_t v1, uint32_t op, uint8_t mode) {
|
uint32_t fcvt_s(uint32_t v1, uint32_t op, uint8_t mode) {
|
||||||
|
|
||||||
float32_t v1f{v1};
|
float32_t v1f{v1};
|
||||||
softfloat_exceptionFlags = 0;
|
softfloat_exceptionFlags = 0;
|
||||||
float32_t r;
|
float32_t r;
|
||||||
@ -204,8 +203,8 @@ uint32_t fclass_s(uint32_t v1) {
|
|||||||
uA.f = a;
|
uA.f = a;
|
||||||
uiA = uA.ui;
|
uiA = uA.ui;
|
||||||
|
|
||||||
uint_fast16_t infOrNaN = expF32UI(uiA) == 0xFF;
|
bool infOrNaN = expF32UI(uiA) == 0xFF;
|
||||||
uint_fast16_t subnormalOrZero = expF32UI(uiA) == 0;
|
bool subnormalOrZero = expF32UI(uiA) == 0;
|
||||||
bool sign = signF32UI(uiA);
|
bool sign = signF32UI(uiA);
|
||||||
bool fracZero = fracF32UI(uiA) == 0;
|
bool fracZero = fracF32UI(uiA) == 0;
|
||||||
bool isNaN = isNaNF32UI(uiA);
|
bool isNaN = isNaNF32UI(uiA);
|
||||||
@ -218,9 +217,13 @@ uint32_t fclass_s(uint32_t v1) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
uint32_t fconv_d2f(uint64_t v1, uint8_t mode) {
|
uint32_t fconv_d2f(uint64_t v1, uint8_t mode) {
|
||||||
|
bool isNan = isNaNF64UI(v1);
|
||||||
|
bool isSNaN = softfloat_isSigNaNF64UI(v1);
|
||||||
softfloat_roundingMode = rmm_map.at(mode);
|
softfloat_roundingMode = rmm_map.at(mode);
|
||||||
bool nan = (v1 & defaultNaNF64UI) == defaultNaNF64UI;
|
softfloat_exceptionFlags = 0;
|
||||||
if(nan) {
|
if(isNan) {
|
||||||
|
if(isSNaN)
|
||||||
|
softfloat_raiseFlags(softfloat_flag_invalid);
|
||||||
return defaultNaNF32UI;
|
return defaultNaNF32UI;
|
||||||
} else {
|
} else {
|
||||||
float32_t res = f64_to_f32(float64_t{v1});
|
float32_t res = f64_to_f32(float64_t{v1});
|
||||||
@ -229,11 +232,11 @@ uint32_t fconv_d2f(uint64_t v1, uint8_t mode) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
uint64_t fconv_f2d(uint32_t v1, uint8_t mode) {
|
uint64_t fconv_f2d(uint32_t v1, uint8_t mode) {
|
||||||
bool nan = (v1 & defaultNaNF32UI) == defaultNaNF32UI;
|
bool infOrNaN = expF32UI(v1) == 0xFF;
|
||||||
if(nan) {
|
bool subnormalOrZero = expF32UI(v1) == 0;
|
||||||
|
if(infOrNaN || subnormalOrZero) {
|
||||||
return defaultNaNF64UI;
|
return defaultNaNF64UI;
|
||||||
} else {
|
} else {
|
||||||
softfloat_roundingMode = rmm_map.at(mode);
|
|
||||||
float64_t res = f32_to_f64(float32_t{v1});
|
float64_t res = f32_to_f64(float32_t{v1});
|
||||||
return res.v;
|
return res.v;
|
||||||
}
|
}
|
||||||
@ -313,22 +316,23 @@ uint64_t fcmp_d(uint64_t v1, uint64_t v2, uint32_t op) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
uint64_t fcvt_d(uint64_t v1, uint32_t op, uint8_t mode) {
|
uint64_t fcvt_d(uint64_t v1, uint32_t op, uint8_t mode) {
|
||||||
|
|
||||||
float64_t v1f{v1};
|
float64_t v1f{v1};
|
||||||
softfloat_exceptionFlags = 0;
|
softfloat_exceptionFlags = 0;
|
||||||
float64_t r;
|
float64_t r;
|
||||||
switch(op) {
|
switch(op) {
|
||||||
case 0: { // l->d, fp to int32
|
case 0: { // l from d
|
||||||
int64_t res = f64_to_i64(v1f, rmm_map.at(mode), true);
|
int64_t res = f64_to_i64(v1f, rmm_map.at(mode), true);
|
||||||
return (uint64_t)res;
|
return (uint64_t)res;
|
||||||
}
|
}
|
||||||
case 1: { // lu->s
|
case 1: { // lu from d
|
||||||
uint64_t res = f64_to_ui64(v1f, rmm_map.at(mode), true);
|
uint64_t res = f64_to_ui64(v1f, rmm_map.at(mode), true);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
case 2: // s->l
|
case 2: // d from l
|
||||||
r = i64_to_f64(v1);
|
r = i64_to_f64(v1);
|
||||||
return r.v;
|
return r.v;
|
||||||
case 3: // s->lu
|
case 3: // d from lu
|
||||||
r = ui64_to_f64(v1);
|
r = ui64_to_f64(v1);
|
||||||
return r.v;
|
return r.v;
|
||||||
}
|
}
|
||||||
@ -336,12 +340,24 @@ uint64_t fcvt_d(uint64_t v1, uint32_t op, uint8_t mode) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
uint64_t fmadd_d(uint64_t v1, uint64_t v2, uint64_t v3, uint32_t op, uint8_t mode) {
|
uint64_t fmadd_d(uint64_t v1, uint64_t v2, uint64_t v3, uint32_t op, uint8_t mode) {
|
||||||
// op should be {softfloat_mulAdd_subProd(2), softfloat_mulAdd_subC(1)}
|
uint64_t F64_SIGN = 1ULL << 63;
|
||||||
|
switch(op) {
|
||||||
|
case 0: // FMADD_D
|
||||||
|
break;
|
||||||
|
case 1: // FMSUB_D
|
||||||
|
v3 ^= F64_SIGN;
|
||||||
|
break;
|
||||||
|
case 2: // FNMADD_D
|
||||||
|
v1 ^= F64_SIGN;
|
||||||
|
v3 ^= F64_SIGN;
|
||||||
|
break;
|
||||||
|
case 3: // FNMSUB_D
|
||||||
|
v1 ^= F64_SIGN;
|
||||||
|
break;
|
||||||
|
}
|
||||||
softfloat_roundingMode = rmm_map.at(mode);
|
softfloat_roundingMode = rmm_map.at(mode);
|
||||||
softfloat_exceptionFlags = 0;
|
softfloat_exceptionFlags = 0;
|
||||||
float64_t res = softfloat_mulAddF64(v1, v2, v3, op & 0x1);
|
float64_t res = softfloat_mulAddF64(v1, v2, v3, 0);
|
||||||
if(op > 1)
|
|
||||||
res.v ^= 1ULL << 63;
|
|
||||||
return res.v;
|
return res.v;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -377,8 +393,8 @@ uint64_t fclass_d(uint64_t v1) {
|
|||||||
uA.f = a;
|
uA.f = a;
|
||||||
uiA = uA.ui;
|
uiA = uA.ui;
|
||||||
|
|
||||||
uint_fast16_t infOrNaN = expF64UI(uiA) == 0x7FF;
|
bool infOrNaN = expF64UI(uiA) == 0x7FF;
|
||||||
uint_fast16_t subnormalOrZero = expF64UI(uiA) == 0;
|
bool subnormalOrZero = expF64UI(uiA) == 0;
|
||||||
bool sign = signF64UI(uiA);
|
bool sign = signF64UI(uiA);
|
||||||
bool fracZero = fracF64UI(uiA) == 0;
|
bool fracZero = fracF64UI(uiA) == 0;
|
||||||
bool isNaN = isNaNF64UI(uiA);
|
bool isNaN = isNaNF64UI(uiA);
|
||||||
|
@ -96,7 +96,8 @@ 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 index<traits::reg_aliases.size()?traits::reg_aliases[index]:"illegal";}
|
inline const char *name(size_t index){return traits::reg_aliases.at(index);}
|
||||||
|
|
||||||
|
|
||||||
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;
|
||||||
|
|
||||||
@ -274,9 +275,6 @@ template <typename CODE_WORD> void debug_fn(CODE_WORD insn) {
|
|||||||
volatile CODE_WORD x = insn;
|
volatile CODE_WORD x = insn;
|
||||||
insn = 2 * x;
|
insn = 2 * x;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename ARCH> vm_impl<ARCH>::vm_impl() { this(new ARCH()); }
|
|
||||||
|
|
||||||
// according to
|
// according to
|
||||||
// https://stackoverflow.com/questions/8871204/count-number-of-1s-in-binary-representation
|
// https://stackoverflow.com/questions/8871204/count-number-of-1s-in-binary-representation
|
||||||
#ifdef __GCC__
|
#ifdef __GCC__
|
||||||
@ -332,17 +330,21 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
|
|||||||
while(!this->core.should_stop() &&
|
while(!this->core.should_stop() &&
|
||||||
!(is_icount_limit_enabled(cond) && icount >= count_limit) &&
|
!(is_icount_limit_enabled(cond) && icount >= count_limit) &&
|
||||||
!(is_fcount_limit_enabled(cond) && fetch_count >= count_limit)){
|
!(is_fcount_limit_enabled(cond) && fetch_count >= count_limit)){
|
||||||
fetch_count++;
|
if(this->debugging_enabled())
|
||||||
|
this->tgt_adapter->check_continue(*PC);
|
||||||
|
pc.val=*PC;
|
||||||
if(fetch_ins(pc, data)!=iss::Ok){
|
if(fetch_ins(pc, data)!=iss::Ok){
|
||||||
this->do_sync(POST_SYNC, std::numeric_limits<unsigned>::max());
|
if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, std::numeric_limits<unsigned>::max());
|
||||||
pc.val = super::core.enter_trap(std::numeric_limits<uint64_t>::max(), pc.val, 0);
|
process_spawn_blocks();
|
||||||
|
if(this->sync_exec && POST_SYNC) this->do_sync(PRE_SYNC, std::numeric_limits<unsigned>::max());
|
||||||
|
pc.val = super::core.enter_trap(arch::traits<ARCH>::RV_CAUSE_FETCH_ACCESS<<16, pc.val, 0);
|
||||||
} else {
|
} else {
|
||||||
if (is_jump_to_self_enabled(cond) &&
|
if (is_jump_to_self_enabled(cond) &&
|
||||||
(instr == 0x0000006f || (instr&0xffff)==0xa001)) throw simulation_stopped(0); // 'J 0' or 'C.J 0'
|
(instr == 0x0000006f || (instr&0xffff)==0xa001)) throw simulation_stopped(0); // 'J 0' or 'C.J 0'
|
||||||
uint32_t inst_index = instr_decoder.decode_instr(instr);
|
uint32_t inst_index = instr_decoder.decode_instr(instr);
|
||||||
opcode_e inst_id = arch::traits<ARCH>::opcode_e::MAX_OPCODE;;
|
opcode_e inst_id = arch::traits<ARCH>::opcode_e::MAX_OPCODE;;
|
||||||
if(inst_index <instr_descr.size())
|
if(inst_index <instr_descr.size())
|
||||||
inst_id = instr_descr.at(instr_decoder.decode_instr(instr)).op;
|
inst_id = instr_descr[inst_index].op;
|
||||||
|
|
||||||
// pre execution stuff
|
// pre execution stuff
|
||||||
this->core.reg.last_branch = 0;
|
this->core.reg.last_branch = 0;
|
||||||
@ -1457,7 +1459,9 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
|
|||||||
case arch::traits<ARCH>::opcode_e::ECALL: {
|
case arch::traits<ARCH>::opcode_e::ECALL: {
|
||||||
if(this->disass_enabled){
|
if(this->disass_enabled){
|
||||||
/* generate console output when executing the command */
|
/* generate console output when executing the command */
|
||||||
this->core.disass_output(pc.val, "ecall");
|
//No disass specified, using instruction name
|
||||||
|
std::string mnemonic = "ecall";
|
||||||
|
this->core.disass_output(pc.val, mnemonic);
|
||||||
}
|
}
|
||||||
// used registers// calculate next pc value
|
// used registers// calculate next pc value
|
||||||
*NEXT_PC = *PC + 4;
|
*NEXT_PC = *PC + 4;
|
||||||
@ -1470,7 +1474,9 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
|
|||||||
case arch::traits<ARCH>::opcode_e::EBREAK: {
|
case arch::traits<ARCH>::opcode_e::EBREAK: {
|
||||||
if(this->disass_enabled){
|
if(this->disass_enabled){
|
||||||
/* generate console output when executing the command */
|
/* generate console output when executing the command */
|
||||||
this->core.disass_output(pc.val, "ebreak");
|
//No disass specified, using instruction name
|
||||||
|
std::string mnemonic = "ebreak";
|
||||||
|
this->core.disass_output(pc.val, mnemonic);
|
||||||
}
|
}
|
||||||
// used registers// calculate next pc value
|
// used registers// calculate next pc value
|
||||||
*NEXT_PC = *PC + 4;
|
*NEXT_PC = *PC + 4;
|
||||||
@ -1483,7 +1489,9 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
|
|||||||
case arch::traits<ARCH>::opcode_e::MRET: {
|
case arch::traits<ARCH>::opcode_e::MRET: {
|
||||||
if(this->disass_enabled){
|
if(this->disass_enabled){
|
||||||
/* generate console output when executing the command */
|
/* generate console output when executing the command */
|
||||||
this->core.disass_output(pc.val, "mret");
|
//No disass specified, using instruction name
|
||||||
|
std::string mnemonic = "mret";
|
||||||
|
this->core.disass_output(pc.val, mnemonic);
|
||||||
}
|
}
|
||||||
// used registers// calculate next pc value
|
// used registers// calculate next pc value
|
||||||
*NEXT_PC = *PC + 4;
|
*NEXT_PC = *PC + 4;
|
||||||
@ -1496,7 +1504,9 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
|
|||||||
case arch::traits<ARCH>::opcode_e::WFI: {
|
case arch::traits<ARCH>::opcode_e::WFI: {
|
||||||
if(this->disass_enabled){
|
if(this->disass_enabled){
|
||||||
/* generate console output when executing the command */
|
/* generate console output when executing the command */
|
||||||
this->core.disass_output(pc.val, "wfi");
|
//No disass specified, using instruction name
|
||||||
|
std::string mnemonic = "wfi";
|
||||||
|
this->core.disass_output(pc.val, mnemonic);
|
||||||
}
|
}
|
||||||
// used registers// calculate next pc value
|
// used registers// calculate next pc value
|
||||||
*NEXT_PC = *PC + 4;
|
*NEXT_PC = *PC + 4;
|
||||||
@ -1720,7 +1730,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
|
|||||||
if(this->disass_enabled){
|
if(this->disass_enabled){
|
||||||
/* generate console output when executing the command */
|
/* generate console output when executing the command */
|
||||||
auto mnemonic = fmt::format(
|
auto mnemonic = fmt::format(
|
||||||
"{mnemonic:10} {rs1}, {rd}, {imm}", fmt::arg("mnemonic", "fence.i"),
|
"{mnemonic:10} {rs1}, {rd}, {imm}", fmt::arg("mnemonic", "fence_i"),
|
||||||
fmt::arg("rs1", name(rs1)), fmt::arg("rd", name(rd)), fmt::arg("imm", imm));
|
fmt::arg("rs1", name(rs1)), fmt::arg("rd", name(rd)), fmt::arg("imm", imm));
|
||||||
this->core.disass_output(pc.val, mnemonic);
|
this->core.disass_output(pc.val, mnemonic);
|
||||||
}
|
}
|
||||||
@ -2094,7 +2104,9 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
|
|||||||
uint8_t nzimm = ((bit_sub<2,5>(instr)) | (bit_sub<12,1>(instr) << 5));
|
uint8_t nzimm = ((bit_sub<2,5>(instr)) | (bit_sub<12,1>(instr) << 5));
|
||||||
if(this->disass_enabled){
|
if(this->disass_enabled){
|
||||||
/* generate console output when executing the command */
|
/* generate console output when executing the command */
|
||||||
this->core.disass_output(pc.val, "c.nop");
|
//No disass specified, using instruction name
|
||||||
|
std::string mnemonic = "c.nop";
|
||||||
|
this->core.disass_output(pc.val, mnemonic);
|
||||||
}
|
}
|
||||||
// used registers// calculate next pc value
|
// used registers// calculate next pc value
|
||||||
*NEXT_PC = *PC + 2;
|
*NEXT_PC = *PC + 2;
|
||||||
@ -2200,7 +2212,9 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
|
|||||||
uint8_t rd = ((bit_sub<7,5>(instr)));
|
uint8_t rd = ((bit_sub<7,5>(instr)));
|
||||||
if(this->disass_enabled){
|
if(this->disass_enabled){
|
||||||
/* generate console output when executing the command */
|
/* generate console output when executing the command */
|
||||||
this->core.disass_output(pc.val, ".reserved_clui");
|
//No disass specified, using instruction name
|
||||||
|
std::string mnemonic = ".reserved_clui";
|
||||||
|
this->core.disass_output(pc.val, mnemonic);
|
||||||
}
|
}
|
||||||
// used registers// calculate next pc value
|
// used registers// calculate next pc value
|
||||||
*NEXT_PC = *PC + 2;
|
*NEXT_PC = *PC + 2;
|
||||||
@ -2519,7 +2533,9 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
|
|||||||
case arch::traits<ARCH>::opcode_e::__reserved_cmv: {
|
case arch::traits<ARCH>::opcode_e::__reserved_cmv: {
|
||||||
if(this->disass_enabled){
|
if(this->disass_enabled){
|
||||||
/* generate console output when executing the command */
|
/* generate console output when executing the command */
|
||||||
this->core.disass_output(pc.val, ".reserved_cmv");
|
//No disass specified, using instruction name
|
||||||
|
std::string mnemonic = ".reserved_cmv";
|
||||||
|
this->core.disass_output(pc.val, mnemonic);
|
||||||
}
|
}
|
||||||
// used registers// calculate next pc value
|
// used registers// calculate next pc value
|
||||||
*NEXT_PC = *PC + 2;
|
*NEXT_PC = *PC + 2;
|
||||||
@ -2585,7 +2601,9 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
|
|||||||
case arch::traits<ARCH>::opcode_e::C__EBREAK: {
|
case arch::traits<ARCH>::opcode_e::C__EBREAK: {
|
||||||
if(this->disass_enabled){
|
if(this->disass_enabled){
|
||||||
/* generate console output when executing the command */
|
/* generate console output when executing the command */
|
||||||
this->core.disass_output(pc.val, "c.ebreak");
|
//No disass specified, using instruction name
|
||||||
|
std::string mnemonic = "c.ebreak";
|
||||||
|
this->core.disass_output(pc.val, mnemonic);
|
||||||
}
|
}
|
||||||
// used registers// calculate next pc value
|
// used registers// calculate next pc value
|
||||||
*NEXT_PC = *PC + 2;
|
*NEXT_PC = *PC + 2;
|
||||||
@ -2624,7 +2642,9 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
|
|||||||
case arch::traits<ARCH>::opcode_e::DII: {
|
case arch::traits<ARCH>::opcode_e::DII: {
|
||||||
if(this->disass_enabled){
|
if(this->disass_enabled){
|
||||||
/* generate console output when executing the command */
|
/* generate console output when executing the command */
|
||||||
this->core.disass_output(pc.val, "dii");
|
//No disass specified, using instruction name
|
||||||
|
std::string mnemonic = "dii";
|
||||||
|
this->core.disass_output(pc.val, mnemonic);
|
||||||
}
|
}
|
||||||
// used registers// calculate next pc value
|
// used registers// calculate next pc value
|
||||||
*NEXT_PC = *PC + 2;
|
*NEXT_PC = *PC + 2;
|
||||||
@ -2654,11 +2674,11 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
|
|||||||
icount++;
|
icount++;
|
||||||
instret++;
|
instret++;
|
||||||
}
|
}
|
||||||
cycle++;
|
*PC = *NEXT_PC;
|
||||||
pc.val=*NEXT_PC;
|
|
||||||
this->core.reg.PC = this->core.reg.NEXT_PC;
|
|
||||||
this->core.reg.trap_state = this->core.reg.pending_trap;
|
this->core.reg.trap_state = this->core.reg.pending_trap;
|
||||||
}
|
}
|
||||||
|
fetch_count++;
|
||||||
|
cycle++;
|
||||||
}
|
}
|
||||||
return pc;
|
return pc;
|
||||||
}
|
}
|
||||||
|
La diferencia del archivo ha sido suprimido porque es demasiado grande
Cargar Diff
La diferencia del archivo ha sido suprimido porque es demasiado grande
Cargar Diff
Referencia en una nueva incidencia
Block a user