diff options
author | Tim Newsome <tim@sifive.com> | 2022-03-24 11:12:39 -0700 |
---|---|---|
committer | Tim Newsome <tim@sifive.com> | 2022-04-05 10:33:27 -0700 |
commit | f3d14f936965fb48a140ab010a9e1b0b2908bf2d (patch) | |
tree | 7ae78337dc6a12f25a378f32a8a49def1b633393 /riscv | |
parent | bd7ca31454507df073e66d4c9e1d32a062231fc2 (diff) | |
download | spike-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.cc | 2 | ||||
-rw-r--r-- | riscv/mmu.h | 18 | ||||
-rw-r--r-- | riscv/triggers.cc | 74 | ||||
-rw-r--r-- | riscv/triggers.h | 26 |
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; |