feat(npc): ebreak support through external inst matching

This commit is contained in:
xinyangli 2024-04-11 11:44:54 +08:00
parent 55230247b2
commit e99236f711
Signed by: xin
SSH key fingerprint: SHA256:qZ/tzd8lYRtUFSrfBDBMcUqV4GHKxqeqRA3huItgvbk
8 changed files with 97 additions and 25 deletions

View file

@ -49,8 +49,10 @@ vpiHandle pc = nullptr;
namespace NPC {
void npc_memcpy(paddr_t addr, void *buf, size_t sz, bool direction) {
if (direction == TRM_FROM_MACHINE) {
memcpy(buf, static_cast<Memory<int, 128 * 1024> *>(pmem_get())->mem.data(),
sz);
memcpy(
buf,
static_cast<Memory<int, 128 * 1024> *>(pmem_get())->guest_to_host(addr),
sz);
}
};

View file

@ -79,5 +79,8 @@ public:
// printf("waddr: 0x%x\n", waddr);
mem[addr_to_index((uint32_t)waddr)] = expand_bits(wmask) & wdata;
}
void *guest_to_host(std::size_t addr) {
return mem.data() + addr_to_index(addr);
}
};
#endif

View file

@ -34,19 +34,29 @@ struct DifftestTrmInterface : public TrmInterface {
fetch_state();
};
exec = [this](uint64_t n) {
while (n--) {
bool enable_disasm = true;
if (n > 30) {
enable_disasm = false;
}
while (n--) {
word_t pc = this->ref.at("pc");
word_t inst = this->ref.at(pc);
std::cout << d.disassemble(pc, (uint8_t *)&inst, WORD_BYTES)
<< std::endl;
if (enable_disasm)
std::cout << d.disassemble(pc, (uint8_t *)&inst, WORD_BYTES)
<< std::endl;
if (inst == 1048691) {
// ebreak
throw TrmRuntimeException(TrmRuntimeException::EBREAK, "ebreak");
}
this->ref.exec(1);
this->dut.exec(1);
this->ref.fetch_state();
this->dut.fetch_state();
if (*(CPUState *)this->ref.cpu_state !=
*(CPUState *)this->dut.cpu_state) {
throw std::runtime_error("Difftest failed");
throw TrmRuntimeException(TrmRuntimeException::DIFFTEST_FAILED,
"Difftest failed");
}
}
};

View file

@ -96,6 +96,21 @@ public:
virtual void print(std::ostream &os) const = 0;
};
class TrmRuntimeException : public std::exception {
private:
const char *msg_;
int code_;
public:
enum { EBREAK, DIFFTEST_FAILED };
TrmRuntimeException(int code, const char *message)
: code_(code), msg_(message) {}
virtual const char *what() const throw() { return msg_; }
int error_code() const { return code_; }
};
struct RefTrmInterface : TrmInterface {
RefTrmInterface(std::filesystem::path lib_file) {
void *handle = dlopen(lib_file.c_str(), RTLD_LAZY);

View file

@ -83,6 +83,12 @@ void Console::registerCommand(const std::string &s, CommandFunction f) {
pimpl_->commands_[s] = f;
}
void Console::removeCommands(const std::vector<std::string> sv) {
for (auto const &s : sv) {
pimpl_->commands_.erase(s);
}
}
std::vector<std::string> Console::getRegisteredCommands() const {
std::vector<std::string> allCommands;
for (auto &pair : pimpl_->commands_)

View file

@ -64,6 +64,13 @@ public:
*/
void registerCommand(const std::string &s, CommandFunction f);
/**
* @brief This function removes a list of registered commands.
*
* @param sv The vector of command names to be removed.
*/
void removeCommands(const std::vector<std::string> sv);
/**
* @brief This function returns a list with the currently available commands.
*

View file

@ -5,6 +5,7 @@
#include <console.hpp>
#include <memory>
#include <stdexcept>
#include <string>
#include <trm_interface.hpp>
#include <types.h>
@ -13,7 +14,12 @@ using ret = cr::Console::ReturnCode;
namespace SDB {
enum SDBStatus { SDB_SUCCESS, SDB_WRONG_ARGUMENT, SDB_DIFFTEST_FAILED };
enum SDBStatus {
SDB_SUCCESS,
SDB_EBREAK = 2,
SDB_WRONG_ARGUMENT,
SDB_DIFFTEST_FAILED
};
class SDBHandlers;
@ -36,10 +42,11 @@ private:
int cmd_step(const std::vector<std::string> &input);
int cmd_info_registers(const std::vector<std::string> &input);
int cmd_print(const std::vector<std::string> &input);
int exec_catch(uint64_t);
public:
SDBHandlers(const TrmInterface &funcs) : funcs(funcs){};
void registerHandlers(cr::Console *c);
void register_handlers(cr::Console *c);
};
class SDB {
@ -54,24 +61,34 @@ public:
: handlers(SDBHandlers{funcs}), funcs(funcs) {
c = std::make_unique<CppReadline::Console>(greeting);
handlers.registerHandlers(c.get());
handlers.register_handlers(c.get());
};
int main_loop() {
int retCode;
int ret_code;
funcs.init(0);
std::vector<std::string> step_commands{"c", "continue", "si",
"step-instruction"};
do {
retCode = c->readLine();
ret_code = c->readLine();
// We can also change the prompt based on last return value:
if (retCode == ret::Ok)
if (ret_code == SDB_SUCCESS || ret_code == SDB_EBREAK)
c->setGreeting("\033[1;34m(npc)\033[0m ");
else
c->setGreeting("\033[1;31m(npc)\033[0m ");
if (retCode == SDB_WRONG_ARGUMENT) {
std::cout << "Wrong argument give to command\n";
switch (ret_code) {
case SDB_EBREAK: {
std::cout << "\033[1;31m=== ebreak ===\033[0m" << std::endl;
c->removeCommands(step_commands);
break;
}
} while (retCode != ret::Quit);
case SDB_WRONG_ARGUMENT: {
std::cout << "Wrong argument(s) is given to command handler\n";
break;
}
}
} while (ret_code != ret::Quit);
return 0;
}
};

View file

@ -20,11 +20,28 @@ std::ostream &operator<<(std::ostream &os, const TrmInterface &d) {
namespace SDB {
int SDBHandlers::exec_catch(uint64_t n) {
try {
this->funcs.exec(n);
} catch (TrmRuntimeException &e) {
switch (e.error_code()) {
case TrmRuntimeException::EBREAK:
return SDB_EBREAK;
case TrmRuntimeException::DIFFTEST_FAILED:
std::cout << "Difftest Failed" << std::endl << funcs << std::endl;
return SDB_DIFFTEST_FAILED;
default:
std::cerr << "Unknown error code" << std::endl;
exit(1);
}
}
return SDB_SUCCESS;
}
int SDBHandlers::cmd_continue(const cr::Console::Arguments &input) {
if (input.size() > 1)
return SDB_WRONG_ARGUMENT;
this->funcs.exec(-1);
return SDB_SUCCESS;
return exec_catch(-1);
}
int SDBHandlers::cmd_step(const std::vector<std::string> &input) {
@ -32,14 +49,8 @@ int SDBHandlers::cmd_step(const std::vector<std::string> &input) {
return SDB_WRONG_ARGUMENT;
}
uint64_t step_count = input.size() == 2 ? std::stoull(input[1]) : 1;
try {
this->funcs.exec(step_count);
} catch (std::runtime_error) {
std::cout << "Difftest Failed" << std::endl << funcs << std::endl;
return SDB_DIFFTEST_FAILED;
}
return exec_catch(step_count);
// std::cout << funcs << std::endl;
return SDB_SUCCESS;
}
int SDBHandlers::cmd_info_registers(const std::vector<std::string> &input) {
@ -72,7 +83,7 @@ int SDBHandlers::cmd_print(const std::vector<std::string> &input) {
return SDB_SUCCESS;
}
void SDBHandlers::registerHandlers(cr::Console *c) {
void SDBHandlers::register_handlers(cr::Console *c) {
for (auto &h : this->all_handlers) {
for (auto &name : h.names) {
std::function<int(std::vector<std::string>)> f{
@ -81,4 +92,5 @@ void SDBHandlers::registerHandlers(cr::Console *c) {
}
}
}
} // namespace SDB