aboutsummaryrefslogtreecommitdiff
path: root/riscv/triggers.cc
diff options
context:
space:
mode:
authorTim Newsome <tim@sifive.com>2022-04-28 10:27:42 -0700
committerTim Newsome <tim@sifive.com>2022-05-02 13:15:13 -0700
commit85fbd75d44c369ccb358d70bb4adc3a82a23c495 (patch)
tree067efdf80197b3f7fbb9aaf4bf17ea7006113e1b /riscv/triggers.cc
parentf2f6037fea9313f43f7e94872304ab18ead0181d (diff)
downloadspike-85fbd75d44c369ccb358d70bb4adc3a82a23c495.zip
spike-85fbd75d44c369ccb358d70bb4adc3a82a23c495.tar.gz
spike-85fbd75d44c369ccb358d70bb4adc3a82a23c495.tar.bz2
Implement mcontrol trigger hit bit.
Diffstat (limited to 'riscv/triggers.cc')
-rw-r--r--riscv/triggers.cc12
1 files changed, 12 insertions, 0 deletions
diff --git a/riscv/triggers.cc b/riscv/triggers.cc
index 7f6be44..ed9105e 100644
--- a/riscv/triggers.cc
+++ b/riscv/triggers.cc
@@ -1,3 +1,4 @@
+#include "debug_defines.h"
#include "processor.h"
#include "triggers.h"
@@ -16,6 +17,7 @@ reg_t mcontrol_t::tdata1_read(const processor_t * const proc) const noexcept {
v = set_field(v, MCONTROL_TYPE(xlen), 2);
v = set_field(v, MCONTROL_DMODE(xlen), dmode);
v = set_field(v, MCONTROL_MASKMAX(xlen), 0);
+ v = set_field(v, CSR_MCONTROL_HIT, hit);
v = set_field(v, MCONTROL_SELECT, select);
v = set_field(v, MCONTROL_TIMING, timing);
v = set_field(v, MCONTROL_ACTION, action);
@@ -36,6 +38,7 @@ bool mcontrol_t::tdata1_write(processor_t * const proc, const reg_t val) noexcep
}
auto xlen = proc->get_xlen();
dmode = get_field(val, MCONTROL_DMODE(xlen));
+ hit = get_field(val, CSR_MCONTROL_HIT);
select = get_field(val, MCONTROL_SELECT);
timing = get_field(val, MCONTROL_TIMING);
action = (triggers::action_t) get_field(val, MCONTROL_ACTION);
@@ -131,6 +134,9 @@ match_result_t mcontrol_t::memory_access_match(processor_t * const proc, operati
}
if (simple_match(xlen, value)) {
+ /* This is OK because this function is only called if the trigger was not
+ * inhibited by the previous trigger in the chain. */
+ hit = true;
if (timing)
return MATCH_FIRE_AFTER;
else
@@ -165,6 +171,12 @@ match_result_t module_t::memory_access_match(action_t * const action, operation_
continue;
}
+ /* Note: We call memory_access_match for each trigger in a chain as long as
+ * the triggers are matching. This results in "temperature coding" so that
+ * `hit` is set on each of the consecutive triggers that matched, even if the
+ * 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. */
match_result_t result = triggers[i]->memory_access_match(proc, operation, address, data);
if (result != MATCH_NONE && !triggers[i]->chain()) {
*action = triggers[i]->action;