Changes handling of HaltReason
Change the stored type of HaltReason to be the HaltReasonValueType (the
integer type underlying enum class HaltReason), and allow for user defined
halt reasons to be used in architectures to provide ways to signal usecase
specific halt reasons.
PiperOrigin-RevId: 563146717
diff --git a/sim/BUILD b/sim/BUILD
index 922f393..de6e67c 100644
--- a/sim/BUILD
+++ b/sim/BUILD
@@ -113,6 +113,7 @@
"@com_google_mpact-sim//mpact/sim/generic:arch_state",
"@com_google_mpact-sim//mpact/sim/generic:core",
"@com_google_mpact-sim//mpact/sim/generic:instruction",
+ "@com_google_mpact-sim//mpact/sim/generic:type_helpers",
"@com_google_mpact-sim//mpact/sim/util/memory",
],
)
@@ -148,6 +149,7 @@
"@com_google_mpact-sim//mpact/sim/generic:core_debug_interface",
"@com_google_mpact-sim//mpact/sim/generic:counters",
"@com_google_mpact-sim//mpact/sim/generic:decode_cache",
+ "@com_google_mpact-sim//mpact/sim/generic:type_helpers",
"@com_google_mpact-sim//mpact/sim/util/memory",
],
)
diff --git a/sim/kelvin_top.cc b/sim/kelvin_top.cc
index b71173d..13e5c58 100644
--- a/sim/kelvin_top.cc
+++ b/sim/kelvin_top.cc
@@ -36,6 +36,7 @@
#include "mpact/sim/generic/data_buffer.h"
#include "mpact/sim/generic/decode_cache.h"
#include "mpact/sim/generic/resource_operand_interface.h"
+#include "mpact/sim/generic/type_helpers.h"
#include "mpact/sim/util/memory/flat_demand_memory.h"
ABSL_FLAG(bool, use_semihost, false, "Use semihost in the simulation");
@@ -45,6 +46,8 @@
namespace kelvin::sim {
+using ::mpact::sim::riscv::operator*; // NOLINT: clang-tidy false positive.
+
constexpr char kKelvinName[] = "Kelvin";
// Local helper function used to execute instructions.
@@ -209,7 +212,7 @@
return absl::FailedPreconditionError(
"KelvinTop::Halt: Core is not running");
}
- halt_reason_ = HaltReason::kUserRequest;
+ halt_reason_ = *HaltReason::kUserRequest;
halted_ = true;
return absl::OkStatus();
}
@@ -256,8 +259,8 @@
halted_ = false;
// First check to see if the previous halt was due to a breakpoint. If so,
// need to step over the breakpoint.
- if (halt_reason_ == HaltReason::kSoftwareBreakpoint) {
- halt_reason_ = HaltReason::kNone;
+ if (halt_reason_ == *HaltReason::kSoftwareBreakpoint) {
+ halt_reason_ = *HaltReason::kNone;
auto status = StepPastBreakpoint();
if (!status.ok()) return status;
count++;
@@ -295,7 +298,7 @@
next_pc = pc_operand->AsUint64(0);
}
// Update the pc register, now that it can be read.
- if (halt_reason_ == HaltReason::kSoftwareBreakpoint) {
+ if (halt_reason_ == *HaltReason::kSoftwareBreakpoint) {
// If at a breakpoint, keep the pc at the current value.
SetPc(pc);
} else {
@@ -304,7 +307,7 @@
}
// If there is no halt request, there is no specific halt reason.
if (!halted_) {
- halt_reason_ = HaltReason::kNone;
+ halt_reason_ = *HaltReason::kNone;
}
run_status_ = RunStatus::kHalted;
return count;
@@ -318,8 +321,8 @@
}
// First check to see if the previous halt was due to a breakpoint. If so,
// need to step over the breakpoint.
- if (halt_reason_ == HaltReason::kSoftwareBreakpoint) {
- halt_reason_ = HaltReason::kNone;
+ if (halt_reason_ == *HaltReason::kSoftwareBreakpoint) {
+ halt_reason_ = *HaltReason::kNone;
auto status = StepPastBreakpoint();
if (!status.ok()) return status;
}
@@ -379,7 +382,7 @@
}
// Update the pc register, now that it can be read (since we are not
// running).
- if (halt_reason_ == HaltReason::kSoftwareBreakpoint) {
+ if (halt_reason_ == *HaltReason::kSoftwareBreakpoint) {
// If at a breakpoint, keep the pc at the current value.
SetPc(pc);
} else {
@@ -413,7 +416,7 @@
return run_status_;
}
-absl::StatusOr<KelvinTop::HaltReason> KelvinTop::GetLastHaltReason() {
+absl::StatusOr<KelvinTop::HaltReasonValueType> KelvinTop::GetLastHaltReason() {
return halt_reason_;
}
@@ -478,8 +481,8 @@
// If stopped at a software breakpoint and the pc is changed, change the
// halt reason, since the next instruction won't be where we stopped.
- if ((name == "pc") && (halt_reason_ == HaltReason::kSoftwareBreakpoint)) {
- halt_reason_ = HaltReason::kNone;
+ if ((name == "pc") && (halt_reason_ == *HaltReason::kSoftwareBreakpoint)) {
+ halt_reason_ = *HaltReason::kNone;
}
auto *db = (iter->second)->data_buffer();
@@ -663,13 +666,20 @@
return absl::OkStatus();
}
-void KelvinTop::RequestHalt(HaltReason halt_reason,
+void KelvinTop::RequestHalt(HaltReasonValueType halt_reason,
const mpact::sim::generic::Instruction *inst) {
// First set the halt_reason_, then the half flag.
halt_reason_ = halt_reason;
halted_ = true;
}
+void KelvinTop::RequestHalt(HaltReason halt_reason,
+ const mpact::sim::generic::Instruction *inst) {
+ // First set the halt_reason_, then the half flag.
+ halt_reason_ = static_cast<HaltReasonValueType>(halt_reason);
+ halted_ = true;
+}
+
void KelvinTop::SetPc(uint64_t value) {
if (pc_->data_buffer()->size<uint8_t>() == 4) {
pc_->data_buffer()->Set<uint32_t>(0, static_cast<uint32_t>(value));
diff --git a/sim/kelvin_top.h b/sim/kelvin_top.h
index 551d127..9c28e30 100644
--- a/sim/kelvin_top.h
+++ b/sim/kelvin_top.h
@@ -39,6 +39,8 @@
public:
using RunStatus = mpact::sim::generic::CoreDebugInterface::RunStatus;
using HaltReason = mpact::sim::generic::CoreDebugInterface::HaltReason;
+ using HaltReasonValueType =
+ mpact::sim::generic::CoreDebugInterface::HaltReasonValueType;
explicit KelvinTop(std::string name);
~KelvinTop() override;
@@ -50,7 +52,7 @@
absl::Status Wait() override;
absl::StatusOr<RunStatus> GetRunStatus() override;
- absl::StatusOr<HaltReason> GetLastHaltReason() override;
+ absl::StatusOr<HaltReasonValueType> GetLastHaltReason() override;
// Register access by register name.
absl::StatusOr<uint64_t> ReadRegister(const std::string &name) override;
@@ -76,6 +78,8 @@
absl::StatusOr<std::string> GetDisassembly(uint64_t address) override;
// Called when a halt is requested.
+ void RequestHalt(HaltReasonValueType halt_reason,
+ const mpact::sim::generic::Instruction *inst);
void RequestHalt(HaltReason halt_reason,
const mpact::sim::generic::Instruction *inst);
@@ -100,7 +104,8 @@
mpact::sim::generic::DataBufferFactory db_factory_;
// Current status and last halt reasons.
RunStatus run_status_ = RunStatus::kHalted;
- HaltReason halt_reason_ = HaltReason::kNone;
+ HaltReasonValueType halt_reason_ =
+ static_cast<HaltReasonValueType>(HaltReason::kNone);
// Halting flag. This is set to true when execution must halt.
bool halted_ = false;
absl::Notification *run_halted_;
diff --git a/sim/renode/BUILD b/sim/renode/BUILD
index f87d6be..c53af89 100644
--- a/sim/renode/BUILD
+++ b/sim/renode/BUILD
@@ -18,6 +18,7 @@
"@com_google_absl//absl/log",
"@com_google_absl//absl/strings",
"@com_google_mpact-sim//mpact/sim/generic:core_debug_interface",
+ "@com_google_mpact-sim//mpact/sim/generic:type_helpers",
"@com_google_mpact-sim//mpact/sim/util/program_loader:elf_loader",
],
alwayslink = True,
diff --git a/sim/renode/kelvin_renode.cc b/sim/renode/kelvin_renode.cc
index c0ba412..618a08f 100644
--- a/sim/renode/kelvin_renode.cc
+++ b/sim/renode/kelvin_renode.cc
@@ -23,7 +23,8 @@
namespace kelvin::sim {
-using HaltReason = mpact::sim::generic::CoreDebugInterface::HaltReason;
+using HaltReasonValueType =
+ mpact::sim::generic::CoreDebugInterface::HaltReasonValueType;
using RunStatus = mpact::sim::generic::CoreDebugInterface::RunStatus;
using Instruction = mpact::sim::generic::Instruction;
using RiscVDebugInfo = mpact::sim::riscv::RiscVDebugInfo;
@@ -43,7 +44,7 @@
absl::StatusOr<RunStatus> KelvinRenode::GetRunStatus() {
return kelvin_top_->GetRunStatus();
}
-absl::StatusOr<HaltReason> KelvinRenode::GetLastHaltReason() {
+absl::StatusOr<HaltReasonValueType> KelvinRenode::GetLastHaltReason() {
return kelvin_top_->GetLastHaltReason();
}
diff --git a/sim/renode/kelvin_renode.h b/sim/renode/kelvin_renode.h
index 0469eed..331d912 100644
--- a/sim/renode/kelvin_renode.h
+++ b/sim/renode/kelvin_renode.h
@@ -24,7 +24,7 @@
class KelvinRenode : public renode::RenodeDebugInterface {
public:
- using mpact::sim::generic::CoreDebugInterface::HaltReason;
+ using mpact::sim::generic::CoreDebugInterface::HaltReasonValueType;
using mpact::sim::generic::CoreDebugInterface::RunStatus;
using RenodeCpuRegister = kelvin::sim::renode::RenodeCpuRegister;
@@ -45,7 +45,7 @@
// Returns the current run status.
absl::StatusOr<RunStatus> GetRunStatus() override;
// Returns the reason for the most recent halt.
- absl::StatusOr<HaltReason> GetLastHaltReason() override;
+ absl::StatusOr<HaltReasonValueType> GetLastHaltReason() override;
// Read/write the named registers.
absl::StatusOr<uint64_t> ReadRegister(const std::string &name) override;
absl::Status WriteRegister(const std::string &name, uint64_t value) override;
diff --git a/sim/renode/renode_mpact.cc b/sim/renode/renode_mpact.cc
index 5a1035d..e01903f 100644
--- a/sim/renode/renode_mpact.cc
+++ b/sim/renode/renode_mpact.cc
@@ -8,6 +8,7 @@
#include "absl/log/log.h"
#include "absl/strings/str_cat.h"
#include "mpact/sim/generic/core_debug_interface.h"
+#include "mpact/sim/generic/type_helpers.h"
#include "mpact/sim/util/program_loader/elf_program_loader.h"
// This function must be defined in the library.
@@ -242,7 +243,8 @@
// If the previous halt reason was a semihost halt request, then we shouldn't
// step any further. Just return with "waiting for interrupt" code.
using HaltReason = RenodeDebugInterface::HaltReason;
- if (halt_res.value() == HaltReason::kSemihostHaltRequest) {
+ using mpact::sim::riscv::operator*; // NOLINT: used below.
+ if (halt_res.value() == *HaltReason::kSemihostHaltRequest) {
if (status != nullptr) {
*status = static_cast<int32_t>(ExecutionResult::kAborted);
}
@@ -270,17 +272,17 @@
return total_executed;
}
switch (halt_res.value()) {
- case HaltReason::kSemihostHaltRequest:
+ case *HaltReason::kSemihostHaltRequest:
return total_executed;
break;
- case HaltReason::kSoftwareBreakpoint:
- case HaltReason::kHardwareBreakpoint:
+ case *HaltReason::kSoftwareBreakpoint:
+ case *HaltReason::kHardwareBreakpoint:
if (status != nullptr) {
*status = static_cast<int32_t>(ExecutionResult::kStoppedAtBreakpoint);
}
return total_executed;
break;
- case HaltReason::kUserRequest:
+ case *HaltReason::kUserRequest:
if (status != nullptr) {
*status = static_cast<int32_t>(ExecutionResult::kOk);
}
@@ -332,18 +334,19 @@
}
// Map the halt status appropriately.
using HaltReason = RenodeDebugInterface::HaltReason;
+ using mpact::sim::riscv::operator*; // NOLINT: used below.
if (status != nullptr) {
switch (halt_res.value()) {
- case HaltReason::kSemihostHaltRequest:
+ case *HaltReason::kSemihostHaltRequest:
*status = static_cast<int32_t>(ExecutionResult::kAborted);
break;
- case HaltReason::kSoftwareBreakpoint:
+ case *HaltReason::kSoftwareBreakpoint:
*status = static_cast<int32_t>(ExecutionResult::kStoppedAtBreakpoint);
break;
- case HaltReason::kUserRequest:
+ case *HaltReason::kUserRequest:
*status = static_cast<int32_t>(ExecutionResult::kInterrupted);
break;
- case HaltReason::kNone:
+ case *HaltReason::kNone:
*status = static_cast<int32_t>(ExecutionResult::kOk);
break;
default: