Browse Source

triggers: implement tdata3 CSR fields

pull/1160/head
YenHaoChen 3 years ago
parent
commit
a0fdc2b225
  1. 4
      riscv/csrs.cc
  2. 59
      riscv/triggers.cc
  3. 19
      riscv/triggers.h

4
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) :

59
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();

19
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(); }

Loading…
Cancel
Save