Added history and color to riscv debug cli PiperOrigin-RevId: 903365115 Change-Id: If20c32ff42c69252472de3abaa2bbeb871b0a99c
diff --git a/MODULE.bazel b/MODULE.bazel index 147be0f..822ae87 100644 --- a/MODULE.bazel +++ b/MODULE.bazel
@@ -53,6 +53,10 @@ name = "rules_cc", version = "0.1.3", ) +bazel_dep( + name = "linenoise", + version = "2.0.0", +) sim_deps = use_extension( "@mpact-sim//:extensions.bzl",
diff --git a/riscv/BUILD b/riscv/BUILD index cb65100..961213f 100644 --- a/riscv/BUILD +++ b/riscv/BUILD
@@ -1241,6 +1241,7 @@ "@abseil-cpp//absl/strings", "@abseil-cpp//absl/strings:str_format", "@com_googlesource_code_re2//:re2", + "@linenoise", "@mpact-sim//mpact/sim/generic:core", "@mpact-sim//mpact/sim/generic:core_debug_interface", "@mpact-sim//mpact/sim/generic:debug_command_shell_interface",
diff --git a/riscv/debug_command_shell.cc b/riscv/debug_command_shell.cc index 2e32fae..36ae310 100644 --- a/riscv/debug_command_shell.cc +++ b/riscv/debug_command_shell.cc
@@ -15,6 +15,7 @@ #include "riscv/debug_command_shell.h" #include <cstdint> +#include <cstdlib> #include <cstring> #include <fstream> #include <istream> @@ -31,6 +32,7 @@ #include "absl/strings/str_cat.h" #include "absl/strings/str_format.h" #include "absl/strings/string_view.h" +#include "linenoise.h" #include "mpact/sim/generic/core_debug_interface.h" #include "mpact/sim/generic/data_buffer.h" #include "mpact/sim/generic/type_helpers.h" @@ -186,45 +188,49 @@ std::string previous_line; current_core_ = 0; absl::string_view line_view; + linenoiseHistorySetMaxLen(1000); while (true) { // Prompt and read in the next command. auto pc_result = core_access_[current_core_].debug_interface->ReadRegister("pc"); - std::string prompt; + std::string pre_prompt; auto result = core_access_[current_core_].debug_interface->GetLastHaltReason(); if (result.ok()) { switch (result.value()) { case *HaltReason::kSoftwareBreakpoint: - absl::StrAppend(&prompt, "Stopped at software breakpoint\n"); + absl::StrAppend(&pre_prompt, "Stopped at software breakpoint\n"); break; case *HaltReason::kUserRequest: - absl::StrAppend(&prompt, "Stopped at user request\n"); + absl::StrAppend(&pre_prompt, "Stopped at user request\n"); break; case *HaltReason::kDataWatchPoint: - absl::StrAppend(&prompt, "Stopped at data watchpoint\n"); + absl::StrAppend(&pre_prompt, "Stopped at data watchpoint\n"); break; case *HaltReason::kProgramDone: - absl::StrAppend(&prompt, "Program done\n"); + absl::StrAppend(&pre_prompt, "Program done\n"); break; default: if ((result.value() >= *HaltReason::kUserSpecifiedMin) && (result.value() <= *HaltReason::kUserSpecifiedMax)) { - absl::StrAppend(&prompt, "Stopped for custom halt reason\n"); + absl::StrAppend(&pre_prompt, "Stopped for custom halt reason\n"); } break; } } + std::string prompt; if (pc_result.ok()) { auto* loader = core_access_[current_core_].loader_getter(); if (loader != nullptr) { auto fcn_result = loader->GetFunctionName(pc_result.value()); if (fcn_result.ok()) { - absl::StrAppend(&prompt, "[", fcn_result.value(), "]:\n"); + absl::StrAppend(&pre_prompt, kSymbolColor, "[", fcn_result.value(), + "]:\n", kDefaultColor); } auto symbol_result = loader->GetFcnSymbolName(pc_result.value()); if (symbol_result.ok()) { - absl::StrAppend(&prompt, symbol_result.value(), ":\n"); + absl::StrAppend(&pre_prompt, kSymbolColor, symbol_result.value(), + kDefaultColor, ":\n"); } } absl::StrAppend(&prompt, @@ -233,9 +239,10 @@ core_access_[current_core_].debug_interface->GetDisassembly( pc_result.value()); if (disasm_result.ok()) { - absl::StrAppend(&prompt, " ", disasm_result.value()); + absl::StrAppend(&pre_prompt, " ", kTextColor, disasm_result.value(), + kDefaultColor); } - absl::StrAppend(&prompt, "\n"); + absl::StrAppend(&pre_prompt, "\n"); } absl::StrAppend(&prompt, "[", current_core_, "] > "); while (!command_streams_.empty()) { @@ -245,8 +252,18 @@ // Read a command from the input stream. If it's from a file, then ignore // empty lines and comments. do { - if (command_streams_.size() == 1) os << prompt; - current_is.getline(line, kLineSize); + if (command_streams_.size() == 1) { + os << pre_prompt; + char* line_c = linenoise(prompt.c_str()); + if (line_c != nullptr) { + absl::SNPrintF(line, kLineSize, "%s", line_c); + free(line_c); + } else { + line[0] = '\0'; + } + } else { + current_is.getline(line, kLineSize); + } } while ((is_file && RE2::FullMatch(line, *empty_re_)) && !current_is.bad() && !current_is.eof()); @@ -276,6 +293,7 @@ if (line[0] != '\0') { previous_line = line; + linenoiseHistoryAdd(line); } line_view = absl::string_view(previous_line); @@ -510,14 +528,16 @@ if (std::string str_value, format; RE2::FullMatch(line_view, *read_mem_re_, &str_value, &format)) { - os << ReadMemory(current_core_, str_value, format) << std::endl; + os << kValueColor << ReadMemory(current_core_, str_value, format) + << kDefaultColor << std::endl; continue; } if (std::string str_value1, format, str_value2; RE2::FullMatch( line_view, *write_mem_re_, &str_value1, &format, &str_value2)) { - os << WriteMemory(current_core_, str_value1, format, str_value2) - << std::endl; + os << kValueColor + << WriteMemory(current_core_, str_value1, format, str_value2) + << kDefaultColor << std::endl; continue; } @@ -676,7 +696,9 @@ auto result = core_access_[current_core_].debug_interface->ReadRegister(name); if (result.ok()) { - os << absl::StrCat(name, " = ", absl::Hex(result.value())) << std::endl; + os << absl::StrCat(kValueColor, name, " = ", absl::Hex(result.value()), + kDefaultColor) + << std::endl; } else { os << "Error: " << result.status().message() << std::endl; } @@ -976,7 +998,8 @@ if (std::string str_value, format; RE2::FullMatch(line_view, *read_mem2_re_, &str_value, &format)) { - os << ReadMemory(current_core_, str_value, format) << std::endl; + os << kValueColor << ReadMemory(current_core_, str_value, format) + << kDefaultColor << std::endl; continue; } // Action points. @@ -1472,7 +1495,8 @@ auto result = core_access_[current_core_].debug_interface->ReadRegister(reg_name); if (result.ok()) { - absl::StrAppend(&output, reg_name, " = ", absl::Hex(result.value())); + absl::StrAppend(&output, kValueColor, reg_name, " = ", + absl::Hex(result.value()), kDefaultColor); } else { absl::StrAppend(&output, "Error reading '", reg_name, "': ", result.status().message());
diff --git a/riscv/debug_command_shell.h b/riscv/debug_command_shell.h index bc8e786..a44bd1c 100644 --- a/riscv/debug_command_shell.h +++ b/riscv/debug_command_shell.h
@@ -177,6 +177,11 @@ std::deque<std::string> previous_commands_; std::vector<absl::btree_map<int, ActionPointInfo>> core_action_point_info_; std::vector<int> core_action_point_id_; + + static constexpr absl::string_view kTextColor = "\033[38;5;58m"; + static constexpr absl::string_view kSymbolColor = "\033[38;5;21m"; + static constexpr absl::string_view kValueColor = "\033[38;5;27m"; + static constexpr absl::string_view kDefaultColor = "\033[0m"; }; } // namespace riscv