From 3acab0a751529342414b9df6df7c067c2aff0317 Mon Sep 17 00:00:00 2001 From: xinyangli Date: Tue, 9 Jul 2024 20:42:01 +0800 Subject: [PATCH] npc: wip, cannot build --- npc/CMakeLists.txt | 33 ++++-- npc/core/src/main/resources/RamDpi.v | 8 +- npc/core/src/main/scala/top/FlowMain.scala | 4 +- npc/csrc/CMakeLists.txt | 3 +- npc/csrc/Flow/CMakeLists.txt | 38 ++++--- npc/csrc/Flow/config.cpp | 2 +- npc/csrc/Flow/main.cpp | 87 +++++++++++---- npc/csrc/devices/CMakeLists.txt | 3 + npc/csrc/devices/include/devices.hpp | 85 ++++++++++++++ npc/csrc/devices/rtc.cpp | 49 +++++++++ npc/csrc/devices/serial.cpp | 22 ++++ npc/csrc_nvboard/Flow/CMakeLists.txt | 36 +++--- npc/include/components.hpp | 122 +++++++++++++-------- npc/include/config.hpp | 4 +- npc/include/trm_interface.hpp | 3 +- npc/utils/CMakeLists.txt | 2 +- npc/utils/sdb/CMakeLists.txt | 28 ++++- npc/utils/sdb/include/sdb.hpp | 2 +- npc/utils/sdb/sdb.cpp | 1 - 19 files changed, 404 insertions(+), 128 deletions(-) create mode 100644 npc/csrc/devices/CMakeLists.txt create mode 100644 npc/csrc/devices/include/devices.hpp create mode 100644 npc/csrc/devices/rtc.cpp create mode 100644 npc/csrc/devices/serial.cpp diff --git a/npc/CMakeLists.txt b/npc/CMakeLists.txt index bb6cd95..035d603 100644 --- a/npc/CMakeLists.txt +++ b/npc/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_minimum_required(VERSION 3.26) project(flow) -set (CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD 17) cmake_policy(SET CMP0144 NEW) include(CMakeDependentOption) @@ -12,17 +12,24 @@ list(APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake) # -- Build options option(BUILD_USE_BLOOP "Whether to use bloop to speed up elaborate" OFF) option(BUILD_SIM_TARGET "Whether to build verilator simulation binary" ON) -cmake_dependent_option(BUILD_SIM_NVBOARD_TARGET "Whether to build nvboard target" OFF "BUILD_SIM_TARGET" OFF) +cmake_dependent_option( + BUILD_SIM_NVBOARD_TARGET "Whether to build nvboard target" OFF + "BUILD_SIM_TARGET" OFF) option(ENABLE_YSYX_GIT_TRACKER "Ysyx tracker support" ON) -set(TOPMODULE "Flow" CACHE STRING "Topmodule name in chisel") -set(DIFFTEST_LIB "" CACHE STRING "Dynamic library file used as difftest reference") +set(TOPMODULE + "Flow" + CACHE STRING "Topmodule name in chisel") +set(DIFFTEST_LIB + "" + CACHE FILEPATH "Dynamic library file used as difftest reference") +set(DIFFTEST_RESOURCE_DIR + "" + CACHE PATH "Dynamic library file used as difftest reference") # -- Ysyx tracker, configure if(ENABLE_YSYX_GIT_TRACKER) - execute_process( - COMMAND ${CMAKE_SOURCE_DIR}/../git_commit.sh "configure(npc)" - WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/.. - ) + execute_process(COMMAND ${CMAKE_SOURCE_DIR}/../git_commit.sh "configure(npc)" + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/..) endif() # -- Check dependencies @@ -51,13 +58,15 @@ set(CHISEL_OUTPUT_VERILATOR_CONF ${CHISEL_OUTPUT_DIR}/conf.vlt) set(CHISEL_OUTPUT_TOPMODULE ${CHISEL_OUTPUT_DIR}/${TOPMODULE}.sv) set(CHISEL_EMIT_ARGS "--target-dir ${CHISEL_OUTPUT_DIR}") +# -- Find difftest binaries +file(GLOB_RECURSE DIFFTEST_BINARY_FILES "${DIFFTEST_RESOURCE_DIR}/*.bin") + # -- Build NVBoard executable if(BUILD_SIM_NVBOARD_TARGET) add_subdirectory(csrc_nvboard) endif() # -- Build Verilator executable and add to test -include_directories(include) add_subdirectory(utils) add_subdirectory(csrc) @@ -66,7 +75,7 @@ add_subdirectory(csrc) if(ENABLE_YSYX_GIT_TRACKER) add_custom_target( ysyx_git_tracer ALL - COMMAND ${CMAKE_SOURCE_DIR}/../git_commit.sh "build_${CMAKE_PROJECT_NAME}_V${TOPMODULE}" - WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/.. - ) + COMMAND ${CMAKE_SOURCE_DIR}/../git_commit.sh + "build_${CMAKE_PROJECT_NAME}_V${TOPMODULE}" + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/..) endif() diff --git a/npc/core/src/main/resources/RamDpi.v b/npc/core/src/main/resources/RamDpi.v index 0f4308b..cbab381 100644 --- a/npc/core/src/main/resources/RamDpi.v +++ b/npc/core/src/main/resources/RamDpi.v @@ -14,7 +14,7 @@ module RamDpi ( input reg [31:0] pc, output reg [31:0] inst ); - always @(*) begin + always @(posedge clock) begin if (valid) begin // 有读写请求时 readData = pmem_read(readAddr); if (writeEnable) begin // 有写请求时 @@ -22,8 +22,8 @@ module RamDpi ( end end else begin - readData = 0; + readData = 32'h80000000; end - inst = pmem_read(pc); end -endmodule \ No newline at end of file + assign inst = pmem_read(pc); +endmodule diff --git a/npc/core/src/main/scala/top/FlowMain.scala b/npc/core/src/main/scala/top/FlowMain.scala index b6aa888..3377689 100644 --- a/npc/core/src/main/scala/top/FlowMain.scala +++ b/npc/core/src/main/scala/top/FlowMain.scala @@ -242,12 +242,12 @@ class Control(width: Int) extends RawModule { (xori , (r(true.B) :: r(rAluOut) :: r(false.B) :: r(pStaticNpc) :: - r(aOpOr) :: r(aSrcARs1) :: r(aSrcBImmI) :: l(Bool()) :: + r(aOpXor) :: r(aSrcARs1) :: r(aSrcBImmI) :: l(Bool()) :: r(false.B) :: l(UInt(4.W)):: r(false.B) :: HNil)), (ori , (r(true.B) :: r(rAluOut) :: r(false.B) :: r(pStaticNpc) :: - r(aOpXor) :: r(aSrcARs1) :: r(aSrcBImmI) :: l(Bool()) :: + r(aOpOr) :: r(aSrcARs1) :: r(aSrcBImmI) :: l(Bool()) :: r(false.B) :: l(UInt(4.W)):: r(false.B) :: HNil)), (andi , (r(true.B) :: r(rAluOut) :: diff --git a/npc/csrc/CMakeLists.txt b/npc/csrc/CMakeLists.txt index 3f645a7..4adbc86 100644 --- a/npc/csrc/CMakeLists.txt +++ b/npc/csrc/CMakeLists.txt @@ -1 +1,2 @@ -add_subdirectory(${TOPMODULE}) \ No newline at end of file +add_subdirectory(devices) +add_subdirectory(${TOPMODULE}) diff --git a/npc/csrc/Flow/CMakeLists.txt b/npc/csrc/Flow/CMakeLists.txt index 16aaef1..5ea7fce 100644 --- a/npc/csrc/Flow/CMakeLists.txt +++ b/npc/csrc/Flow/CMakeLists.txt @@ -1,19 +1,29 @@ include(ChiselBuild) add_executable(V${TOPMODULE} config.cpp main.cpp) -target_link_libraries(V${TOPMODULE} PRIVATE sdb) +target_link_libraries(V${TOPMODULE} PRIVATE sdb devices) +target_include_directories(V${TOPMODULE} PRIVATE ${CMAKE_SOURCE_DIR}/include) -verilate(V${TOPMODULE} TRACE THREADS - TOP_MODULE ${TOPMODULE} - PREFIX V${TOPMODULE} - SOURCES ${CHISEL_OUTPUT_TOPMODULE} ${CHISEL_OUTPUT_VERILATOR_CONF} - INCLUDE_DIRS ${CHISEL_OUTPUT_DIR} +verilate( + V${TOPMODULE} + TRACE + THREADS + TOP_MODULE + ${TOPMODULE} + PREFIX + V${TOPMODULE} + SOURCES + ${CHISEL_OUTPUT_TOPMODULE} + ${CHISEL_OUTPUT_VERILATOR_CONF} + INCLUDE_DIRS + ${CHISEL_OUTPUT_DIR} VERILATOR_ARGS - "--vpi" # Enable VPI - "-Wno-UNOPTFLAT" -) + "--vpi" # Enable VPI + "-Wno-UNOPTFLAT") -add_test( - NAME V${TOPMODULE} - COMMAND V${TOPMODULE} - --no-bin -m ${PROJECT_SOURCE_DIR}/resource/addi.txt - --diff-lib ${DIFFTEST_LIB}) +foreach(DIFFTEST_BINARY_FILE IN LISTS DIFFTEST_BINARY_FILES) + get_filename_component(FILENAME ${DIFFTEST_BINARY_FILE} NAME_WE) + add_test(NAME V${TOPMODULE}.${FILENAME} + COMMAND V${TOPMODULE} -m ${DIFFTEST_BINARY_FILE} --diff-lib + ${DIFFTEST_LIB}) + unset(FILENAME) +endforeach() diff --git a/npc/csrc/Flow/config.cpp b/npc/csrc/Flow/config.cpp index fd49141..71e042f 100644 --- a/npc/csrc/Flow/config.cpp +++ b/npc/csrc/Flow/config.cpp @@ -8,7 +8,7 @@ void Config::cli_parse(int argc, char **argv) { app.add_flag("!--no-bin", memory_file_binary, "Memory file is in text format"); app.add_option("--wav", wavefile, "output .vcd file path"); - app.add_option("-t", max_sim_time, "Max simulation timestep"); + app.add_flag("-i", interactive, "Launch sdb for interactive session"); app.add_option("--diff-lib", lib_ref, "Dynamic library file of difftest reference") ->check(CLI::ExistingFile); diff --git a/npc/csrc/Flow/main.cpp b/npc/csrc/Flow/main.cpp index 664db56..324156f 100644 --- a/npc/csrc/Flow/main.cpp +++ b/npc/csrc/Flow/main.cpp @@ -1,11 +1,15 @@ #include "VFlow___024root.h" +#include "components.hpp" #include +#include #include #include #include +#include #include #include #include +#include #include #include #include @@ -25,27 +29,38 @@ VlModule *top; Registers *regs; vpiHandle pc = nullptr; +const size_t PMEM_START = 0x80000000; +const size_t PMEM_END = 0x87ffffff; + extern "C" { +using MMap = MemoryMap, Devices::DeviceMap>; void *pmem_get() { - static auto pmem = - new Memory(config.memory_file, config.memory_file_binary, - std::move(config.mtrace_ranges)); + static Devices::DeviceMap devices{ + new Devices::Serial(0x10000000, 0x1000), + new Devices::RTC(0x10001000, 0x1000), + }; + static auto pmem = new MemoryMap, Devices::DeviceMap>( + std::make_unique>( + config.memory_file, config.memory_file_binary, PMEM_START, PMEM_END), + std::make_unique(devices), config.mtrace_ranges); return pmem; } int pmem_read(int raddr) { void *pmem = pmem_get(); - auto mem = static_cast *>(pmem); + auto mem = static_cast(pmem); // TODO: Do memory difftest at memory read and write to diagnose at a finer // granularity if (config.do_mtrace) mem->trace(raddr, true, regs->get_pc()); + if (g_skip_memcheck) + return mem->read(PMEM_START); return mem->read(raddr); } void pmem_write(int waddr, int wdata, char wmask) { void *pmem = pmem_get(); - auto mem = static_cast *>(pmem); + auto mem = static_cast(pmem); if (config.do_mtrace) mem->trace((std::size_t)waddr, false, regs->get_pc(), wdata); return mem->write((std::size_t)waddr, wdata, wmask); @@ -55,10 +70,7 @@ void pmem_write(int waddr, int wdata, char wmask) { namespace NPC { void npc_memcpy(paddr_t addr, void *buf, size_t sz, bool direction) { if (direction == TRM_FROM_MACHINE) { - memcpy( - buf, - static_cast *>(pmem_get())->guest_to_host(addr), - sz); + static_cast(pmem_get())->copy_to(addr, (uint8_t *)buf, sz); } }; @@ -110,7 +122,10 @@ public: this->memcpy(addr, &buf, sizeof(word_t), TRM_FROM_MACHINE); return buf; } - void print(std::ostream &os) const override {} + void print(std::ostream &os) const override { + this->regcpy(cpu_state, TRM_FROM_MACHINE); + os << *(CPUState *)cpu_state << std::endl; + } }; DutTrmInterface npc_interface = @@ -126,18 +141,50 @@ word_t reg_str2val(const char *name, bool *success) { int main(int argc, char **argv, char **env) { config.cli_parse(argc, argv); - if (config.max_sim_time > 1) { - NPC::npc_interface.exec(config.max_sim_time / 2); - } else { - /* -- Difftest -- */ - std::filesystem::path ref{config.lib_ref}; - RefTrmInterface ref_interface{ref}; - DifftestTrmInterface diff_interface{NPC::npc_interface, ref_interface, - pmem_get(), 128 * 1024}; - SDB::SDB sdb_diff{diff_interface}; + if (config.lib_ref.empty()) { + if (config.interactive) { + SDB::SDB sdb_npc{NPC::npc_interface}; + sdb_npc.main_loop(); + return 0; + } else { + NPC::npc_interface.init(0); + while (true) { + word_t inst = NPC::npc_interface.at(regs->get_pc()); + if (inst == 1048691) { + return 0; + } + NPC::npc_interface.exec(1); + } + } + } - int t = 8; + /* -- Difftest -- */ + std::filesystem::path ref{config.lib_ref}; + RefTrmInterface ref_interface{ref}; + DifftestTrmInterface diff_interface{ + NPC::npc_interface, ref_interface, + static_cast(pmem_get())->get_pmem(), 128 * 1024}; + if (config.interactive) { + SDB::SDB sdb_diff{diff_interface}; sdb_diff.main_loop(); + return 0; + } + + try { + diff_interface.init(0); + diff_interface.exec(-1); + } catch (TrmRuntimeException &e) { + switch (e.error_code()) { + case TrmRuntimeException::EBREAK: + return 0; + case TrmRuntimeException::DIFFTEST_FAILED: + std::cout << "Difftest Failed" << std::endl; + diff_interface.print(std::cout); + return 1; + default: + std::cerr << "Unknown error happened" << std::endl; + return 1; + } } return 0; diff --git a/npc/csrc/devices/CMakeLists.txt b/npc/csrc/devices/CMakeLists.txt new file mode 100644 index 0000000..fa33794 --- /dev/null +++ b/npc/csrc/devices/CMakeLists.txt @@ -0,0 +1,3 @@ +add_library(devices serial.cpp rtc.cpp) + +target_include_directories(devices PUBLIC include) diff --git a/npc/csrc/devices/include/devices.hpp b/npc/csrc/devices/include/devices.hpp new file mode 100644 index 0000000..4954ac0 --- /dev/null +++ b/npc/csrc/devices/include/devices.hpp @@ -0,0 +1,85 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace Devices { +class Device { +public: + uint8_t *p_buf; + uint64_t addr; + size_t len; + Device(uint64_t addr, size_t len, uint8_t buf[]) + : addr(addr), len(len), p_buf(buf) {} + virtual ~Device(){}; + virtual void io_handler(uint32_t offset, size_t len, bool is_write) = 0; + void transfer(uint8_t *src, size_t len, bool is_write) { + if (is_write) { + memmove(p_buf, src, len); + } else { + memmove(src, p_buf, len); + } + }; +}; + +class Serial : public Device { + uint8_t buf[1]; + +public: + Serial(uint64_t addr, size_t len); + ~Serial() override{}; + void io_handler(uint32_t offset, size_t len, bool is_write) override; + // void transfer(uint8_t *src, size_t len, bool is_write) override; +}; + +class RTC : public Device { + uint8_t buf[8]; + uint64_t boot_time; + uint64_t get_time_internal(); + uint64_t get_time(); + +public: + RTC(uint64_t addr, size_t len); + ~RTC() override{}; + void io_handler(uint32_t offset, size_t len, bool is_write) override; + // void transfer(uint8_t *src, size_t len, bool is_write) override; +}; + +class DeviceMap { + std::map addr_to_device; + +public: + DeviceMap(std::initializer_list devices) { + for (auto device : devices) { + addr_to_device.insert(std::make_pair(device->addr, device)); + } + } + bool handle(uint64_t addr, uint8_t *data, size_t len, bool is_write) { + auto it = addr_to_device.upper_bound(addr); + if (it == addr_to_device.begin() || + (--it)->second->addr + it->second->len <= addr) { + std::cerr << "Use of a unintialized device at memory addr: 0x" << std::hex + << addr << std::dec << std::endl; + return false; + } + auto &device = it->second; + uint32_t offset = addr - device->addr; + if (is_write) { + device->transfer(data, len, is_write); + device->io_handler(offset, len, is_write); + } else { + device->io_handler(offset, len, is_write); + device->transfer(data, len, is_write); + } + return true; + } +}; +} // namespace Devices diff --git a/npc/csrc/devices/rtc.cpp b/npc/csrc/devices/rtc.cpp new file mode 100644 index 0000000..1a26ab1 --- /dev/null +++ b/npc/csrc/devices/rtc.cpp @@ -0,0 +1,49 @@ +#include +#include + +namespace Devices { +uint64_t RTC::get_time_internal() { +#if defined(CONFIG_TARGET_AM) + uint64_t us = io_read(AM_TIMER_UPTIME).us; +#elif defined(CONFIG_TIMER_GETTIMEOFDAY) + struct timeval now; + gettimeofday(&now, NULL); + uint64_t us = now.tv_sec * 1000000 + now.tv_usec; +#else + struct timespec now; + clock_gettime(CLOCK_MONOTONIC_COARSE, &now); + uint64_t us = now.tv_sec * 1000000 + now.tv_nsec / 1000; +#endif + return us; +} + +uint64_t RTC::get_time() { + if (boot_time == 0) + boot_time = get_time_internal(); + uint64_t now = get_time_internal(); + return now - boot_time; +} + +RTC::RTC(uint64_t addr, size_t len) : Device(addr, len, buf) { + *(uint64_t *)buf = 0; +}; + +void RTC::io_handler(uint32_t offset, size_t len, bool is_write) { + assert(offset == 0 || offset == 4); + if (!is_write && offset == 4) { + uint64_t us = get_time(); + buf[0] = (uint32_t)us; + buf[1] = us >> 32; + } +} + +// void RTC::transfer(uint8_t *src, size_t len, bool is_write) { +// if (is_write) { +// for (size_t i = 0; i < len; i++) +// buf[i] = src[i]; +// } else { +// for (size_t i = 0; i < len; i++) +// src[i] = buf[i]; +// } +// } +} // namespace Devices diff --git a/npc/csrc/devices/serial.cpp b/npc/csrc/devices/serial.cpp new file mode 100644 index 0000000..8a09551 --- /dev/null +++ b/npc/csrc/devices/serial.cpp @@ -0,0 +1,22 @@ +#include +#include + +namespace Devices { +Serial::Serial(uint64_t addr, size_t len) : Device(addr, len, buf) { + buf[0] = 0; +}; +void Serial::io_handler(uint32_t offset, size_t len, bool is_write) { + if (is_write) { + std::cout << (char)buf[0]; + } +} +// void Serial::transfer(uint8_t *src, size_t len, bool is_write) { +// if (is_write) { +// for (size_t i = 0; i < len; i++) +// buf[i] = src[i]; +// } else { +// for (size_t i = 0; i < len; i++) +// src[i] = buf[i]; +// } +// } +} // namespace Devices diff --git a/npc/csrc_nvboard/Flow/CMakeLists.txt b/npc/csrc_nvboard/Flow/CMakeLists.txt index 82143bc..6e3e1b3 100644 --- a/npc/csrc_nvboard/Flow/CMakeLists.txt +++ b/npc/csrc_nvboard/Flow/CMakeLists.txt @@ -2,22 +2,30 @@ include(ChiselBuild) add_custom_command( OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${TOPMODULE}/auto_bind.cpp - COMMAND auto_pin_bind ${CMAKE_SOURCE_DIR}/constr/${TOPMODULE}.nxdc ${CMAKE_CURRENT_BINARY_DIR}/${TOPMODULE}/auto_bind.cpp - DEPENDS ${CMAKE_SOURCE_DIR}/constr/${TOPMODULE}.nxdc -) + COMMAND auto_pin_bind ${CMAKE_SOURCE_DIR}/constr/${TOPMODULE}.nxdc + ${CMAKE_CURRENT_BINARY_DIR}/${TOPMODULE}/auto_bind.cpp + DEPENDS ${CMAKE_SOURCE_DIR}/constr/${TOPMODULE}.nxdc) add_executable(V${TOPMODULE}_nvboard - ${CMAKE_CURRENT_BINARY_DIR}/${TOPMODULE}/auto_bind.cpp - main.cpp -) + ${CMAKE_CURRENT_BINARY_DIR}/${TOPMODULE}/auto_bind.cpp main.cpp) -verilate(V${TOPMODULE}_nvboard TRACE THREADS - TOP_MODULE ${TOPMODULE} - PREFIX V${TOPMODULE} - SOURCES ${CHISEL_OUTPUT_TOPMODULE} - INCLUDE_DIRS ${CHISEL_OUTPUT_DIR}) +verilate( + V${TOPMODULE}_nvboard + TRACE + THREADS + TOP_MODULE + ${TOPMODULE} + PREFIX + V${TOPMODULE} + SOURCES + ${CHISEL_OUTPUT_TOPMODULE} + INCLUDE_DIRS + ${CHISEL_OUTPUT_DIR}) -target_include_directories(V${TOPMODULE}_nvboard PRIVATE ${NVBOARD_INCLUDE_DIR} ${SDL2_INCLUDE_DIRS}) -target_link_libraries(V${TOPMODULE}_nvboard PRIVATE ${NVBOARD_LIBRARY} SDL2::SDL2 SDL2_image::SDL2_image) +target_include_directories(V${TOPMODULE}_nvboard PRIVATE ${NVBOARD_INCLUDE_DIR} + ${SDL2_INCLUDE_DIRS}) +target_link_libraries( + V${TOPMODULE}_nvboard PRIVATE ${NVBOARD_LIBRARY} SDL2::SDL2 + SDL2_image::SDL2_image) -install(TARGETS V${TOPMODULE}_nvboard) \ No newline at end of file +install(TARGETS V${TOPMODULE}_nvboard) diff --git a/npc/include/components.hpp b/npc/include/components.hpp index 91847a7..ca86156 100644 --- a/npc/include/components.hpp +++ b/npc/include/components.hpp @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -32,21 +33,21 @@ public: } }; -template class Memory { - uint32_t expand_bits(uint8_t bits) { - uint32_t x = bits; - x = (x | (x << 7) | (x << 14) | (x << 21)) & 0x01010101; - x = x * 0xFF; - // printf("expand: %hhx->%x\n", bits, x); - return x; - } +// class MemoryFile { +// std::filesystem::path filepath; +// public: + +// }; + +template class Memory { + paddr_t pmem_start, pmem_end; public: - std::array mem; - std::vector> trace_ranges; - Memory(std::filesystem::path filepath, bool is_binary, - std::vector> &&trace_ranges) - : trace_ranges(std::move(trace_ranges)) { + std::array mem; + // TODO: Read memory file before init and use memcpy to initialize memory. + Memory(std::filesystem::path filepath, bool is_binary, paddr_t pmem_start, + paddr_t pmem_end) + : pmem_start(pmem_start), pmem_end(pmem_end) { if (!std::filesystem::exists(filepath)) throw std::runtime_error("Memory file not found"); if (is_binary) { @@ -62,54 +63,79 @@ public: } } } - const T &operator[](std::size_t addr) { return this->read(addr); } - /** - * Always reads and returns 4 bytes from the address raddr & ~0x3u. - */ - T read(paddr_t raddr) { - // printf("raddr: 0x%x\n", raddr); - return *(word_t *)guest_to_host(raddr); + const word_t &operator[](std::size_t addr) { return this->read(addr); } + void transfer(paddr_t addr, uint8_t data[], size_t len, bool is_write) { + if (is_write) { + // memcpy(guest_to_host(addr), data, len); + size_t offset = (addr - pmem_start); + std::copy(data, data + len, &mem[offset]); + } else { + // memcpy(data, guest_to_host(addr), len); + size_t offset = (addr - pmem_start); + std::copy(&mem[offset], &mem[offset + len], data); + } } - /** - * Always writes to the 4 bytes at the address `waddr` & ~0x3u. - * Each bit in `wmask` represents a mask for one byte in wdata. - * For example, wmask = 0x3 means only the lowest 2 bytes are written, - * and the other bytes in memory remain unchanged. - */ - void write(paddr_t waddr, T wdata, char wmask) { + bool in_pmem(paddr_t addr) const { + return addr >= pmem_start && addr <= pmem_end; + } +}; + +template class MemoryMap { + std::unique_ptr ram; + std::unique_ptr devices; + const std::vector> &trace_ranges; + +public: + MemoryMap(std::unique_ptr &&ram, std::unique_ptr &&devices, + const std::vector> &trace_ranges) + : ram(std::move(ram)), devices(std::move(devices)), + trace_ranges(trace_ranges) {} + void write(paddr_t waddr, word_t wdata, char wmask) { // printf("waddr: 0x%x\n", waddr); - uint8_t *p_data = (uint8_t *)&wdata; - while (wmask & 0x1) { - memcpy(guest_to_host(waddr), p_data, 1); - waddr++; - p_data++; - wmask >>= 1; + size_t len = (wmask & 1) + ((wmask & 2) >> 1) + ((wmask & 4) >> 2) + + ((wmask & 8) >> 3); + if (ram->in_pmem(waddr)) { + ram->transfer(waddr, (uint8_t *)&wdata, len, true); + } else if (devices->handle(waddr, (uint8_t *)&wdata, len, true)) { } } - void *guest_to_host(std::size_t addr) { - extern bool g_skip_memcheck; - if (g_skip_memcheck) { - return mem.data(); + word_t read(paddr_t raddr) const { + word_t res = 0; + // printf("raddr: 0x%x, in_pmem: %d\n", raddr, ram->in_pmem(raddr)); + if (ram->in_pmem(raddr)) { + ram->transfer(raddr, (uint8_t *)&res, 4, false); + } else if (devices->handle(raddr, (uint8_t *)&res, 4, false)) { } - if (addr < 0x80000000 || addr > 0x87ffffff) { - std::cerr << std::hex << "ACCESS " << addr << std::dec << std::endl; - throw std::runtime_error("Invalid memory access"); - } - // Linear mapping - return (uint8_t *)(mem.data() + (addr >> 2) - 0x20000000) + (addr & 0x3); + return res; } + void copy_to(paddr_t addr, uint8_t *buf, size_t len) const { + if (ram->in_pmem(addr)) { + ram->transfer(addr, buf, len, false); + } else { + std::cerr << "Not in pmem" << std::endl; + } + } + void copy_from(paddr_t addr, const uint8_t *buf, size_t len) { + if (ram->in_pmem(addr)) { + ram->transfer(addr, buf, len, true); + } else { + std::cerr << "Not in pmem" << std::endl; + } + } + void *get_pmem() { return ram->mem.data(); } void trace(paddr_t addr, bool is_read, word_t pc = 0, word_t value = 0) { for (auto &r : trace_ranges) { if (r[0] <= addr && r[1] >= addr) { std::stringstream os; - os << std::hex; if (pc != 0) - os << "0x" << pc << " "; + os << "0x" << std::hex << pc << " "; if (is_read) - os << "[R] "; + os << "[R] " + << "0x" << addr << ": 0x" << this->read(addr); else - os << "[W] " << value << " -> "; - os << "0x" << addr << std::dec << std::endl; + os << "[W] " << value << " -> " + << "0x" << addr; + os << std::dec << std::endl; std::cout << os.rdbuf(); break; } diff --git a/npc/include/config.hpp b/npc/include/config.hpp index de536b6..c57ca2e 100644 --- a/npc/include/config.hpp +++ b/npc/include/config.hpp @@ -9,7 +9,7 @@ struct Config { std::filesystem::path memory_file; - uint64_t max_sim_time = 0; + bool interactive{false}; bool memory_file_binary = {true}; bool do_mtrace{false}; std::vector> mtrace_ranges{ @@ -21,4 +21,4 @@ struct Config { extern Config config; -#endif \ No newline at end of file +#endif diff --git a/npc/include/trm_interface.hpp b/npc/include/trm_interface.hpp index 5acb8d6..5410820 100644 --- a/npc/include/trm_interface.hpp +++ b/npc/include/trm_interface.hpp @@ -37,6 +37,7 @@ template struct CPUStateBase { /* This does not update the register!!! */ R at(std::string name) { + // FIXME: Using this to get pc seems broken return name == "pc" ? pc : reg[regs_by_name.at(name)]; } @@ -154,4 +155,4 @@ struct RefTrmInterface : TrmInterface { void print(std::ostream &os) const override { os << *(CPUState *)cpu_state; } }; -#endif \ No newline at end of file +#endif diff --git a/npc/utils/CMakeLists.txt b/npc/utils/CMakeLists.txt index d61f3d8..545b778 100644 --- a/npc/utils/CMakeLists.txt +++ b/npc/utils/CMakeLists.txt @@ -1,3 +1,3 @@ -if (ENABLE_SDB) +if(ENABLE_SDB) add_subdirectory(sdb) endif() diff --git a/npc/utils/sdb/CMakeLists.txt b/npc/utils/sdb/CMakeLists.txt index 2a41fbf..70b3f3d 100644 --- a/npc/utils/sdb/CMakeLists.txt +++ b/npc/utils/sdb/CMakeLists.txt @@ -5,14 +5,30 @@ find_package(LLVM CONFIG REQUIRED) set(PARSER_DIR "${CMAKE_CURRENT_BINARY_DIR}") set(LEXER_OUT "${PARSER_DIR}/lexer.c") set(PARSER_OUT "${PARSER_DIR}/parser.c") -flex_target(LEXER addrexp.l "${LEXER_OUT}" DEFINES_FILE "${PARSER_DIR}/addrexp_lex.h") -bison_target(PARSER addrexp.y "${PARSER_OUT}" DEFINES_FILE "${PARSER_DIR}/addrexp.h") +flex_target(LEXER addrexp.l "${LEXER_OUT}" + DEFINES_FILE "${PARSER_DIR}/addrexp_lex.h") +bison_target(PARSER addrexp.y "${PARSER_OUT}" + DEFINES_FILE "${PARSER_DIR}/addrexp.h") add_flex_bison_dependency(LEXER PARSER) -add_library(sdb OBJECT sdb.cpp console.cpp disasm.cpp "${LEXER_OUT}" "${PARSER_OUT}") -llvm_map_components_to_libnames(LLVM_LIBS core target asmparser riscvasmparser riscvdesc riscvdisassembler riscvinfo riscvtargetmca) +add_library(sdb OBJECT sdb.cpp console.cpp disasm.cpp "${LEXER_OUT}" + "${PARSER_OUT}") +llvm_map_components_to_libnames( + LLVM_LIBS + core + target + asmparser + riscvasmparser + riscvdesc + riscvdisassembler + riscvinfo + riscvtargetmca) target_link_libraries(sdb PUBLIC ${LLVM_LIBS}) target_link_libraries(sdb PRIVATE ${Readline_LIBRARY}) -target_include_directories(sdb PRIVATE ${PARSER_DIR}) -target_include_directories(sdb PRIVATE ${Readline_INCLUDE_DIR}) + +target_include_directories( + sdb + PRIVATE ${PARSER_DIR} ${Readline_INCLUDE_DIR} + PUBLIC ${CMAKE_SOURCE_DIR}/include) + target_include_directories(sdb PUBLIC include) diff --git a/npc/utils/sdb/include/sdb.hpp b/npc/utils/sdb/include/sdb.hpp index 964412a..569773b 100644 --- a/npc/utils/sdb/include/sdb.hpp +++ b/npc/utils/sdb/include/sdb.hpp @@ -96,4 +96,4 @@ public: }; } // namespace SDB -#endif \ No newline at end of file +#endif diff --git a/npc/utils/sdb/sdb.cpp b/npc/utils/sdb/sdb.cpp index 55d6d41..36aa787 100644 --- a/npc/utils/sdb/sdb.cpp +++ b/npc/utils/sdb/sdb.cpp @@ -3,7 +3,6 @@ #include #include #include -#include #include #include extern "C" {