aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorScott Johnson <scott.johnson@arilinc.com>2023-01-04 09:22:51 -0800
committerGitHub <noreply@github.com>2023-01-04 09:22:51 -0800
commitb3946f8500b58c934ca9bd036cb8f4b614788caf (patch)
tree7c64d3aaeb6019ef9cf7e7bc9c4103950ed2a44f
parent4ac904b7c09c80c455e3006d3a934ea49b169ffd (diff)
parent89a44eb0a28f5c530aa93ffddc17a9897397ac56 (diff)
downloadspike-b3946f8500b58c934ca9bd036cb8f4b614788caf.zip
spike-b3946f8500b58c934ca9bd036cb8f4b614788caf.tar.gz
spike-b3946f8500b58c934ca9bd036cb8f4b614788caf.tar.bz2
Merge pull request #1207 from YenHaoChen/pr-trap-trigger-common
triggers: refactor: add trap_common_t
-rw-r--r--riscv/triggers.cc36
-rw-r--r--riscv/triggers.h31
2 files changed, 34 insertions, 33 deletions
diff --git a/riscv/triggers.cc b/riscv/triggers.cc
index 0ff36e8..f451f05 100644
--- a/riscv/triggers.cc
+++ b/riscv/triggers.cc
@@ -54,6 +54,10 @@ void trigger_t::tdata3_write(processor_t * const proc, const reg_t val) noexcept
sselect = (sselect_t)((proc->extension_enabled_const('S') && get_field(val, CSR_TEXTRA_SSELECT(xlen)) <= SSELECT_MAXVAL) ? get_field(val, CSR_TEXTRA_SSELECT(xlen)) : SSELECT_IGNORE);
}
+bool trigger_t::common_match(processor_t * const proc) const noexcept {
+ return mode_match(proc->get_state()) && textra_match(proc);
+}
+
bool trigger_t::mode_match(state_t * const state) const noexcept
{
switch (state->prv) {
@@ -190,7 +194,7 @@ std::optional<match_result_t> mcontrol_common_t::detect_memory_access_match(proc
if ((operation == triggers::OPERATION_EXECUTE && !execute) ||
(operation == triggers::OPERATION_STORE && !store) ||
(operation == triggers::OPERATION_LOAD && !load) ||
- !mode_match(proc->get_state())) {
+ !common_match(proc)) {
return std::nullopt;
}
@@ -310,22 +314,27 @@ void itrigger_t::tdata1_write(processor_t * const proc, const reg_t val, const b
action = legalize_action(get_field(val, CSR_ITRIGGER_ACTION));
}
-std::optional<match_result_t> itrigger_t::detect_trap_match(processor_t * const proc, const trap_t& t) noexcept
+std::optional<match_result_t> trap_common_t::detect_trap_match(processor_t * const proc, const trap_t& t) noexcept
{
- if (!mode_match(proc->get_state()))
+ if (!common_match(proc))
return std::nullopt;
auto xlen = proc->get_xlen();
bool interrupt = (t.cause() & ((reg_t)1 << (xlen - 1))) != 0;
reg_t bit = t.cause() & ~((reg_t)1 << (xlen - 1));
assert(bit < xlen);
- if (interrupt && ((bit == 0 && nmi) || ((tdata2 >> bit) & 1))) { // Assume NMI's exception code is 0
+ if (simple_match(interrupt, bit)) {
hit = true;
return match_result_t(TIMING_AFTER, action);
}
return std::nullopt;
}
+bool itrigger_t::simple_match(bool interrupt, reg_t bit) const
+{
+ return interrupt && ((bit == 0 && nmi) || ((tdata2 >> bit) & 1)); // Assume NMI's exception code is 0
+}
+
reg_t etrigger_t::tdata1_read(const processor_t * const proc) const noexcept
{
auto xlen = proc->get_xlen();
@@ -356,20 +365,9 @@ void etrigger_t::tdata1_write(processor_t * const proc, const reg_t val, const b
action = legalize_action(get_field(val, CSR_ETRIGGER_ACTION));
}
-std::optional<match_result_t> etrigger_t::detect_trap_match(processor_t * const proc, const trap_t& t) noexcept
+bool etrigger_t::simple_match(bool interrupt, reg_t bit) const
{
- if (!mode_match(proc->get_state()))
- return std::nullopt;
-
- auto xlen = proc->get_xlen();
- bool interrupt = (t.cause() & ((reg_t)1 << (xlen - 1))) != 0;
- reg_t bit = t.cause() & ~((reg_t)1 << (xlen - 1));
- assert(bit < xlen);
- if (!interrupt && ((tdata2 >> bit) & 1)) {
- hit = true;
- return match_result_t(TIMING_AFTER, action);
- }
- return std::nullopt;
+ return !interrupt && ((tdata2 >> bit) & 1);
}
module_t::module_t(unsigned count) : triggers(count) {
@@ -483,7 +481,7 @@ std::optional<match_result_t> module_t::detect_memory_access_match(operation_t o
* entire chain did not match. This is allowed by the spec, because the final
* trigger in the chain will never get `hit` set unless the entire chain
* matches. */
- auto result = trigger->textra_match(proc) ? trigger->detect_memory_access_match(proc, operation, address, data) : std::nullopt;
+ auto result = trigger->detect_memory_access_match(proc, operation, address, data);
if (result.has_value() && !trigger->get_chain())
return result;
@@ -499,7 +497,7 @@ std::optional<match_result_t> module_t::detect_trap_match(const trap_t& t) noexc
return std::nullopt;
for (auto trigger: triggers) {
- auto result = trigger->textra_match(proc) ? trigger->detect_trap_match(proc, t) : std::nullopt;
+ auto result = trigger->detect_trap_match(proc, t);
if (result.has_value())
return result;
}
diff --git a/riscv/triggers.h b/riscv/triggers.h
index 62d6db8..31c5b30 100644
--- a/riscv/triggers.h
+++ b/riscv/triggers.h
@@ -83,11 +83,10 @@ public:
virtual std::optional<match_result_t> detect_memory_access_match(processor_t UNUSED * const proc,
operation_t UNUSED operation, reg_t UNUSED address, std::optional<reg_t> UNUSED data) noexcept { return std::nullopt; }
virtual std::optional<match_result_t> detect_trap_match(processor_t UNUSED * const proc, const trap_t UNUSED & t) noexcept { return std::nullopt; }
- bool textra_match(processor_t * const proc) const noexcept;
protected:
action_t legalize_action(reg_t val) const noexcept;
- bool mode_match(state_t * const state) const noexcept;
+ bool common_match(processor_t * const proc) const noexcept;
reg_t tdata2;
bool vs = false;
@@ -98,6 +97,8 @@ protected:
private:
unsigned legalize_mhselect(bool h_enabled) const noexcept;
+ bool mode_match(state_t * const state) const noexcept;
+ bool textra_match(processor_t * const proc) const noexcept;
struct mhselect_interpretation {
const unsigned mhselect;
@@ -145,37 +146,39 @@ private:
bool dmode;
};
-class itrigger_t : public trigger_t {
+class trap_common_t : public trigger_t {
public:
- virtual reg_t tdata1_read(const processor_t * const proc) const noexcept override;
- virtual void tdata1_write(processor_t * const proc, const reg_t val, const bool allow_chain) noexcept override;
-
bool get_dmode() const override { return dmode; }
virtual action_t get_action() const override { return action; }
virtual std::optional<match_result_t> detect_trap_match(processor_t * const proc, const trap_t& t) noexcept override;
private:
+ virtual bool simple_match(bool interrupt, reg_t bit) const = 0;
+
+protected:
bool dmode;
bool hit;
- bool nmi;
action_t action;
};
-class etrigger_t : public trigger_t {
+class itrigger_t : public trap_common_t {
public:
virtual reg_t tdata1_read(const processor_t * const proc) const noexcept override;
virtual void tdata1_write(processor_t * const proc, const reg_t val, const bool allow_chain) noexcept override;
- bool get_dmode() const override { return dmode; }
- virtual action_t get_action() const override { return action; }
+private:
+ virtual bool simple_match(bool interrupt, reg_t bit) const override;
+ bool nmi;
+};
- virtual std::optional<match_result_t> detect_trap_match(processor_t * const proc, const trap_t& t) noexcept override;
+class etrigger_t : public trap_common_t {
+public:
+ virtual reg_t tdata1_read(const processor_t * const proc) const noexcept override;
+ virtual void tdata1_write(processor_t * const proc, const reg_t val, const bool allow_chain) noexcept override;
private:
- bool dmode;
- bool hit;
- action_t action;
+ virtual bool simple_match(bool interrupt, reg_t bit) const override;
};
class mcontrol_common_t : public trigger_t {