diff --git a/CMakeLists.txt b/CMakeLists.txt index 2a36dad..8559904 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,80 +1,75 @@ cmake_minimum_required(VERSION 3.12) +list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake) ############################################################################### # ############################################################################### project(dbt-rise-tgc VERSION 1.0.0) include(GNUInstallDirs) +include(flink) find_package(elfio QUIET) find_package(Boost COMPONENTS coroutine) find_package(jsoncpp) +if(TARGET tcc::tcc) + set(WITH_TCC ON) +endif() + if(WITH_LLVM) if(DEFINED ENV{LLVM_HOME}) find_path (LLVM_DIR LLVM-Config.cmake $ENV{LLVM_HOME}/lib/cmake/llvm) - endif(DEFINED ENV{LLVM_HOME}) - find_package(LLVM REQUIRED CONFIG) - message(STATUS "Found LLVM ${LLVM_PACKAGE_VERSION}") - message(STATUS "Using LLVMConfig.cmake in: ${LLVM_DIR}") - llvm_map_components_to_libnames(llvm_libs support core mcjit x86codegen x86asmparser) + endif() + find_package(LLVM QUIET CONFIG) + if(LLVM_FOUND) + message(STATUS "Found LLVM ${LLVM_PACKAGE_VERSION}") + message(STATUS "Using LLVMConfig.cmake in: ${LLVM_DIR}") + llvm_map_components_to_libnames(llvm_libs support core mcjit x86codegen x86asmparser) + else() + find_package(LLVM REQUIRED LLVMSupport LLVMCore LLVMMCJIT LLVMX86CodeGen LLVMX86AsmParser) + endif() endif() -#Mac needed variables (adapt for your needs - http://www.cmake.org/Wiki/CMake_RPATH_handling#Mac_OS_X_and_the_RPATH) -#set(CMAKE_MACOSX_RPATH ON) -#set(CMAKE_SKIP_BUILD_RPATH FALSE) -#set(CMAKE_BUILD_WITH_INSTALL_RPATH FALSE) -#set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib") -#set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE) - add_subdirectory(softfloat) set(LIB_SOURCES src/iss/plugin/instruction_count.cpp src/iss/arch/tgc_c.cpp + src/vm/tcc/vm_tgc_c.cpp src/vm/interp/vm_tgc_c.cpp src/vm/fp_functions.cpp ) +if(WITH_TCC) + list(APPEND LIB_SOURCES src/vm/tcc/vm_tgc_c.cpp) +endif() # library files -if(TARGET ${CORE_NAME}_cpp) - list(APPEND LIB_SOURCES ${${CORE_NAME}_OUTPUT_FILES}) -else() - 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) - list(APPEND LIB_SOURCES ${GEN_ISS_SOURCES} ${GEN_VM_SOURCES}) - foreach(FILEPATH ${GEN_ISS_SOURCES}) - get_filename_component(CORE ${FILEPATH} NAME_WE) - string(TOUPPER ${CORE} CORE) - list(APPEND LIB_DEFINES CORE_${CORE}) - endforeach() - message("Defines are ${LIB_DEFINES}") +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) +list(APPEND LIB_SOURCES ${GEN_ISS_SOURCES} ${GEN_VM_SOURCES}) +foreach(FILEPATH ${GEN_ISS_SOURCES}) + get_filename_component(CORE ${FILEPATH} NAME_WE) + string(TOUPPER ${CORE} CORE) + list(APPEND LIB_DEFINES CORE_${CORE}) +endforeach() +message("Core defines are ${LIB_DEFINES}") + +if(WITH_LLVM) + FILE(GLOB LLVM_GEN_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src-gen/vm/llvm/vm_*.cpp) + list(APPEND LIB_SOURCES ${LLVM_GEN_SOURCES}) +endif() + +if(WITH_TCC) + FILE(GLOB TCC_GEN_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src-gen/vm/tcc/vm_*.cpp) + list(APPEND LIB_SOURCES ${TCC_GEN_SOURCES}) endif() if(TARGET RapidJSON OR TARGET RapidJSON::RapidJSON) list(APPEND LIB_SOURCES src/iss/plugin/cycle_estimate.cpp src/iss/plugin/pctrace.cpp) endif() -if(WITH_LLVM) - FILE(GLOB LLVM_GEN_SOURCES - ${CMAKE_CURRENT_SOURCE_DIR}/src-gen/vm/llvm/vm_*.cpp - ) - list(APPEND LIB_SOURCES ${LLVM_GEN_SOURCES}) -endif() - -if(WITH_TCC) - FILE(GLOB TCC_GEN_SOURCES - ${CMAKE_CURRENT_SOURCE_DIR}/src/vm/tcc/vm_*.cpp - ) - list(APPEND LIB_SOURCES ${TCC_GEN_SOURCES}) -endif() - # Define the library add_library(${PROJECT_NAME} ${LIB_SOURCES}) -# list code gen dependencies -if(TARGET ${CORE_NAME}_cpp) - add_dependencies(${PROJECT_NAME} ${CORE_NAME}_cpp) -endif() if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") target_compile_options(${PROJECT_NAME} PRIVATE -Wno-shift-count-overflow) @@ -89,8 +84,8 @@ if(TARGET jsoncpp::jsoncpp) else() target_link_libraries(${PROJECT_NAME} PUBLIC jsoncpp) endif() -if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" AND BUILD_SHARED_LIBS) - target_link_libraries(${PROJECT_NAME} PUBLIC -Wl,--whole-archive dbt-rise-core -Wl,--no-whole-archive) +if(BUILD_SHARED_LIBS) + target_force_link_libraries(${PROJECT_NAME} PUBLIC dbt-rise-core) else() target_link_libraries(${PROJECT_NAME} PUBLIC dbt-rise-core) endif() @@ -161,7 +156,7 @@ if(WITH_TCC) target_compile_definitions(${PROJECT_NAME} PRIVATE WITH_TCC) endif() # Links the target exe against the libraries -target_link_libraries(${PROJECT_NAME} PUBLIC dbt-rise-tgc) +target_force_link_libraries(${PROJECT_NAME} PUBLIC dbt-rise-tgc) if(TARGET Boost::program_options) target_link_libraries(${PROJECT_NAME} PUBLIC Boost::program_options) else() @@ -186,7 +181,13 @@ install(TARGETS tgc-sim ############################################################################### if(TARGET scc-sysc) project(dbt-rise-tgc_sc VERSION 1.0.0) - add_library(${PROJECT_NAME} src/sysc/core_complex.cpp) + set(LIB_SOURCES + src/sysc/core_complex.cpp + src/sysc/register_tgc_c.cpp + ) + FILE(GLOB GEN_SC_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src-gen/sysc/register_*.cpp) + list(APPEND LIB_SOURCES ${GEN_SC_SOURCES}) + add_library(${PROJECT_NAME} ${LIB_SOURCES}) target_compile_definitions(${PROJECT_NAME} PUBLIC WITH_SYSTEMC) target_compile_definitions(${PROJECT_NAME} PRIVATE CORE_${CORE_NAME}) foreach(F IN LISTS TGC_SOURCES) diff --git a/cmake/flink.cmake b/cmake/flink.cmake new file mode 100644 index 0000000..69b5c9f --- /dev/null +++ b/cmake/flink.cmake @@ -0,0 +1,35 @@ +# according to https://github.com/horance-liu/flink.cmake/tree/master +# SPDX-License-Identifier: Apache-2.0 + +include(CMakeParseArguments) + +function(target_do_force_link_libraries target visibility lib) + if(MSVC) + target_link_libraries(${target} ${visibility} "/WHOLEARCHIVE:${lib}") + elseif(APPLE) + target_link_libraries(${target} ${visibility} -Wl,-force_load ${lib}) + else() + target_link_libraries(${target} ${visibility} -Wl,--whole-archive ${lib} -Wl,--no-whole-archive) + endif() +endfunction() + +function(target_force_link_libraries target) + cmake_parse_arguments(FLINK + "" + "" + "PUBLIC;INTERFACE;PRIVATE" + ${ARGN} + ) + + foreach(lib IN LISTS FLINK_PUBLIC) + target_do_force_link_libraries(${target} PUBLIC ${lib}) + endforeach() + + foreach(lib IN LISTS FLINK_INTERFACE) + target_do_force_link_libraries(${target} INTERFACE ${lib}) + endforeach() + + foreach(lib IN LISTS FLINK_PRIVATE) + target_do_force_link_libraries(${target} PRIVATE ${lib}) + endforeach() +endfunction() \ No newline at end of file diff --git a/gen_input/templates/CORENAME.h.gtl b/gen_input/templates/CORENAME.h.gtl index 83fb8e1..2debd97 100644 --- a/gen_input/templates/CORENAME.h.gtl +++ b/gen_input/templates/CORENAME.h.gtl @@ -55,7 +55,7 @@ def byteSize(int size){ return 128; } def getCString(def val){ - return val.toString() + return val.toString()+'ULL' } %> #ifndef _${coreDef.name.toUpperCase()}_H_ @@ -111,7 +111,7 @@ template <> struct traits<${coreDef.name.toLowerCase()}> { enum mem_type_e { ${spaces.collect{it.name}.join(', ')} }; - enum class opcode_e : unsigned short {<%instructions.eachWithIndex{instr, index -> %> + enum class opcode_e {<%instructions.eachWithIndex{instr, index -> %> ${instr.instruction.name} = ${index},<%}%> MAX_OPCODE }; diff --git a/gen_input/templates/CORENAME_sysc.cpp.gtl b/gen_input/templates/CORENAME_sysc.cpp.gtl new file mode 100644 index 0000000..e56e7db --- /dev/null +++ b/gen_input/templates/CORENAME_sysc.cpp.gtl @@ -0,0 +1,72 @@ +/******************************************************************************* + * Copyright (C) 2023 MINRES Technologies GmbH + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + *******************************************************************************/ + +#include "iss_factory.h" +#include +#include +#include +#include "sc_core_adapter.h" +#include "core_complex.h" + +namespace iss { +namespace interp { +using namespace sysc; +volatile std::array ${coreDef.name.toLowerCase()}_init = { + iss_factory::instance().register_creator("${coreDef.name.toLowerCase()}|m_p|interp", [](unsigned gdb_port, void* data) -> iss_factory::base_t { + auto* cc = reinterpret_cast(data); + auto* cpu = new sc_core_adapter>(cc); + return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast(cpu), gdb_port)}}; + }), + iss_factory::instance().register_creator("${coreDef.name.toLowerCase()}|mu_p|interp", [](unsigned gdb_port, void* data) -> iss_factory::base_t { + auto* cc = reinterpret_cast(data); + auto* cpu = new sc_core_adapter>(cc); + return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast(cpu), gdb_port)}}; + }) +}; +} +#if defined(WITH_TCC) +namespace tcc { +volatile std::array ${coreDef.name.toLowerCase()}_init = { + core_factory::instance().register_creator("${coreDef.name.toLowerCase()}|m_p|tcc", [](unsigned gdb_port, void* data) -> std::tuple{ + auto cc = reinterpret_cast(data); + auto* cpu = new sc_core_adapter>(cc); + return {cpu_ptr{cpu}, vm_ptr{create(static_cast(cpu), gdb_port)}}; + }), + core_factory::instance().register_creator("${coreDef.name.toLowerCase()}|mu_p|tcc", [](unsigned gdb_port, void* data) -> std::tuple{ + auto cc = reinterpret_cast(data); + auto* cpu = new sc_core_adapter>(cc); + return {cpu_ptr{cpu}, vm_ptr{create(static_cast(cpu), gdb_port)}}; + }) +}; +} +#endif +} diff --git a/gen_input/templates/interp/CORENAME.cpp.gtl b/gen_input/templates/interp/CORENAME.cpp.gtl index 9585627..333a9eb 100644 --- a/gen_input/templates/interp/CORENAME.cpp.gtl +++ b/gen_input/templates/interp/CORENAME.cpp.gtl @@ -34,10 +34,9 @@ def nativeTypeSize(int size){ if(size<=8) return 8; else if(size<=16) return 16; else if(size<=32) return 32; else return 64; } %> +#include #include #include -#include -#include #include #include #include @@ -343,7 +342,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co return pc; } -} +} // namespace ${coreDef.name.toLowerCase()} template <> std::unique_ptr create(arch::${coreDef.name.toLowerCase()} *core, unsigned short port, bool dump) { @@ -353,3 +352,25 @@ std::unique_ptr create(arch::${coreD } } // namespace interp } // namespace iss + +#include +#include +#include +namespace iss { +namespace { +volatile std::array dummy = { + core_factory::instance().register_creator("${coreDef.name.toLowerCase()}|m_p|interp", [](unsigned port, void*) -> std::tuple{ + auto* cpu = new iss::arch::riscv_hart_m_p(); + auto vm = new interp::${coreDef.name.toLowerCase()}::vm_impl(*cpu, false); + if (port != 0) debugger::server::run_server(vm, port); + return {cpu_ptr{cpu}, vm_ptr{vm}}; + }), + core_factory::instance().register_creator("${coreDef.name.toLowerCase()}|mu_p|interp", [](unsigned port, void*) -> std::tuple{ + auto* cpu = new iss::arch::riscv_hart_mu_p(); + auto vm = new interp::${coreDef.name.toLowerCase()}::vm_impl(*cpu, false); + if (port != 0) debugger::server::run_server(vm, port); + return {cpu_ptr{cpu}, vm_ptr{vm}}; + }) +}; +} +} diff --git a/gen_input/templates/tcc/CORENAME.cpp.gtl b/gen_input/templates/tcc/CORENAME.cpp.gtl index 809ae00..832422a 100644 --- a/gen_input/templates/tcc/CORENAME.cpp.gtl +++ b/gen_input/templates/tcc/CORENAME.cpp.gtl @@ -31,7 +31,6 @@ *******************************************************************************/ #include -#include #include #include #include @@ -300,7 +299,7 @@ template void vm_impl::gen_trap_behavior(tu_builder& tu) { tu("return *next_pc;"); } -} // namespace mnrv32 +} // namespace ${coreDef.name.toLowerCase()} template <> std::unique_ptr create(arch::${coreDef.name.toLowerCase()} *core, unsigned short port, bool dump) { @@ -308,5 +307,27 @@ std::unique_ptr create(arch::${coreD if (port != 0) debugger::server::run_server(ret, port); return std::unique_ptr(ret); } -} +} // namesapce tcc } // namespace iss + +#include +#include +#include +namespace iss { +namespace { +volatile std::array dummy = { + core_factory::instance().register_creator("${coreDef.name.toLowerCase()}|m_p|tcc", [](unsigned port, void*) -> std::tuple{ + auto* cpu = new iss::arch::riscv_hart_m_p(); + auto vm = new tcc::${coreDef.name.toLowerCase()}::vm_impl(*cpu, false); + if (port != 0) debugger::server::run_server(vm, port); + return {cpu_ptr{cpu}, vm_ptr{vm}}; + }), + core_factory::instance().register_creator("${coreDef.name.toLowerCase()}|mu_p|tcc", [](unsigned port, void*) -> std::tuple{ + auto* cpu = new iss::arch::riscv_hart_mu_p(); + auto vm = new tcc::${coreDef.name.toLowerCase()}::vm_impl(*cpu, false); + if (port != 0) debugger::server::run_server(vm, port); + return {cpu_ptr{cpu}, vm_ptr{vm}}; + }) +}; +} +} diff --git a/src-gen/.gitignore b/src-gen/.gitignore index d3fcb35..454f93f 100644 --- a/src-gen/.gitignore +++ b/src-gen/.gitignore @@ -1,2 +1,3 @@ /iss -/vm \ No newline at end of file +/vm +/sysc \ No newline at end of file diff --git a/src/iss/arch/tgc_c.h b/src/iss/arch/tgc_c.h index f0d53f3..2f33ca5 100644 --- a/src/iss/arch/tgc_c.h +++ b/src/iss/arch/tgc_c.h @@ -53,7 +53,7 @@ template <> struct traits { static constexpr std::array reg_aliases{ {"ZERO", "RA", "SP", "GP", "TP", "T0", "T1", "T2", "S0", "S1", "A0", "A1", "A2", "A3", "A4", "A5", "A6", "A7", "S2", "S3", "S4", "S5", "S6", "S7", "S8", "S9", "S10", "S11", "T3", "T4", "T5", "T6", "PC", "NEXT_PC", "PRIV", "DPC"}}; - enum constants {MISA_VAL=1073746180, MARCHID_VAL=2147483651, XLEN=32, INSTR_ALIGNMENT=2, RFS=32, fence=0, fencei=1, fencevmal=2, fencevmau=3, CSR_SIZE=4096, MUL_LEN=64}; + enum constants {MISA_VAL=1073746180ULL, MARCHID_VAL=2147483651ULL, XLEN=32ULL, INSTR_ALIGNMENT=2ULL, RFS=32ULL, fence=0ULL, fencei=1ULL, fencevmal=2ULL, fencevmau=3ULL, CSR_SIZE=4096ULL, MUL_LEN=64ULL}; constexpr static unsigned FP_REGS_SIZE = 0; @@ -83,7 +83,7 @@ template <> struct traits { enum mem_type_e { MEM, FENCE, RES, CSR }; - enum class opcode_e : unsigned short { + enum class opcode_e { LUI = 0, AUIPC = 1, JAL = 2, diff --git a/src/iss/factory.h b/src/iss/factory.h index 0d43538..c24fefb 100644 --- a/src/iss/factory.h +++ b/src/iss/factory.h @@ -34,6 +34,12 @@ #define _ISS_FACTORY_H_ #include +#include +#include +#include +#include +#include +#include namespace iss { @@ -57,6 +63,44 @@ std::tuple create_cpu(std::string const& backend, unsigned gdb_ return {nullptr, nullptr}; } + +class core_factory { + using cpu_ptr = std::unique_ptr; + using vm_ptr= std::unique_ptr; + using base_t = std::tuple; + using create_fn = std::function; + using registry_t = std::unordered_map ; + + registry_t registry; + + core_factory() = default; + core_factory(const core_factory &) = delete; + core_factory & operator=(const core_factory &) = delete; + +public: + static core_factory & instance() { static core_factory bf; return bf; } + + bool register_creator(const std::string & className, create_fn const& fn) { + registry[className] = fn; + return true; + } + + base_t create(std::string const& className, unsigned gdb_port=0, void* init_data=nullptr) const { + registry_t::const_iterator regEntry = registry.find(className); + if (regEntry != registry.end()) + return regEntry->second(gdb_port, init_data); + return {nullptr, nullptr}; + } + + std::vector get_names() { + std::vector keys{registry.size()}; + std::transform(std::begin(registry), std::end(registry), std::begin(keys), [](std::pair const& p){ + return p.first; + }); + return keys; + } +}; + } #endif /* _ISS_FACTORY_H_ */ diff --git a/src/main.cpp b/src/main.cpp index 5aeb3f8..0452578 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -33,13 +33,13 @@ #include #include #include -#include "iss/factory.h" +#include #include #include #include "iss/arch/tgc_mapper.h" #ifdef WITH_LLVM -#include +#include #endif #include #include "iss/plugin/cycle_estimate.h" @@ -113,53 +113,24 @@ int main(int argc, char *argv[]) { iss::init_jit_debug(argc, argv); #endif bool dump = clim.count("dump-ir"); + auto & f = iss::core_factory::instance(); // instantiate the simulator iss::vm_ptr vm{nullptr}; iss::cpu_ptr cpu{nullptr}; std::string isa_opt(clim["isa"].as()); - if (isa_opt == "tgc_c") { - std::tie(cpu, vm) = - iss::create_cpu(clim["backend"].as(), clim["gdb-port"].as()); - } else -#ifdef CORE_TGC_B - if (isa_opt == "tgc_b") { - std::tie(cpu, vm) = - iss::create_cpu(clim["backend"].as(), clim["gdb-port"].as()); - } else -#endif -#ifdef CORE_TGC_C_XRB_NN - if (isa_opt == "tgc_c_xrb_nn") { - std::tie(cpu, vm) = - iss::create_cpu(clim["backend"].as(), clim["gdb-port"].as()); - } else -#endif -#ifdef CORE_TGC_D - if (isa_opt == "tgc_d") { - std::tie(cpu, vm) = - iss::create_cpu(clim["backend"].as(), clim["gdb-port"].as()); - } else -#endif -#ifdef CORE_TGC_D_XRB_MAC - if (isa_opt == "tgc_d_xrb_mac") { - std::tie(cpu, vm) = - iss::create_cpu(clim["backend"].as(), clim["gdb-port"].as()); - } else -#endif -#ifdef CORE_TGC_D_XRB_NN - if (isa_opt == "tgc_d_xrb_nn") { - std::tie(cpu, vm) = - iss::create_cpu(clim["backend"].as(), clim["gdb-port"].as()); - } else -#endif -#ifdef CORE_TGC_E - if (isa_opt == "tgc_e") { - std::tie(cpu, vm) = - iss::create_cpu(clim["backend"].as(), clim["gdb-port"].as()); - } else -#endif - { - LOG(ERR) << "Illegal argument value for '--isa': " << isa_opt << std::endl; - return 127; + if(isa_opt.size()==0 || isa_opt == "?") { + std::cout<<"Available cores: "<(), clim["gdb-port"].as()); + } else { + auto base_isa = isa_opt.substr(0, 5); + if(base_isa=="tgc_d" || base_isa=="tgc_e") { + isa_opt += "|mu_p_clic_pmp|"+clim["backend"].as(); + } else { + isa_opt += "|m_p|"+clim["backend"].as(); + } + std::tie(cpu, vm) = f.create(isa_opt, clim["gdb-port"].as()); } if(!cpu ){ LOG(ERR) << "Could not create cpu for isa " << isa_opt << " and backend " <()<< std::endl; diff --git a/src/sysc/core_complex.cpp b/src/sysc/core_complex.cpp index b135117..be25f53 100644 --- a/src/sysc/core_complex.cpp +++ b/src/sysc/core_complex.cpp @@ -37,10 +37,11 @@ #include #include #include +#include "iss_factory.h" #ifndef WIN32 #include #endif -#include "core_complex.h" +#include "sc_core_adapter_if.h" #include #include #include @@ -85,136 +86,9 @@ using namespace sc_core; namespace { iss::debugger::encoder_decoder encdec; - std::array lvl = {{'U', 'S', 'H', 'M'}}; } -template -class core_wrapper_t : public PLAT { -public: - using reg_t = typename arch::traits::reg_t; - using phys_addr_t = typename arch::traits::phys_addr_t; - using heart_state_t = typename PLAT::hart_state_type; - core_wrapper_t(core_complex *owner) - : owner(owner) { } - - uint32_t get_mode() { return this->reg.PRIV; } - - inline void set_interrupt_execution(bool v) { this->interrupt_sim = v?1:0; } - - inline bool get_interrupt_execution() { return this->interrupt_sim; } - - heart_state_t &get_state() { return this->state; } - - void notify_phase(iss::arch_if::exec_phase p) override { - if (p == iss::arch_if::ISTART) - owner->sync(this->instr_if.get_total_cycles()); - } - - sync_type needed_sync() const override { return PRE_SYNC; } - - void disass_output(uint64_t pc, const std::string instr) override { - if (!owner->disass_output(pc, instr)) { - std::stringstream s; - 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 << "]"; - SCCDEBUG(owner->name())<<"disass: " - << "0x" << std::setw(16) << std::right << std::setfill('0') << std::hex << pc << "\t\t" << std::setw(40) - << std::setfill(' ') << std::left << instr << s.str(); - } - }; - - status read_mem(phys_addr_t addr, unsigned length, uint8_t *const data) override { - if (addr.access && access_type::DEBUG) - return owner->read_mem_dbg(addr.val, length, data) ? Ok : Err; - else { - return owner->read_mem(addr.val, length, data, is_fetch(addr.access)) ? Ok : Err; - } - } - - status write_mem(phys_addr_t addr, unsigned length, const uint8_t *const data) override { - if (addr.access && access_type::DEBUG) - return owner->write_mem_dbg(addr.val, length, data) ? Ok : Err; - else { - auto res = owner->write_mem(addr.val, length, data) ? Ok : Err; - // clear MTIP on mtimecmp write - if (addr.val == 0x2004000) { - reg_t val; - this->read_csr(arch::mip, val); - if (val & (1ULL << 7)) this->write_csr(arch::mip, val & ~(1ULL << 7)); - } - return res; - } - } - - status read_csr(unsigned addr, reg_t &val) override { -#ifndef CWR_SYSTEMC - if((addr==arch::time || addr==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(time_val); - } else if (addr == iss::arch::timeh) { - if (sizeof(reg_t) != 4) return iss::Err; - val = static_cast(time_val >> 32); - } - return ret?Ok:Err; -#else - if((addr==arch::time || addr==arch::timeh)){ - uint64_t time_val = owner->mtime_i.read(); - if (addr == iss::arch::time) { - val = static_cast(time_val); - } else if (addr == iss::arch::timeh) { - if (sizeof(reg_t) != 4) return iss::Err; - val = static_cast(time_val >> 32); - } - return Ok; -#endif - } else { - return PLAT::read_csr(addr, val); - } - } - - void wait_until(uint64_t flags) override { - SCCDEBUG(owner->name()) << "Sleeping until interrupt"; - while(this->reg.pending_trap == 0 && (this->csr[arch::mip] & this->csr[arch::mie]) == 0) { - sc_core::wait(wfi_evt); - } - PLAT::wait_until(flags); - } - - void local_irq(short id, bool value) { - reg_t mask = 0; - switch (id) { - case 3: // SW - mask = 1 << 3; - break; - case 7: // timer - mask = 1 << 7; - break; - case 11: // external - mask = 1 << 11; - break; - default: - if(id>15) mask = 1 << id; - break; - } - if (value) { - this->csr[arch::mip] |= mask; - wfi_evt.notify(); - } else - this->csr[arch::mip] &= ~mask; - this->check_interrupt(); - if(value) - SCCTRACE(owner->name()) << "Triggering interrupt " << id << " Pending trap: " << this->reg.pending_trap; - } - -private: - core_complex *const owner; - sc_event wfi_evt; -}; - int cmd_sysc(int argc, char *argv[], debugger::out_func of, debugger::data_func df, debugger::target_adapter_if *tgt_adapter) { if (argc > 1) { @@ -254,7 +128,9 @@ public: void reset(uint64_t addr){vm->reset(addr);} inline void start(){vm->start();} - inline std::pair load_file(std::string const& name){ return cpu->load_file(name);}; + inline std::pair load_file(std::string const& name){ + iss::arch_if* cc = cpu->get_arch_if(); + return cc->load_file(name);}; std::function get_mode; std::function get_state; @@ -262,45 +138,35 @@ public: std::function set_interrupt_execution; std::function local_irq; - template - std::tuple create_core(std::string const& backend, unsigned gdb_port, uint32_t hart_id){ - auto* lcpu = new core_wrapper_t(owner); - lcpu->set_mhartid(hart_id); - get_mode = [lcpu]() { return lcpu->get_mode(); }; - get_state = [lcpu]() { return lcpu->get_state().mstatus.backing.val; }; - get_interrupt_execution = [lcpu]() { return lcpu->get_interrupt_execution(); }; - set_interrupt_execution = [lcpu](bool b) { return lcpu->set_interrupt_execution(b); }; - local_irq = [lcpu](short s, bool b) { return lcpu->local_irq(s, b); }; - if(backend == "interp") - return {cpu_ptr{lcpu}, vm_ptr{iss::interp::create(static_cast(lcpu), gdb_port)}}; -#ifdef WITH_LLVM - if(backend == "llvm") - return {cpu_ptr{lcpu}, vm_ptr{iss::llvm::create(lcpu, gdb_port)}}; -#endif -#ifdef WITH_TCC - if(backend == "tcc") - s return {cpu_ptr{lcpu}, vm_ptr{iss::tcc::create(lcpu, gdb_port)}}; -#endif - return {nullptr, nullptr}; - } - void create_cpu(std::string const& type, std::string const& backend, unsigned gdb_port, uint32_t hart_id){ - CREATE_CORE(tgc_c) -#ifdef CORE_TGC_B - CREATE_CORE(tgc_b) -#endif -#ifdef CORE_TGC_D - CREATE_CORE(tgc_d) -#endif -#ifdef CORE_TGC_D_XRB_MAC - CREATE_CORE(tgc_d_xrb_mac) -#endif -#ifdef CORE_TGC_D_XRB_NN - CREATE_CORE(tgc_d_xrb_nn) -#endif - { - LOG(ERR) << "Illegal argument value for core type: " << type << std::endl; + auto & f = sysc::iss_factory::instance(); + if(type.size()==0 || type == "?") { + std::cout<<"Available cores: "<(cpu.get()); + sc_cpu_if->set_mhartid(hart_id); + get_mode = [sc_cpu_if]() { return sc_cpu_if->get_mode(); }; + get_state = [sc_cpu_if]() { return sc_cpu_if->get_state(); }; + get_interrupt_execution = [sc_cpu_if]() { return sc_cpu_if->get_interrupt_execution(); }; + set_interrupt_execution = [sc_cpu_if](bool b) { return sc_cpu_if->set_interrupt_execution(b); }; + local_irq = [sc_cpu_if](short s, bool b) { return sc_cpu_if->local_irq(s, b); }; + auto *srv = debugger::server::get(); if (srv) tgt_adapter = srv->get_target(); if (tgt_adapter) @@ -313,7 +179,7 @@ public: core_complex * const owner; vm_ptr vm{nullptr}; - cpu_ptr cpu{nullptr}; + sc_cpu_ptr cpu{nullptr}; iss::debugger::target_adapter_if *tgt_adapter{nullptr}; }; @@ -634,5 +500,5 @@ bool core_complex::write_mem_dbg(uint64_t addr, unsigned length, const uint8_t * gp.set_streaming_width(length); return dbus->transport_dbg(gp) == length; } -} /* namespace SiFive */ +} /* namespace tgfs */ } /* namespace sysc */ diff --git a/src/sysc/iss_factory.h b/src/sysc/iss_factory.h new file mode 100644 index 0000000..f29a5b0 --- /dev/null +++ b/src/sysc/iss_factory.h @@ -0,0 +1,88 @@ +/******************************************************************************* + * Copyright (C) 2021 MINRES Technologies GmbH + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + *******************************************************************************/ + +#ifndef _ISS_FACTORY_H_ +#define _ISS_FACTORY_H_ + +#include +#include "sc_core_adapter_if.h" +#include +#include +#include +#include +#include +#include + +namespace sysc { + +using sc_cpu_ptr = std::unique_ptr; +using vm_ptr= std::unique_ptr; + +class iss_factory { +public: + using base_t = std::tuple; + using create_fn = std::function; + using registry_t = std::unordered_map ; + + iss_factory() = default; + iss_factory(const iss_factory &) = delete; + iss_factory & operator=(const iss_factory &) = delete; + + static iss_factory & instance() { static iss_factory bf; return bf; } + + bool register_creator(const std::string & className, create_fn const& fn) { + registry[className] = fn; + return true; + } + + base_t create(std::string const& className, unsigned gdb_port=0, void* init_data=nullptr) const { + registry_t::const_iterator regEntry = registry.find(className); + if (regEntry != registry.end()) + return regEntry->second(gdb_port, init_data); + return {nullptr, nullptr}; + } + + std::vector get_names() { + std::vector keys{registry.size()}; + std::transform(std::begin(registry), std::end(registry), std::begin(keys), [](std::pair const& p){ + return p.first; + }); + return keys; + } +private: + registry_t registry; + +}; + +} + +#endif /* _ISS_FACTORY_H_ */ diff --git a/src/sysc/register_tgc_c.cpp b/src/sysc/register_tgc_c.cpp new file mode 100644 index 0000000..31a99a5 --- /dev/null +++ b/src/sysc/register_tgc_c.cpp @@ -0,0 +1,72 @@ +/******************************************************************************* + * Copyright (C) 2023 MINRES Technologies GmbH + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + *******************************************************************************/ + +#include "iss_factory.h" +#include +#include +#include +#include "sc_core_adapter.h" +#include "core_complex.h" + +namespace iss { +namespace interp { +using namespace sysc; +volatile std::array tgc_init = { + iss_factory::instance().register_creator("tgc_c|m_p|interp", [](unsigned gdb_port, void* data) -> iss_factory::base_t { + auto* cc = reinterpret_cast(data); + auto* cpu = new sc_core_adapter>(cc); + return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast(cpu), gdb_port)}}; + }), + iss_factory::instance().register_creator("tgc_c|mu_p|interp", [](unsigned gdb_port, void* data) -> iss_factory::base_t { + auto* cc = reinterpret_cast(data); + auto* cpu = new sc_core_adapter>(cc); + return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast(cpu), gdb_port)}}; + }) +}; +} +#if defined(WITH_TCC) +namespace tcc { +volatile std::array tgc_init = { + core_factory::instance().register_creator("tgc_c|m_p|tcc", [](unsigned gdb_port, void* data) -> std::tuple{ + auto cc = reinterpret_cast(data); + auto* cpu = new sc_core_adapter>(cc); + return {cpu_ptr{cpu}, vm_ptr{create(static_cast(cpu), gdb_port)}}; + }), + core_factory::instance().register_creator("tgc_c|mu_p|tcc", [](unsigned gdb_port, void* data) -> std::tuple{ + auto cc = reinterpret_cast(data); + auto* cpu = new sc_core_adapter>(cc); + return {cpu_ptr{cpu}, vm_ptr{create(static_cast(cpu), gdb_port)}}; + }) +}; +} +#endif +} diff --git a/src/sysc/sc_core_adapter.h b/src/sysc/sc_core_adapter.h new file mode 100644 index 0000000..bbd1465 --- /dev/null +++ b/src/sysc/sc_core_adapter.h @@ -0,0 +1,151 @@ +/* + * sc_core_adapter.h + * + * Created on: Jul 5, 2023 + * Author: eyck + */ + +#ifndef _SYSC_SC_CORE_ADAPTER_H_ +#define _SYSC_SC_CORE_ADAPTER_H_ + + +#include +#include +#include "sc_core_adapter_if.h" +#include +#include +#include + +namespace sysc { +template +class sc_core_adapter : public PLAT, public sc_core_adapter_if { +public: + using reg_t = typename iss::arch::traits::reg_t; + using phys_addr_t = typename iss::arch::traits::phys_addr_t; + using heart_state_t = typename PLAT::hart_state_type; + sc_core_adapter(sysc::tgfs::core_complex *owner) + : owner(owner) { } + + iss::arch_if* get_arch_if() override { return this;} + + void set_mhartid(unsigned id) override { PLAT::set_mhartid(id); } + + uint32_t get_mode() override { return this->reg.PRIV; } + + void set_interrupt_execution(bool v) override { this->interrupt_sim = v?1:0; } + + bool get_interrupt_execution() override { return this->interrupt_sim; } + + uint64_t get_state() override { return this->state.mstatus.backing.val; } + + void notify_phase(iss::arch_if::exec_phase p) override { + if (p == iss::arch_if::ISTART) + owner->sync(this->instr_if.get_total_cycles()); + } + + iss::sync_type needed_sync() const override { return iss::PRE_SYNC; } + + void disass_output(uint64_t pc, const std::string instr) override { + static constexpr std::array lvl = {{'U', 'S', 'H', 'M'}}; + if (!owner->disass_output(pc, instr)) { + std::stringstream s; + 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 << "]"; + SCCDEBUG(owner->name())<<"disass: " + << "0x" << std::setw(16) << std::right << std::setfill('0') << std::hex << pc << "\t\t" << std::setw(40) + << std::setfill(' ') << std::left << instr << s.str(); + } + }; + + iss::status read_mem(phys_addr_t addr, unsigned length, uint8_t *const data) override { + if (addr.access && iss::access_type::DEBUG) + return owner->read_mem_dbg(addr.val, length, data) ? iss::Ok : iss::Err; + else { + return owner->read_mem(addr.val, length, data, is_fetch(addr.access)) ? iss::Ok : iss::Err; + } + } + + iss::status write_mem(phys_addr_t addr, unsigned length, const uint8_t *const data) override { + if (addr.access && iss::access_type::DEBUG) + return owner->write_mem_dbg(addr.val, length, data) ? iss::Ok : iss::Err; + else { + auto res = owner->write_mem(addr.val, length, data) ? iss::Ok : iss::Err; + // clear MTIP on mtimecmp write + if (addr.val == 0x2004000) { + reg_t val; + this->read_csr(iss::arch::mip, val); + if (val & (1ULL << 7)) this->write_csr(iss::arch::mip, val & ~(1ULL << 7)); + } + return res; + } + } + + 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(time_val); + } else if (addr == iss::arch::timeh) { + if (sizeof(reg_t) != 4) return iss::Err; + val = static_cast(time_val >> 32); + } + return ret?iss::Ok:iss::Err; +#else + if((addr==iss::arch::time || addr==iss::arch::timeh)){ + uint64_t time_val = owner->mtime_i.read(); + if (addr == iss::arch::time) { + val = static_cast(time_val); + } else if (addr == iss::arch::timeh) { + if (sizeof(reg_t) != 4) return iss::Err; + val = static_cast(time_val >> 32); + } + return iss::Ok; +#endif + } else { + return PLAT::read_csr(addr, val); + } + } + + void wait_until(uint64_t flags) override { + SCCDEBUG(owner->name()) << "Sleeping until interrupt"; + while(this->reg.pending_trap == 0 && (this->csr[iss::arch::mip] & this->csr[iss::arch::mie]) == 0) { + sc_core::wait(wfi_evt); + } + PLAT::wait_until(flags); + } + + void local_irq(short id, bool value) override { + reg_t mask = 0; + switch (id) { + case 3: // SW + mask = 1 << 3; + break; + case 7: // timer + mask = 1 << 7; + break; + case 11: // external + mask = 1 << 11; + break; + default: + if(id>15) mask = 1 << id; + break; + } + if (value) { + this->csr[iss::arch::mip] |= mask; + wfi_evt.notify(); + } else + this->csr[iss::arch::mip] &= ~mask; + this->check_interrupt(); + if(value) + SCCTRACE(owner->name()) << "Triggering interrupt " << id << " Pending trap: " << this->reg.pending_trap; + } + +private: + sysc::tgfs::core_complex *const owner; + sc_core::sc_event wfi_evt; +}; +} +#endif /* _SYSC_SC_CORE_ADAPTER_H_ */ diff --git a/src/sysc/sc_core_adapter_if.h b/src/sysc/sc_core_adapter_if.h new file mode 100644 index 0000000..05a2c61 --- /dev/null +++ b/src/sysc/sc_core_adapter_if.h @@ -0,0 +1,31 @@ +/* + * sc_core_adapter.h + * + * Created on: Jul 5, 2023 + * Author: eyck + */ + +#ifndef _SYSC_SC_CORE_ADAPTER_IF_H_ +#define _SYSC_SC_CORE_ADAPTER_IF_H_ + + +#include +#include +#include "core_complex.h" +#include +#include +#include + +namespace sysc { +struct sc_core_adapter_if { + virtual iss::arch_if* get_arch_if() = 0; + virtual void set_mhartid(unsigned) = 0; + virtual uint32_t get_mode() = 0; + virtual uint64_t get_state() = 0; + virtual bool get_interrupt_execution() = 0; + virtual void set_interrupt_execution(bool v) = 0; + virtual void local_irq(short id, bool value) = 0; + virtual ~sc_core_adapter_if() = default; +}; +} +#endif /* _SYSC_SC_CORE_ADAPTER_IF_H_ */ diff --git a/src/vm/interp/vm_tgc_c.cpp b/src/vm/interp/vm_tgc_c.cpp index 55c75d5..bb9f5f4 100644 --- a/src/vm/interp/vm_tgc_c.cpp +++ b/src/vm/interp/vm_tgc_c.cpp @@ -30,10 +30,9 @@ * *******************************************************************************/ +#include #include #include -#include -#include #include #include #include @@ -1769,7 +1768,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co raise(0, 2); } else { - int64_t res = (int32_t)*(X+rs1) * (int32_t)*(X+rs2); + int64_t res = (int64_t)((int64_t)(int32_t)*(X+rs1) * (int64_t)(int32_t)*(X+rs2)); if(rd != 0) { *(X+rd) = (uint32_t)res; } @@ -1797,7 +1796,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co raise(0, 2); } else { - int64_t res = (int32_t)*(X+rs1) * (int32_t)*(X+rs2); + int64_t res = (int64_t)((int64_t)(int32_t)*(X+rs1) * (int64_t)(int32_t)*(X+rs2)); if(rd != 0) { *(X+rd) = (uint32_t)(res >> traits::XLEN); } @@ -1825,7 +1824,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co raise(0, 2); } else { - int64_t res = (int32_t)*(X+rs1) * *(X+rs2); + int64_t res = (int64_t)((int64_t)(int32_t)*(X+rs1) * (uint64_t)*(X+rs2)); if(rd != 0) { *(X+rd) = (uint32_t)(res >> traits::XLEN); } @@ -1853,7 +1852,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co raise(0, 2); } else { - uint64_t res = *(X+rs1) * *(X+rs2); + uint64_t res = (uint64_t)((uint64_t)*(X+rs1) * (uint64_t)*(X+rs2)); if(rd != 0) { *(X+rd) = (uint32_t)(res >> traits::XLEN); } @@ -2051,8 +2050,8 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co *NEXT_PC = *PC + 2; // execute instruction { - uint32_t load_address = (uint32_t)(*(X+rs1 + 8) + uimm); - int32_t read_res = super::template read_mem(traits::MEM, load_address); + uint32_t offs = (uint32_t)(*(X+rs1 + 8) + uimm); + int32_t read_res = super::template read_mem(traits::MEM, offs); if(this->core.reg.trap_state>=0x80000000UL) goto TRAP_CLW; *(X+rd + 8) = (uint32_t)(int32_t)read_res; } @@ -2074,8 +2073,8 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co *NEXT_PC = *PC + 2; // execute instruction { - uint32_t load_address = (uint32_t)(*(X+rs1 + 8) + uimm); - super::template write_mem(traits::MEM, load_address, (uint32_t)*(X+rs2 + 8)); + uint32_t offs = (uint32_t)(*(X+rs1 + 8) + uimm); + super::template write_mem(traits::MEM, offs, (uint32_t)*(X+rs2 + 8)); if(this->core.reg.trap_state>=0x80000000UL) goto TRAP_CSW; } TRAP_CSW:break; @@ -2476,8 +2475,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co uint32_t offs = (uint32_t)(*(X+2) + uimm); int32_t read_res = super::template read_mem(traits::MEM, offs); if(this->core.reg.trap_state>=0x80000000UL) goto TRAP_CLWSP; - int32_t res = (int32_t)read_res; - *(X+rd) = (uint32_t)res; + *(X+rd) = (uint32_t)(int32_t)read_res; } } TRAP_CLWSP:break; @@ -2675,7 +2673,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co return pc; } -} +} // namespace tgc_c template <> std::unique_ptr create(arch::tgc_c *core, unsigned short port, bool dump) { @@ -2685,3 +2683,25 @@ std::unique_ptr create(arch::tgc_c *core, unsigned short por } } // namespace interp } // namespace iss + +#include +#include +#include +namespace iss { +namespace { +volatile std::array dummy = { + core_factory::instance().register_creator("tgc_c|m_p|interp", [](unsigned port, void*) -> std::tuple{ + auto* cpu = new iss::arch::riscv_hart_m_p(); + auto vm = new interp::tgc_c::vm_impl(*cpu, false); + if (port != 0) debugger::server::run_server(vm, port); + return {cpu_ptr{cpu}, vm_ptr{vm}}; + }), + core_factory::instance().register_creator("tgc_c|mu_p|interp", [](unsigned port, void*) -> std::tuple{ + auto* cpu = new iss::arch::riscv_hart_mu_p(); + auto vm = new interp::tgc_c::vm_impl(*cpu, false); + if (port != 0) debugger::server::run_server(vm, port); + return {cpu_ptr{cpu}, vm_ptr{vm}}; + }) +}; +} +} diff --git a/src/vm/tcc/vm_tgc_c.cpp b/src/vm/tcc/vm_tgc_c.cpp index fde3ec3..3a29227 100644 --- a/src/vm/tcc/vm_tgc_c.cpp +++ b/src/vm/tcc/vm_tgc_c.cpp @@ -31,7 +31,6 @@ *******************************************************************************/ #include -#include #include #include #include @@ -3209,7 +3208,7 @@ template void vm_impl::gen_trap_behavior(tu_builder& tu) { tu("return *next_pc;"); } -} // namespace mnrv32 +} // namespace tgc_c template <> std::unique_ptr create(arch::tgc_c *core, unsigned short port, bool dump) { @@ -3217,5 +3216,27 @@ std::unique_ptr create(arch::tgc_c *core, unsigned short por if (port != 0) debugger::server::run_server(ret, port); return std::unique_ptr(ret); } -} +} // namespace tcc } // namespace iss + +#include +#include +#include +namespace iss { +namespace { +volatile std::array dummy = { + core_factory::instance().register_creator("tgc_c|m_p|tcc", [](unsigned port, void*) -> std::tuple{ + auto* cpu = new iss::arch::riscv_hart_m_p(); + auto* vm = new tcc::tgc_c::vm_impl(*cpu, false); + if (port != 0) debugger::server::run_server(vm, port); + return {cpu_ptr{cpu}, vm_ptr{vm}}; + }), + core_factory::instance().register_creator("tgc_c|mu_p|tcc", [](unsigned port, void*) -> std::tuple{ + auto* cpu = new iss::arch::riscv_hart_mu_p(); + auto* vm = new tcc::tgc_c::vm_impl(*cpu, false); + if (port != 0) debugger::server::run_server(vm, port); + return {cpu_ptr{cpu}, vm_ptr{vm}}; + }) +}; +} +}