feat: support switching targets through monitor commands
This commit is contained in:
parent
407216b17c
commit
b96a280e10
3 changed files with 55 additions and 9 deletions
|
@ -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);
|
||||
|
|
|
@ -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 = ⌖
|
||||
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);
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue