blob: 5fd15cab78377976aaca7dbc921029e4dc57969f [file] [log] [blame]
#include "sim/kelvin_state.h"
#include <cstdint>
#include <iostream>
#include <string>
#include "absl/log/check.h"
#include "absl/strings/string_view.h"
namespace kelvin::sim {
constexpr uint32_t kVectorRegisterWidth = 32;
KelvinState::KelvinState(
absl::string_view id, mpact::sim::riscv::RiscVXlen xlen,
mpact::sim::util::MemoryInterface *memory,
mpact::sim::util::AtomicMemoryOpInterface *atomic_memory)
: mpact::sim::riscv::RiscVState(id, xlen, memory, atomic_memory) {
set_vector_register_width(kVectorRegisterWidth);
}
KelvinState::KelvinState(absl::string_view id,
mpact::sim::riscv::RiscVXlen xlen,
mpact::sim::util::MemoryInterface *memory)
: KelvinState(id, xlen, memory, nullptr) {}
KelvinState::KelvinState(absl::string_view id,
mpact::sim::riscv::RiscVXlen xlen)
: KelvinState(id, xlen, nullptr, nullptr) {}
void KelvinState::MPause(const Instruction *inst) {
for (auto &handler : on_mpause_) {
bool res = handler(inst);
if (res) return;
}
// Set the return address to the current instruction.
auto epc = (inst != nullptr) ? inst->address() : 0;
Trap(/*is_interrupt=*/false, 0, 3, epc, inst);
}
// Print the logging message based on log_args_.
void KelvinState::PrintLog(absl::string_view format_string) {
char *print_ptr = const_cast<char *>(format_string.data());
while (*print_ptr) {
if (*print_ptr == '%') {
CHECK_GT(log_args_.size(), 0)
<< "Invalid program with insufficient log argurments";
if (log_args_[0].type() == typeid(uint32_t)) {
std::cout << std::any_cast<uint32_t>(log_args_[0]);
}
if (log_args_[0].type() == typeid(std::string)) {
std::cout << std::any_cast<std::string>(log_args_[0]);
}
log_args_.erase(log_args_.begin());
print_ptr += 2; // skip the format specifier too.
} else {
std::cout << *print_ptr++;
}
}
// Flush log_args_
log_args_.clear();
}
} // namespace kelvin::sim