diff options
author | Scott Johnson <scott.johnson@arilinc.com> | 2023-01-04 09:22:51 -0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-01-04 09:22:51 -0800 |
commit | b3946f8500b58c934ca9bd036cb8f4b614788caf (patch) | |
tree | 7c64d3aaeb6019ef9cf7e7bc9c4103950ed2a44f | |
parent | 4ac904b7c09c80c455e3006d3a934ea49b169ffd (diff) | |
parent | 89a44eb0a28f5c530aa93ffddc17a9897397ac56 (diff) | |
download | riscv-isa-sim-b3946f8500b58c934ca9bd036cb8f4b614788caf.zip riscv-isa-sim-b3946f8500b58c934ca9bd036cb8f4b614788caf.tar.gz riscv-isa-sim-b3946f8500b58c934ca9bd036cb8f4b614788caf.tar.bz2 |
Merge pull request #1207 from YenHaoChen/pr-trap-trigger-common
triggers: refactor: add trap_common_t
-rw-r--r-- | riscv/triggers.cc | 36 | ||||
-rw-r--r-- | riscv/triggers.h | 31 |
2 files changed, 34 insertions, 33 deletions
diff --git a/riscv/triggers.cc b/riscv/triggers.cc index 0ff36e8..f451f05 100644 --- a/riscv/triggers.cc +++ b/riscv/triggers.cc @@ -54,6 +54,10 @@ void trigger_t::tdata3_write(processor_t * const proc, const reg_t val) noexcept sselect = (sselect_t)((proc->extension_enabled_const('S') && get_field(val, CSR_TEXTRA_SSELECT(xlen)) <= SSELECT_MAXVAL) ? get_field(val, CSR_TEXTRA_SSELECT(xlen)) : SSELECT_IGNORE); } +bool trigger_t::common_match(processor_t * const proc) const noexcept { + return mode_match(proc->get_state()) && textra_match(proc); +} + bool trigger_t::mode_match(state_t * const state) const noexcept { switch (state->prv) { @@ -190,7 +194,7 @@ std::optional<match_result_t> mcontrol_common_t::detect_memory_access_match(proc if ((operation == triggers::OPERATION_EXECUTE && !execute) || (operation == triggers::OPERATION_STORE && !store) || (operation == triggers::OPERATION_LOAD && !load) || - !mode_match(proc->get_state())) { + !common_match(proc)) { return std::nullopt; } @@ -310,22 +314,27 @@ void itrigger_t::tdata1_write(processor_t * const proc, const reg_t val, const b action = legalize_action(get_field(val, CSR_ITRIGGER_ACTION)); } -std::optional<match_result_t> itrigger_t::detect_trap_match(processor_t * const proc, const trap_t& t) noexcept +std::optional<match_result_t> trap_common_t::detect_trap_match(processor_t * const proc, const trap_t& t) noexcept { - if (!mode_match(proc->get_state())) + if (!common_match(proc)) return std::nullopt; auto xlen = proc->get_xlen(); bool interrupt = (t.cause() & ((reg_t)1 << (xlen - 1))) != 0; reg_t bit = t.cause() & ~((reg_t)1 << (xlen - 1)); assert(bit < xlen); - if (interrupt && ((bit == 0 && nmi) || ((tdata2 >> bit) & 1))) { // Assume NMI's exception code is 0 + if (simple_match(interrupt, bit)) { hit = true; return match_result_t(TIMING_AFTER, action); } return std::nullopt; } +bool itrigger_t::simple_match(bool interrupt, reg_t bit) const +{ + return interrupt && ((bit == 0 && nmi) || ((tdata2 >> bit) & 1)); // Assume NMI's exception code is 0 +} + reg_t etrigger_t::tdata1_read(const processor_t * const proc) const noexcept { auto xlen = proc->get_xlen(); @@ -356,20 +365,9 @@ void etrigger_t::tdata1_write(processor_t * const proc, const reg_t val, const b action = legalize_action(get_field(val, CSR_ETRIGGER_ACTION)); } -std::optional<match_result_t> etrigger_t::detect_trap_match(processor_t * const proc, const trap_t& t) noexcept +bool etrigger_t::simple_match(bool interrupt, reg_t bit) const { - if (!mode_match(proc->get_state())) - return std::nullopt; - - auto xlen = proc->get_xlen(); - bool interrupt = (t.cause() & ((reg_t)1 << (xlen - 1))) != 0; - reg_t bit = t.cause() & ~((reg_t)1 << (xlen - 1)); - assert(bit < xlen); - if (!interrupt && ((tdata2 >> bit) & 1)) { - hit = true; - return match_result_t(TIMING_AFTER, action); - } - return std::nullopt; + return !interrupt && ((tdata2 >> bit) & 1); } module_t::module_t(unsigned count) : triggers(count) { @@ -483,7 +481,7 @@ std::optional<match_result_t> module_t::detect_memory_access_match(operation_t o * 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. */ - auto result = trigger->textra_match(proc) ? trigger->detect_memory_access_match(proc, operation, address, data) : std::nullopt; + auto result = trigger->detect_memory_access_match(proc, operation, address, data); if (result.has_value() && !trigger->get_chain()) return result; @@ -499,7 +497,7 @@ std::optional<match_result_t> module_t::detect_trap_match(const trap_t& t) noexc return std::nullopt; for (auto trigger: triggers) { - auto result = trigger->textra_match(proc) ? trigger->detect_trap_match(proc, t) : std::nullopt; + auto result = trigger->detect_trap_match(proc, t); if (result.has_value()) return result; } diff --git a/riscv/triggers.h b/riscv/triggers.h index 62d6db8..31c5b30 100644 --- a/riscv/triggers.h +++ b/riscv/triggers.h @@ -83,11 +83,10 @@ public: virtual std::optional<match_result_t> detect_memory_access_match(processor_t UNUSED * const proc, operation_t UNUSED operation, reg_t UNUSED address, std::optional<reg_t> UNUSED data) noexcept { return std::nullopt; } virtual std::optional<match_result_t> detect_trap_match(processor_t UNUSED * const proc, const trap_t UNUSED & t) noexcept { return std::nullopt; } - bool textra_match(processor_t * const proc) const noexcept; protected: action_t legalize_action(reg_t val) const noexcept; - bool mode_match(state_t * const state) const noexcept; + bool common_match(processor_t * const proc) const noexcept; reg_t tdata2; bool vs = false; @@ -98,6 +97,8 @@ protected: private: unsigned legalize_mhselect(bool h_enabled) const noexcept; + bool mode_match(state_t * const state) const noexcept; + bool textra_match(processor_t * const proc) const noexcept; struct mhselect_interpretation { const unsigned mhselect; @@ -145,37 +146,39 @@ private: bool dmode; }; -class itrigger_t : public trigger_t { +class trap_common_t : public trigger_t { public: - virtual reg_t tdata1_read(const processor_t * const proc) const noexcept override; - virtual void tdata1_write(processor_t * const proc, const reg_t val, const bool allow_chain) noexcept override; - bool get_dmode() const override { return dmode; } virtual action_t get_action() const override { return action; } virtual std::optional<match_result_t> detect_trap_match(processor_t * const proc, const trap_t& t) noexcept override; private: + virtual bool simple_match(bool interrupt, reg_t bit) const = 0; + +protected: bool dmode; bool hit; - bool nmi; action_t action; }; -class etrigger_t : public trigger_t { +class itrigger_t : public trap_common_t { public: virtual reg_t tdata1_read(const processor_t * const proc) const noexcept override; virtual void tdata1_write(processor_t * const proc, const reg_t val, const bool allow_chain) noexcept override; - bool get_dmode() const override { return dmode; } - virtual action_t get_action() const override { return action; } +private: + virtual bool simple_match(bool interrupt, reg_t bit) const override; + bool nmi; +}; - virtual std::optional<match_result_t> detect_trap_match(processor_t * const proc, const trap_t& t) noexcept override; +class etrigger_t : public trap_common_t { +public: + virtual reg_t tdata1_read(const processor_t * const proc) const noexcept override; + virtual void tdata1_write(processor_t * const proc, const reg_t val, const bool allow_chain) noexcept override; private: - bool dmode; - bool hit; - action_t action; + virtual bool simple_match(bool interrupt, reg_t bit) const override; }; class mcontrol_common_t : public trigger_t { |