aboutsummaryrefslogtreecommitdiff
path: root/riscv
diff options
context:
space:
mode:
authorTim Newsome <tim@sifive.com>2022-03-24 11:12:39 -0700
committerTim Newsome <tim@sifive.com>2022-04-05 10:33:27 -0700
commitf3d14f936965fb48a140ab010a9e1b0b2908bf2d (patch)
tree7ae78337dc6a12f25a378f32a8a49def1b633393 /riscv
parentbd7ca31454507df073e66d4c9e1d32a062231fc2 (diff)
downloadspike-f3d14f936965fb48a140ab010a9e1b0b2908bf2d.zip
spike-f3d14f936965fb48a140ab010a9e1b0b2908bf2d.tar.gz
spike-f3d14f936965fb48a140ab010a9e1b0b2908bf2d.tar.bz2
Move trigger match logic into triggers.cc
Diffstat (limited to 'riscv')
-rw-r--r--riscv/execute.cc2
-rw-r--r--riscv/mmu.h18
-rw-r--r--riscv/triggers.cc74
-rw-r--r--riscv/triggers.h26
4 files changed, 71 insertions, 49 deletions
diff --git a/riscv/execute.cc b/riscv/execute.cc
index c57ca3d..98e3cdb 100644
--- a/riscv/execute.cc
+++ b/riscv/execute.cc
@@ -324,7 +324,7 @@ void processor_t::step(size_t n)
delete mmu->matched_trigger;
mmu->matched_trigger = NULL;
}
- switch (TM.triggers[t.index]->action) {
+ switch (t.action) {
case triggers::ACTION_DEBUG_MODE:
enter_debug_mode(DCSR_CAUSE_HWBP);
break;
diff --git a/riscv/mmu.h b/riscv/mmu.h
index 7faa266..0f009c6 100644
--- a/riscv/mmu.h
+++ b/riscv/mmu.h
@@ -457,9 +457,10 @@ private:
}
if (unlikely(tlb_insn_tag[vpn % TLB_ENTRIES] == (vpn | TLB_CHECK_TRIGGERS))) {
target_endian<uint16_t>* ptr = (target_endian<uint16_t>*)(tlb_data[vpn % TLB_ENTRIES].host_offset + addr);
- int match = proc->TM.memory_access_match(triggers::OPERATION_EXECUTE, addr, from_target(*ptr));
- if (match >= 0) {
- throw triggers::matched_t(match, triggers::OPERATION_EXECUTE, addr, from_target(*ptr));
+ triggers::action_t action;
+ auto match = proc->TM.memory_access_match(&action, triggers::OPERATION_EXECUTE, addr, from_target(*ptr));
+ if (match != triggers::MATCH_NONE) {
+ throw triggers::matched_t(triggers::OPERATION_EXECUTE, addr, from_target(*ptr), action);
}
}
return result;
@@ -475,13 +476,14 @@ private:
if (!proc) {
return NULL;
}
- int match = proc->TM.memory_access_match(operation, address, data);
- if (match == -1)
+ triggers::action_t action;
+ auto match = proc->TM.memory_access_match(&action, operation, address, data);
+ if (match == triggers::MATCH_NONE)
return NULL;
- if (proc->TM.triggers[match]->timing == 0) {
- throw triggers::matched_t(match, operation, address, data);
+ if (match == triggers::MATCH_FIRE_BEFORE) {
+ throw triggers::matched_t(operation, address, data, action);
}
- return new triggers::matched_t(match, operation, address, data);
+ return new triggers::matched_t(operation, address, data, action);
}
reg_t pmp_homogeneous(reg_t addr, reg_t len);
diff --git a/riscv/triggers.cc b/riscv/triggers.cc
index b693bfd..5b9d853 100644
--- a/riscv/triggers.cc
+++ b/riscv/triggers.cc
@@ -81,31 +81,7 @@ bool mcontrol_t::tdata2_write(processor_t *proc, const reg_t val) noexcept {
return true;
}
-bool mcontrol_t::memory_access_match(processor_t *proc, operation_t operation, reg_t address, reg_t data) {
- state_t *state = proc->get_state();
- if ((operation == triggers::OPERATION_EXECUTE && !execute) ||
- (operation == triggers::OPERATION_STORE && !store) ||
- (operation == triggers::OPERATION_LOAD && !load) ||
- (state->prv == PRV_M && !m) ||
- (state->prv == PRV_S && !s) ||
- (state->prv == PRV_U && !u)) {
- return false;
- }
-
- reg_t value;
- if (select) {
- value = data;
- } else {
- value = address;
- }
-
- // We need this because in 32-bit mode sometimes the PC bits get sign
- // extended.
- auto xlen = proc->get_xlen();
- if (xlen == 32) {
- value &= 0xffffffff;
- }
-
+bool mcontrol_t::simple_match(unsigned xlen, reg_t value) const {
switch (match) {
case triggers::mcontrol_t::MATCH_EQUAL:
return value == tdata2;
@@ -132,18 +108,51 @@ bool mcontrol_t::memory_access_match(processor_t *proc, operation_t operation, r
assert(0);
}
+match_result_t mcontrol_t::memory_access_match(processor_t *proc, operation_t operation, reg_t address, reg_t data) {
+ state_t *state = proc->get_state();
+ if ((operation == triggers::OPERATION_EXECUTE && !execute) ||
+ (operation == triggers::OPERATION_STORE && !store) ||
+ (operation == triggers::OPERATION_LOAD && !load) ||
+ (state->prv == PRV_M && !m) ||
+ (state->prv == PRV_S && !s) ||
+ (state->prv == PRV_U && !u)) {
+ return MATCH_NONE;
+ }
+
+ reg_t value;
+ if (select) {
+ value = data;
+ } else {
+ value = address;
+ }
+
+ // We need this because in 32-bit mode sometimes the PC bits get sign
+ // extended.
+ auto xlen = proc->get_xlen();
+ if (xlen == 32) {
+ value &= 0xffffffff;
+ }
+
+ if (simple_match(xlen, value)) {
+ if (timing)
+ return MATCH_FIRE_AFTER;
+ else
+ return MATCH_FIRE_BEFORE;
+ }
+ return MATCH_NONE;
+}
+
module_t::module_t(unsigned count) : triggers(count) {
for (unsigned i = 0; i < count; i++) {
triggers[i] = new mcontrol_t();
}
}
-// Return the index of a trigger that matched, or -1.
-int module_t::memory_access_match(triggers::operation_t operation, reg_t address, reg_t data)
+match_result_t module_t::memory_access_match(action_t *action, operation_t operation, reg_t address, reg_t data)
{
state_t *state = proc->get_state();
if (state->debug_mode)
- return -1;
+ return MATCH_NONE;
bool chain_ok = true;
@@ -153,14 +162,15 @@ int module_t::memory_access_match(triggers::operation_t operation, reg_t address
continue;
}
- if (triggers[i]->memory_access_match(proc, operation, address, data) &&
- !triggers[i]->chain) {
- return i;
+ match_result_t result = triggers[i]->memory_access_match(proc, operation, address, data);
+ if (result != MATCH_NONE && !triggers[i]->chain) {
+ *action = triggers[i]->action;
+ return result;
}
chain_ok = true;
}
- return -1;
+ return MATCH_NONE;
}
diff --git a/riscv/triggers.h b/riscv/triggers.h
index 8163887..41bff75 100644
--- a/riscv/triggers.h
+++ b/riscv/triggers.h
@@ -22,22 +22,27 @@ typedef enum
ACTION_TRACE_EMIT = MCONTROL_ACTION_TRACE_EMIT
} action_t;
+typedef enum {
+ MATCH_NONE,
+ MATCH_FIRE_BEFORE,
+ MATCH_FIRE_AFTER
+} match_result_t;
+
class matched_t
{
public:
- matched_t(int index,
- triggers::operation_t operation, reg_t address, reg_t data) :
- index(index), operation(operation), address(address), data(data) {}
+ matched_t(triggers::operation_t operation, reg_t address, reg_t data, action_t action) :
+ operation(operation), address(address), data(data), action(action) {}
- int index;
triggers::operation_t operation;
reg_t address;
reg_t data;
+ action_t action;
};
class trigger_t {
public:
- virtual bool memory_access_match(processor_t *proc,
+ virtual match_result_t memory_access_match(processor_t *proc,
operation_t operation, reg_t address, reg_t data) = 0;
public:
@@ -67,9 +72,13 @@ public:
reg_t tdata2_read(const processor_t *proc) const noexcept;
bool tdata2_write(processor_t *proc, const reg_t val) noexcept;
- virtual bool memory_access_match(processor_t *proc,
+ virtual match_result_t memory_access_match(processor_t *proc,
operation_t operation, reg_t address, reg_t data) override;
+private:
+ bool simple_match(unsigned xlen, reg_t value) const;
+
+public:
uint8_t type;
uint8_t maskmax;
bool select;
@@ -84,14 +93,15 @@ public:
bool store;
bool load;
reg_t tdata2;
+
};
class module_t {
public:
module_t(unsigned count);
- // Return the index of a trigger that matched, or -1.
- int memory_access_match(triggers::operation_t operation, reg_t address, reg_t data);
+ match_result_t memory_access_match(action_t *action,
+ operation_t operation, reg_t address, reg_t data);
processor_t *proc;
std::vector<mcontrol_t *> triggers;