diff --git a/CMakeLists.txt b/CMakeLists.txt index 5d0720c..6f4e3f8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,5 +6,7 @@ set(CMAKE_C_STANDARD 17) include(GNUInstallDirs) +find_package(spdlog REQUIRED) + include_directories(include) add_subdirectory(src) diff --git a/difftest.toml b/difftest.toml new file mode 100644 index 0000000..f45fd50 --- /dev/null +++ b/difftest.toml @@ -0,0 +1,13 @@ +# ref = "/home/xin/repo/spike-diff/build/lib/libspike-diff.so" +# ref-prefix = "spike_" +# dut = "/home/xin/repo/ysyx-workbench/nemu/build/riscv32-nemu-interpreter-so" +# dut-prefix = "nemu_" + +ref = /home/xin/repo/ysyx-workbench/nemu/build/riscv32-nemu-interpreter-so +ref-prefix = nemu_ +dut = "/home/xin/repo/spike-diff/build/lib/libspike-diff.so" +dut-prefix = "spike_" +listen = "/tmp/gdbstub-diffu.sock" +# listen = "127.0.0.1:1234" +memory = "/nix/store/37986mdgsqm5m8w74k0f5llzqhxgsbnv-am-kernel-riscv32-none-elf-2024-07-10/share/am-kernels/string.bin" +# g = true diff --git a/flake.lock b/flake.lock index 5e5d23f..fae0e3e 100644 --- a/flake.lock +++ b/flake.lock @@ -112,11 +112,11 @@ ] }, "locked": { - "lastModified": 1721457008, - "narHash": "sha256-ekpve0om5hzC1Ntd3zm1cZ9oS5pnr7a2n/tueyqFOsg=", + "lastModified": 1721891452, + "narHash": "sha256-2c9nDuXXARzoRXE67lte5kKBeFb1XmTNsvdiIbRUEgE=", "ref": "refs/heads/master", - "rev": "e7aa3319d52fa987ac2192f63aef3dcb1b057e3a", - "revCount": 151, + "rev": "de8ad578fc4fe527772cec23a7f660bde14c8570", + "revCount": 152, "type": "git", "url": "https://git.xinyang.life/xin/nur.git" }, diff --git a/flake.nix b/flake.nix index fb8fb90..1ef76ad 100644 --- a/flake.nix +++ b/flake.nix @@ -38,14 +38,16 @@ }; }; }; - devShells.default = with pkgs; mkShell { + devShells.default = with pkgs; (mkShell.override { stdenv = ccacheStdenv; }) { inherit (self.checks.${system}.pre-commit-check) shellHook; buildInputs = self.checks.${system}.pre-commit-check.enabledPackages; packages = [ clang-tools cmake + ninja gdb cli11 + spdlog mini-gdbstub ]; }; diff --git a/include/difftest.hpp b/include/difftest.hpp index 7410e0e..c585844 100644 --- a/include/difftest.hpp +++ b/include/difftest.hpp @@ -2,13 +2,12 @@ #define _DIFFTEST_DIFFTEST_H_ #include "api.hpp" #include -#include +#include #include extern "C" { #include } -#include class Difftest { private: Target dut; @@ -55,17 +54,22 @@ public: arch_info_t get_arch() const { return *dut.isa_arch_info; } static bool check(Target &dut, Target &ref) { + size_t pcref, pcdut; + bool passed = true; + dut.ops.read_reg(dut.args.data(), 32, &pcdut); + ref.ops.read_reg(ref.args.data(), 32, &pcref); for (int r = 0; r < dut.isa_arch_info->reg_num; r++) { size_t regdut = 0, regref = 0; dut.ops.read_reg(dut.args.data(), r, ®dut); ref.ops.read_reg(ref.args.data(), r, ®ref); if (regdut != regref) { - std::cout << "reg: " << r << " dut: " << regdut << " ref: " << regref - << std::endl; - throw std::runtime_error("Difftest failed"); + spdlog::error("Reg {} different: \n\tPC:\t(ref) {:x}\t(dut) {:x}\n\t" + "value:\t(ref) {:x}\t(dut) {:x}", + r, pcref, pcdut, regref, regdut); + passed = false; } } - return true; + return passed; }; class Iterator { diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 2c13e71..6166ab9 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,4 +1,3 @@ add_executable(diffu cli.cpp difftest.cpp gdbstub.cpp loader.cpp main.cpp) -target_link_libraries(diffu PRIVATE gdbstub) +target_link_libraries(diffu PRIVATE gdbstub spdlog::spdlog) install ( TARGETS diffu ) - diff --git a/src/difftest.cpp b/src/difftest.cpp index 8da7c30..acba918 100644 --- a/src/difftest.cpp +++ b/src/difftest.cpp @@ -2,10 +2,9 @@ #include #include #include +#include #include -#include - Difftest::Difftest(Target &&dut, std::vector &&refs) { this->dut = std::move(dut); this->refs = std::move(refs); @@ -36,6 +35,7 @@ void Difftest::setup(const std::filesystem::path &memory_file) { for (auto it = this->begin(); it != this->end(); ++it) { auto &target = *it; target.ops.init(target.args.data()); + target.ops.write_reg(target.args.data(), 32, 0x80000000UL); if (target.ops.write_mem(target.args.data(), 0x80000000UL, membuf.size(), membuf.data()) != 0) throw std::runtime_error("write_mem failed"); @@ -43,10 +43,12 @@ void Difftest::setup(const std::filesystem::path &memory_file) { } bool Difftest::check_all() { + bool passed = true; for (auto &ref : refs) { - check(dut, ref); + if (check(dut, ref) == false) + passed = false; } - return true; + return passed; } Difftest::ExecRet Difftest::exec(size_t n, gdb_action_t *ret) { @@ -58,9 +60,12 @@ Difftest::ExecRet Difftest::exec(size_t n, gdb_action_t *ret) { auto &target = *it; *target.do_difftest = true; target.ops.stepi(target.args.data(), &target.last_res); + spdlog::trace("{} stepped once", target.meta.name); if (target.is_on_breakpoint()) { exec_ret.at_breakpoint = true; pbreak = ⌖ + spdlog::trace("{} on breakpoint", target.meta.name); + continue; } exec_ret.do_difftest = *target.do_difftest && exec_ret.do_difftest; } @@ -88,7 +93,10 @@ gdb_action_t Difftest::cont() { while (!is_halt()) { exec_ret = exec(1, &ret); if (exec_ret.do_difftest) - check_all(); + if (check_all() == false) { + ret.reason = gdb_action_t::ACT_BREAKPOINT; + break; + } if (exec_ret.at_breakpoint) break; }; @@ -122,6 +130,7 @@ int Difftest::sync_regs_to_ref(void) { return ret; } } + spdlog::trace("Applied registers value from dut to ref"); return ret; } diff --git a/src/gdbstub.cpp b/src/gdbstub.cpp index 6d613bb..e5774f2 100644 --- a/src/gdbstub.cpp +++ b/src/gdbstub.cpp @@ -2,10 +2,10 @@ #include #include #include +#include #include extern "C" { #include -} static void difftest_cont(void *args, gdb_action_t *res) { Difftest *diff = (Difftest *)args; @@ -65,6 +65,7 @@ std::vector split_into_args(const std::string &command) { static char *gdbstub_monitor(void *args, const char *s) { Difftest *diff = (Difftest *)args; + spdlog::trace("monitor"); CLI::App parser; std::string ret = ""; @@ -110,6 +111,7 @@ static char *gdbstub_monitor(void *args, const char *s) { return strdup(ret_stream.str().c_str()); } } +} int gdbstub_loop(Difftest *diff, std::string socket_addr) { target_ops gdbstub_ops = {.cont = difftest_cont, @@ -124,14 +126,16 @@ int gdbstub_loop(Difftest *diff, std::string socket_addr) { .monitor = gdbstub_monitor}; gdbstub_t gdbstub_priv; - std::cout << "Waiting for gdb connection at " << socket_addr << std::endl; + arch_info_t arch = diff->get_arch(); - if (!gdbstub_init(&gdbstub_priv, &gdbstub_ops, diff->get_arch(), + if (!gdbstub_init(&gdbstub_priv, &gdbstub_ops, arch, nullptr, socket_addr.c_str())) { - std::cerr << "Failed to init socket at: " << socket_addr << std::endl; + spdlog::error("Failed to init socket at: {}", socket_addr); return false; } + spdlog::info("Connected to gdb at {}", socket_addr); + bool success = gdbstub_run(&gdbstub_priv, diff); gdbstub_close(&gdbstub_priv); return !success; diff --git a/src/loader.cpp b/src/loader.cpp index fa5b062..b7f8413 100644 --- a/src/loader.cpp +++ b/src/loader.cpp @@ -1,7 +1,7 @@ #include "api.hpp" -#include #include #include +#include #include Target::Target(const std::string &name, const std::string &func_prefix, @@ -11,16 +11,19 @@ Target::Target(const std::string &name, const std::string &func_prefix, .libpath = path, .dlhandle = dlopen(path.c_str(), RTLD_NOW)}; + spdlog::info("Library handle: {}", meta.dlhandle); if (!meta.dlhandle) { throw std::runtime_error(dlerror()); } #define LOAD_SYMBOL(ops, handle, prefix, name) \ do { \ + std::string symbol_name = func_prefix + #name; \ (ops).name = reinterpret_cast( \ - dlsym((handle), ((prefix) + #name).c_str())); \ + dlsym((handle), symbol_name.c_str())); \ if (!((ops).name)) \ goto load_error; \ + spdlog::debug("Found {} at {}", symbol_name, ((void *)((ops).name))); \ } while (0); LOAD_SYMBOL(ops, meta.dlhandle, func_prefix, cont); diff --git a/src/main.cpp b/src/main.cpp index 7b1110d..29d209f 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,10 +1,12 @@ #include "api.hpp" #include "config.hpp" #include "difftest.hpp" +#include int gdbstub_loop(Difftest *, std::string); int main(int argc, char **argv) { + spdlog::cfg::load_env_levels(); Config config; int ret = 0; ret = config.cli_parse(argc, argv);