aboutsummaryrefslogtreecommitdiff
path: root/riscv
diff options
context:
space:
mode:
authorYenHaoChen <howard25336284@gmail.com>2022-09-30 11:48:44 +0800
committerYenHaoChen <howard25336284@gmail.com>2022-09-30 11:48:44 +0800
commitb724db52f9d7be3e3068e5bf01ac939ece8d032b (patch)
treeeddd458343c4a65764195961e9014938c64aa84a /riscv
parent37003b120b1ea704918022216c717e13c391be6c (diff)
downloadspike-b724db52f9d7be3e3068e5bf01ac939ece8d032b.zip
spike-b724db52f9d7be3e3068e5bf01ac939ece8d032b.tar.gz
spike-b724db52f9d7be3e3068e5bf01ac939ece8d032b.tar.bz2
Add has_data argument to trigger checking functions
The mcontrol trigger can select either address or data for checking. The The selection decides the priority of the trigger. For instance, the address trigger has a higher priority over the page fault, and the page fault has a higher priority over the data trigger. The previous implementation only has the checking functions for data trigger, which results in incorrect priority of address trigger. This commit adds a has_data argument to indicate address trigger and the priority of the trigger.
Diffstat (limited to 'riscv')
-rw-r--r--riscv/mmu.cc4
-rw-r--r--riscv/mmu.h10
-rw-r--r--riscv/triggers.cc8
-rw-r--r--riscv/triggers.h6
4 files changed, 15 insertions, 13 deletions
diff --git a/riscv/mmu.cc b/riscv/mmu.cc
index d0a55f0..0dbb94e 100644
--- a/riscv/mmu.cc
+++ b/riscv/mmu.cc
@@ -155,7 +155,7 @@ void mmu_t::load_slow_path(reg_t addr, reg_t len, uint8_t* bytes, uint32_t xlate
if (!matched_trigger) {
reg_t data = reg_from_bytes(len, bytes);
- matched_trigger = trigger_exception(triggers::OPERATION_LOAD, addr, data);
+ matched_trigger = trigger_exception(triggers::OPERATION_LOAD, addr, true, data);
if (matched_trigger)
throw *matched_trigger;
}
@@ -167,7 +167,7 @@ void mmu_t::store_slow_path(reg_t addr, reg_t len, const uint8_t* bytes, uint32_
if (!matched_trigger) {
reg_t data = reg_from_bytes(len, bytes);
- matched_trigger = trigger_exception(triggers::OPERATION_STORE, addr, data);
+ matched_trigger = trigger_exception(triggers::OPERATION_STORE, addr, true, data);
if (matched_trigger)
throw *matched_trigger;
}
diff --git a/riscv/mmu.h b/riscv/mmu.h
index ca8b792..ebe4f9b 100644
--- a/riscv/mmu.h
+++ b/riscv/mmu.h
@@ -113,7 +113,7 @@ public:
if ((xlate_flags) == 0 && unlikely(tlb_load_tag[vpn % TLB_ENTRIES] == (vpn | TLB_CHECK_TRIGGERS))) { \
type##_t data = from_target(*(target_endian<type##_t>*)(tlb_data[vpn % TLB_ENTRIES].host_offset + addr)); \
if (!matched_trigger) { \
- matched_trigger = trigger_exception(triggers::OPERATION_LOAD, addr, data); \
+ matched_trigger = trigger_exception(triggers::OPERATION_LOAD, addr, true, data); \
if (matched_trigger) \
throw *matched_trigger; \
} \
@@ -178,7 +178,7 @@ public:
else if ((xlate_flags) == 0 && unlikely(tlb_store_tag[vpn % TLB_ENTRIES] == (vpn | TLB_CHECK_TRIGGERS))) { \
if (actually_store) { \
if (!matched_trigger) { \
- matched_trigger = trigger_exception(triggers::OPERATION_STORE, addr, val); \
+ matched_trigger = trigger_exception(triggers::OPERATION_STORE, addr, true, val); \
if (matched_trigger) \
throw *matched_trigger; \
} \
@@ -479,7 +479,7 @@ private:
}
target_endian<uint16_t>* ptr = (target_endian<uint16_t>*)(result.host_offset + addr);
triggers::action_t action;
- auto match = proc->TM.memory_access_match(&action, triggers::OPERATION_EXECUTE, addr, from_target(*ptr));
+ auto match = proc->TM.memory_access_match(&action, triggers::OPERATION_EXECUTE, addr, true, from_target(*ptr));
if (match != triggers::MATCH_NONE) {
throw triggers::matched_t(triggers::OPERATION_EXECUTE, addr, from_target(*ptr), action);
}
@@ -491,13 +491,13 @@ private:
}
inline triggers::matched_t *trigger_exception(triggers::operation_t operation,
- reg_t address, reg_t data)
+ reg_t address, bool has_data, reg_t data=0)
{
if (!proc) {
return NULL;
}
triggers::action_t action;
- auto match = proc->TM.memory_access_match(&action, operation, address, data);
+ auto match = proc->TM.memory_access_match(&action, operation, address, has_data, data);
if (match == triggers::MATCH_NONE)
return NULL;
if (match == triggers::MATCH_FIRE_BEFORE) {
diff --git a/riscv/triggers.cc b/riscv/triggers.cc
index 4b73715..e357b4a 100644
--- a/riscv/triggers.cc
+++ b/riscv/triggers.cc
@@ -101,7 +101,7 @@ bool mcontrol_t::simple_match(unsigned xlen, reg_t value) const {
assert(0);
}
-match_result_t mcontrol_t::memory_access_match(processor_t * const proc, operation_t operation, reg_t address, reg_t data) {
+match_result_t mcontrol_t::memory_access_match(processor_t * const proc, operation_t operation, reg_t address, bool has_data, reg_t data) {
state_t * const state = proc->get_state();
if ((operation == triggers::OPERATION_EXECUTE && !execute_bit) ||
(operation == triggers::OPERATION_STORE && !store_bit) ||
@@ -115,6 +115,8 @@ match_result_t mcontrol_t::memory_access_match(processor_t * const proc, operati
reg_t value;
if (select) {
value = data;
+ if (!has_data)
+ return MATCH_NONE;
} else {
value = address;
}
@@ -150,7 +152,7 @@ module_t::~module_t() {
}
}
-match_result_t module_t::memory_access_match(action_t * const action, operation_t operation, reg_t address, reg_t data)
+match_result_t module_t::memory_access_match(action_t * const action, operation_t operation, reg_t address, bool has_data, reg_t data)
{
state_t * const state = proc->get_state();
if (state->debug_mode)
@@ -170,7 +172,7 @@ match_result_t module_t::memory_access_match(action_t * const action, operation_
* 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);
+ match_result_t result = triggers[i]->memory_access_match(proc, operation, address, has_data, data);
if (result != MATCH_NONE && !triggers[i]->chain()) {
*action = triggers[i]->action;
return result;
diff --git a/riscv/triggers.h b/riscv/triggers.h
index 8f1b81d..b7512ef 100644
--- a/riscv/triggers.h
+++ b/riscv/triggers.h
@@ -43,7 +43,7 @@ class matched_t
class trigger_t {
public:
virtual match_result_t memory_access_match(processor_t * const proc,
- operation_t operation, reg_t address, reg_t data) = 0;
+ operation_t operation, reg_t address, bool has_data, reg_t data=0) = 0;
virtual reg_t tdata1_read(const processor_t * const proc) const noexcept = 0;
virtual bool tdata1_write(processor_t * const proc, const reg_t val) noexcept = 0;
@@ -88,7 +88,7 @@ public:
virtual bool load() const override { return load_bit; }
virtual match_result_t memory_access_match(processor_t * const proc,
- operation_t operation, reg_t address, reg_t data) override;
+ operation_t operation, reg_t address, bool has_data, reg_t data=0) override;
private:
bool simple_match(unsigned xlen, reg_t value) const;
@@ -115,7 +115,7 @@ public:
unsigned count() const { return triggers.size(); }
match_result_t memory_access_match(action_t * const action,
- operation_t operation, reg_t address, reg_t data);
+ operation_t operation, reg_t address, bool has_data, reg_t data=0);
reg_t tdata1_read(const processor_t * const proc, unsigned index) const noexcept;
bool tdata1_write(processor_t * const proc, unsigned index, const reg_t val) noexcept;