diff options
-rw-r--r-- | riscv/csrs.cc | 4 | ||||
-rw-r--r-- | riscv/triggers.cc | 59 | ||||
-rw-r--r-- | riscv/triggers.h | 19 |
3 files changed, 80 insertions, 2 deletions
diff --git a/riscv/csrs.cc b/riscv/csrs.cc index 7149c13..c41890b 100644 --- a/riscv/csrs.cc +++ b/riscv/csrs.cc @@ -1158,11 +1158,11 @@ tdata3_csr_t::tdata3_csr_t(processor_t* const proc, const reg_t addr): } reg_t tdata3_csr_t::read() const noexcept { - return 0; + return proc->TM.tdata3_read(state->tselect->read()); } bool tdata3_csr_t::unlogged_write(const reg_t val) noexcept { - return false; + return proc->TM.tdata3_write(state->tselect->read(), val); } tinfo_csr_t::tinfo_csr_t(processor_t* const proc, const reg_t addr) : diff --git a/riscv/triggers.cc b/riscv/triggers.cc index 81d059c..68baedd 100644 --- a/riscv/triggers.cc +++ b/riscv/triggers.cc @@ -3,6 +3,12 @@ #include "processor.h" #include "triggers.h" +#define CSR_TEXTRA_MHVALUE(XLEN) (XLEN == 32 ? CSR_TEXTRA32_MHVALUE : CSR_TEXTRA64_MHVALUE) +#define CSR_TEXTRA_MHSELECT(XLEN) (XLEN == 32 ? CSR_TEXTRA32_MHSELECT : CSR_TEXTRA64_MHSELECT) +#define CSR_TEXTRA_SBYTEMASK(XLEN) (XLEN == 32 ? CSR_TEXTRA32_SBYTEMASK : CSR_TEXTRA64_SBYTEMASK) +#define CSR_TEXTRA_SVALUE(XLEN) (XLEN == 32 ? CSR_TEXTRA32_SVALUE : CSR_TEXTRA64_SVALUE) +#define CSR_TEXTRA_SSELECT(XLEN) (XLEN == 32 ? CSR_TEXTRA32_SSELECT : CSR_TEXTRA64_SSELECT) + namespace triggers { reg_t trigger_t::tdata2_read(const processor_t UNUSED * const proc) const noexcept { @@ -17,6 +23,42 @@ action_t trigger_t::legalize_action(reg_t val) const noexcept { return (val > ACTION_MAXVAL || (val == ACTION_DEBUG_MODE && get_dmode() == 0)) ? ACTION_DEBUG_EXCEPTION : (action_t)val; } +unsigned trigger_t::legalize_mhselect(bool h_enabled) const noexcept { + // consider a mask with lowest bit 0 + unsigned convert[8] = { + (unsigned) 0 , // 0 + (unsigned) 0 , // 1 + (unsigned)(h_enabled ? 2 : 0), // 2 + (unsigned) 0 , // 3 + (unsigned) 0 , // 4 + (unsigned) 0 , // 5 + (unsigned)(h_enabled ? 6 : 0), // 6 + (unsigned) 0 // 7 + }; + assert(mhselect < 8); + return convert[mhselect]; +} + +reg_t trigger_t::tdata3_read(const processor_t * const proc) const noexcept { + auto xlen = proc->get_xlen(); + reg_t tdata3 = 0; + tdata3 = set_field(tdata3, CSR_TEXTRA_MHVALUE(xlen), mhvalue); + tdata3 = set_field(tdata3, CSR_TEXTRA_MHSELECT(xlen), legalize_mhselect(proc->extension_enabled('H'))); + tdata3 = set_field(tdata3, CSR_TEXTRA_SBYTEMASK(xlen), sbytemask); + tdata3 = set_field(tdata3, CSR_TEXTRA_SVALUE(xlen), svalue); + tdata3 = set_field(tdata3, CSR_TEXTRA_SSELECT(xlen), sselect); + return tdata3; +} + +void trigger_t::tdata3_write(processor_t * const proc, const reg_t val) noexcept { + auto xlen = proc->get_xlen(); + mhvalue = get_field(val, CSR_TEXTRA_MHVALUE(xlen)); + mhselect = get_field(val, CSR_TEXTRA_MHSELECT(xlen)); + sbytemask = get_field(val, CSR_TEXTRA_SBYTEMASK(xlen)); + svalue = proc->extension_enabled_const('S') ? get_field(val, CSR_TEXTRA_SVALUE(xlen)) : 0; + sselect = (sselect_t)((proc->extension_enabled_const('S') && get_field(val, CSR_TEXTRA_SSELECT(xlen)) == SSELECT_ASID) ? SSELECT_ASID : SSELECT_IGNORE); +} + reg_t disabled_trigger_t::tdata1_read(const processor_t * const proc) const noexcept { auto xlen = proc->get_xlen(); @@ -290,6 +332,7 @@ bool module_t::tdata1_write(unsigned index, const reg_t val) noexcept unsigned type = get_field(val, CSR_TDATA1_TYPE(xlen)); reg_t tdata1 = val; reg_t tdata2 = triggers[index]->tdata2_read(proc); + reg_t tdata3 = triggers[index]->tdata3_read(proc); // hardware must zero chain in writes that set dmode to 0 if the next trigger has dmode of 1 const bool allow_chain = !(index+1 < triggers.size() && triggers[index+1]->get_dmode() && !get_field(val, CSR_TDATA1_DMODE(xlen))); @@ -312,6 +355,7 @@ bool module_t::tdata1_write(unsigned index, const reg_t val) noexcept triggers[index]->tdata1_write(proc, tdata1, allow_chain); triggers[index]->tdata2_write(proc, tdata2); + triggers[index]->tdata3_write(proc, tdata3); proc->trigger_updated(triggers); return true; } @@ -331,6 +375,21 @@ bool module_t::tdata2_write(unsigned index, const reg_t val) noexcept return true; } +reg_t module_t::tdata3_read(unsigned index) const noexcept +{ + return triggers[index]->tdata3_read(proc); +} + +bool module_t::tdata3_write(unsigned index, const reg_t val) noexcept +{ + if (triggers[index]->get_dmode() && !proc->get_state()->debug_mode) { + return false; + } + triggers[index]->tdata3_write(proc, val); + proc->trigger_updated(triggers); + return true; +} + std::optional<match_result_t> module_t::detect_memory_access_match(operation_t operation, reg_t address, std::optional<reg_t> data) noexcept { state_t * const state = proc->get_state(); diff --git a/riscv/triggers.h b/riscv/triggers.h index fccd45b..bf164d3 100644 --- a/riscv/triggers.h +++ b/riscv/triggers.h @@ -29,6 +29,13 @@ typedef enum { TIMING_AFTER = 1 } timing_t; +typedef enum { + SSELECT_IGNORE = 0, + SSELECT_SCONTEXT = 1, + SSELECT_ASID = 2, + SSELECT_MAXVAL = 2 +} sselect_t; + struct match_result_t { match_result_t(const timing_t t=TIMING_BEFORE, const action_t a=ACTION_DEBUG_EXCEPTION) { timing = t; @@ -57,6 +64,8 @@ public: virtual void tdata1_write(processor_t * const proc, const reg_t val, const bool allow_chain) noexcept = 0; reg_t tdata2_read(const processor_t * const proc) const noexcept; void tdata2_write(processor_t * const proc, const reg_t val) noexcept; + reg_t tdata3_read(const processor_t * const proc) const noexcept; + void tdata3_write(processor_t * const proc, const reg_t val) noexcept; virtual bool get_dmode() const = 0; virtual bool get_chain() const { return false; } @@ -72,6 +81,14 @@ public: protected: action_t legalize_action(reg_t val) const noexcept; reg_t tdata2; + +private: + unsigned legalize_mhselect(bool h_enabled) const noexcept; + sselect_t sselect; + unsigned svalue; + unsigned sbytemask; + unsigned mhselect; + unsigned mhvalue; }; class disabled_trigger_t : public trigger_t { @@ -180,6 +197,8 @@ public: bool tdata1_write(unsigned index, const reg_t val) noexcept; reg_t tdata2_read(unsigned index) const noexcept; bool tdata2_write(unsigned index, const reg_t val) noexcept; + reg_t tdata3_read(unsigned index) const noexcept; + bool tdata3_write(unsigned index, const reg_t val) noexcept; reg_t tinfo_read(unsigned index) const noexcept; unsigned count() const { return triggers.size(); } |