Adds gdbserver to simulators and makes config general. PiperOrigin-RevId: 890418526 Change-Id: Icb7b88981eec72797a5df5b69c2059cb3d883ddd
diff --git a/riscv/BUILD b/riscv/BUILD index ad224eb..cb65100 100644 --- a/riscv/BUILD +++ b/riscv/BUILD
@@ -1253,8 +1253,6 @@ srcs = [ "riscv_debug_info.cc", "riscv_gdb_debug_info.cc", - "riscv_gdb_debug_info_32.inc", - "riscv_gdb_debug_info_64.inc", ], hdrs = [ "riscv_debug_info.h", @@ -1340,6 +1338,7 @@ ":riscv32g_vec_decoder", ":riscv32gzb_vec_decoder", ":riscv_arm_semihost", + ":riscv_debug_info", ":riscv_fp_state", ":riscv_state", ":riscv_top", @@ -1352,6 +1351,7 @@ "@abseil-cpp//absl/strings", "@abseil-cpp//absl/strings:str_format", "@abseil-cpp//absl/time", + "@abseil-cpp//absl/types:span", "@com_google_protobuf//:protobuf", "@com_googlesource_code_re2//:re2", "@mpact-sim//mpact/sim/generic:core", @@ -1359,6 +1359,7 @@ "@mpact-sim//mpact/sim/generic:counters", "@mpact-sim//mpact/sim/generic:instruction", "@mpact-sim//mpact/sim/proto:component_data_cc_proto", + "@mpact-sim//mpact/sim/util/gdbserver", "@mpact-sim//mpact/sim/util/memory", "@mpact-sim//mpact/sim/util/program_loader:elf_loader", ], @@ -1374,6 +1375,7 @@ ":debug_command_shell", ":riscv64g_decoder", ":riscv_arm_semihost", + ":riscv_debug_info", ":riscv_fp_state", ":riscv_state", ":riscv_top", @@ -1386,12 +1388,14 @@ "@abseil-cpp//absl/strings", "@abseil-cpp//absl/strings:str_format", "@abseil-cpp//absl/time", + "@abseil-cpp//absl/types:span", "@com_google_protobuf//:protobuf", "@com_googlesource_code_re2//:re2", "@mpact-sim//mpact/sim/generic:core_debug_interface", "@mpact-sim//mpact/sim/generic:counters", "@mpact-sim//mpact/sim/generic:instruction", "@mpact-sim//mpact/sim/proto:component_data_cc_proto", + "@mpact-sim//mpact/sim/util/gdbserver", "@mpact-sim//mpact/sim/util/memory", "@mpact-sim//mpact/sim/util/program_loader:elf_loader", ], @@ -1408,6 +1412,7 @@ ":riscv64g_vec_decoder", ":riscv64gzb_vec_decoder", ":riscv_arm_semihost", + ":riscv_debug_info", ":riscv_fp_state", ":riscv_state", ":riscv_top", @@ -1420,6 +1425,7 @@ "@abseil-cpp//absl/strings", "@abseil-cpp//absl/strings:str_format", "@abseil-cpp//absl/time", + "@abseil-cpp//absl/types:span", "@com_google_protobuf//:protobuf", "@com_googlesource_code_re2//:re2", "@mpact-sim//mpact/sim/generic:core", @@ -1427,6 +1433,7 @@ "@mpact-sim//mpact/sim/generic:counters", "@mpact-sim//mpact/sim/generic:instruction", "@mpact-sim//mpact/sim/proto:component_data_cc_proto", + "@mpact-sim//mpact/sim/util/gdbserver", "@mpact-sim//mpact/sim/util/memory", "@mpact-sim//mpact/sim/util/program_loader:elf_loader", ],
diff --git a/riscv/riscv_gdb_debug_info.cc b/riscv/riscv_gdb_debug_info.cc index 81cdee0..e9f5c06 100644 --- a/riscv/riscv_gdb_debug_info.cc +++ b/riscv/riscv_gdb_debug_info.cc
@@ -14,35 +14,59 @@ #include "riscv/riscv_gdb_debug_info.h" +#include <string> +#include <string_view> + +#include "absl/container/flat_hash_map.h" #include "absl/strings/str_cat.h" #include "absl/strings/str_format.h" #include "mpact/sim/generic/type_helpers.h" +namespace { + +std::string EscapeString(std::string_view str) { + std::string escaped_string; + escaped_string.reserve(str.size() * 2); + for (char c : str) { + if ((c == '$') || (c == '#') || (c == '*') || (c == '}')) { + escaped_string.push_back('}'); + escaped_string.push_back(c ^ 0x20); + } else { + escaped_string.push_back(c); + } + } + return escaped_string; +} + +} // namespace + namespace mpact::sim::riscv { using ::mpact::sim::generic::operator*; // NOLINT -RiscVGdbDebugInfo* RiscVGdbDebugInfo::Instance(int gpr_width) { - if (gpr_width != 32 && gpr_width != 64) { +RiscVGdbDebugInfo* RiscVGdbDebugInfo::Instance(int gpr_width, int fp_width, + int vec_width) { + static absl::flat_hash_map<int, RiscVGdbDebugInfo*> instance_map; + // Check for valid widths. + if (gpr_width != 32 && gpr_width != 64) return nullptr; + if (fp_width != 0 && fp_width != 32 && fp_width != 64) return nullptr; + if (vec_width != 0 && vec_width != 128 && vec_width != 256 && + vec_width != 512 && vec_width != 1024) { return nullptr; } - static RiscVGdbDebugInfo* instance32 = nullptr; - static RiscVGdbDebugInfo* instance64 = nullptr; - if (gpr_width == 32) { - if (instance32 == nullptr) { - instance32 = new RiscVGdbDebugInfo(gpr_width); - } - return instance32; - } else { - if (instance64 == nullptr) { - instance64 = new RiscVGdbDebugInfo(gpr_width); - } - return instance64; + int key = gpr_width | (fp_width << 16) | (vec_width << 24); + auto it = instance_map.find(key); + if (it != instance_map.end()) { + return it->second; } - return nullptr; + RiscVGdbDebugInfo* instance = + new RiscVGdbDebugInfo(gpr_width, fp_width, vec_width); + instance_map[key] = instance; + return instance; } -RiscVGdbDebugInfo::RiscVGdbDebugInfo(int gpr_width) : gpr_width_(gpr_width) { +RiscVGdbDebugInfo::RiscVGdbDebugInfo(int gpr_width, int fp_width, int vec_width) + : gpr_width_(gpr_width), fp_width_(fp_width), vec_width_(vec_width) { host_info_ = absl::StrFormat( "triple:riscv%d-unknown-elf;" "endian:little;" @@ -57,29 +81,111 @@ debug_register_map_.emplace( i, absl::StrCat("x", i - *RiscVGdbRegisterEnum::kGprX0)); } - // Floating point registers. - for (int i = *RiscVGdbRegisterEnum::kFprFirst; - i <= *RiscVGdbRegisterEnum::kFprLast; ++i) { - debug_register_map_.emplace( - i, absl::StrCat("f", i - *RiscVGdbRegisterEnum::kFprFirst)); + if (fp_width != 0) { + // Floating point registers. + for (int i = *RiscVGdbRegisterEnum::kFprFirst; + i <= *RiscVGdbRegisterEnum::kFprLast; ++i) { + debug_register_map_.emplace( + i, absl::StrCat("f", i - *RiscVGdbRegisterEnum::kFprFirst)); + } + // CSRs. + debug_register_map_.emplace(*RiscVGdbRegisterEnum::kFprFcsr, "fcsr"); } - // CSRs. - debug_register_map_.emplace(*RiscVGdbRegisterEnum::kFprFcsr, "fcsr"); - debug_register_map_.emplace(*RiscVGdbRegisterEnum::kVprVstart, "vstart"); - debug_register_map_.emplace(*RiscVGdbRegisterEnum::kVprVxsat, "vxsat"); - debug_register_map_.emplace(*RiscVGdbRegisterEnum::kVprVxrm, "vxrm"); - debug_register_map_.emplace(*RiscVGdbRegisterEnum::kVprVcsr, "vcsr"); - debug_register_map_.emplace(*RiscVGdbRegisterEnum::kVprVl, "vl"); - debug_register_map_.emplace(*RiscVGdbRegisterEnum::kVprVType, "vtype"); - debug_register_map_.emplace(*RiscVGdbRegisterEnum::kVprVlenb, "vlenb"); - // xml - if (gpr_width == 32) { - gdb_target_xml_ = -#include "riscv/riscv_gdb_debug_info_32.inc" - } else { - gdb_target_xml_ = -#include "riscv/riscv_gdb_debug_info_64.inc" + if (vec_width != 0) { + // Vector control registers. + debug_register_map_.emplace(*RiscVGdbRegisterEnum::kVprVstart, "vstart"); + debug_register_map_.emplace(*RiscVGdbRegisterEnum::kVprVxsat, "vxsat"); + debug_register_map_.emplace(*RiscVGdbRegisterEnum::kVprVxrm, "vxrm"); + debug_register_map_.emplace(*RiscVGdbRegisterEnum::kVprVcsr, "vcsr"); + debug_register_map_.emplace(*RiscVGdbRegisterEnum::kVprVl, "vl"); + debug_register_map_.emplace(*RiscVGdbRegisterEnum::kVprVtype, "vtype"); + debug_register_map_.emplace(*RiscVGdbRegisterEnum::kVprVlenb, "vlenb"); } + // Construct the gdb target xml string. + gdb_target_xml_ = R"xml(<?xml version="1.0"?> +<!DOCTYPE target SYSTEM "gdb-target.dtd"> +<target version="1.0"> + <architecture>riscv</architecture>)xml"; + absl::StrAppend(&gdb_target_xml_, + "\n <feature name=\"org.gnu.gdb.riscv.cpu\">\n"); + // GPR registers. + int regnum = 0; + for (int i = 0; i < 32; ++i) { + absl::StrAppend( + &gdb_target_xml_, + absl::StrFormat(" <reg name=\"x%d\" bitsize=\"%d\" regnum=\"%d\" " + "type=\"uint%d\" group=\"general\"/>\n", + i, gpr_width_, regnum++, gpr_width_)); + } + absl::StrAppend( + &gdb_target_xml_, + absl::StrFormat(" <reg name=\"pc\" bitsize=\"%d\" regnum=\"%d\" " + "type=\"code_ptr\" group=\"general\"/>\n", + gpr_width_, regnum++)); + absl::StrAppend(&gdb_target_xml_, " </feature>\n"); + + // FP registers. + if (fp_width != 0) { + absl::StrAppend(&gdb_target_xml_, + " <feature name=\"org.gnu.gdb.riscv.fpu\">\n"); + std::string fp_type = fp_width == 64 ? "ieee_double" : "ieee_float"; + for (int i = 0; i < 32; ++i) { + absl::StrAppend( + &gdb_target_xml_, + absl::StrFormat(" <reg name=\"f%d\" bitsize=\"%d\" " + "regnum=\"%d\" type=\"%s\" group=\"float\"/>\n", + i, fp_width_, regnum++, fp_type)); + } + absl::StrAppend( + &gdb_target_xml_, + absl::StrFormat(" <reg name=\"fcsr\" bitsize=\"%d\" regnum=\"%d\" " + "type=\"uint32\" group=\"float\"/>\n", + 32, regnum++)); + absl::StrAppend(&gdb_target_xml_, " </feature>\n"); + } + // Vector registers. + if (vec_width != 0) { + absl::StrAppend(&gdb_target_xml_, + " <feature name=\"org.gnu.gdb.riscv.vector\">\n"); + // Add vector data type. + absl::StrAppend( + &gdb_target_xml_, + absl::StrFormat( + " <vector id=\"v%d\" type=\"uint8\" count=\"%d\"/>\n", + vec_width_, vec_width_ / 8)); + for (int i = 0; i < 32; ++i) { + absl::StrAppend(&gdb_target_xml_, + absl::StrFormat(" <reg name=\"v%d\" bitsize=\"%d\" " + "regnum=\"%d\" type=\"v%d\" " + "group=\"vector\"/>\n", + i, vec_width_, regnum++, vec_width_)); + } + absl::StrAppend(&gdb_target_xml_, + " <reg name=\"vstart\" bitsize=\"32\" type=\"uint32\" " + "group=\"vector\"/>\n"); + absl::StrAppend(&gdb_target_xml_, + " <reg name=\"vxsat\" bitsize=\"32\" type=\"uint32\" " + "group=\"vector\"/>\n"); + absl::StrAppend(&gdb_target_xml_, + " <reg name=\"vxrm\" bitsize=\"32\" type=\"uint32\" " + "group=\"vector\"/>\n"); + absl::StrAppend(&gdb_target_xml_, + " <reg name=\"vcsr\" bitsize=\"32\" type=\"uint32\" " + "group=\"vector\"/>\n"); + absl::StrAppend(&gdb_target_xml_, + " <reg name=\"vl\" bitsize=\"32\" type=\"uint32\" " + "group=\"vector\"/>\n"); + absl::StrAppend(&gdb_target_xml_, + " <reg name=\"vtype\" bitsize=\"32\" type=\"uint32\" " + "group=\"vector\"/>\n"); + absl::StrAppend(&gdb_target_xml_, + " <reg name=\"vlenb\" bitsize=\"32\" type=\"uint32\" " + "group=\"vector\"/>\n"); + absl::StrAppend(&gdb_target_xml_, " </feature>\n"); + } + absl::StrAppend(&gdb_target_xml_, "</target>\n"); + // Escape the string for GDB + gdb_target_xml_ = EscapeString(gdb_target_xml_); } } // namespace mpact::sim::riscv
diff --git a/riscv/riscv_gdb_debug_info.h b/riscv/riscv_gdb_debug_info.h index 0e6b14d..0d0055b 100644 --- a/riscv/riscv_gdb_debug_info.h +++ b/riscv/riscv_gdb_debug_info.h
@@ -30,8 +30,7 @@ enum class RiscVGdbRegisterEnum : int { // Integer registers. kGprFirst = 0, - kGprPc = kGprFirst, - kGprX0, + kGprX0 = kGprFirst, kGprX1, kGprX2, kGprX3, @@ -63,7 +62,8 @@ kGprX29, kGprX30, kGprX31, - kGprLast = kGprX31, + kGprPc, + kGprLast = kGprPc, // Floating point registers. kFprFirst = kGprLast + 1, kFprF0 = kFprFirst, @@ -99,23 +99,57 @@ kFprF30, kFprF31, kFprLast = kFprF31, - // CSRs. - kCsrFirst = 4096, - kFprFcsr = kCsrFirst + 0x003, - kVprVstart = kCsrFirst + 0x008, - kVprVxsat = kCsrFirst + 0x009, - kVprVxrm = kCsrFirst + 0x00a, - kVprVcsr = kCsrFirst + 0x00f, - kVprVl = kCsrFirst + 0xc20, - kVprVType = kCsrFirst + 0xc21, - kVprVlenb = kCsrFirst + 0xc22, + kFprFcsr, + // Vector registers. + kVprFirst = kFprFcsr + 1, + kVprV0 = kVprFirst, + kVprV1, + kVprV2, + kVprV3, + kVprV4, + kVprV5, + kVprV6, + kVprV7, + kVprV8, + kVprV9, + kVprV10, + kVprV11, + kVprV12, + kVprV13, + kVprV14, + kVprV15, + kVprV16, + kVprV17, + kVprV18, + kVprV19, + kVprV20, + kVprV21, + kVprV22, + kVprV23, + kVprV24, + kVprV25, + kVprV26, + kVprV27, + kVprV28, + kVprV29, + kVprV30, + kVprV31, + kVprLast = kVprV31, + kVprVstart, + kVprVxsat, + kVprVxrm, + kVprVcsr, + kVprVl, + kVprVtype, + kVprVlenb, }; class RiscVGdbDebugInfo : public generic::DebugInfo { public: using DebugRegisterMap = generic::DebugInfo::DebugRegisterMap; - static RiscVGdbDebugInfo* Instance(int gpr_width); + static RiscVGdbDebugInfo* Instance(int gpr_width, int fp_width, + int vec_width); const DebugRegisterMap& debug_register_map() const override { return debug_register_map_; @@ -139,11 +173,14 @@ } private: - explicit RiscVGdbDebugInfo(int gpr_width); + RiscVGdbDebugInfo(int gpr_width, int fp_width, int vec_width); int gpr_width_; + int fp_width_; + int vec_width_; std::string host_info_; DebugRegisterMap debug_register_map_; - std::string_view gdb_target_xml_; + // "Escaped" GDB target XML string. + std::string gdb_target_xml_; }; } // namespace mpact::sim::riscv
diff --git a/riscv/rv32g_sim.cc b/riscv/rv32g_sim.cc index 43f18e8..4692495 100644 --- a/riscv/rv32g_sim.cc +++ b/riscv/rv32g_sim.cc
@@ -503,7 +503,8 @@ } if (gdbserver_port > 0) { std::array<CoreDebugInterface*, 1> core_debug_interfaces = {&riscv_top}; - RiscVGdbDebugInfo* debug_info = RiscVGdbDebugInfo::Instance(32); + RiscVGdbDebugInfo* debug_info = RiscVGdbDebugInfo::Instance( + /*gpr_width=*/32, /*fp_width=*/64, /*vec_width=*/0); GdbServer gdb_server(absl::MakeSpan(core_debug_interfaces), *debug_info); std::cerr << "Starting gdbserver on port " << gdbserver_port << std::endl; gdb_server.Connect(gdbserver_port);
diff --git a/riscv/rv32gv_sim.cc b/riscv/rv32gv_sim.cc index 14a3a8f..0ac0013 100644 --- a/riscv/rv32gv_sim.cc +++ b/riscv/rv32gv_sim.cc
@@ -14,6 +14,7 @@ #include <signal.h> +#include <array> #include <cstdint> #include <cstdlib> #include <fstream> @@ -37,11 +38,13 @@ #include "absl/strings/string_view.h" #include "absl/time/clock.h" #include "absl/time/time.h" +#include "absl/types/span.h" #include "mpact/sim/generic/core_debug_interface.h" #include "mpact/sim/generic/counters.h" #include "mpact/sim/generic/decoder_interface.h" #include "mpact/sim/generic/instruction.h" #include "mpact/sim/proto/component_data.pb.h" +#include "mpact/sim/util/gdbserver/gdbserver.h" #include "mpact/sim/util/memory/atomic_memory.h" #include "mpact/sim/util/memory/flat_demand_memory.h" #include "mpact/sim/util/memory/memory_interface.h" @@ -55,6 +58,7 @@ #include "riscv/riscv_arm_semihost.h" #include "riscv/riscv_csr.h" #include "riscv/riscv_fp_state.h" +#include "riscv/riscv_gdb_debug_info.h" #include "riscv/riscv_register.h" #include "riscv/riscv_register_aliases.h" #include "riscv/riscv_state.h" @@ -62,6 +66,7 @@ #include "riscv/riscv_vector_state.h" #include "src/google/protobuf/text_format.h" +using ::mpact::sim::generic::CoreDebugInterface; using ::mpact::sim::generic::Instruction; using ::mpact::sim::proto::ComponentData; using ::mpact::sim::riscv::RiscV32GVecDecoder; @@ -69,11 +74,13 @@ using ::mpact::sim::riscv::RiscV32HtifSemiHost; using ::mpact::sim::riscv::RiscVArmSemihost; using ::mpact::sim::riscv::RiscVFPState; +using ::mpact::sim::riscv::RiscVGdbDebugInfo; using ::mpact::sim::riscv::RiscVState; using ::mpact::sim::riscv::RiscVVectorState; using ::mpact::sim::riscv::RiscVXlen; using ::mpact::sim::riscv::RV32Register; using ::mpact::sim::riscv::RVFpRegister; +using ::mpact::sim::util::gdbserver::GdbServer; using AddressRange = mpact::sim::util::MemoryWatcher::AddressRange; @@ -164,6 +171,10 @@ // Flag to set the vector length in bytes (VLENB). ABSL_FLAG(int, vlen, 16, "Vector length in bytes (VLENB)"); +// Flag to run the simulator with a gdbserver listening for connections on the +// given port. +ABSL_FLAG(int, gdbserver, -1, "Run simulator in gdbserver mode"); + constexpr char kStackEndSymbolName[] = "__stack_end"; constexpr char kStackSizeSymbolName[] = "__stack_size"; @@ -466,9 +477,24 @@ sa.sa_handler = &sim_sigint_handler; sigaction(SIGINT, &sa, nullptr); - // Determine if this is being run interactively or as a batch job. + // Determine if this is being run interactively, as gdbserver, or as a batch + // job. bool interactive = absl::GetFlag(FLAGS_i) || absl::GetFlag(FLAGS_interactive); - if (interactive) { + int gdbserver_port = absl::GetFlag(FLAGS_gdbserver); + if (interactive && gdbserver_port > 0) { + std::cerr << "Gdbserver cannot be used in interactive mode\n"; + return -1; + } + if (gdbserver_port > 0) { + std::array<CoreDebugInterface*, 1> core_debug_interfaces = {&riscv_top}; + RiscVGdbDebugInfo* debug_info = RiscVGdbDebugInfo::Instance( + /*gpr_width=*/32, + /*fp_width=*/64, /*vec_width=*/absl::GetFlag(FLAGS_vlen) * 8); + GdbServer gdb_server(absl::MakeSpan(core_debug_interfaces), *debug_info); + std::cerr << "Starting gdbserver on port " << gdbserver_port << std::endl; + gdb_server.Connect(gdbserver_port); + std::cerr << "Gdbserver disconnected" << std::endl; + } else if (interactive) { mpact::sim::riscv::DebugCommandShell cmd_shell; cmd_shell.AddCore({&riscv_top, [&elf_loader]() { return &elf_loader; }}); // Add custom command to interactive debug command shell.
diff --git a/riscv/rv64g_sim.cc b/riscv/rv64g_sim.cc index fe80fcc..e0e75fe 100644 --- a/riscv/rv64g_sim.cc +++ b/riscv/rv64g_sim.cc
@@ -14,6 +14,7 @@ #include <signal.h> +#include <array> #include <cstdint> #include <cstdlib> #include <fstream> @@ -37,10 +38,12 @@ #include "absl/strings/string_view.h" #include "absl/time/clock.h" #include "absl/time/time.h" +#include "absl/types/span.h" #include "mpact/sim/generic/core_debug_interface.h" #include "mpact/sim/generic/counters.h" #include "mpact/sim/generic/instruction.h" #include "mpact/sim/proto/component_data.pb.h" +#include "mpact/sim/util/gdbserver/gdbserver.h" #include "mpact/sim/util/memory/atomic_memory.h" #include "mpact/sim/util/memory/flat_demand_memory.h" #include "mpact/sim/util/memory/memory_interface.h" @@ -52,21 +55,25 @@ #include "riscv/riscv_arm_semihost.h" #include "riscv/riscv_csr.h" #include "riscv/riscv_fp_state.h" +#include "riscv/riscv_gdb_debug_info.h" #include "riscv/riscv_register.h" #include "riscv/riscv_register_aliases.h" #include "riscv/riscv_state.h" #include "riscv/riscv_top.h" #include "src/google/protobuf/text_format.h" +using ::mpact::sim::generic::CoreDebugInterface; using ::mpact::sim::generic::Instruction; using ::mpact::sim::proto::ComponentData; using ::mpact::sim::riscv::RiscV64Decoder; using ::mpact::sim::riscv::RiscVArmSemihost; using ::mpact::sim::riscv::RiscVFPState; +using ::mpact::sim::riscv::RiscVGdbDebugInfo; using ::mpact::sim::riscv::RiscVState; using ::mpact::sim::riscv::RiscVXlen; using ::mpact::sim::riscv::RV64Register; using ::mpact::sim::riscv::RVFpRegister; +using ::mpact::sim::util::gdbserver::GdbServer; using AddressRange = mpact::sim::util::MemoryWatcher::AddressRange; // Flags for specifying interactive mode. @@ -150,6 +157,10 @@ // Flag to set the default value for the misa CSR. ABSL_FLAG(std::optional<uint64_t>, misa, std::nullopt, "misa value"); +// Flag to run the simulator with a gdbserver listening for connections on the +// given port. +ABSL_FLAG(int, gdbserver, -1, "Run simulator in gdbserver mode"); + constexpr char kStackEndSymbolName[] = "__stack_end"; constexpr char kStackSizeSymbolName[] = "__stack_size"; @@ -405,9 +416,23 @@ sa.sa_handler = &sim_sigint_handler; sigaction(SIGINT, &sa, nullptr); - // Determine if this is being run interactively or as a batch job. + // Determine if this is being run interactively, as gdbserver, or as a batch + // job. bool interactive = absl::GetFlag(FLAGS_i) || absl::GetFlag(FLAGS_interactive); - if (interactive) { + int gdbserver_port = absl::GetFlag(FLAGS_gdbserver); + if (interactive && gdbserver_port > 0) { + std::cerr << "Gdbserver cannot be used in interactive mode\n"; + return -1; + } + if (gdbserver_port > 0) { + std::array<CoreDebugInterface*, 1> core_debug_interfaces = {&riscv_top}; + RiscVGdbDebugInfo* debug_info = RiscVGdbDebugInfo::Instance( + /*gpr_width=*/64, /*fp_width=*/64, /*vec_width=*/0); + GdbServer gdb_server(absl::MakeSpan(core_debug_interfaces), *debug_info); + std::cerr << "Starting gdbserver on port " << gdbserver_port << std::endl; + gdb_server.Connect(gdbserver_port); + std::cerr << "Gdbserver disconnected" << std::endl; + } else if (interactive) { mpact::sim::riscv::DebugCommandShell cmd_shell; cmd_shell.AddCore({&riscv_top, [&elf_loader]() { return &elf_loader; }}); // Add custom command to interactive debug command shell.
diff --git a/riscv/rv64gv_sim.cc b/riscv/rv64gv_sim.cc index 992ed7f..6556a4d 100644 --- a/riscv/rv64gv_sim.cc +++ b/riscv/rv64gv_sim.cc
@@ -14,6 +14,7 @@ #include <signal.h> +#include <array> #include <cstdint> #include <cstdlib> #include <fstream> @@ -37,11 +38,13 @@ #include "absl/strings/string_view.h" #include "absl/time/clock.h" #include "absl/time/time.h" +#include "absl/types/span.h" #include "mpact/sim/generic/core_debug_interface.h" #include "mpact/sim/generic/counters.h" #include "mpact/sim/generic/decoder_interface.h" #include "mpact/sim/generic/instruction.h" #include "mpact/sim/proto/component_data.pb.h" +#include "mpact/sim/util/gdbserver/gdbserver.h" #include "mpact/sim/util/memory/atomic_memory.h" #include "mpact/sim/util/memory/flat_demand_memory.h" #include "mpact/sim/util/memory/memory_interface.h" @@ -54,6 +57,7 @@ #include "riscv/riscv_arm_semihost.h" #include "riscv/riscv_csr.h" #include "riscv/riscv_fp_state.h" +#include "riscv/riscv_gdb_debug_info.h" #include "riscv/riscv_register.h" #include "riscv/riscv_register_aliases.h" #include "riscv/riscv_state.h" @@ -61,17 +65,20 @@ #include "riscv/riscv_vector_state.h" #include "src/google/protobuf/text_format.h" +using ::mpact::sim::generic::CoreDebugInterface; using ::mpact::sim::generic::Instruction; using ::mpact::sim::proto::ComponentData; using ::mpact::sim::riscv::RiscV64GVecDecoder; using ::mpact::sim::riscv::RiscV64GZBVecDecoder; using ::mpact::sim::riscv::RiscVArmSemihost; using ::mpact::sim::riscv::RiscVFPState; +using ::mpact::sim::riscv::RiscVGdbDebugInfo; using ::mpact::sim::riscv::RiscVState; using ::mpact::sim::riscv::RiscVVectorState; using ::mpact::sim::riscv::RiscVXlen; using ::mpact::sim::riscv::RV64Register; using ::mpact::sim::riscv::RVFpRegister; +using ::mpact::sim::util::gdbserver::GdbServer; using AddressRange = mpact::sim::util::MemoryWatcher::AddressRange; // Flags for specifying interactive mode. @@ -158,6 +165,10 @@ // Flag to set the vector length in bytes (VLENB). ABSL_FLAG(int, vlen, 64, "Vector length in bytes (VLENB)"); +// Flag to run the simulator with a gdbserver listening for connections on the +// given port. +ABSL_FLAG(int, gdbserver, -1, "Run simulator in gdbserver mode"); + constexpr char kStackEndSymbolName[] = "__stack_end"; constexpr char kStackSizeSymbolName[] = "__stack_size"; @@ -420,9 +431,24 @@ sa.sa_handler = &sim_sigint_handler; sigaction(SIGINT, &sa, nullptr); - // Determine if this is being run interactively or as a batch job. + // Determine if this is being run interactively, as gdbserver, or as a batch + // job. bool interactive = absl::GetFlag(FLAGS_i) || absl::GetFlag(FLAGS_interactive); - if (interactive) { + int gdbserver_port = absl::GetFlag(FLAGS_gdbserver); + if (interactive && gdbserver_port > 0) { + std::cerr << "Gdbserver cannot be used in interactive mode\n"; + return -1; + } + if (gdbserver_port > 0) { + std::array<CoreDebugInterface*, 1> core_debug_interfaces = {&riscv_top}; + RiscVGdbDebugInfo* debug_info = RiscVGdbDebugInfo::Instance( + /*gpr_width=*/64, + /*fp_width=*/64, /*vec_width=*/absl::GetFlag(FLAGS_vlen) * 8); + GdbServer gdb_server(absl::MakeSpan(core_debug_interfaces), *debug_info); + std::cerr << "Starting gdbserver on port " << gdbserver_port << std::endl; + gdb_server.Connect(gdbserver_port); + std::cerr << "Gdbserver disconnected" << std::endl; + } else if (interactive) { mpact::sim::riscv::DebugCommandShell cmd_shell; cmd_shell.AddCore({&riscv_top, [&elf_loader]() { return &elf_loader; }}); // Add custom command to interactive debug command shell.