@@ -55,11 +55,18 @@ void trigger_t::tdata3_write(processor_t * const proc, const reg_t val) noexcept
55
55
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);
56
56
}
57
57
58
+ static reg_t tcontrol_value (const state_t * state) {
59
+ if (state->tcontrol )
60
+ return state->tcontrol ->read ();
61
+ else
62
+ return 0 ;
63
+ }
64
+
58
65
bool trigger_t::common_match (processor_t * const proc, bool use_prev_prv) const noexcept {
59
66
auto state = proc->get_state ();
60
67
auto prv = use_prev_prv ? state->prev_prv : state->prv ;
61
68
auto v = use_prev_prv ? state->prev_v : state->v ;
62
- auto m_enabled = get_action () != 0 || (state-> tcontrol -> read ( ) & CSR_TCONTROL_MTE);
69
+ auto m_enabled = get_action () != 0 || (tcontrol_value (state ) & CSR_TCONTROL_MTE);
63
70
return (prv < PRV_M || m_enabled) && mode_match (prv, v) && textra_match (proc);
64
71
}
65
72
@@ -110,17 +117,29 @@ bool trigger_t::textra_match(processor_t * const proc) const noexcept
110
117
return true ;
111
118
}
112
119
113
- bool trigger_t::allow_action (const state_t * const state ) const
120
+ bool trigger_t::allow_action (processor_t * const proc ) const
114
121
{
122
+ const state_t *state = proc->get_state ();
115
123
if (get_action () == ACTION_DEBUG_EXCEPTION) {
116
- const bool mstatus_mie = state->mstatus ->read () & MSTATUS_MIE;
117
- const bool sstatus_sie = state->sstatus ->read () & MSTATUS_SIE;
118
- const bool vsstatus_sie = state->vsstatus ->read () & MSTATUS_SIE;
119
- const bool medeleg_breakpoint = (state->medeleg ->read () >> CAUSE_BREAKPOINT) & 1 ;
120
- const bool hedeleg_breakpoint = (state->hedeleg ->read () >> CAUSE_BREAKPOINT) & 1 ;
121
- return (state->prv != PRV_M || mstatus_mie) &&
122
- (state->prv != PRV_S || state->v || !medeleg_breakpoint || sstatus_sie) &&
123
- (state->prv != PRV_S || !state->v || !medeleg_breakpoint || !hedeleg_breakpoint || vsstatus_sie);
124
+ if (proc->extension_enabled (' S' )) {
125
+ // The hardware prevents triggers with action=0 from matching or firing
126
+ // while in M-mode and while MIE in mstatus is 0. If medeleg [3]=1 then it
127
+ // prevents triggers with action=0 from matching or firing while in S-mode
128
+ // and while SIE in sstatus is 0. If medeleg [3]=1 and hedeleg [3]=1 then
129
+ // it prevents triggers with action=0 from matching or firing while in
130
+ // VS-mode and while SIE in vstatus is 0.
131
+ const bool mstatus_mie = state->mstatus ->read () & MSTATUS_MIE;
132
+ const bool sstatus_sie = state->sstatus ->read () & MSTATUS_SIE;
133
+ const bool vsstatus_sie = state->vsstatus ->read () & MSTATUS_SIE;
134
+ const bool medeleg_breakpoint = (state->medeleg ->read () >> CAUSE_BREAKPOINT) & 1 ;
135
+ const bool hedeleg_breakpoint = (state->hedeleg ->read () >> CAUSE_BREAKPOINT) & 1 ;
136
+ return (state->prv != PRV_M || mstatus_mie) &&
137
+ (state->prv != PRV_S || state->v || !medeleg_breakpoint || sstatus_sie) &&
138
+ (state->prv != PRV_S || !state->v || !medeleg_breakpoint || !hedeleg_breakpoint || vsstatus_sie);
139
+ } else {
140
+ // mte and mpte in tcontrol is implemented. medeleg [3] is hard-wired to 0.
141
+ return (state->prv != PRV_M) || (tcontrol_value (state) & CSR_TCONTROL_MTE);
142
+ }
124
143
}
125
144
return true ;
126
145
}
@@ -235,7 +254,7 @@ std::optional<match_result_t> mcontrol_common_t::detect_memory_access_match(proc
235
254
value &= 0xffffffff ;
236
255
}
237
256
238
- if (simple_match (xlen, value) && allow_action (proc-> get_state () )) {
257
+ if (simple_match (xlen, value) && allow_action (proc)) {
239
258
/* This is OK because this function is only called if the trigger was not
240
259
* inhibited by the previous trigger in the chain. */
241
260
set_hit (timing ? HIT_IMMEDIATELY_AFTER : HIT_BEFORE);
@@ -324,7 +343,7 @@ void mcontrol6_t::tdata1_write(processor_t * const proc, const reg_t val, const
324
343
325
344
std::optional<match_result_t > icount_t::detect_icount_fire (processor_t * const proc) noexcept
326
345
{
327
- if (!common_match (proc) || !allow_action (proc-> get_state () ))
346
+ if (!common_match (proc) || !allow_action (proc))
328
347
return std::nullopt;
329
348
330
349
std::optional<match_result_t > ret = std::nullopt;
@@ -339,7 +358,7 @@ std::optional<match_result_t> icount_t::detect_icount_fire(processor_t * const p
339
358
340
359
void icount_t::detect_icount_decrement (processor_t * const proc) noexcept
341
360
{
342
- if (!common_match (proc) || !allow_action (proc-> get_state () ))
361
+ if (!common_match (proc) || !allow_action (proc))
343
362
return ;
344
363
345
364
if (count >= 1 ) {
@@ -431,7 +450,7 @@ std::optional<match_result_t> trap_common_t::detect_trap_match(processor_t * con
431
450
bool interrupt = (t.cause () & ((reg_t )1 << (xlen - 1 ))) != 0 ;
432
451
reg_t bit = t.cause () & ~((reg_t )1 << (xlen - 1 ));
433
452
assert (bit < xlen);
434
- if (simple_match (interrupt, bit) && allow_action (proc-> get_state () )) {
453
+ if (simple_match (interrupt, bit) && allow_action (proc)) {
435
454
hit = true ;
436
455
return match_result_t (TIMING_AFTER, action);
437
456
}
0 commit comments