Compare commits
No commits in common. "fbda1424f3118263c0b2190e2941eb117b3864a8" and "db5765b3429efd6674e349ab5a6cd2b8b258dd1a" have entirely different histories.
fbda1424f3
...
db5765b342
@ -1,9 +1,8 @@
|
|||||||
cmake_minimum_required(VERSION 3.12)
|
cmake_minimum_required(VERSION 3.12)
|
||||||
list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake)
|
list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake)
|
||||||
|
###############################################################################
|
||||||
# ##############################################################################
|
|
||||||
#
|
#
|
||||||
# ##############################################################################
|
###############################################################################
|
||||||
project(dbt-rise-tgc VERSION 1.0.0)
|
project(dbt-rise-tgc VERSION 1.0.0)
|
||||||
|
|
||||||
include(GNUInstallDirs)
|
include(GNUInstallDirs)
|
||||||
@ -20,40 +19,33 @@ 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/semihosting/semihosting.cpp
|
|
||||||
)
|
)
|
||||||
|
|
||||||
if(WITH_TCC)
|
if(WITH_TCC)
|
||||||
list(APPEND LIB_SOURCES
|
list(APPEND LIB_SOURCES
|
||||||
src/vm/tcc/vm_tgc5c.cpp
|
src/vm/tcc/vm_tgc5c.cpp
|
||||||
)
|
)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(WITH_LLVM)
|
if(WITH_LLVM)
|
||||||
list(APPEND LIB_SOURCES
|
list(APPEND LIB_SOURCES
|
||||||
src/vm/llvm/vm_tgc5c.cpp
|
src/vm/llvm/vm_tgc5c.cpp
|
||||||
src/vm/llvm/fp_impl.cpp
|
src/vm/llvm/fp_impl.cpp
|
||||||
)
|
)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(WITH_ASMJIT)
|
if(WITH_ASMJIT)
|
||||||
list(APPEND LIB_SOURCES
|
list(APPEND LIB_SOURCES
|
||||||
src/vm/asmjit/vm_tgc5c.cpp
|
src/vm/asmjit/vm_tgc5c.cpp
|
||||||
)
|
)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# library files
|
# library files
|
||||||
FILE(GLOB GEN_ISS_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src-gen/iss/arch/*.cpp)
|
FILE(GLOB GEN_ISS_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src-gen/iss/arch/*.cpp)
|
||||||
FILE(GLOB GEN_VM_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src-gen/vm/interp/vm_*.cpp)
|
FILE(GLOB GEN_VM_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src-gen/vm/interp/vm_*.cpp)
|
||||||
FILE(GLOB GEN_YAML_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/contrib/instr/*.yaml)
|
FILE(GLOB GEN_YAML_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/contrib/instr/*.yaml)
|
||||||
list(APPEND LIB_SOURCES ${GEN_ISS_SOURCES} ${GEN_VM_SOURCES})
|
list(APPEND LIB_SOURCES ${GEN_ISS_SOURCES} ${GEN_VM_SOURCES})
|
||||||
|
|
||||||
foreach(FILEPATH ${GEN_ISS_SOURCES})
|
foreach(FILEPATH ${GEN_ISS_SOURCES})
|
||||||
get_filename_component(CORE ${FILEPATH} NAME_WE)
|
get_filename_component(CORE ${FILEPATH} NAME_WE)
|
||||||
string(TOUPPER ${CORE} CORE)
|
string(TOUPPER ${CORE} CORE)
|
||||||
list(APPEND LIB_DEFINES CORE_${CORE})
|
list(APPEND LIB_DEFINES CORE_${CORE})
|
||||||
endforeach()
|
endforeach()
|
||||||
|
|
||||||
message(STATUS "Core defines are ${LIB_DEFINES}")
|
message(STATUS "Core defines are ${LIB_DEFINES}")
|
||||||
|
|
||||||
if(WITH_LLVM)
|
if(WITH_LLVM)
|
||||||
@ -65,19 +57,16 @@ if(WITH_TCC)
|
|||||||
FILE(GLOB TCC_GEN_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src-gen/vm/tcc/vm_*.cpp)
|
FILE(GLOB TCC_GEN_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src-gen/vm/tcc/vm_*.cpp)
|
||||||
list(APPEND LIB_SOURCES ${TCC_GEN_SOURCES})
|
list(APPEND LIB_SOURCES ${TCC_GEN_SOURCES})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(WITH_ASMJIT)
|
if(WITH_ASMJIT)
|
||||||
FILE(GLOB TCC_GEN_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src-gen/vm/asmjit/vm_*.cpp)
|
FILE(GLOB TCC_GEN_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src-gen/vm/asmjit/vm_*.cpp)
|
||||||
list(APPEND LIB_SOURCES ${TCC_GEN_SOURCES})
|
list(APPEND LIB_SOURCES ${TCC_GEN_SOURCES})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(TARGET yaml-cpp::yaml-cpp)
|
if(TARGET yaml-cpp::yaml-cpp)
|
||||||
list(APPEND LIB_SOURCES
|
list(APPEND LIB_SOURCES
|
||||||
src/iss/plugin/cycle_estimate.cpp
|
src/iss/plugin/cycle_estimate.cpp
|
||||||
src/iss/plugin/instruction_count.cpp
|
src/iss/plugin/instruction_count.cpp
|
||||||
)
|
)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Define the library
|
# Define the library
|
||||||
add_library(${PROJECT_NAME} SHARED ${LIB_SOURCES})
|
add_library(${PROJECT_NAME} SHARED ${LIB_SOURCES})
|
||||||
|
|
||||||
@ -86,23 +75,19 @@ if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
|
|||||||
elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
|
elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
|
||||||
target_compile_options(${PROJECT_NAME} PRIVATE /wd4293)
|
target_compile_options(${PROJECT_NAME} PRIVATE /wd4293)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
target_include_directories(${PROJECT_NAME} PUBLIC src)
|
target_include_directories(${PROJECT_NAME} PUBLIC src)
|
||||||
target_include_directories(${PROJECT_NAME} PUBLIC src-gen)
|
target_include_directories(${PROJECT_NAME} PUBLIC src-gen)
|
||||||
|
|
||||||
target_force_link_libraries(${PROJECT_NAME} PRIVATE dbt-rise-core)
|
target_force_link_libraries(${PROJECT_NAME} PRIVATE dbt-rise-core)
|
||||||
|
|
||||||
# only re-export the include paths
|
# only re-export the include paths
|
||||||
get_target_property(DBT_CORE_INCL dbt-rise-core INTERFACE_INCLUDE_DIRECTORIES)
|
get_target_property(DBT_CORE_INCL dbt-rise-core INTERFACE_INCLUDE_DIRECTORIES)
|
||||||
target_include_directories(${PROJECT_NAME} INTERFACE ${DBT_CORE_INCL})
|
target_include_directories(${PROJECT_NAME} INTERFACE ${DBT_CORE_INCL})
|
||||||
get_target_property(DBT_CORE_DEFS dbt-rise-core INTERFACE_COMPILE_DEFINITIONS)
|
get_target_property(DBT_CORE_DEFS dbt-rise-core INTERFACE_COMPILE_DEFINITIONS)
|
||||||
|
if(NOT (DBT_CORE_DEFS STREQUAL DBT_CORE_DEFS-NOTFOUND))
|
||||||
if(NOT(DBT_CORE_DEFS STREQUAL DBT_CORE_DEFS-NOTFOUND))
|
|
||||||
target_compile_definitions(${PROJECT_NAME} INTERFACE ${DBT_CORE_DEFS})
|
target_compile_definitions(${PROJECT_NAME} INTERFACE ${DBT_CORE_DEFS})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
target_link_libraries(${PROJECT_NAME} PUBLIC elfio::elfio softfloat scc-util Boost::coroutine)
|
target_link_libraries(${PROJECT_NAME} PUBLIC elfio::elfio softfloat scc-util Boost::coroutine)
|
||||||
|
|
||||||
if(TARGET yaml-cpp::yaml-cpp)
|
if(TARGET yaml-cpp::yaml-cpp)
|
||||||
target_compile_definitions(${PROJECT_NAME} PUBLIC WITH_PLUGINS)
|
target_compile_definitions(${PROJECT_NAME} PUBLIC WITH_PLUGINS)
|
||||||
target_link_libraries(${PROJECT_NAME} PUBLIC yaml-cpp::yaml-cpp)
|
target_link_libraries(${PROJECT_NAME} PUBLIC yaml-cpp::yaml-cpp)
|
||||||
@ -112,9 +97,8 @@ if(WITH_LLVM)
|
|||||||
find_package(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()
|
||||||
|
|
||||||
@ -135,18 +119,16 @@ install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/incl/iss COMPONENT ${PROJECT_NAME}
|
|||||||
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} # target directory
|
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} # target directory
|
||||||
FILES_MATCHING # install only matched files
|
FILES_MATCHING # install only matched files
|
||||||
PATTERN "*.h" # select header files
|
PATTERN "*.h" # select header files
|
||||||
)
|
)
|
||||||
install(FILES ${GEN_YAML_SOURCES} DESTINATION share/tgc-vp)
|
install(FILES ${GEN_YAML_SOURCES} DESTINATION share/tgc-vp)
|
||||||
|
###############################################################################
|
||||||
# ##############################################################################
|
|
||||||
#
|
#
|
||||||
# ##############################################################################
|
###############################################################################
|
||||||
set(CMAKE_INSTALL_RPATH $ORIGIN/../${CMAKE_INSTALL_LIBDIR})
|
set(CMAKE_INSTALL_RPATH $ORIGIN/../${CMAKE_INSTALL_LIBDIR})
|
||||||
project(tgc-sim)
|
project(tgc-sim)
|
||||||
find_package(Boost COMPONENTS program_options thread REQUIRED)
|
find_package(Boost COMPONENTS program_options thread REQUIRED)
|
||||||
|
|
||||||
add_executable(${PROJECT_NAME} src/main.cpp)
|
add_executable(${PROJECT_NAME} src/main.cpp)
|
||||||
|
|
||||||
if(TARGET ${CORE_NAME}_cpp)
|
if(TARGET ${CORE_NAME}_cpp)
|
||||||
list(APPEND TGC_SOURCES ${${CORE_NAME}_OUTPUT_FILES})
|
list(APPEND TGC_SOURCES ${${CORE_NAME}_OUTPUT_FILES})
|
||||||
else()
|
else()
|
||||||
@ -158,20 +140,21 @@ else()
|
|||||||
endif()
|
endif()
|
||||||
|
|
||||||
foreach(F IN LISTS TGC_SOURCES)
|
foreach(F IN LISTS TGC_SOURCES)
|
||||||
if(${F} MATCHES ".*/arch/([^/]*)\.cpp")
|
if (${F} MATCHES ".*/arch/([^/]*)\.cpp")
|
||||||
string(REGEX REPLACE ".*/([^/]*)\.cpp" "\\1" CORE_NAME_LC ${F})
|
string(REGEX REPLACE ".*/([^/]*)\.cpp" "\\1" CORE_NAME_LC ${F})
|
||||||
string(TOUPPER ${CORE_NAME_LC} CORE_NAME)
|
string(TOUPPER ${CORE_NAME_LC} CORE_NAME)
|
||||||
target_compile_definitions(${PROJECT_NAME} PRIVATE CORE_${CORE_NAME})
|
target_compile_definitions(${PROJECT_NAME} PRIVATE CORE_${CORE_NAME})
|
||||||
endif()
|
endif()
|
||||||
endforeach()
|
endforeach()
|
||||||
|
|
||||||
# if(WITH_LLVM)
|
#if(WITH_LLVM)
|
||||||
# target_compile_definitions(${PROJECT_NAME} PRIVATE WITH_LLVM)
|
# target_compile_definitions(${PROJECT_NAME} PRIVATE WITH_LLVM)
|
||||||
# #target_link_libraries(${PROJECT_NAME} PUBLIC ${llvm_libs})
|
# #target_link_libraries(${PROJECT_NAME} PUBLIC ${llvm_libs})
|
||||||
# endif()
|
#endif()
|
||||||
# if(WITH_TCC)
|
#if(WITH_TCC)
|
||||||
# target_compile_definitions(${PROJECT_NAME} PRIVATE WITH_TCC)
|
# target_compile_definitions(${PROJECT_NAME} PRIVATE WITH_TCC)
|
||||||
# endif()
|
#endif()
|
||||||
|
|
||||||
target_link_libraries(${PROJECT_NAME} PUBLIC dbt-rise-tgc fmt::fmt)
|
target_link_libraries(${PROJECT_NAME} PUBLIC dbt-rise-tgc fmt::fmt)
|
||||||
|
|
||||||
if(TARGET Boost::program_options)
|
if(TARGET Boost::program_options)
|
||||||
@ -179,10 +162,8 @@ if(TARGET Boost::program_options)
|
|||||||
else()
|
else()
|
||||||
target_link_libraries(${PROJECT_NAME} PUBLIC ${BOOST_program_options_LIBRARY})
|
target_link_libraries(${PROJECT_NAME} PUBLIC ${BOOST_program_options_LIBRARY})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
target_link_libraries(${PROJECT_NAME} PUBLIC ${CMAKE_DL_LIBS})
|
target_link_libraries(${PROJECT_NAME} PUBLIC ${CMAKE_DL_LIBS})
|
||||||
|
if (Tcmalloc_FOUND)
|
||||||
if(Tcmalloc_FOUND)
|
|
||||||
target_link_libraries(${PROJECT_NAME} PUBLIC ${Tcmalloc_LIBRARIES})
|
target_link_libraries(${PROJECT_NAME} PUBLIC ${Tcmalloc_LIBRARIES})
|
||||||
endif(Tcmalloc_FOUND)
|
endif(Tcmalloc_FOUND)
|
||||||
|
|
||||||
@ -200,26 +181,22 @@ if(BUILD_TESTING)
|
|||||||
# ... CMake code to create tests ...
|
# ... CMake code to create tests ...
|
||||||
add_test(NAME tgc-sim-interp
|
add_test(NAME tgc-sim-interp
|
||||||
COMMAND tgc-sim -f ${CMAKE_BINARY_DIR}/../../Firmwares/hello-world/hello --backend interp)
|
COMMAND tgc-sim -f ${CMAKE_BINARY_DIR}/../../Firmwares/hello-world/hello --backend interp)
|
||||||
|
|
||||||
if(WITH_TCC)
|
if(WITH_TCC)
|
||||||
add_test(NAME tgc-sim-tcc
|
add_test(NAME tgc-sim-tcc
|
||||||
COMMAND tgc-sim -f ${CMAKE_BINARY_DIR}/../../Firmwares/hello-world/hello --backend tcc)
|
COMMAND tgc-sim -f ${CMAKE_BINARY_DIR}/../../Firmwares/hello-world/hello --backend tcc)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(WITH_LLVM)
|
if(WITH_LLVM)
|
||||||
add_test(NAME tgc-sim-llvm
|
add_test(NAME tgc-sim-llvm
|
||||||
COMMAND tgc-sim -f ${CMAKE_BINARY_DIR}/../../Firmwares/hello-world/hello --backend llvm)
|
COMMAND tgc-sim -f ${CMAKE_BINARY_DIR}/../../Firmwares/hello-world/hello --backend llvm)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(WITH_ASMJIT)
|
if(WITH_ASMJIT)
|
||||||
add_test(NAME tgc-sim-asmjit
|
add_test(NAME tgc-sim-asmjit
|
||||||
COMMAND tgc-sim -f ${CMAKE_BINARY_DIR}/../../Firmwares/hello-world/hello --backend asmjit)
|
COMMAND tgc-sim -f ${CMAKE_BINARY_DIR}/../../Firmwares/hello-world/hello --backend asmjit)
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
###############################################################################
|
||||||
# ##############################################################################
|
|
||||||
#
|
#
|
||||||
# ##############################################################################
|
###############################################################################
|
||||||
if(TARGET scc-sysc)
|
if(TARGET scc-sysc)
|
||||||
project(dbt-rise-tgc_sc VERSION 1.0.0)
|
project(dbt-rise-tgc_sc VERSION 1.0.0)
|
||||||
set(LIB_SOURCES
|
set(LIB_SOURCES
|
||||||
@ -231,20 +208,18 @@ if(TARGET scc-sysc)
|
|||||||
add_library(${PROJECT_NAME} ${LIB_SOURCES})
|
add_library(${PROJECT_NAME} ${LIB_SOURCES})
|
||||||
target_compile_definitions(${PROJECT_NAME} PUBLIC WITH_SYSTEMC)
|
target_compile_definitions(${PROJECT_NAME} PUBLIC WITH_SYSTEMC)
|
||||||
target_compile_definitions(${PROJECT_NAME} PRIVATE CORE_${CORE_NAME})
|
target_compile_definitions(${PROJECT_NAME} PRIVATE CORE_${CORE_NAME})
|
||||||
|
|
||||||
foreach(F IN LISTS TGC_SOURCES)
|
foreach(F IN LISTS TGC_SOURCES)
|
||||||
if(${F} MATCHES ".*/arch/([^/]*)\.cpp")
|
if (${F} MATCHES ".*/arch/([^/]*)\.cpp")
|
||||||
string(REGEX REPLACE ".*/([^/]*)\.cpp" "\\1" CORE_NAME_LC ${F})
|
string(REGEX REPLACE ".*/([^/]*)\.cpp" "\\1" CORE_NAME_LC ${F})
|
||||||
string(TOUPPER ${CORE_NAME_LC} CORE_NAME)
|
string(TOUPPER ${CORE_NAME_LC} CORE_NAME)
|
||||||
target_compile_definitions(${PROJECT_NAME} PRIVATE CORE_${CORE_NAME})
|
target_compile_definitions(${PROJECT_NAME} PRIVATE CORE_${CORE_NAME})
|
||||||
endif()
|
endif()
|
||||||
endforeach()
|
endforeach()
|
||||||
|
|
||||||
target_link_libraries(${PROJECT_NAME} PUBLIC dbt-rise-tgc scc-sysc)
|
target_link_libraries(${PROJECT_NAME} PUBLIC dbt-rise-tgc scc-sysc)
|
||||||
|
# if(WITH_LLVM)
|
||||||
|
# target_link_libraries(${PROJECT_NAME} PUBLIC ${llvm_libs})
|
||||||
|
# endif()
|
||||||
|
|
||||||
# if(WITH_LLVM)
|
|
||||||
# target_link_libraries(${PROJECT_NAME} PUBLIC ${llvm_libs})
|
|
||||||
# endif()
|
|
||||||
set(LIB_HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/src/sysc/core_complex.h)
|
set(LIB_HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/src/sysc/core_complex.h)
|
||||||
set_target_properties(${PROJECT_NAME} PROPERTIES
|
set_target_properties(${PROJECT_NAME} PROPERTIES
|
||||||
VERSION ${PROJECT_VERSION}
|
VERSION ${PROJECT_VERSION}
|
||||||
@ -261,3 +236,4 @@ if(TARGET scc-sysc)
|
|||||||
INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} # headers
|
INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} # headers
|
||||||
)
|
)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
@ -263,24 +263,16 @@ std::unique_ptr<vm_if> create<arch::${coreDef.name.toLowerCase()}>(arch::${coreD
|
|||||||
namespace iss {
|
namespace iss {
|
||||||
namespace {
|
namespace {
|
||||||
volatile std::array<bool, 2> dummy = {
|
volatile std::array<bool, 2> dummy = {
|
||||||
core_factory::instance().register_creator("${coreDef.name.toLowerCase()}|m_p|asmjit", [](unsigned port, void* init_data) -> std::tuple<cpu_ptr, vm_ptr>{
|
core_factory::instance().register_creator("${coreDef.name.toLowerCase()}|m_p|asmjit", [](unsigned port, void*) -> std::tuple<cpu_ptr, vm_ptr>{
|
||||||
auto* cpu = new iss::arch::riscv_hart_m_p<iss::arch::${coreDef.name.toLowerCase()}>();
|
auto* cpu = new iss::arch::riscv_hart_m_p<iss::arch::${coreDef.name.toLowerCase()}>();
|
||||||
auto vm = new asmjit::${coreDef.name.toLowerCase()}::vm_impl<arch::${coreDef.name.toLowerCase()}>(*cpu, false);
|
auto* vm = new asmjit::${coreDef.name.toLowerCase()}::vm_impl<arch::${coreDef.name.toLowerCase()}>(*cpu, false);
|
||||||
if (port != 0) debugger::server<debugger::gdb_session>::run_server(vm, port);
|
if (port != 0) debugger::server<debugger::gdb_session>::run_server(vm, port);
|
||||||
if(init_data){
|
|
||||||
auto* cb = reinterpret_cast<std::function<void(arch_if*, arch::traits<arch::${coreDef.name.toLowerCase()}>::reg_t, arch::traits<arch::${coreDef.name.toLowerCase()}>::reg_t)>*>(init_data);
|
|
||||||
cpu->set_semihosting_callback(*cb);
|
|
||||||
}
|
|
||||||
return {cpu_ptr{cpu}, vm_ptr{vm}};
|
return {cpu_ptr{cpu}, vm_ptr{vm}};
|
||||||
}),
|
}),
|
||||||
core_factory::instance().register_creator("${coreDef.name.toLowerCase()}|mu_p|asmjit", [](unsigned port, void* init_data) -> std::tuple<cpu_ptr, vm_ptr>{
|
core_factory::instance().register_creator("${coreDef.name.toLowerCase()}|mu_p|asmjit", [](unsigned port, void*) -> std::tuple<cpu_ptr, vm_ptr>{
|
||||||
auto* cpu = new iss::arch::riscv_hart_mu_p<iss::arch::${coreDef.name.toLowerCase()}>();
|
auto* cpu = new iss::arch::riscv_hart_mu_p<iss::arch::${coreDef.name.toLowerCase()}>();
|
||||||
auto vm = new asmjit::${coreDef.name.toLowerCase()}::vm_impl<arch::${coreDef.name.toLowerCase()}>(*cpu, false);
|
auto* vm = new asmjit::${coreDef.name.toLowerCase()}::vm_impl<arch::${coreDef.name.toLowerCase()}>(*cpu, false);
|
||||||
if (port != 0) debugger::server<debugger::gdb_session>::run_server(vm, port);
|
if (port != 0) debugger::server<debugger::gdb_session>::run_server(vm, port);
|
||||||
if(init_data){
|
|
||||||
auto* cb = reinterpret_cast<std::function<void(arch_if*, arch::traits<arch::${coreDef.name.toLowerCase()}>::reg_t, arch::traits<arch::${coreDef.name.toLowerCase()}>::reg_t)>*>(init_data);
|
|
||||||
cpu->set_semihosting_callback(*cb);
|
|
||||||
}
|
|
||||||
return {cpu_ptr{cpu}, vm_ptr{vm}};
|
return {cpu_ptr{cpu}, vm_ptr{vm}};
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
|
@ -363,24 +363,16 @@ std::unique_ptr<vm_if> create<arch::${coreDef.name.toLowerCase()}>(arch::${coreD
|
|||||||
namespace iss {
|
namespace iss {
|
||||||
namespace {
|
namespace {
|
||||||
volatile std::array<bool, 2> dummy = {
|
volatile std::array<bool, 2> dummy = {
|
||||||
core_factory::instance().register_creator("${coreDef.name.toLowerCase()}|m_p|interp", [](unsigned port, void* init_data) -> std::tuple<cpu_ptr, vm_ptr>{
|
core_factory::instance().register_creator("${coreDef.name.toLowerCase()}|m_p|interp", [](unsigned port, void*) -> std::tuple<cpu_ptr, vm_ptr>{
|
||||||
auto* cpu = new iss::arch::riscv_hart_m_p<iss::arch::${coreDef.name.toLowerCase()}>();
|
auto* cpu = new iss::arch::riscv_hart_m_p<iss::arch::${coreDef.name.toLowerCase()}>();
|
||||||
auto vm = new interp::${coreDef.name.toLowerCase()}::vm_impl<arch::${coreDef.name.toLowerCase()}>(*cpu, false);
|
auto vm = new interp::${coreDef.name.toLowerCase()}::vm_impl<arch::${coreDef.name.toLowerCase()}>(*cpu, false);
|
||||||
if (port != 0) debugger::server<debugger::gdb_session>::run_server(vm, port);
|
if (port != 0) debugger::server<debugger::gdb_session>::run_server(vm, port);
|
||||||
if(init_data){
|
|
||||||
auto* cb = reinterpret_cast<std::function<void(arch_if*, arch::traits<arch::${coreDef.name.toLowerCase()}>::reg_t, arch::traits<arch::${coreDef.name.toLowerCase()}>::reg_t)>*>(init_data);
|
|
||||||
cpu->set_semihosting_callback(*cb);
|
|
||||||
}
|
|
||||||
return {cpu_ptr{cpu}, vm_ptr{vm}};
|
return {cpu_ptr{cpu}, vm_ptr{vm}};
|
||||||
}),
|
}),
|
||||||
core_factory::instance().register_creator("${coreDef.name.toLowerCase()}|mu_p|interp", [](unsigned port, void* init_data) -> std::tuple<cpu_ptr, vm_ptr>{
|
core_factory::instance().register_creator("${coreDef.name.toLowerCase()}|mu_p|interp", [](unsigned port, void*) -> std::tuple<cpu_ptr, vm_ptr>{
|
||||||
auto* cpu = new iss::arch::riscv_hart_mu_p<iss::arch::${coreDef.name.toLowerCase()}>();
|
auto* cpu = new iss::arch::riscv_hart_mu_p<iss::arch::${coreDef.name.toLowerCase()}>();
|
||||||
auto vm = new interp::${coreDef.name.toLowerCase()}::vm_impl<arch::${coreDef.name.toLowerCase()}>(*cpu, false);
|
auto vm = new interp::${coreDef.name.toLowerCase()}::vm_impl<arch::${coreDef.name.toLowerCase()}>(*cpu, false);
|
||||||
if (port != 0) debugger::server<debugger::gdb_session>::run_server(vm, port);
|
if (port != 0) debugger::server<debugger::gdb_session>::run_server(vm, port);
|
||||||
if(init_data){
|
|
||||||
auto* cb = reinterpret_cast<std::function<void(arch_if*, arch::traits<arch::${coreDef.name.toLowerCase()}>::reg_t, arch::traits<arch::${coreDef.name.toLowerCase()}>::reg_t)>*>(init_data);
|
|
||||||
cpu->set_semihosting_callback(*cb);
|
|
||||||
}
|
|
||||||
return {cpu_ptr{cpu}, vm_ptr{vm}};
|
return {cpu_ptr{cpu}, vm_ptr{vm}};
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
|
@ -365,24 +365,16 @@ std::unique_ptr<vm_if> create<arch::${coreDef.name.toLowerCase()}>(arch::${coreD
|
|||||||
namespace iss {
|
namespace iss {
|
||||||
namespace {
|
namespace {
|
||||||
volatile std::array<bool, 2> dummy = {
|
volatile std::array<bool, 2> dummy = {
|
||||||
core_factory::instance().register_creator("${coreDef.name.toLowerCase()}|m_p|llvm", [](unsigned port, void* init_data) -> std::tuple<cpu_ptr, vm_ptr>{
|
core_factory::instance().register_creator("${coreDef.name.toLowerCase()}|m_p|llvm", [](unsigned port, void*) -> std::tuple<cpu_ptr, vm_ptr>{
|
||||||
auto* cpu = new iss::arch::riscv_hart_m_p<iss::arch::${coreDef.name.toLowerCase()}>();
|
auto* cpu = new iss::arch::riscv_hart_m_p<iss::arch::${coreDef.name.toLowerCase()}>();
|
||||||
auto vm = new llvm::${coreDef.name.toLowerCase()}::vm_impl<arch::${coreDef.name.toLowerCase()}>(*cpu, false);
|
auto* vm = new llvm::${coreDef.name.toLowerCase()}::vm_impl<arch::${coreDef.name.toLowerCase()}>(*cpu, false);
|
||||||
if (port != 0) debugger::server<debugger::gdb_session>::run_server(vm, port);
|
if (port != 0) debugger::server<debugger::gdb_session>::run_server(vm, port);
|
||||||
if(init_data){
|
|
||||||
auto* cb = reinterpret_cast<std::function<void(arch_if*, arch::traits<arch::${coreDef.name.toLowerCase()}>::reg_t, arch::traits<arch::${coreDef.name.toLowerCase()}>::reg_t)>*>(init_data);
|
|
||||||
cpu->set_semihosting_callback(*cb);
|
|
||||||
}
|
|
||||||
return {cpu_ptr{cpu}, vm_ptr{vm}};
|
return {cpu_ptr{cpu}, vm_ptr{vm}};
|
||||||
}),
|
}),
|
||||||
core_factory::instance().register_creator("${coreDef.name.toLowerCase()}|mu_p|llvm", [](unsigned port, void* init_data) -> std::tuple<cpu_ptr, vm_ptr>{
|
core_factory::instance().register_creator("${coreDef.name.toLowerCase()}|mu_p|llvm", [](unsigned port, void*) -> std::tuple<cpu_ptr, vm_ptr>{
|
||||||
auto* cpu = new iss::arch::riscv_hart_mu_p<iss::arch::${coreDef.name.toLowerCase()}>();
|
auto* cpu = new iss::arch::riscv_hart_mu_p<iss::arch::${coreDef.name.toLowerCase()}>();
|
||||||
auto vm = new llvm::${coreDef.name.toLowerCase()}::vm_impl<arch::${coreDef.name.toLowerCase()}>(*cpu, false);
|
auto* vm = new llvm::${coreDef.name.toLowerCase()}::vm_impl<arch::${coreDef.name.toLowerCase()}>(*cpu, false);
|
||||||
if (port != 0) debugger::server<debugger::gdb_session>::run_server(vm, port);
|
if (port != 0) debugger::server<debugger::gdb_session>::run_server(vm, port);
|
||||||
if(init_data){
|
|
||||||
auto* cb = reinterpret_cast<std::function<void(arch_if*, arch::traits<arch::${coreDef.name.toLowerCase()}>::reg_t, arch::traits<arch::${coreDef.name.toLowerCase()}>::reg_t)>*>(init_data);
|
|
||||||
cpu->set_semihosting_callback(*cb);
|
|
||||||
}
|
|
||||||
return {cpu_ptr{cpu}, vm_ptr{vm}};
|
return {cpu_ptr{cpu}, vm_ptr{vm}};
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
|
@ -329,24 +329,16 @@ std::unique_ptr<vm_if> create<arch::${coreDef.name.toLowerCase()}>(arch::${coreD
|
|||||||
namespace iss {
|
namespace iss {
|
||||||
namespace {
|
namespace {
|
||||||
volatile std::array<bool, 2> dummy = {
|
volatile std::array<bool, 2> dummy = {
|
||||||
core_factory::instance().register_creator("${coreDef.name.toLowerCase()}|m_p|tcc", [](unsigned port, void* init_data) -> std::tuple<cpu_ptr, vm_ptr>{
|
core_factory::instance().register_creator("${coreDef.name.toLowerCase()}|m_p|tcc", [](unsigned port, void*) -> std::tuple<cpu_ptr, vm_ptr>{
|
||||||
auto* cpu = new iss::arch::riscv_hart_m_p<iss::arch::${coreDef.name.toLowerCase()}>();
|
auto* cpu = new iss::arch::riscv_hart_m_p<iss::arch::${coreDef.name.toLowerCase()}>();
|
||||||
auto vm = new tcc::${coreDef.name.toLowerCase()}::vm_impl<arch::${coreDef.name.toLowerCase()}>(*cpu, false);
|
auto vm = new tcc::${coreDef.name.toLowerCase()}::vm_impl<arch::${coreDef.name.toLowerCase()}>(*cpu, false);
|
||||||
if (port != 0) debugger::server<debugger::gdb_session>::run_server(vm, port);
|
if (port != 0) debugger::server<debugger::gdb_session>::run_server(vm, port);
|
||||||
if(init_data){
|
|
||||||
auto* cb = reinterpret_cast<std::function<void(arch_if*, arch::traits<arch::${coreDef.name.toLowerCase()}>::reg_t, arch::traits<arch::${coreDef.name.toLowerCase()}>::reg_t)>*>(init_data);
|
|
||||||
cpu->set_semihosting_callback(*cb);
|
|
||||||
}
|
|
||||||
return {cpu_ptr{cpu}, vm_ptr{vm}};
|
return {cpu_ptr{cpu}, vm_ptr{vm}};
|
||||||
}),
|
}),
|
||||||
core_factory::instance().register_creator("${coreDef.name.toLowerCase()}|mu_p|tcc", [](unsigned port, void* init_data) -> std::tuple<cpu_ptr, vm_ptr>{
|
core_factory::instance().register_creator("${coreDef.name.toLowerCase()}|mu_p|tcc", [](unsigned port, void*) -> std::tuple<cpu_ptr, vm_ptr>{
|
||||||
auto* cpu = new iss::arch::riscv_hart_mu_p<iss::arch::${coreDef.name.toLowerCase()}>();
|
auto* cpu = new iss::arch::riscv_hart_mu_p<iss::arch::${coreDef.name.toLowerCase()}>();
|
||||||
auto vm = new tcc::${coreDef.name.toLowerCase()}::vm_impl<arch::${coreDef.name.toLowerCase()}>(*cpu, false);
|
auto vm = new tcc::${coreDef.name.toLowerCase()}::vm_impl<arch::${coreDef.name.toLowerCase()}>(*cpu, false);
|
||||||
if (port != 0) debugger::server<debugger::gdb_session>::run_server(vm, port);
|
if (port != 0) debugger::server<debugger::gdb_session>::run_server(vm, port);
|
||||||
if(init_data){
|
|
||||||
auto* cb = reinterpret_cast<std::function<void(arch_if*, arch::traits<arch::${coreDef.name.toLowerCase()}>::reg_t, arch::traits<arch::${coreDef.name.toLowerCase()}>::reg_t)>*>(init_data);
|
|
||||||
cpu->set_semihosting_callback(*cb);
|
|
||||||
}
|
|
||||||
return {cpu_ptr{cpu}, vm_ptr{vm}};
|
return {cpu_ptr{cpu}, vm_ptr{vm}};
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
|
@ -55,8 +55,6 @@
|
|||||||
#include <util/ities.h>
|
#include <util/ities.h>
|
||||||
#include <util/sparse_array.h>
|
#include <util/sparse_array.h>
|
||||||
|
|
||||||
#include <iss/semihosting/semihosting.h>
|
|
||||||
|
|
||||||
#if defined(__GNUC__)
|
#if defined(__GNUC__)
|
||||||
#define likely(x) __builtin_expect(!!(x), 1)
|
#define likely(x) __builtin_expect(!!(x), 1)
|
||||||
#define unlikely(x) __builtin_expect(!!(x), 0)
|
#define unlikely(x) __builtin_expect(!!(x), 0)
|
||||||
@ -292,8 +290,6 @@ public:
|
|||||||
|
|
||||||
void set_irq_num(unsigned i) { mcause_max_irq = 1 << util::ilog2(i); }
|
void set_irq_num(unsigned i) { mcause_max_irq = 1 << util::ilog2(i); }
|
||||||
|
|
||||||
void set_semihosting_callback(std::function<void(arch_if*, reg_t, reg_t)>& cb) { semihosting_cb = cb; };
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
struct riscv_instrumentation_if : public iss::instrumentation_if {
|
struct riscv_instrumentation_if : public iss::instrumentation_if {
|
||||||
|
|
||||||
@ -348,11 +344,9 @@ protected:
|
|||||||
reg_t fault_data;
|
reg_t fault_data;
|
||||||
uint64_t tohost = tohost_dflt;
|
uint64_t tohost = tohost_dflt;
|
||||||
uint64_t fromhost = fromhost_dflt;
|
uint64_t fromhost = fromhost_dflt;
|
||||||
bool tohost_lower_written = false;
|
unsigned to_host_wr_cnt = 0;
|
||||||
riscv_instrumentation_if instr_if;
|
riscv_instrumentation_if instr_if;
|
||||||
|
|
||||||
std::function<void(arch_if*, reg_t, reg_t)> semihosting_cb;
|
|
||||||
|
|
||||||
using mem_type = util::sparse_array<uint8_t, 1ULL << 32>;
|
using mem_type = util::sparse_array<uint8_t, 1ULL << 32>;
|
||||||
using csr_type = util::sparse_array<typename traits<BASE>::reg_t, 1ULL << 12, 12>;
|
using csr_type = util::sparse_array<typename traits<BASE>::reg_t, 1ULL << 12, 12>;
|
||||||
using csr_page_type = typename csr_type::page_type;
|
using csr_page_type = typename csr_type::page_type;
|
||||||
@ -425,7 +419,6 @@ protected:
|
|||||||
feature_config cfg;
|
feature_config cfg;
|
||||||
unsigned mcause_max_irq{(FEAT & features_e::FEAT_CLIC) ? std::max(16U, static_cast<unsigned>(traits<BASE>::CLIC_NUM_IRQ)) : 16U};
|
unsigned mcause_max_irq{(FEAT & features_e::FEAT_CLIC) ? std::max(16U, static_cast<unsigned>(traits<BASE>::CLIC_NUM_IRQ)) : 16U};
|
||||||
inline bool debug_mode_active() { return this->reg.PRIV & 0x4; }
|
inline bool debug_mode_active() { return this->reg.PRIV & 0x4; }
|
||||||
|
|
||||||
std::pair<std::function<mem_read_f>, std::function<mem_write_f>> replace_mem_access(std::function<mem_read_f> rd,
|
std::pair<std::function<mem_read_f>, std::function<mem_write_f>> replace_mem_access(std::function<mem_read_f> rd,
|
||||||
std::function<mem_write_f> wr) {
|
std::function<mem_write_f> wr) {
|
||||||
std::pair<std::function<mem_read_f>, std::function<mem_write_f>> ret{hart_mem_rd_delegate, hart_mem_wr_delegate};
|
std::pair<std::function<mem_read_f>, std::function<mem_write_f>> ret{hart_mem_rd_delegate, hart_mem_wr_delegate};
|
||||||
@ -791,7 +784,7 @@ iss::status riscv_hart_m_p<BASE, FEAT>::write(const address_type type, const acc
|
|||||||
res = write_mem(phys_addr, length, data);
|
res = write_mem(phys_addr, length, data);
|
||||||
}
|
}
|
||||||
if(unlikely(res != iss::Ok && (access & access_type::DEBUG) == 0)) {
|
if(unlikely(res != iss::Ok && (access & access_type::DEBUG) == 0)) {
|
||||||
this->reg.trap_state = (1UL << 31) | (7UL << 16); // issue trap 7 (Store/AMO access fault)
|
this->reg.trap_state = (1UL << 31) | (7 << 16); // issue trap 7 (Store/AMO access fault)
|
||||||
fault_data = addr;
|
fault_data = addr;
|
||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
@ -1105,7 +1098,6 @@ iss::status riscv_hart_m_p<BASE, FEAT>::read_mem(phys_addr_t paddr, unsigned len
|
|||||||
template <typename BASE, features_e FEAT>
|
template <typename BASE, features_e FEAT>
|
||||||
iss::status riscv_hart_m_p<BASE, FEAT>::write_mem(phys_addr_t paddr, unsigned length, const uint8_t* const data) {
|
iss::status riscv_hart_m_p<BASE, FEAT>::write_mem(phys_addr_t paddr, unsigned length, const uint8_t* const data) {
|
||||||
switch(paddr.val) {
|
switch(paddr.val) {
|
||||||
// TODO remove UART, Peripherals should not be part of the ISS
|
|
||||||
case 0xFFFF0000: // UART0 base, TXFIFO reg
|
case 0xFFFF0000: // UART0 base, TXFIFO reg
|
||||||
if(((char)data[0]) == '\n' || data[0] == 0) {
|
if(((char)data[0]) == '\n' || data[0] == 0) {
|
||||||
LOG(INFO) << "UART" << ((paddr.val >> 12) & 0x3) << " send '" << uart_buf.str() << "'";
|
LOG(INFO) << "UART" << ((paddr.val >> 12) & 0x3) << " send '" << uart_buf.str() << "'";
|
||||||
@ -1123,8 +1115,7 @@ iss::status riscv_hart_m_p<BASE, FEAT>::write_mem(phys_addr_t paddr, unsigned le
|
|||||||
auto tohost_lower = (traits<BASE>::XLEN == 32 && paddr.val == tohost) || (traits<BASE>::XLEN == 64 && paddr.val == tohost);
|
auto tohost_lower = (traits<BASE>::XLEN == 32 && paddr.val == tohost) || (traits<BASE>::XLEN == 64 && paddr.val == tohost);
|
||||||
if(tohost_lower || tohost_upper) {
|
if(tohost_lower || tohost_upper) {
|
||||||
uint64_t hostvar = *reinterpret_cast<uint64_t*>(p.data() + (tohost & mem.page_addr_mask));
|
uint64_t hostvar = *reinterpret_cast<uint64_t*>(p.data() + (tohost & mem.page_addr_mask));
|
||||||
// in case of 32 bit system, two writes to tohost are needed, only evaluate on the second (high) write
|
if(tohost_upper || (tohost_lower && to_host_wr_cnt > 0)) {
|
||||||
if(tohost_upper && (tohost_lower || tohost_lower_written)) {
|
|
||||||
switch(hostvar >> 48) {
|
switch(hostvar >> 48) {
|
||||||
case 0:
|
case 0:
|
||||||
if(hostvar != 0x1) {
|
if(hostvar != 0x1) {
|
||||||
@ -1147,13 +1138,13 @@ iss::status riscv_hart_m_p<BASE, FEAT>::write_mem(phys_addr_t paddr, unsigned le
|
|||||||
uart_buf.str("");
|
uart_buf.str("");
|
||||||
} else
|
} else
|
||||||
uart_buf << c;
|
uart_buf << c;
|
||||||
|
to_host_wr_cnt = 0;
|
||||||
} break;
|
} break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
tohost_lower_written = false;
|
|
||||||
} else if(tohost_lower)
|
} else if(tohost_lower)
|
||||||
tohost_lower_written = true;
|
to_host_wr_cnt++;
|
||||||
} else if((traits<BASE>::XLEN == 32 && paddr.val == fromhost + 4) || (traits<BASE>::XLEN == 64 && paddr.val == fromhost)) {
|
} else if((traits<BASE>::XLEN == 32 && paddr.val == fromhost + 4) || (traits<BASE>::XLEN == 64 && paddr.val == fromhost)) {
|
||||||
uint64_t fhostvar = *reinterpret_cast<uint64_t*>(p.data() + (fromhost & mem.page_addr_mask));
|
uint64_t fhostvar = *reinterpret_cast<uint64_t*>(p.data() + (fromhost & mem.page_addr_mask));
|
||||||
*reinterpret_cast<uint64_t*>(p.data() + (tohost & mem.page_addr_mask)) = fhostvar;
|
*reinterpret_cast<uint64_t*>(p.data() + (tohost & mem.page_addr_mask)) = fhostvar;
|
||||||
@ -1262,31 +1253,6 @@ template <typename BASE, features_e FEAT> uint64_t riscv_hart_m_p<BASE, FEAT>::e
|
|||||||
} else {
|
} else {
|
||||||
csr[mtval] = addr;
|
csr[mtval] = addr;
|
||||||
}
|
}
|
||||||
if(semihosting_cb) {
|
|
||||||
// Check for semihosting call
|
|
||||||
phys_addr_t p_addr(access_type::DEBUG_READ, traits<BASE>::MEM, addr - 4);
|
|
||||||
std::array<uint8_t, 8> data;
|
|
||||||
// check for SLLI_X0_X0_0X1F and SRAI_X0_X0_0X07
|
|
||||||
this->read_mem(p_addr, 4, data.data());
|
|
||||||
p_addr.val += 8;
|
|
||||||
this->read_mem(p_addr, 4, data.data() + 4);
|
|
||||||
|
|
||||||
const std::array<uint8_t, 8> ref_data = {0x13, 0x10, 0xf0, 0x01, 0x13, 0x50, 0x70, 0x40};
|
|
||||||
if(data == ref_data) {
|
|
||||||
this->reg.NEXT_PC = addr + 8;
|
|
||||||
|
|
||||||
std::array<char, 32> buffer;
|
|
||||||
#if defined(_MSC_VER)
|
|
||||||
sprintf(buffer.data(), "0x%016llx", addr);
|
|
||||||
#else
|
|
||||||
sprintf(buffer.data(), "0x%016lx", addr);
|
|
||||||
#endif
|
|
||||||
CLOG(INFO, disass) << "Semihosting call at address " << buffer.data() << " occurred ";
|
|
||||||
|
|
||||||
semihosting_callback(this, this->reg.X10 /*a0*/, this->reg.X11 /*a1*/);
|
|
||||||
return this->reg.NEXT_PC;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
case 6:
|
case 6:
|
||||||
|
@ -55,8 +55,6 @@
|
|||||||
#include <util/ities.h>
|
#include <util/ities.h>
|
||||||
#include <util/sparse_array.h>
|
#include <util/sparse_array.h>
|
||||||
|
|
||||||
#include <iss/semihosting/semihosting.h>
|
|
||||||
|
|
||||||
#if defined(__GNUC__)
|
#if defined(__GNUC__)
|
||||||
#define likely(x) __builtin_expect(!!(x), 1)
|
#define likely(x) __builtin_expect(!!(x), 1)
|
||||||
#define unlikely(x) __builtin_expect(!!(x), 0)
|
#define unlikely(x) __builtin_expect(!!(x), 0)
|
||||||
@ -343,8 +341,6 @@ public:
|
|||||||
|
|
||||||
void set_irq_num(unsigned i) { mcause_max_irq = 1 << util::ilog2(i); }
|
void set_irq_num(unsigned i) { mcause_max_irq = 1 << util::ilog2(i); }
|
||||||
|
|
||||||
void set_semihosting_callback(std::function<void(arch_if*, reg_t, reg_t)>& cb) { semihosting_cb = cb; };
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
struct riscv_instrumentation_if : public iss::instrumentation_if {
|
struct riscv_instrumentation_if : public iss::instrumentation_if {
|
||||||
|
|
||||||
@ -399,11 +395,9 @@ protected:
|
|||||||
std::array<vm_info, 2> vm;
|
std::array<vm_info, 2> vm;
|
||||||
uint64_t tohost = tohost_dflt;
|
uint64_t tohost = tohost_dflt;
|
||||||
uint64_t fromhost = fromhost_dflt;
|
uint64_t fromhost = fromhost_dflt;
|
||||||
bool tohost_lower_written = false;
|
unsigned to_host_wr_cnt = 0;
|
||||||
riscv_instrumentation_if instr_if;
|
riscv_instrumentation_if instr_if;
|
||||||
|
|
||||||
std::function<void(arch_if*, reg_t, reg_t)> semihosting_cb;
|
|
||||||
|
|
||||||
using mem_type = util::sparse_array<uint8_t, 1ULL << 32>;
|
using mem_type = util::sparse_array<uint8_t, 1ULL << 32>;
|
||||||
using csr_type = util::sparse_array<typename traits<BASE>::reg_t, 1ULL << 12, 12>;
|
using csr_type = util::sparse_array<typename traits<BASE>::reg_t, 1ULL << 12, 12>;
|
||||||
using csr_page_type = typename csr_type::page_type;
|
using csr_page_type = typename csr_type::page_type;
|
||||||
@ -1098,8 +1092,7 @@ template <typename BASE> iss::status riscv_hart_msu_vp<BASE>::write_mem(phys_add
|
|||||||
auto tohost_lower = (traits<BASE>::XLEN == 32 && paddr.val == tohost) || (traits<BASE>::XLEN == 64 && paddr.val == tohost);
|
auto tohost_lower = (traits<BASE>::XLEN == 32 && paddr.val == tohost) || (traits<BASE>::XLEN == 64 && paddr.val == tohost);
|
||||||
if(tohost_lower || tohost_upper) {
|
if(tohost_lower || tohost_upper) {
|
||||||
uint64_t hostvar = *reinterpret_cast<uint64_t*>(p.data() + (tohost & mem.page_addr_mask));
|
uint64_t hostvar = *reinterpret_cast<uint64_t*>(p.data() + (tohost & mem.page_addr_mask));
|
||||||
// in case of 32 bit system, two writes to tohost are needed, only evaluate on the second (high) write
|
if(tohost_upper || (tohost_lower && to_host_wr_cnt > 0)) {
|
||||||
if(tohost_upper && (tohost_lower || tohost_lower_written)) {
|
|
||||||
switch(hostvar >> 48) {
|
switch(hostvar >> 48) {
|
||||||
case 0:
|
case 0:
|
||||||
if(hostvar != 0x1) {
|
if(hostvar != 0x1) {
|
||||||
@ -1111,10 +1104,8 @@ template <typename BASE> iss::status riscv_hart_msu_vp<BASE>::write_mem(phys_add
|
|||||||
}
|
}
|
||||||
this->reg.trap_state = std::numeric_limits<uint32_t>::max();
|
this->reg.trap_state = std::numeric_limits<uint32_t>::max();
|
||||||
this->interrupt_sim = hostvar;
|
this->interrupt_sim = hostvar;
|
||||||
#ifndef WITH_TCC
|
|
||||||
throw(iss::simulation_stopped(hostvar));
|
|
||||||
#endif
|
|
||||||
break;
|
break;
|
||||||
|
// throw(iss::simulation_stopped(hostvar));
|
||||||
case 0x0101: {
|
case 0x0101: {
|
||||||
char c = static_cast<char>(hostvar & 0xff);
|
char c = static_cast<char>(hostvar & 0xff);
|
||||||
if(c == '\n' || c == 0) {
|
if(c == '\n' || c == 0) {
|
||||||
@ -1122,13 +1113,13 @@ template <typename BASE> iss::status riscv_hart_msu_vp<BASE>::write_mem(phys_add
|
|||||||
uart_buf.str("");
|
uart_buf.str("");
|
||||||
} else
|
} else
|
||||||
uart_buf << c;
|
uart_buf << c;
|
||||||
|
to_host_wr_cnt = 0;
|
||||||
} break;
|
} break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
tohost_lower_written = false;
|
|
||||||
} else if(tohost_lower)
|
} else if(tohost_lower)
|
||||||
tohost_lower_written = true;
|
to_host_wr_cnt++;
|
||||||
} else if((traits<BASE>::XLEN == 32 && paddr.val == fromhost + 4) || (traits<BASE>::XLEN == 64 && paddr.val == fromhost)) {
|
} else if((traits<BASE>::XLEN == 32 && paddr.val == fromhost + 4) || (traits<BASE>::XLEN == 64 && paddr.val == fromhost)) {
|
||||||
uint64_t fhostvar = *reinterpret_cast<uint64_t*>(p.data() + (fromhost & mem.page_addr_mask));
|
uint64_t fhostvar = *reinterpret_cast<uint64_t*>(p.data() + (fromhost & mem.page_addr_mask));
|
||||||
*reinterpret_cast<uint64_t*>(p.data() + (tohost & mem.page_addr_mask)) = fhostvar;
|
*reinterpret_cast<uint64_t*>(p.data() + (tohost & mem.page_addr_mask)) = fhostvar;
|
||||||
@ -1313,31 +1304,6 @@ template <typename BASE> uint64_t riscv_hart_msu_vp<BASE>::enter_trap(uint64_t f
|
|||||||
// csr[dpc] = addr;
|
// csr[dpc] = addr;
|
||||||
// csr[dcsr] = (csr[dcsr] & ~0x1c3) | (1<<6) | PRIV_M; //FIXME: cause should not be 4 (stepi)
|
// csr[dcsr] = (csr[dcsr] & ~0x1c3) | (1<<6) | PRIV_M; //FIXME: cause should not be 4 (stepi)
|
||||||
csr[utval | (new_priv << 8)] = addr;
|
csr[utval | (new_priv << 8)] = addr;
|
||||||
if(semihosting_cb) {
|
|
||||||
// Check for semihosting call
|
|
||||||
phys_addr_t p_addr(access_type::DEBUG_READ, traits<BASE>::MEM, addr - 4);
|
|
||||||
std::array<uint8_t, 8> data;
|
|
||||||
// check for SLLI_X0_X0_0X1F and SRAI_X0_X0_0X07
|
|
||||||
this->read_mem(p_addr, 4, data.data());
|
|
||||||
p_addr.val += 8;
|
|
||||||
this->read_mem(p_addr, 4, data.data() + 4);
|
|
||||||
|
|
||||||
const std::array<uint8_t, 8> ref_data = {0x13, 0x10, 0xf0, 0x01, 0x13, 0x50, 0x70, 0x40};
|
|
||||||
if(data == ref_data) {
|
|
||||||
this->reg.NEXT_PC = addr + 8;
|
|
||||||
|
|
||||||
std::array<char, 32> buffer;
|
|
||||||
#if defined(_MSC_VER)
|
|
||||||
sprintf(buffer.data(), "0x%016llx", addr);
|
|
||||||
#else
|
|
||||||
sprintf(buffer.data(), "0x%016lx", addr);
|
|
||||||
#endif
|
|
||||||
CLOG(INFO, disass) << "Semihosting call at address " << buffer.data() << " occurred ";
|
|
||||||
|
|
||||||
semihosting_callback(this, this->reg.X10 /*a0*/, this->reg.X11 /*a1*/);
|
|
||||||
return this->reg.NEXT_PC;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
case 6:
|
case 6:
|
||||||
@ -1355,7 +1321,7 @@ template <typename BASE> uint64_t riscv_hart_msu_vp<BASE>::enter_trap(uint64_t f
|
|||||||
this->reg.pending_trap = 0;
|
this->reg.pending_trap = 0;
|
||||||
}
|
}
|
||||||
size_t adr = ucause | (new_priv << 8);
|
size_t adr = ucause | (new_priv << 8);
|
||||||
csr[adr] = (trap_id << (traits<BASE>::XLEN - 1)) + cause;
|
csr[adr] = (trap_id << 31) + cause;
|
||||||
// update mstatus
|
// update mstatus
|
||||||
// xPP field of mstatus is written with the active privilege mode at the time
|
// xPP field of mstatus is written with the active privilege mode at the time
|
||||||
// of the trap; the x PIE field of mstatus
|
// of the trap; the x PIE field of mstatus
|
||||||
|
@ -55,8 +55,6 @@
|
|||||||
#include <util/ities.h>
|
#include <util/ities.h>
|
||||||
#include <util/sparse_array.h>
|
#include <util/sparse_array.h>
|
||||||
|
|
||||||
#include <iss/semihosting/semihosting.h>
|
|
||||||
|
|
||||||
#if defined(__GNUC__)
|
#if defined(__GNUC__)
|
||||||
#define likely(x) __builtin_expect(!!(x), 1)
|
#define likely(x) __builtin_expect(!!(x), 1)
|
||||||
#define unlikely(x) __builtin_expect(!!(x), 0)
|
#define unlikely(x) __builtin_expect(!!(x), 0)
|
||||||
@ -319,8 +317,6 @@ public:
|
|||||||
|
|
||||||
void set_irq_num(unsigned i) { mcause_max_irq = 1 << util::ilog2(i); }
|
void set_irq_num(unsigned i) { mcause_max_irq = 1 << util::ilog2(i); }
|
||||||
|
|
||||||
void set_semihosting_callback(std::function<void(arch_if*, reg_t, reg_t)>& cb) { semihosting_cb = cb; };
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
struct riscv_instrumentation_if : public iss::instrumentation_if {
|
struct riscv_instrumentation_if : public iss::instrumentation_if {
|
||||||
|
|
||||||
@ -375,11 +371,9 @@ protected:
|
|||||||
reg_t fault_data;
|
reg_t fault_data;
|
||||||
uint64_t tohost = tohost_dflt;
|
uint64_t tohost = tohost_dflt;
|
||||||
uint64_t fromhost = fromhost_dflt;
|
uint64_t fromhost = fromhost_dflt;
|
||||||
bool tohost_lower_written = false;
|
unsigned to_host_wr_cnt = 0;
|
||||||
riscv_instrumentation_if instr_if;
|
riscv_instrumentation_if instr_if;
|
||||||
|
|
||||||
std::function<void(arch_if*, reg_t, reg_t)> semihosting_cb;
|
|
||||||
|
|
||||||
using mem_type = util::sparse_array<uint8_t, 1ULL << 32>;
|
using mem_type = util::sparse_array<uint8_t, 1ULL << 32>;
|
||||||
using csr_type = util::sparse_array<typename traits<BASE>::reg_t, 1ULL << 12, 12>;
|
using csr_type = util::sparse_array<typename traits<BASE>::reg_t, 1ULL << 12, 12>;
|
||||||
using csr_page_type = typename csr_type::page_type;
|
using csr_page_type = typename csr_type::page_type;
|
||||||
@ -1323,7 +1317,6 @@ iss::status riscv_hart_mu_p<BASE, FEAT>::read_mem(phys_addr_t paddr, unsigned le
|
|||||||
template <typename BASE, features_e FEAT>
|
template <typename BASE, features_e FEAT>
|
||||||
iss::status riscv_hart_mu_p<BASE, FEAT>::write_mem(phys_addr_t paddr, unsigned length, const uint8_t* const data) {
|
iss::status riscv_hart_mu_p<BASE, FEAT>::write_mem(phys_addr_t paddr, unsigned length, const uint8_t* const data) {
|
||||||
switch(paddr.val) {
|
switch(paddr.val) {
|
||||||
// TODO remove UART, Peripherals should not be part of the ISS
|
|
||||||
case 0xFFFF0000: // UART0 base, TXFIFO reg
|
case 0xFFFF0000: // UART0 base, TXFIFO reg
|
||||||
if(((char)data[0]) == '\n' || data[0] == 0) {
|
if(((char)data[0]) == '\n' || data[0] == 0) {
|
||||||
LOG(INFO) << "UART" << ((paddr.val >> 12) & 0x3) << " send '" << uart_buf.str() << "'";
|
LOG(INFO) << "UART" << ((paddr.val >> 12) & 0x3) << " send '" << uart_buf.str() << "'";
|
||||||
@ -1341,8 +1334,7 @@ iss::status riscv_hart_mu_p<BASE, FEAT>::write_mem(phys_addr_t paddr, unsigned l
|
|||||||
auto tohost_lower = (traits<BASE>::XLEN == 32 && paddr.val == tohost) || (traits<BASE>::XLEN == 64 && paddr.val == tohost);
|
auto tohost_lower = (traits<BASE>::XLEN == 32 && paddr.val == tohost) || (traits<BASE>::XLEN == 64 && paddr.val == tohost);
|
||||||
if(tohost_lower || tohost_upper) {
|
if(tohost_lower || tohost_upper) {
|
||||||
uint64_t hostvar = *reinterpret_cast<uint64_t*>(p.data() + (tohost & mem.page_addr_mask));
|
uint64_t hostvar = *reinterpret_cast<uint64_t*>(p.data() + (tohost & mem.page_addr_mask));
|
||||||
// in case of 32 bit system, two writes to tohost are needed, only evaluate on the second (high) write
|
if(tohost_upper || (tohost_lower && to_host_wr_cnt > 0)) {
|
||||||
if(tohost_upper && (tohost_lower || tohost_lower_written)) {
|
|
||||||
switch(hostvar >> 48) {
|
switch(hostvar >> 48) {
|
||||||
case 0:
|
case 0:
|
||||||
if(hostvar != 0x1) {
|
if(hostvar != 0x1) {
|
||||||
@ -1354,10 +1346,8 @@ iss::status riscv_hart_mu_p<BASE, FEAT>::write_mem(phys_addr_t paddr, unsigned l
|
|||||||
}
|
}
|
||||||
this->reg.trap_state = std::numeric_limits<uint32_t>::max();
|
this->reg.trap_state = std::numeric_limits<uint32_t>::max();
|
||||||
this->interrupt_sim = hostvar;
|
this->interrupt_sim = hostvar;
|
||||||
#ifndef WITH_TCC
|
|
||||||
throw(iss::simulation_stopped(hostvar));
|
|
||||||
#endif
|
|
||||||
break;
|
break;
|
||||||
|
// throw(iss::simulation_stopped(hostvar));
|
||||||
case 0x0101: {
|
case 0x0101: {
|
||||||
char c = static_cast<char>(hostvar & 0xff);
|
char c = static_cast<char>(hostvar & 0xff);
|
||||||
if(c == '\n' || c == 0) {
|
if(c == '\n' || c == 0) {
|
||||||
@ -1365,13 +1355,13 @@ iss::status riscv_hart_mu_p<BASE, FEAT>::write_mem(phys_addr_t paddr, unsigned l
|
|||||||
uart_buf.str("");
|
uart_buf.str("");
|
||||||
} else
|
} else
|
||||||
uart_buf << c;
|
uart_buf << c;
|
||||||
|
to_host_wr_cnt = 0;
|
||||||
} break;
|
} break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
tohost_lower_written = false;
|
|
||||||
} else if(tohost_lower)
|
} else if(tohost_lower)
|
||||||
tohost_lower_written = true;
|
to_host_wr_cnt++;
|
||||||
} else if((traits<BASE>::XLEN == 32 && paddr.val == fromhost + 4) || (traits<BASE>::XLEN == 64 && paddr.val == fromhost)) {
|
} else if((traits<BASE>::XLEN == 32 && paddr.val == fromhost + 4) || (traits<BASE>::XLEN == 64 && paddr.val == fromhost)) {
|
||||||
uint64_t fhostvar = *reinterpret_cast<uint64_t*>(p.data() + (fromhost & mem.page_addr_mask));
|
uint64_t fhostvar = *reinterpret_cast<uint64_t*>(p.data() + (fromhost & mem.page_addr_mask));
|
||||||
*reinterpret_cast<uint64_t*>(p.data() + (tohost & mem.page_addr_mask)) = fhostvar;
|
*reinterpret_cast<uint64_t*>(p.data() + (tohost & mem.page_addr_mask)) = fhostvar;
|
||||||
@ -1484,31 +1474,6 @@ template <typename BASE, features_e FEAT> uint64_t riscv_hart_mu_p<BASE, FEAT>::
|
|||||||
} else {
|
} else {
|
||||||
csr[utval | (new_priv << 8)] = addr;
|
csr[utval | (new_priv << 8)] = addr;
|
||||||
}
|
}
|
||||||
if(semihosting_cb) {
|
|
||||||
// Check for semihosting call
|
|
||||||
phys_addr_t p_addr(access_type::DEBUG_READ, traits<BASE>::MEM, addr - 4);
|
|
||||||
std::array<uint8_t, 8> data;
|
|
||||||
// check for SLLI_X0_X0_0X1F and SRAI_X0_X0_0X07
|
|
||||||
this->read_mem(p_addr, 4, data.data());
|
|
||||||
p_addr.val += 8;
|
|
||||||
this->read_mem(p_addr, 4, data.data() + 4);
|
|
||||||
|
|
||||||
const std::array<uint8_t, 8> ref_data = {0x13, 0x10, 0xf0, 0x01, 0x13, 0x50, 0x70, 0x40};
|
|
||||||
if(data == ref_data) {
|
|
||||||
this->reg.NEXT_PC = addr + 8;
|
|
||||||
|
|
||||||
std::array<char, 32> buffer;
|
|
||||||
#if defined(_MSC_VER)
|
|
||||||
sprintf(buffer.data(), "0x%016llx", addr);
|
|
||||||
#else
|
|
||||||
sprintf(buffer.data(), "0x%016lx", addr);
|
|
||||||
#endif
|
|
||||||
CLOG(INFO, disass) << "Semihosting call at address " << buffer.data() << " occurred ";
|
|
||||||
|
|
||||||
semihosting_callback(this, this->reg.X10 /*a0*/, this->reg.X11 /*a1*/);
|
|
||||||
return this->reg.NEXT_PC;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
case 6:
|
case 6:
|
||||||
|
@ -1,132 +0,0 @@
|
|||||||
#include "semihosting.h"
|
|
||||||
#include <cstdint>
|
|
||||||
#include <iss/vm_types.h>
|
|
||||||
#include <stdexcept>
|
|
||||||
// explanation of syscalls can be found at https://github.com/SpinalHDL/openocd_riscv/blob/riscv_spinal/src/target/semihosting_common.h
|
|
||||||
template <typename T> void semihosting_callback(iss::arch_if* arch_if_ptr, T call_number, T parameter) {
|
|
||||||
switch(static_cast<semihosting_syscalls>(call_number)) {
|
|
||||||
case semihosting_syscalls::SYS_CLOCK: {
|
|
||||||
throw std::runtime_error("Semihosting Call not Implemented");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case semihosting_syscalls::SYS_CLOSE: {
|
|
||||||
throw std::runtime_error("Semihosting Call not Implemented");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case semihosting_syscalls::SYS_ELAPSED: {
|
|
||||||
throw std::runtime_error("Semihosting Call not Implemented");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case semihosting_syscalls::SYS_ERRNO: {
|
|
||||||
throw std::runtime_error("Semihosting Call not Implemented");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case semihosting_syscalls::SYS_EXIT: {
|
|
||||||
|
|
||||||
throw std::runtime_error("ISS terminated by Semihost: SYS_EXIT");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case semihosting_syscalls::SYS_EXIT_EXTENDED: {
|
|
||||||
throw std::runtime_error("ISS terminated by Semihost: SYS_EXIT_EXTENDED");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case semihosting_syscalls::SYS_FLEN: {
|
|
||||||
throw std::runtime_error("Semihosting Call not Implemented");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case semihosting_syscalls::SYS_GET_CMDLINE: {
|
|
||||||
throw std::runtime_error("Semihosting Call not Implemented");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case semihosting_syscalls::SYS_HEAPINFO: {
|
|
||||||
throw std::runtime_error("Semihosting Call not Implemented");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case semihosting_syscalls::SYS_ISERROR: {
|
|
||||||
throw std::runtime_error("Semihosting Call not Implemented");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case semihosting_syscalls::SYS_ISTTY: {
|
|
||||||
throw std::runtime_error("Semihosting Call not Implemented");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case semihosting_syscalls::SYS_OPEN: {
|
|
||||||
throw std::runtime_error("Semihosting Call not Implemented");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case semihosting_syscalls::SYS_READ: {
|
|
||||||
throw std::runtime_error("Semihosting Call not Implemented");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case semihosting_syscalls::SYS_READC: {
|
|
||||||
throw std::runtime_error("Semihosting Call not Implemented");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case semihosting_syscalls::SYS_REMOVE: {
|
|
||||||
throw std::runtime_error("Semihosting Call not Implemented");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case semihosting_syscalls::SYS_RENAME: {
|
|
||||||
throw std::runtime_error("Semihosting Call not Implemented");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case semihosting_syscalls::SYS_SEEK: {
|
|
||||||
throw std::runtime_error("Semihosting Call not Implemented");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case semihosting_syscalls::SYS_SYSTEM: {
|
|
||||||
throw std::runtime_error("Semihosting Call not Implemented");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case semihosting_syscalls::SYS_TICKFREQ: {
|
|
||||||
throw std::runtime_error("Semihosting Call not Implemented");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case semihosting_syscalls::SYS_TIME: {
|
|
||||||
throw std::runtime_error("Semihosting Call not Implemented");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case semihosting_syscalls::SYS_TMPNAM: {
|
|
||||||
throw std::runtime_error("Semihosting Call not Implemented");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case semihosting_syscalls::SYS_WRITE: {
|
|
||||||
throw std::runtime_error("Semihosting Call not Implemented");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case semihosting_syscalls::SYS_WRITEC: {
|
|
||||||
uint8_t character;
|
|
||||||
auto res = arch_if_ptr->read(iss::address_type::PHYSICAL, iss::access_type::DEBUG_READ, 0, parameter, 1, &character);
|
|
||||||
if(res != iss::Ok)
|
|
||||||
return;
|
|
||||||
putchar(character);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case semihosting_syscalls::SYS_WRITE0: {
|
|
||||||
uint8_t character;
|
|
||||||
while(1) {
|
|
||||||
auto res = arch_if_ptr->read(iss::address_type::PHYSICAL, iss::access_type::DEBUG_READ, 0, parameter, 1, &character);
|
|
||||||
if(res != iss::Ok)
|
|
||||||
return;
|
|
||||||
if(character == 0)
|
|
||||||
break;
|
|
||||||
putchar(character);
|
|
||||||
parameter++;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case semihosting_syscalls::USER_CMD_0x100: {
|
|
||||||
throw std::runtime_error("Semihosting Call not Implemented");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case semihosting_syscalls::USER_CMD_0x1FF: {
|
|
||||||
throw std::runtime_error("Semihosting Call not Implemented");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
throw std::runtime_error("Semihosting Call not Implemented");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
template void semihosting_callback<uint32_t>(iss::arch_if* arch_if_ptr, uint32_t call_number, uint32_t parameter);
|
|
||||||
template void semihosting_callback<uint64_t>(iss::arch_if* arch_if_ptr, uint64_t call_number, uint64_t parameter);
|
|
@ -1,53 +0,0 @@
|
|||||||
#ifndef _SEMIHOSTING_H_
|
|
||||||
#define _SEMIHOSTING_H_
|
|
||||||
#include <iss/arch_if.h>
|
|
||||||
/*
|
|
||||||
* According to:
|
|
||||||
* "Semihosting for AArch32 and AArch64, Release 2.0"
|
|
||||||
* https://static.docs.arm.com/100863/0200/semihosting.pdf
|
|
||||||
* from ARM Ltd.
|
|
||||||
*
|
|
||||||
* The available semihosting operation numbers passed in A0 are allocated
|
|
||||||
* as follows:
|
|
||||||
* - 0x00-0x31 Used by ARM.
|
|
||||||
* - 0x32-0xFF Reserved for future use by ARM.
|
|
||||||
* - 0x100-0x1FF Reserved for user applications. These are not used by ARM.
|
|
||||||
* However, if you are writing your own SVC operations, you are advised
|
|
||||||
* to use a different SVC number rather than using the semihosted
|
|
||||||
* SVC number and these operation type numbers.
|
|
||||||
* - 0x200-0xFFFFFFFF Undefined and currently unused. It is recommended
|
|
||||||
* that you do not use these.
|
|
||||||
*/
|
|
||||||
enum class semihosting_syscalls {
|
|
||||||
|
|
||||||
SYS_OPEN = 0x01,
|
|
||||||
SYS_CLOSE = 0x02,
|
|
||||||
SYS_WRITEC = 0x03,
|
|
||||||
SYS_WRITE0 = 0x04,
|
|
||||||
SYS_WRITE = 0x05,
|
|
||||||
SYS_READ = 0x06,
|
|
||||||
SYS_READC = 0x07,
|
|
||||||
SYS_ISERROR = 0x08,
|
|
||||||
SYS_ISTTY = 0x09,
|
|
||||||
SYS_SEEK = 0x0A,
|
|
||||||
SYS_FLEN = 0x0C,
|
|
||||||
SYS_TMPNAM = 0x0D,
|
|
||||||
SYS_REMOVE = 0x0E,
|
|
||||||
SYS_RENAME = 0x0F,
|
|
||||||
SYS_CLOCK = 0x10,
|
|
||||||
SYS_TIME = 0x11,
|
|
||||||
SYS_SYSTEM = 0x12,
|
|
||||||
SYS_ERRNO = 0x13,
|
|
||||||
SYS_GET_CMDLINE = 0x15,
|
|
||||||
SYS_HEAPINFO = 0x16,
|
|
||||||
SYS_EXIT = 0x18,
|
|
||||||
SYS_EXIT_EXTENDED = 0x20,
|
|
||||||
SYS_ELAPSED = 0x30,
|
|
||||||
SYS_TICKFREQ = 0x31,
|
|
||||||
USER_CMD_0x100 = 0x100,
|
|
||||||
USER_CMD_0x1FF = 0x1FF,
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename T> void semihosting_callback(iss::arch_if* arch_if_ptr, T call_number, T parameter);
|
|
||||||
|
|
||||||
#endif
|
|
@ -31,10 +31,8 @@
|
|||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <cstdint>
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <iss/factory.h>
|
#include <iss/factory.h>
|
||||||
#include <iss/semihosting/semihosting.h>
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "iss/arch/tgc_mapper.h"
|
#include "iss/arch/tgc_mapper.h"
|
||||||
@ -54,6 +52,7 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace po = boost::program_options;
|
namespace po = boost::program_options;
|
||||||
|
|
||||||
int main(int argc, char* argv[]) {
|
int main(int argc, char* argv[]) {
|
||||||
/*
|
/*
|
||||||
* Define and parse the program options
|
* Define and parse the program options
|
||||||
@ -117,7 +116,6 @@ int main(int argc, char* argv[]) {
|
|||||||
// instantiate the simulator
|
// instantiate the simulator
|
||||||
iss::vm_ptr vm{nullptr};
|
iss::vm_ptr vm{nullptr};
|
||||||
iss::cpu_ptr cpu{nullptr};
|
iss::cpu_ptr cpu{nullptr};
|
||||||
std::function<void(iss::arch_if*, uint32_t, uint32_t)> semihosting_cb = &semihosting_callback<uint32_t>;
|
|
||||||
std::string isa_opt(clim["isa"].as<std::string>());
|
std::string isa_opt(clim["isa"].as<std::string>());
|
||||||
if(isa_opt.size() == 0 || isa_opt == "?") {
|
if(isa_opt.size() == 0 || isa_opt == "?") {
|
||||||
auto list = f.get_names();
|
auto list = f.get_names();
|
||||||
@ -125,8 +123,7 @@ int main(int argc, char* argv[]) {
|
|||||||
std::cout << "Available implementations (core|platform|backend):\n - " << util::join(list, "\n - ") << std::endl;
|
std::cout << "Available implementations (core|platform|backend):\n - " << util::join(list, "\n - ") << std::endl;
|
||||||
return 0;
|
return 0;
|
||||||
} else if(isa_opt.find('|') != std::string::npos) {
|
} else if(isa_opt.find('|') != std::string::npos) {
|
||||||
std::tie(cpu, vm) =
|
std::tie(cpu, vm) = f.create(isa_opt + "|" + clim["backend"].as<std::string>(), clim["gdb-port"].as<unsigned>());
|
||||||
f.create(isa_opt + "|" + clim["backend"].as<std::string>(), clim["gdb-port"].as<unsigned>(), &semihosting_cb);
|
|
||||||
} else {
|
} else {
|
||||||
auto base_isa = isa_opt.substr(0, 5);
|
auto base_isa = isa_opt.substr(0, 5);
|
||||||
if(base_isa == "tgc5d" || base_isa == "tgc5e") {
|
if(base_isa == "tgc5d" || base_isa == "tgc5e") {
|
||||||
@ -134,7 +131,7 @@ int main(int argc, char* argv[]) {
|
|||||||
} else {
|
} else {
|
||||||
isa_opt += "|m_p|" + clim["backend"].as<std::string>();
|
isa_opt += "|m_p|" + clim["backend"].as<std::string>();
|
||||||
}
|
}
|
||||||
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>());
|
||||||
}
|
}
|
||||||
if(!cpu) {
|
if(!cpu) {
|
||||||
LOG(ERR) << "Could not create cpu for isa " << isa_opt << " and backend " << clim["backend"].as<std::string>() << std::endl;
|
LOG(ERR) << "Could not create cpu for isa " << isa_opt << " and backend " << clim["backend"].as<std::string>() << std::endl;
|
||||||
|
@ -3752,24 +3752,16 @@ std::unique_ptr<vm_if> create<arch::tgc5c>(arch::tgc5c *core, unsigned short por
|
|||||||
namespace iss {
|
namespace iss {
|
||||||
namespace {
|
namespace {
|
||||||
volatile std::array<bool, 2> dummy = {
|
volatile std::array<bool, 2> dummy = {
|
||||||
core_factory::instance().register_creator("tgc5c|m_p|asmjit", [](unsigned port, void* init_data) -> std::tuple<cpu_ptr, vm_ptr>{
|
core_factory::instance().register_creator("tgc5c|m_p|asmjit", [](unsigned port, void*) -> std::tuple<cpu_ptr, vm_ptr>{
|
||||||
auto* cpu = new iss::arch::riscv_hart_m_p<iss::arch::tgc5c>();
|
auto* cpu = new iss::arch::riscv_hart_m_p<iss::arch::tgc5c>();
|
||||||
auto vm = new asmjit::tgc5c::vm_impl<arch::tgc5c>(*cpu, false);
|
auto* vm = new asmjit::tgc5c::vm_impl<arch::tgc5c>(*cpu, false);
|
||||||
if (port != 0) debugger::server<debugger::gdb_session>::run_server(vm, port);
|
if (port != 0) debugger::server<debugger::gdb_session>::run_server(vm, port);
|
||||||
if(init_data){
|
|
||||||
auto* cb = reinterpret_cast<std::function<void(arch_if*, arch::traits<arch::tgc5c>::reg_t, arch::traits<arch::tgc5c>::reg_t)>*>(init_data);
|
|
||||||
cpu->set_semihosting_callback(*cb);
|
|
||||||
}
|
|
||||||
return {cpu_ptr{cpu}, vm_ptr{vm}};
|
return {cpu_ptr{cpu}, vm_ptr{vm}};
|
||||||
}),
|
}),
|
||||||
core_factory::instance().register_creator("tgc5c|mu_p|asmjit", [](unsigned port, void* init_data) -> std::tuple<cpu_ptr, vm_ptr>{
|
core_factory::instance().register_creator("tgc5c|mu_p|asmjit", [](unsigned port, void*) -> std::tuple<cpu_ptr, vm_ptr>{
|
||||||
auto* cpu = new iss::arch::riscv_hart_mu_p<iss::arch::tgc5c>();
|
auto* cpu = new iss::arch::riscv_hart_mu_p<iss::arch::tgc5c>();
|
||||||
auto vm = new asmjit::tgc5c::vm_impl<arch::tgc5c>(*cpu, false);
|
auto* vm = new asmjit::tgc5c::vm_impl<arch::tgc5c>(*cpu, false);
|
||||||
if (port != 0) debugger::server<debugger::gdb_session>::run_server(vm, port);
|
if (port != 0) debugger::server<debugger::gdb_session>::run_server(vm, port);
|
||||||
if(init_data){
|
|
||||||
auto* cb = reinterpret_cast<std::function<void(arch_if*, arch::traits<arch::tgc5c>::reg_t, arch::traits<arch::tgc5c>::reg_t)>*>(init_data);
|
|
||||||
cpu->set_semihosting_callback(*cb);
|
|
||||||
}
|
|
||||||
return {cpu_ptr{cpu}, vm_ptr{vm}};
|
return {cpu_ptr{cpu}, vm_ptr{vm}};
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
|
@ -2695,24 +2695,16 @@ std::unique_ptr<vm_if> create<arch::tgc5c>(arch::tgc5c *core, unsigned short por
|
|||||||
namespace iss {
|
namespace iss {
|
||||||
namespace {
|
namespace {
|
||||||
volatile std::array<bool, 2> dummy = {
|
volatile std::array<bool, 2> dummy = {
|
||||||
core_factory::instance().register_creator("tgc5c|m_p|interp", [](unsigned port, void* init_data) -> std::tuple<cpu_ptr, vm_ptr>{
|
core_factory::instance().register_creator("tgc5c|m_p|interp", [](unsigned port, void*) -> std::tuple<cpu_ptr, vm_ptr>{
|
||||||
auto* cpu = new iss::arch::riscv_hart_m_p<iss::arch::tgc5c>();
|
auto* cpu = new iss::arch::riscv_hart_m_p<iss::arch::tgc5c>();
|
||||||
auto vm = new interp::tgc5c::vm_impl<arch::tgc5c>(*cpu, false);
|
auto vm = new interp::tgc5c::vm_impl<arch::tgc5c>(*cpu, false);
|
||||||
if (port != 0) debugger::server<debugger::gdb_session>::run_server(vm, port);
|
if (port != 0) debugger::server<debugger::gdb_session>::run_server(vm, port);
|
||||||
if(init_data){
|
|
||||||
auto* cb = reinterpret_cast<std::function<void(arch_if*, arch::traits<arch::tgc5c>::reg_t, arch::traits<arch::tgc5c>::reg_t)>*>(init_data);
|
|
||||||
cpu->set_semihosting_callback(*cb);
|
|
||||||
}
|
|
||||||
return {cpu_ptr{cpu}, vm_ptr{vm}};
|
return {cpu_ptr{cpu}, vm_ptr{vm}};
|
||||||
}),
|
}),
|
||||||
core_factory::instance().register_creator("tgc5c|mu_p|interp", [](unsigned port, void* init_data) -> std::tuple<cpu_ptr, vm_ptr>{
|
core_factory::instance().register_creator("tgc5c|mu_p|interp", [](unsigned port, void*) -> std::tuple<cpu_ptr, vm_ptr>{
|
||||||
auto* cpu = new iss::arch::riscv_hart_mu_p<iss::arch::tgc5c>();
|
auto* cpu = new iss::arch::riscv_hart_mu_p<iss::arch::tgc5c>();
|
||||||
auto vm = new interp::tgc5c::vm_impl<arch::tgc5c>(*cpu, false);
|
auto vm = new interp::tgc5c::vm_impl<arch::tgc5c>(*cpu, false);
|
||||||
if (port != 0) debugger::server<debugger::gdb_session>::run_server(vm, port);
|
if (port != 0) debugger::server<debugger::gdb_session>::run_server(vm, port);
|
||||||
if(init_data){
|
|
||||||
auto* cb = reinterpret_cast<std::function<void(arch_if*, arch::traits<arch::tgc5c>::reg_t, arch::traits<arch::tgc5c>::reg_t)>*>(init_data);
|
|
||||||
cpu->set_semihosting_callback(*cb);
|
|
||||||
}
|
|
||||||
return {cpu_ptr{cpu}, vm_ptr{vm}};
|
return {cpu_ptr{cpu}, vm_ptr{vm}};
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user