From 8da8a8c89a937eb4e97fa1158deda84721b5900a Mon Sep 17 00:00:00 2001 From: YenHaoChen Date: Wed, 16 Nov 2022 13:02:02 +0800 Subject: [PATCH] triggers: add etrigger_t --- README.md | 2 +- riscv/triggers.cc | 61 ++++++++++++++++++++++++++++++++++++++++++++++- riscv/triggers.h | 21 ++++++++++++++++ 3 files changed, 82 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index ec4783eb..8d3dbf02 100644 --- a/README.md +++ b/README.md @@ -38,7 +38,7 @@ Spike supports the following RISC-V ISA features: - Svpbmt extension, v1.0 - Svinval extension, v1.0 - Debug v0.14 - - 4 triggers support type=2 (mcontrol), type=4 (itrigger), and type=15 (disabled) + - 4 triggers support type=2 (mcontrol), type=4 (itrigger), type=5 (etrigger), and type=15 (disabled) - Smepmp extension v1.0 - Smstateen extension, v1.0 - Sscofpmf v0.5.2 diff --git a/riscv/triggers.cc b/riscv/triggers.cc index a51e7994..2fc38adb 100644 --- a/riscv/triggers.cc +++ b/riscv/triggers.cc @@ -204,6 +204,60 @@ match_result_t itrigger_t::detect_trap_match(processor_t * const proc, const tra return match_result_t(false); } +reg_t etrigger_t::tdata1_read(const processor_t * const proc) const noexcept +{ + auto xlen = proc->get_xlen(); + reg_t tdata1 = 0; + tdata1 = set_field(tdata1, CSR_ETRIGGER_TYPE(xlen), CSR_TDATA1_TYPE_ETRIGGER); + tdata1 = set_field(tdata1, CSR_ETRIGGER_DMODE(xlen), dmode); + tdata1 = set_field(tdata1, CSR_ETRIGGER_HIT(xlen), hit); + tdata1 = set_field(tdata1, CSR_ETRIGGER_VS, proc->extension_enabled('H') ? vs : 0); + tdata1 = set_field(tdata1, CSR_ETRIGGER_VU, proc->extension_enabled('H') ? vu : 0); + tdata1 = set_field(tdata1, CSR_ETRIGGER_M, m); + tdata1 = set_field(tdata1, CSR_ETRIGGER_S, s); + tdata1 = set_field(tdata1, CSR_ETRIGGER_U, u); + tdata1 = set_field(tdata1, CSR_ETRIGGER_ACTION, action); + return tdata1; +} + +void etrigger_t::tdata1_write(processor_t * const proc, const reg_t val, const bool UNUSED allow_chain) noexcept +{ + auto xlen = proc->get_xlen(); + assert(get_field(val, CSR_ETRIGGER_TYPE(xlen)) == CSR_TDATA1_TYPE_ETRIGGER); + dmode = get_field(val, CSR_ETRIGGER_DMODE(xlen)); + hit = get_field(val, CSR_ETRIGGER_HIT(xlen)); + vs = get_field(val, CSR_ETRIGGER_VS); + vu = get_field(val, CSR_ETRIGGER_VU); + m = get_field(val, CSR_ETRIGGER_M); + s = proc->extension_enabled_const('S') ? get_field(val, CSR_ETRIGGER_S) : 0; + u = proc->extension_enabled_const('U') ? get_field(val, CSR_ETRIGGER_U) : 0; + action = (action_t)get_field(val, CSR_ETRIGGER_ACTION); + if (action > ACTION_MAXVAL || (action==ACTION_DEBUG_MODE && dmode==0)) + action = ACTION_DEBUG_EXCEPTION; +} + +match_result_t etrigger_t::detect_trap_match(processor_t * const proc, const trap_t& t) +{ + state_t * const state = proc->get_state(); + if ((state->prv == PRV_M && !m) || + (!state->v && state->prv == PRV_S && !s) || + (!state->v && state->prv == PRV_U && !u) || + (state->v && state->prv == PRV_S && !vs) || + (state->v && state->prv == PRV_U && !vu)) { + return match_result_t(false); + } + + 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(true, TIMING_AFTER, action); + } + return match_result_t(false); +} + module_t::module_t(unsigned count) : triggers(count) { for (unsigned i = 0; i < count; i++) { triggers[i] = new disabled_trigger_t(); @@ -244,6 +298,7 @@ bool module_t::tdata1_write(processor_t * const proc, unsigned index, const reg_ if (!proc->get_state()->debug_mode) { assert(CSR_TDATA1_DMODE(xlen) == CSR_MCONTROL_DMODE(xlen)); assert(CSR_TDATA1_DMODE(xlen) == CSR_ITRIGGER_DMODE(xlen)); + assert(CSR_TDATA1_DMODE(xlen) == CSR_ETRIGGER_DMODE(xlen)); tdata1 = set_field(tdata1, CSR_TDATA1_DMODE(xlen), 0); } @@ -251,6 +306,7 @@ bool module_t::tdata1_write(processor_t * const proc, unsigned index, const reg_ switch (type) { case CSR_TDATA1_TYPE_MCONTROL: triggers[index] = new mcontrol_t(); break; case CSR_TDATA1_TYPE_ITRIGGER: triggers[index] = new itrigger_t(); break; + case CSR_TDATA1_TYPE_ETRIGGER: triggers[index] = new etrigger_t(); break; default: triggers[index] = new disabled_trigger_t(); break; } @@ -321,7 +377,10 @@ match_result_t module_t::detect_trap_match(const trap_t& t) reg_t module_t::tinfo_read(UNUSED const processor_t * const proc, unsigned UNUSED index) const noexcept { /* In spike, every trigger supports the same types. */ - return (1 << CSR_TDATA1_TYPE_MCONTROL) | (1 << CSR_TDATA1_TYPE_ITRIGGER) | (1 << CSR_TDATA1_TYPE_DISABLED); + return (1 << CSR_TDATA1_TYPE_MCONTROL) | + (1 << CSR_TDATA1_TYPE_ITRIGGER) | + (1 << CSR_TDATA1_TYPE_ETRIGGER) | + (1 << CSR_TDATA1_TYPE_DISABLED); } }; diff --git a/riscv/triggers.h b/riscv/triggers.h index e3dd5a63..497f86c5 100644 --- a/riscv/triggers.h +++ b/riscv/triggers.h @@ -114,6 +114,27 @@ private: action_t action; }; +class etrigger_t : public trigger_with_tdata2_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 match_result_t detect_trap_match(processor_t * const proc, const trap_t& t) override; + +private: + bool dmode; + bool hit; + bool vs; + bool vu; + bool m; + bool s; + bool u; + action_t action; +}; + class mcontrol_t : public trigger_with_tdata2_t { public: typedef enum