diff --git a/.gitignore b/.gitignore index 76cec07..dcecdc1 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ +**/.gdbinit !*/ difftest/ !/nemu/* diff --git a/flake.nix b/flake.nix index d5c35f1..74de402 100644 --- a/flake.nix +++ b/flake.nix @@ -93,7 +93,7 @@ devShells.npc = pkgs.mkShell.override { stdenv = pkgs.ccacheStdenv; } { inherit (self.checks.${system}.pre-commit-check) shellHook; CHISEL_FIRTOOL_PATH = "${nixpkgs-circt162.legacyPackages.${system}.circt}/bin"; - NPC_IMAGES_DIR="${self.packages.${system}.am-kernels-npc}/share/am-kernels"; + NPC_IMAGES_PATH = "${self.packages.${system}.rv32Cross.am-kernels-npc}/share/am-kernels"; packages = with pkgs; [ clang-tools cmake @@ -109,6 +109,7 @@ nativeBuildInputs = with pkgs; [ cmake + ninja sbt nvboard nixpkgs-circt162.legacyPackages.${system}.circt @@ -117,10 +118,11 @@ flex bison verilator - self.packages.${system}.am-kernels-npc + self.packages.${system}.rv32Cross.am-kernels-npc ]; buildInputs = with pkgs; [ + spdlog nvboard openssl libllvm @@ -128,10 +130,6 @@ readline mini-gdbstub ] ++ self.checks.${system}.pre-commit-check.enabledPackages; - - cmakeFlags = [ - "-DDIFFTEST_LIB:string=${self.packages.${system}.nemu-lib}/lib/riscv32-nemu-interpreter-so" - ]; }; } ); diff --git a/npc/CMakeLists.txt b/npc/CMakeLists.txt index 4b4424e..2903475 100644 --- a/npc/CMakeLists.txt +++ b/npc/CMakeLists.txt @@ -41,6 +41,7 @@ if(BUILD_SIM_NVBOARD_TARGET) find_package(SDL2_image REQUIRED) endif() find_package(CLI11 CONFIG REQUIRED) +find_package(spdlog REQUIRED) option(ENABLE_SDB "Enable simple debugger" OFF) @@ -58,9 +59,6 @@ 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) diff --git a/npc/csrc/Flow/CMakeLists.txt b/npc/csrc/Flow/CMakeLists.txt index d64cfca..2af6a5b 100644 --- a/npc/csrc/Flow/CMakeLists.txt +++ b/npc/csrc/Flow/CMakeLists.txt @@ -1,6 +1,6 @@ include(ChiselBuild) -add_executable(V${TOPMODULE} config.cpp main.cpp) -target_link_libraries(V${TOPMODULE} PRIVATE devices gdbstub) +add_executable(V${TOPMODULE} config.cpp gdbstub_wrapper.cpp main.cpp) +target_link_libraries(V${TOPMODULE} PRIVATE devices gdbstub spdlog::spdlog) target_include_directories(V${TOPMODULE} PRIVATE ${CMAKE_SOURCE_DIR}/include) verilate( @@ -28,8 +28,8 @@ foreach(DIFFTEST_BINARY_FILE IN LISTS DIFFTEST_BINARY_FILES) unset(FILENAME) endforeach() -add_library(${TOPMODULE} SHARED config.cpp main.cpp) -target_link_libraries(${TOPMODULE} PRIVATE devices gdbstub) +add_library(${TOPMODULE} SHARED config.cpp gdbstub_wrapper.cpp) +target_link_libraries(${TOPMODULE} PRIVATE devices gdbstub spdlog::spdlog) target_include_directories(${TOPMODULE} PRIVATE ${CMAKE_SOURCE_DIR}/include) set_property(TARGET PROPERTY POSITION_INDEPENDENT_CODE ON) target_link_options(${TOPMODULE} PRIVATE -Wl,-E) diff --git a/npc/csrc/Flow/config.cpp b/npc/csrc/Flow/config.cpp index 71e042f..035fe24 100644 --- a/npc/csrc/Flow/config.cpp +++ b/npc/csrc/Flow/config.cpp @@ -2,8 +2,10 @@ void Config::cli_parse(int argc, char **argv) { CLI::App app; + app.add_option("-l,--listen", gdbsocket, + "Listen to debugger at this address"); + app.add_flag("-g", do_debug, "Listen for gdb"); app.add_option("-m,--memory", memory_file, "Content of memory") - ->required() ->check(CLI::ExistingFile); app.add_flag("!--no-bin", memory_file_binary, "Memory file is in text format"); @@ -12,11 +14,6 @@ void Config::cli_parse(int argc, char **argv) { app.add_option("--diff-lib", lib_ref, "Dynamic library file of difftest reference") ->check(CLI::ExistingFile); - app.add_flag("--mtrace", do_mtrace, "Enable memory tracing"); - app.add_option( - "--mtrace-range", mtrace_ranges, - "Specify memory tracing range (default: 0x80000000-0x8fffffff)") - ->delimiter(','); try { app.parse(argc, argv); diff --git a/npc/csrc/Flow/gdbstub_wrapper.cpp b/npc/csrc/Flow/gdbstub_wrapper.cpp new file mode 100644 index 0000000..970ce55 --- /dev/null +++ b/npc/csrc/Flow/gdbstub_wrapper.cpp @@ -0,0 +1,196 @@ +extern "C" { +#include +} +#include "components.hpp" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using Registers = _RegistersVPI; +using VlModule = VlModuleInterfaceCommon; + +// SDB::SDB sdb_dut; +bool g_skip_memcheck = false; +VlModule *top; +Registers *regs; +vpiHandle pc = nullptr; + +const size_t PMEM_START = 0x80000000; +const size_t PMEM_END = 0x87ffffff; + +extern "C" { +/* === Memory Access === */ +using MMap = MemoryMap, Devices::DeviceMap>; +void *pmem_get() { + 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, true, PMEM_START, + PMEM_END), + std::make_unique(devices)); + return pmem; +} + +int pmem_read(int raddr) { + void *pmem = pmem_get(); + auto mem = static_cast(pmem); + // TODO: Do memory difftest at memory read and write to diagnose at a finer + // granularity + 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); + mem->trace((std::size_t)waddr, false, regs->get_pc(), wdata); + return mem->write((std::size_t)waddr, wdata, wmask); +} + +/* === For gdbstub === */ + +int npc_read_mem(void *args, size_t addr, size_t len, void *val) { + void *pmem = pmem_get(); + auto mmap = static_cast(pmem); + return mmap->copy_to(addr, (uint8_t *)val, len); +} + +int npc_write_mem(void *args, size_t addr, size_t len, void *val) { + void *pmem = pmem_get(); + auto mmap = static_cast(pmem); + return mmap->copy_from(addr, (uint8_t *)val, len); +} + +int npc_read_reg(void *args, int regno, size_t *value) { + if (regno == 32) + *value = regs->get_pc(); + else + *value = (*regs)[regno]; + return 0; +} + +int npc_write_reg(void *args, int regno, size_t value) { return 1; } + +inline void breakpoint_to_action(const Breakpoint *bp, gdb_action_t *res) { + if (bp == nullptr) { + res->reason = gdb_action_t::ACT_NONE; + return; + } + switch (bp->type) { + case BP_SOFTWARE: + res->reason = gdb_action_t::ACT_BREAKPOINT; + break; + case BP_ACCESS: + res->reason = gdb_action_t::ACT_WATCH; + break; + case BP_WRITE: + res->reason = gdb_action_t::ACT_WWATCH; + break; + case BP_READ: + res->reason = gdb_action_t::ACT_RWATCH; + break; + } + res->data = bp->addr; +} + +void npc_cont(void *args, gdb_action_t *res) { + DbgState *dbg = (DbgState *)args; + const Breakpoint *stopped_at = nullptr; + stopped_at = top->cont(*dbg->bp); + breakpoint_to_action(stopped_at, res); +} + +void npc_stepi(void *args, gdb_action_t *res) { + DbgState *dbg = (DbgState *)args; + const Breakpoint *stopped_at = nullptr; + stopped_at = top->stepi(*dbg->bp); + breakpoint_to_action(stopped_at, res); +} + +bool npc_set_bp(void *args, size_t addr, bp_type_t type) { + DbgState *dbg = (DbgState *)args; + for (const auto &bp : *dbg->bp) { + if (bp.addr == addr && bp.type == type) { + return true; + } + } + dbg->bp->push_back({.addr = addr, .type = type}); + return true; +} + +bool npc_del_bp(void *args, size_t addr, bp_type_t type) { + DbgState *dbg = (DbgState *)args; + for (auto it = dbg->bp->begin(); it != dbg->bp->end(); it++) { + if (it->addr == addr && it->type == type) { + std::swap(*it, *dbg->bp->rbegin()); + dbg->bp->pop_back(); + return true; + } + } + return false; +} + +void npc_on_interrupt(void *args) { ; } + +void npc_init(void *args) { + DbgState *dbg = (DbgState *)args; + void *mem = pmem_get(); + dbg->bp = new std::vector; + + top = new VlModule; + regs = new Registers("TOP.Flow.reg_0.regFile_", "TOP.Flow.pc.out"); + top->setup(config.wavefile, regs); + top->reset_eval(10); +} + +bool npc_do_difftest = true; + +static gdbstub_t gdbstub_priv; +arch_info_t npc_isa_arch_info{ + .target_desc = strdup(TARGET_RV32), .reg_num = 32, .reg_byte = 4}; + +size_t npc_dbg_state_size = sizeof(DbgState); + +} // extern "C" + +int gdbstub_loop() { + DbgState dbg; + + target_ops npc_gdbstub_ops = {.cont = npc_cont, + .stepi = npc_stepi, + .read_reg = npc_read_reg, + .write_reg = npc_write_reg, + .read_mem = npc_read_mem, + .write_mem = npc_write_mem, + .set_bp = npc_set_bp, + .del_bp = npc_del_bp, + .on_interrupt = NULL}; + + if (!config.do_debug) { + gdb_action_t res; + npc_init(&dbg); + npc_cont(&dbg, &res); + return !(res.reason == gdb_action_t::ACT_SHUTDOWN); + } + + if (!gdbstub_init(&gdbstub_priv, &npc_gdbstub_ops, + (arch_info_t)npc_isa_arch_info, NULL, + config.gdbsocket.c_str())) { + return EINVAL; + } + npc_init(&dbg); + + bool success = gdbstub_run(&gdbstub_priv, &dbg); + // gdbstub_close(&gdbstub_priv); + return !success; +} diff --git a/npc/csrc/Flow/main.cpp b/npc/csrc/Flow/main.cpp index 069abe4..ff35334 100644 --- a/npc/csrc/Flow/main.cpp +++ b/npc/csrc/Flow/main.cpp @@ -1,180 +1,13 @@ -extern "C" { -#include -} -// #include "VFlow___024root.h" -#include "components.hpp" -#include #include -#include -#include -#include -#include +#include +#include #include -#include -#include -#include -#include -using Registers = _RegistersVPI; -using VlModule = VlModuleInterfaceCommon; - -// SDB::SDB sdb_dut; -bool g_skip_memcheck = false; -VlModule *top; -Registers *regs; -vpiHandle pc = nullptr; - -const size_t PMEM_START = 0x80000000; -const size_t PMEM_END = 0x87ffffff; - -struct DbgState { - std::vector *bp; -}; - -extern "C" { - -/* === Memory Access === */ -using MMap = MemoryMap, Devices::DeviceMap>; -void *pmem_get() { - static Devices::DeviceMap devices{ - new Devices::Serial(0x10000000, 0x1000), - new Devices::RTC(0x10001000, 0x1000), - }; - static auto pmem = new MemoryMap, Devices::DeviceMap>( - std::make_unique>( - "/nix/store/" - "nv2c00y24qwz1jihfbaip9n1lskbzyb3-am-kernel-riscv32-none-elf-2024-07-" - "10/share/am-kernels/add.bin", - 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); - // 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); - if (config.do_mtrace) - mem->trace((std::size_t)waddr, false, regs->get_pc(), wdata); - return mem->write((std::size_t)waddr, wdata, wmask); -} - -/* === For gdbstub === */ - -int npc_read_mem(void *args, size_t addr, size_t len, void *val) { - void *pmem = pmem_get(); - auto mmap = static_cast(pmem); - mmap->copy_to(addr, (uint8_t *)val, len); - return 0; -} - -int npc_write_mem(void *args, size_t addr, size_t len, void *val) { - void *pmem = pmem_get(); - auto mmap = static_cast(pmem); - mmap->copy_from(addr, (uint8_t *)val, len); - return 0; -} - -int npc_read_reg(void *args, int regno, size_t *value) { - if (regno == 32) - *value = regs->get_pc(); - else - *value = (*regs)[regno]; - return 0; -} - -int npc_write_reg(void *args, int regno, size_t value) { return 1; } - -void npc_cont(void *args, gdb_action_t *res) { - DbgState *dbg = (DbgState *)args; - *res = top->eval(*dbg->bp); -} - -void npc_stepi(void *args, gdb_action_t *res) { - DbgState *dbg = (DbgState *)args; - *res = top->eval(*dbg->bp); -} - -bool npc_set_bp(void *args, size_t addr, bp_type_t type) { - DbgState *dbg = (DbgState *)args; - for (const auto &bp : *dbg->bp) { - if (bp.addr == addr && bp.type == type) { - return true; - } - } - dbg->bp->push_back({.addr = addr, .type = type}); - return true; -} - -bool npc_del_bp(void *args, size_t addr, bp_type_t type) { - DbgState *dbg = (DbgState *)args; - for (auto it = dbg->bp->begin(); it != dbg->bp->end(); it++) { - if (it->addr == addr && it->type == type) { - std::swap(*it, *dbg->bp->rbegin()); - dbg->bp->pop_back(); - return true; - } - } - return false; -} - -void npc_on_interrupt(void *args) { ; } - -void npc_init(void *args) { - DbgState *dbg = (DbgState *)args; - dbg->bp = new std::vector; - - top = new VlModule; - regs = new Registers("TOP.Flow.reg_0.regFile_", "TOP.Flow.pc.out"); - top->setup(config.wavefile, regs); - top->reset_eval(10); -} - -static gdbstub_t gdbstub_priv; -arch_info_t isa_arch_info = { - .target_desc = strdup(TARGET_RV32), .reg_num = 32, .reg_byte = 4}; - -size_t argsize = sizeof(DbgState); - -} // extern "C" - -int gdbstub_loop() { - DbgState dbg; - - target_ops npc_gdbstub_ops = {.cont = npc_cont, - .stepi = npc_stepi, - .read_reg = npc_read_reg, - .write_reg = npc_write_reg, - .read_mem = npc_read_mem, - .write_mem = npc_write_mem, - .set_bp = npc_set_bp, - .del_bp = npc_del_bp, - .on_interrupt = NULL}; - - if (!gdbstub_init(&gdbstub_priv, &npc_gdbstub_ops, (arch_info_t)isa_arch_info, - strdup("/tmp/gdbstub-npc.sock"))) { - return EINVAL; - } - npc_init(&dbg); - - bool success = gdbstub_run(&gdbstub_priv, &dbg); - // gdbstub_close(&gdbstub_priv); - return !success; -} +int gdbstub_loop(); int main(int argc, char **argv, char **env) { + spdlog::cfg::load_env_levels(); config.cli_parse(argc, argv); - + spdlog::debug("Configuration parsed"); return gdbstub_loop(); } diff --git a/npc/csrc/devices/CMakeLists.txt b/npc/csrc/devices/CMakeLists.txt index fa33794..3480105 100644 --- a/npc/csrc/devices/CMakeLists.txt +++ b/npc/csrc/devices/CMakeLists.txt @@ -1,3 +1,4 @@ add_library(devices serial.cpp rtc.cpp) target_include_directories(devices PUBLIC include) +target_link_libraries(devices PRIVATE spdlog::spdlog) diff --git a/npc/csrc/devices/include/devices.hpp b/npc/csrc/devices/include/devices.hpp index 4954ac0..0470a44 100644 --- a/npc/csrc/devices/include/devices.hpp +++ b/npc/csrc/devices/include/devices.hpp @@ -1,14 +1,12 @@ -#include -#include #include #include #include #include #include -#include #include #include -#include +#include +#include #include namespace Devices { @@ -55,6 +53,7 @@ public: class DeviceMap { std::map addr_to_device; + std::shared_ptr logger = spdlog::stdout_color_mt("devicemap"); public: DeviceMap(std::initializer_list devices) { @@ -66,8 +65,8 @@ public: 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; + logger->error("Accessed an unintialized device at memory addr: 0x{:x}", + addr); return false; } auto &device = it->second; diff --git a/npc/csrc_nvboard/Keyboard/main.cpp b/npc/csrc_nvboard/Keyboard/main.cpp index 8f5ea74..372bbaa 100644 --- a/npc/csrc_nvboard/Keyboard/main.cpp +++ b/npc/csrc_nvboard/Keyboard/main.cpp @@ -49,11 +49,10 @@ int main(int argc, char **argv, char **env) { while (true) { nvboard_update(); cycle(top, [&] { - if (keycode != top->io_ps2_data){ + if (keycode != top->io_ps2_data) { keycode = top->io_ps2_data; printf("%d\n", keycode); - } - }); + }); } delete top; -} \ No newline at end of file + } diff --git a/npc/include/components.hpp b/npc/include/components.hpp index bf16895..cfd05f1 100644 --- a/npc/include/components.hpp +++ b/npc/include/components.hpp @@ -3,23 +3,21 @@ #define _NPC_COMPONENTS_H_ #include "types.h" #include -#include #include #include -#include #include #include #include -#include -#include -#include +#include +#include #include #include -#include template class _RegistersBase { std::array regs; T pc; + std::shared_ptr logger = spdlog::stdout_color_mt("registers"); + virtual T fetch_pc() const; virtual T fetch_reg(std::size_t id) const; @@ -33,12 +31,6 @@ public: } }; -// class MemoryFile { -// std::filesystem::path filepath; -// public: - -// }; - template class Memory { paddr_t pmem_start, pmem_end; @@ -83,15 +75,13 @@ public: template class MemoryMap { std::unique_ptr ram; std::unique_ptr devices; - const std::vector> &trace_ranges; + std::shared_ptr logger = spdlog::stdout_color_mt("mmap"); 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) {} + MemoryMap(std::unique_ptr &&ram, std::unique_ptr &&devices) + : ram(std::move(ram)), devices(std::move(devices)) {} + void write(paddr_t waddr, word_t wdata, char wmask) { - // printf("waddr: 0x%x\n", waddr); size_t len = (wmask & 1) + ((wmask & 2) >> 1) + ((wmask & 4) >> 2) + ((wmask & 8) >> 3); if (ram->in_pmem(waddr)) { @@ -99,47 +89,38 @@ public: } else if (devices->handle(waddr, (uint8_t *)&wdata, len, true)) { } } + 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)) { } return res; } - void copy_to(paddr_t addr, uint8_t *buf, size_t len) const { + + int copy_to(paddr_t addr, uint8_t *buf, size_t len) const { if (ram->in_pmem(addr)) { ram->transfer(addr, buf, len, false); + return 0; } else { - std::cerr << "0x" << std::hex << addr << " not in pmem" << std::endl; + return EINVAL; } } - void copy_from(paddr_t addr, uint8_t *buf, size_t len) { + + int copy_from(paddr_t addr, uint8_t *buf, size_t len) { if (ram->in_pmem(addr)) { ram->transfer(addr, buf, len, true); + return 0; } else { - std::cerr << "0x" << std::hex << addr << " not in pmem" << std::endl; + return EINVAL; } } + 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; - if (pc != 0) - os << "0x" << std::hex << pc << " "; - if (is_read) - os << "[R] " - << "0x" << addr << ": 0x" << this->read(addr); - else - os << "[W] " << value << " -> " - << "0x" << addr; - os << std::dec << std::endl; - std::cout << os.rdbuf(); - break; - } - } + logger->trace("[{}] 0x{:x}", is_read ? 'R' : 'W', this->read(addr)); } }; #endif diff --git a/npc/include/config.hpp b/npc/include/config.hpp index c57ca2e..8c12f31 100644 --- a/npc/include/config.hpp +++ b/npc/include/config.hpp @@ -3,17 +3,14 @@ #include #include #include -#include #include -#include struct Config { std::filesystem::path memory_file; + std::string gdbsocket = "gdbstub-npc.sock"; + bool do_debug{false}; bool interactive{false}; bool memory_file_binary = {true}; - bool do_mtrace{false}; - std::vector> mtrace_ranges{ - {0x80000000, 0x8ffffffff}}; std::filesystem::path wavefile; std::filesystem::path lib_ref; void cli_parse(int argc, char **argv); diff --git a/npc/include/types.h b/npc/include/types.h index e991d8a..fcc14e4 100644 --- a/npc/include/types.h +++ b/npc/include/types.h @@ -1,6 +1,11 @@ #ifndef _NPC_TYPES_H__ #define _NPC_TYPES_H__ +#ifdef __cplusplus +extern "C" { +#endif +#include #include +#include typedef uint32_t word_t; typedef int32_t sword_t; @@ -16,9 +21,19 @@ typedef uint32_t paddr_t; #define FMT_ADDR "0x%08x" typedef uint16_t ioaddr_t; +struct Breakpoint { + size_t addr; + bp_type_t type; +}; + +#ifdef __cplusplus +} +#endif + #ifdef __cplusplus #include #include +#include const std::map riscv32_regs_by_name{ {"$0", 0}, {"ra", 1}, {"sp", 2}, {"gp", 3}, {"tp", 4}, {"t0", 5}, @@ -27,12 +42,10 @@ const std::map riscv32_regs_by_name{ {"s2", 18}, {"s3", 19}, {"s4", 20}, {"s5", 21}, {"s6", 22}, {"s7", 23}, {"s8", 24}, {"s9", 25}, {"s10", 26}, {"s11", 27}, {"t3", 28}, {"t4", 29}, {"t5", 30}, {"t6", 31}}; -#endif -#include -struct Breakpoint { - size_t addr; - bp_type_t type; +struct DbgState { + std::vector *bp; }; +#endif #endif diff --git a/npc/include/vl_wrapper.hpp b/npc/include/vl_wrapper.hpp index 02a6ac5..aa8e798 100644 --- a/npc/include/vl_wrapper.hpp +++ b/npc/include/vl_wrapper.hpp @@ -2,6 +2,7 @@ #define _NPC_TRACER_H_ #include "components.hpp" #include "types.h" +#include "verilated.h" #include #include #include @@ -47,7 +48,7 @@ public: registers = r; } - void eval() { + void eval(void) { if (this->is_posedge()) { posedge_cnt++; } @@ -57,35 +58,34 @@ public: if (tracer) tracer->update(); } - void eval(int n) { - for (int i = 0; i < n; i++) { - this->eval(); + + const Breakpoint *stepi(const std::vector &breakpoints) { + this->eval(); + this->eval(); + size_t pc = registers->get_pc(); + for (const auto &bp : breakpoints) { + if (pc == bp.addr) { + return &bp; + } } + return nullptr; } - gdb_action_t eval(const std::vector &breakpoints) { - gdb_action_t res; + const Breakpoint *cont(const std::vector &breakpoints) { + const Breakpoint *res = nullptr; do { - this->eval(); - size_t pc = registers->get_pc(); - for (const auto &bp : breakpoints) { - if (pc == bp.addr) { - res.data = bp.addr; - switch (bp.type) { - default: - res.reason = gdb_action_t::ACT_BREAKPOINT; - } - return res; - } - } - } while (true); + res = stepi(breakpoints); + } while (res == nullptr); + return res; } void reset_eval(int n) { extern bool g_skip_memcheck; g_skip_memcheck = true; this->reset = 1; - this->eval(n); + do { + this->eval(); + } while (--n); this->reset = 0; g_skip_memcheck = false; } diff --git a/npc/include/vpi_wrapper.hpp b/npc/include/vpi_wrapper.hpp index 4aaaeb8..25f26fb 100644 --- a/npc/include/vpi_wrapper.hpp +++ b/npc/include/vpi_wrapper.hpp @@ -1,12 +1,16 @@ #ifndef _NPC_VPI_WRAPPER_H_ #define _NPC_VPI_WRAPPER_H_ #include +#include +#include +#include #include template class _RegistersVPI : public _RegistersBase { std::array reg_handles; vpiHandle pc_handle; + T vpi_get(vpiHandle vh) const { s_vpi_value v; v.format = vpiIntVal;