From b4b03f7850331e03331c3bc3dee2672524eb8208 Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Sun, 9 Jul 2023 22:20:50 +0200 Subject: [PATCH] fixes build system to handle TCC properly --- CMakeLists.txt | 69 +++---- gen_input/templates/interp/CORENAME.cpp.gtl | 2 +- gen_input/templates/tcc/CORENAME.cpp.gtl | 2 +- src/sysc/core_complex.cpp | 195 +++----------------- src/sysc/register_tgc_c.cpp | 20 +- src/sysc/sc_core_adapter.h | 17 +- src/sysc/sc_core_adapter_if.h | 30 +++ src/vm/tcc/vm_tgc_c.cpp | 4 +- 8 files changed, 123 insertions(+), 216 deletions(-) create mode 100644 src/sysc/sc_core_adapter_if.h diff --git a/CMakeLists.txt b/CMakeLists.txt index b269918..f8480fb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -32,49 +32,41 @@ 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("Core 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) @@ -185,11 +177,17 @@ install(TARGETS tgc-sim # ############################################################################### if(TARGET scc-sysc) - project(dbt-rise-tgc_sc VERSION 1.0.0) + if(BUILD_SHARED_LIBS) + set(THIS_PROJECT_NAME dbt-rise-tgc_sc) + else() + set(THIS_PROJECT_NAME dbt-rise-tgc_sc_lib) + endif() + project(${THIS_PROJECT_NAME} VERSION 1.0.0) add_library(${PROJECT_NAME} src/sysc/core_complex.cpp src/sysc/register_tgc_c.cpp ) + target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src) target_compile_definitions(${PROJECT_NAME} PUBLIC WITH_SYSTEMC) target_compile_definitions(${PROJECT_NAME} PRIVATE CORE_${CORE_NAME}) foreach(F IN LISTS TGC_SOURCES) @@ -219,5 +217,14 @@ if(TARGET scc-sysc) PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/sysc # headers for mac (note the different component -> different package) INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} # headers ) + if(NOT BUILD_SHARED_LIBS) + add_library(dbt-rise-tgc_sc INTERFACE) + target_include_directories(dbt-rise-tgc_sc INTERFACE $) + target_include_directories(dbt-rise-tgc_sc INTERFACE $) + target_link_libraries(dbt-rise-tgc_sc INTERFACE + -Wl,--whole-archive,$,--no-whole-archive + $ + scc-sysc) + endif() endif() diff --git a/gen_input/templates/interp/CORENAME.cpp.gtl b/gen_input/templates/interp/CORENAME.cpp.gtl index cd84028..5d6cc35 100644 --- a/gen_input/templates/interp/CORENAME.cpp.gtl +++ b/gen_input/templates/interp/CORENAME.cpp.gtl @@ -304,7 +304,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) { diff --git a/gen_input/templates/tcc/CORENAME.cpp.gtl b/gen_input/templates/tcc/CORENAME.cpp.gtl index f7a2baf..1b000ea 100644 --- a/gen_input/templates/tcc/CORENAME.cpp.gtl +++ b/gen_input/templates/tcc/CORENAME.cpp.gtl @@ -301,7 +301,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) { diff --git a/src/sysc/core_complex.cpp b/src/sysc/core_complex.cpp index b135117..e3b0433 100644 --- a/src/sysc/core_complex.cpp +++ b/src/sysc/core_complex.cpp @@ -37,10 +37,11 @@ #include #include #include +#include #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) { @@ -262,45 +136,34 @@ 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 = iss::core_factory::instance(); + if(type.size()==0 || type == "?") { + std::cout<<"Available cores: "<(*cpu).set_mhartid(hart_id); + get_mode = [this]() { return reinterpret_cast(*cpu).get_mode(); }; + get_state = [this]() { return reinterpret_cast(*cpu).get_state(); }; + get_interrupt_execution = [this]() { return reinterpret_cast(*cpu).get_interrupt_execution(); }; + set_interrupt_execution = [this](bool b) { return reinterpret_cast(*cpu).set_interrupt_execution(b); }; + local_irq = [this](short s, bool b) { return reinterpret_cast(*cpu).local_irq(s, b); }; + auto *srv = debugger::server::get(); if (srv) tgt_adapter = srv->get_target(); if (tgt_adapter) @@ -634,5 +497,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/register_tgc_c.cpp b/src/sysc/register_tgc_c.cpp index 8d86788..1fe4194 100644 --- a/src/sysc/register_tgc_c.cpp +++ b/src/sysc/register_tgc_c.cpp @@ -38,28 +38,34 @@ #include "core_complex.h" namespace iss { -namespace { -volatile std::array dummy = { +namespace interp { +volatile std::array tgc_init = { core_factory::instance().register_creator("tgc_c|m_p|interp", [](unsigned gdb_port, void* data) -> std::tuple{ auto cc = reinterpret_cast(data); arch::tgc_c* cpu = new sc_core_adapter>(cc); - return {cpu_ptr{cpu}, vm_ptr{interp::create(cpu, gdb_port)}}; + return {cpu_ptr{cpu}, vm_ptr{create(cpu, gdb_port)}}; }), core_factory::instance().register_creator("tgc_c|mu_p|interp", [](unsigned gdb_port, void* data) -> std::tuple{ auto cc = reinterpret_cast(data); arch::tgc_c* cpu = new sc_core_adapter>(cc); - return {cpu_ptr{cpu}, vm_ptr{interp::create(cpu, gdb_port)}}; - }), + return {cpu_ptr{cpu}, vm_ptr{create(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); arch::tgc_c* cpu = new sc_core_adapter>(cc); - return {cpu_ptr{cpu}, vm_ptr{tcc::create(cpu, gdb_port)}}; + return {cpu_ptr{cpu}, vm_ptr{create(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); arch::tgc_c* cpu = new sc_core_adapter>(cc); - return {cpu_ptr{cpu}, vm_ptr{tcc::create(cpu, gdb_port)}}; + return {cpu_ptr{cpu}, vm_ptr{create(cpu, gdb_port)}}; }) }; } +#endif } diff --git a/src/sysc/sc_core_adapter.h b/src/sysc/sc_core_adapter.h index 9544765..77c293f 100644 --- a/src/sysc/sc_core_adapter.h +++ b/src/sysc/sc_core_adapter.h @@ -11,14 +11,13 @@ #include #include -#include "core_complex.h" +#include "sc_core_adapter_if.h" #include #include #include - template -class sc_core_adapter : public PLAT { +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; @@ -26,13 +25,15 @@ public: sc_core_adapter(sysc::tgfs::core_complex *owner) : owner(owner) { } - uint32_t get_mode() { return this->reg.PRIV; } + void set_mhartid(unsigned id) override { PLAT::set_mhartid(id); } - inline void set_interrupt_execution(bool v) { this->interrupt_sim = v?1:0; } + uint32_t get_mode() override { return this->reg.PRIV; } - inline bool get_interrupt_execution() { return this->interrupt_sim; } + void set_interrupt_execution(bool v) override { this->interrupt_sim = v?1:0; } - heart_state_t &get_state() { return this->state; } + 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) @@ -113,7 +114,7 @@ public: PLAT::wait_until(flags); } - void local_irq(short id, bool value) { + void local_irq(short id, bool value) override { reg_t mask = 0; switch (id) { case 3: // SW diff --git a/src/sysc/sc_core_adapter_if.h b/src/sysc/sc_core_adapter_if.h new file mode 100644 index 0000000..5445ee0 --- /dev/null +++ b/src/sysc/sc_core_adapter_if.h @@ -0,0 +1,30 @@ +/* + * 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 + +struct sc_core_adapter_if { + 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/tcc/vm_tgc_c.cpp b/src/vm/tcc/vm_tgc_c.cpp index 8027571..371aa95 100644 --- a/src/vm/tcc/vm_tgc_c.cpp +++ b/src/vm/tcc/vm_tgc_c.cpp @@ -3210,7 +3210,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) { @@ -3218,7 +3218,7 @@ 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); } -} // namesapce tcc +} // namespace tcc } // namespace iss #include