aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Waterman <andrew@sifive.com>2023-04-26 11:21:14 -0700
committerGitHub <noreply@github.com>2023-04-26 11:21:14 -0700
commitfcbdbe7946079650d0e656fa3d353e3f652d471f (patch)
treeb79346c6ed565343ec65e9196cd46035cbfdac77
parent87e0a1f86e16e4d3048e0afe7b2c51c821a108ed (diff)
parent83c19daaf202e101e2a79109de4118a02f9d90a7 (diff)
downloadspike-fcbdbe7946079650d0e656fa3d353e3f652d471f.zip
spike-fcbdbe7946079650d0e656fa3d353e3f652d471f.tar.gz
spike-fcbdbe7946079650d0e656fa3d353e3f652d471f.tar.bz2
Merge pull request #1316 from YenHaoChen/pr-native-triggers
implement Debug Specification Section 5.4 Native Triggers
-rw-r--r--riscv/triggers.cc21
-rw-r--r--riscv/triggers.h1
2 files changed, 19 insertions, 3 deletions
diff --git a/riscv/triggers.cc b/riscv/triggers.cc
index 07cd6bf..86dcc81 100644
--- a/riscv/triggers.cc
+++ b/riscv/triggers.cc
@@ -106,6 +106,21 @@ bool trigger_t::textra_match(processor_t * const proc) const noexcept
return true;
}
+bool trigger_t::allow_action(const state_t * const state) const
+{
+ if (get_action() == ACTION_DEBUG_EXCEPTION) {
+ const bool mstatus_mie = state->mstatus->read() & MSTATUS_MIE;
+ const bool sstatus_sie = state->sstatus->read() & MSTATUS_SIE;
+ const bool vsstatus_sie = state->vsstatus->read() & MSTATUS_SIE;
+ const bool medeleg_breakpoint = (state->medeleg->read() >> CAUSE_BREAKPOINT) & 1;
+ const bool hedeleg_breakpoint = (state->hedeleg->read() >> CAUSE_BREAKPOINT) & 1;
+ return (state->prv != PRV_M || mstatus_mie) &&
+ (state->prv != PRV_S || state->v || !medeleg_breakpoint || sstatus_sie) &&
+ (state->prv != PRV_S || !state->v || !medeleg_breakpoint || !hedeleg_breakpoint || vsstatus_sie);
+ }
+ return true;
+}
+
reg_t disabled_trigger_t::tdata1_read(const processor_t * const proc) const noexcept
{
auto xlen = proc->get_xlen();
@@ -212,7 +227,7 @@ std::optional<match_result_t> mcontrol_common_t::detect_memory_access_match(proc
value &= 0xffffffff;
}
- if (simple_match(xlen, value)) {
+ if (simple_match(xlen, value) && allow_action(proc->get_state())) {
/* This is OK because this function is only called if the trigger was not
* inhibited by the previous trigger in the chain. */
hit = true;
@@ -289,7 +304,7 @@ void mcontrol6_t::tdata1_write(processor_t * const proc, const reg_t val, const
std::optional<match_result_t> icount_t::detect_icount_match(processor_t * const proc) noexcept
{
- if (!common_match(proc))
+ if (!common_match(proc) || !allow_action(proc->get_state()))
return std::nullopt;
std::optional<match_result_t> ret = std::nullopt;
@@ -389,7 +404,7 @@ std::optional<match_result_t> trap_common_t::detect_trap_match(processor_t * con
bool interrupt = (t.cause() & ((reg_t)1 << (xlen - 1))) != 0;
reg_t bit = t.cause() & ~((reg_t)1 << (xlen - 1));
assert(bit < xlen);
- if (simple_match(interrupt, bit)) {
+ if (simple_match(interrupt, bit) && allow_action(proc->get_state())) {
hit = true;
return match_result_t(TIMING_AFTER, action);
}
diff --git a/riscv/triggers.h b/riscv/triggers.h
index 0c9dabc..6e3d74d 100644
--- a/riscv/triggers.h
+++ b/riscv/triggers.h
@@ -90,6 +90,7 @@ public:
protected:
static action_t legalize_action(reg_t val, reg_t action_mask, reg_t dmode_mask) noexcept;
bool common_match(processor_t * const proc) const noexcept;
+ bool allow_action(const state_t * const state) const;
reg_t tdata2;
bool vs = false;