feat: support switching targets through monitor commands

This commit is contained in:
xinyangli 2024-08-09 13:10:47 +08:00
parent 407216b17c
commit b96a280e10
Signed by: xin
SSH key fingerprint: SHA256:qZ/tzd8lYRtUFSrfBDBMcUqV4GHKxqeqRA3huItgvbk
3 changed files with 55 additions and 9 deletions

View file

@ -46,6 +46,8 @@ public:
bool check_all();
int sync_regs_to_ref(void);
std::string list_targets(void);
std::string switch_target(int index);
inline void halt() {
__atomic_store_n(&halt_status, true, __ATOMIC_RELAXED);

View file

@ -1,9 +1,12 @@
#include "api.hpp"
#include <cerrno>
#include <difftest.hpp>
#include <fstream>
#include <gdbstub.h>
#include <spdlog/spdlog.h>
#include <sstream>
#include <stdexcept>
#include <string>
Difftest::Difftest(Target &&dut, std::vector<Target> &&refs) {
this->dut = std::move(dut);
@ -82,8 +85,12 @@ Difftest::ExecRet Difftest::exec(size_t n, gdb_action_t *ret) {
gdb_action_t Difftest::stepi() {
gdb_action_t ret = {.reason = gdb_action_t::ACT_NONE};
exec(1, &ret);
ExecRet exec_result = exec(1, &ret);
if (exec_result.do_difftest) {
check_all();
} else {
sync_regs_to_ref();
}
return ret;
}
@ -93,10 +100,13 @@ gdb_action_t Difftest::cont() {
start_run();
while (!is_halt()) {
exec_ret = exec(1, &ret);
if (exec_ret.do_difftest)
if (check_all() == false) {
ret.reason = gdb_action_t::ACT_BREAKPOINT;
break;
if (exec_ret.do_difftest) {
check_all();
} else {
size_t pc = 0;
read_reg(32, &pc);
spdlog::debug("Difftest skipped at {}", (void *)pc);
sync_regs_to_ref();
}
if (exec_ret.at_breakpoint)
break;
@ -135,6 +145,32 @@ int Difftest::sync_regs_to_ref(void) {
return ret;
}
std::string Difftest::list_targets(void) {
std::ostringstream os;
int i = 0;
for (auto it = this->begin(); it != this->end(); ++it, ++i) {
auto &target = *it;
os << i << ": " << target.meta.name << std::endl;
}
os << "current: " << current_target->meta.name << std::endl;
return os.str();
}
std::string Difftest::switch_target(int index) {
std::ostringstream os;
int i = 0;
for (auto it = this->begin(); it != this->end(); ++it, ++i) {
auto &target = *it;
if (i == index) {
current_target = &target;
os << "Switched to " << current_target->meta.name << std::endl;
return os.str();
}
}
os << "Invalid target target index: " << index << std::endl;
return os.str();
}
int Difftest::read_mem(size_t addr, size_t len, void *val) {
return current_target->ops.read_mem(current_target->args.data(), addr, len,
val);

View file

@ -1,3 +1,4 @@
#include "api.hpp"
#include <CLI/App.hpp>
#include <CLI/Error.hpp>
#include <cstring>
@ -69,12 +70,19 @@ static char *gdbstub_monitor(void *args, const char *s) {
CLI::App parser;
std::string ret = "";
auto sync = parser.add_subcommand("sync", "Sync states between targets")
->callback([&]() { diff->sync_regs_to_ref(); });
parser.add_subcommand("list", "List targets.")->callback([&]() {
ret = diff->list_targets();
});
parser.add_subcommand("help", "Print help message")->callback([&]() {
ret = parser.help();
});
auto sync = parser.add_subcommand("sync", "Sync states between targets")
->callback([&]() { diff->sync_regs_to_ref(); });
int target_index = -1;
parser.add_subcommand("switch", "Switch to another target")
->callback([&]() { ret = diff->switch_target(target_index); })
->add_option("target_index", target_index, "Index of the target");
std::string cmdstr;
int slen = strlen(s);
int ch;