aboutsummaryrefslogtreecommitdiff
path: root/riscv
diff options
context:
space:
mode:
authorAndrew Waterman <andrew@sifive.com>2022-10-05 17:17:40 -0700
committerGitHub <noreply@github.com>2022-10-05 17:17:40 -0700
commitcb7e6b840be13ebc46fdcdb23df6db61ff306fde (patch)
tree549393ded86f05531e63f2bc00caf4f5511f504d /riscv
parent9b074198357b77189df989f0e274b23353f7f528 (diff)
parentab104011ba66fb3c88ce8405236908dc8700c679 (diff)
downloadspike-cb7e6b840be13ebc46fdcdb23df6db61ff306fde.zip
spike-cb7e6b840be13ebc46fdcdb23df6db61ff306fde.tar.gz
spike-cb7e6b840be13ebc46fdcdb23df6db61ff306fde.tar.bz2
Merge pull request #1105 from YenHaoChen/pr-trigger-priority
Fix trigger priority
Diffstat (limited to 'riscv')
-rw-r--r--riscv/mmu.cc25
-rw-r--r--riscv/mmu.h28
-rw-r--r--riscv/triggers.cc8
-rw-r--r--riscv/triggers.h6
4 files changed, 47 insertions, 20 deletions
diff --git a/riscv/mmu.cc b/riscv/mmu.cc
index 1028026..367c859 100644
--- a/riscv/mmu.cc
+++ b/riscv/mmu.cc
@@ -141,6 +141,13 @@ bool mmu_t::mmio_store(reg_t addr, size_t len, const uint8_t* bytes)
void mmu_t::load_slow_path(reg_t addr, reg_t len, uint8_t* bytes, uint32_t xlate_flags)
{
+ if (!matched_trigger) {
+ reg_t data = reg_from_bytes(len, bytes);
+ matched_trigger = trigger_exception(triggers::OPERATION_LOAD, addr, false);
+ if (matched_trigger)
+ throw *matched_trigger;
+ }
+
reg_t paddr = translate(addr, len, LOAD, xlate_flags);
if (auto host_addr = sim->addr_to_mem(paddr)) {
@@ -155,7 +162,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;
}
@@ -163,15 +170,17 @@ void mmu_t::load_slow_path(reg_t addr, reg_t len, uint8_t* bytes, uint32_t xlate
void mmu_t::store_slow_path(reg_t addr, reg_t len, const uint8_t* bytes, uint32_t xlate_flags, bool actually_store)
{
- reg_t paddr = translate(addr, len, STORE, xlate_flags);
-
- if (!matched_trigger) {
- reg_t data = reg_from_bytes(len, bytes);
- matched_trigger = trigger_exception(triggers::OPERATION_STORE, addr, data);
- if (matched_trigger)
- throw *matched_trigger;
+ if (actually_store) {
+ if (!matched_trigger) {
+ reg_t data = reg_from_bytes(len, bytes);
+ matched_trigger = trigger_exception(triggers::OPERATION_STORE, addr, true, data);
+ if (matched_trigger)
+ throw *matched_trigger;
+ }
}
+ reg_t paddr = translate(addr, len, STORE, xlate_flags);
+
if (actually_store) {
if (auto host_addr = sim->addr_to_mem(paddr)) {
memcpy(host_addr, bytes, len);
diff --git a/riscv/mmu.h b/riscv/mmu.h
index 4d52618..8b9ff9b 100644
--- a/riscv/mmu.h
+++ b/riscv/mmu.h
@@ -101,6 +101,11 @@ public:
#define load_func(type, prefix, xlate_flags) \
type##_t ALWAYS_INLINE prefix##_##type(reg_t addr, bool require_alignment = false) { \
if (unlikely(addr & (sizeof(type##_t)-1))) { \
+ if (!matched_trigger) { \
+ matched_trigger = trigger_exception(triggers::OPERATION_LOAD, addr, false); \
+ if (matched_trigger) \
+ throw *matched_trigger; \
+ } \
if (require_alignment) load_reserved_address_misaligned(addr); \
else return misaligned_load(addr, sizeof(type##_t), xlate_flags); \
} \
@@ -113,7 +118,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; \
} \
@@ -164,6 +169,13 @@ public:
#define store_func(type, prefix, xlate_flags) \
void ALWAYS_INLINE prefix##_##type(reg_t addr, type##_t val, bool actually_store=true, bool require_alignment=false) { \
if (unlikely(addr & (sizeof(type##_t)-1))) { \
+ if (actually_store) { \
+ if (!matched_trigger) { \
+ matched_trigger = trigger_exception(triggers::OPERATION_STORE, addr, true, val); \
+ if (matched_trigger) \
+ throw *matched_trigger; \
+ } \
+ } \
if (require_alignment) store_conditional_address_misaligned(addr); \
else return misaligned_store(addr, val, sizeof(type##_t), xlate_flags, actually_store); \
} \
@@ -178,7 +190,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; \
} \
@@ -471,6 +483,11 @@ private:
reg_t vpn = addr >> PGSHIFT;
if (likely(tlb_insn_tag[vpn % TLB_ENTRIES] == vpn))
return tlb_data[vpn % TLB_ENTRIES];
+ triggers::action_t action;
+ auto match = proc->TM.memory_access_match(&action, triggers::OPERATION_EXECUTE, addr, false);
+ if (match != triggers::MATCH_NONE) {
+ throw triggers::matched_t(triggers::OPERATION_EXECUTE, addr, 0, action);
+ }
tlb_entry_t result;
if (unlikely(tlb_insn_tag[vpn % TLB_ENTRIES] != (vpn | TLB_CHECK_TRIGGERS))) {
result = fetch_slow_path(addr);
@@ -478,8 +495,7 @@ private:
result = tlb_data[vpn % TLB_ENTRIES];
}
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));
+ 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 +507,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 390ebe4..5e2d1f6 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;