@@ -55,12 +55,54 @@ 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);
63
- return (prv < PRV_M || m_enabled) && mode_match (prv, v) && textra_match (proc);
69
+
70
+ if (!mode_match (prv, v))
71
+ return false ;
72
+
73
+ if (!textra_match (proc))
74
+ return false ;
75
+
76
+ if (get_action () == ACTION_DEBUG_EXCEPTION) {
77
+ if (proc->extension_enabled (' S' )) {
78
+ // The hardware prevents triggers with action=0 from matching or firing
79
+ // while in M-mode and while MIE in mstatus is 0. If medeleg [3]=1 then it
80
+ // prevents triggers with action=0 from matching or firing while in S-mode
81
+ // and while SIE in sstatus is 0. If medeleg [3]=1 and hedeleg [3]=1 then
82
+ // it prevents triggers with action=0 from matching or firing while in
83
+ // VS-mode and while SIE in vstatus is 0.
84
+
85
+ const bool mstatus_mie = state->mstatus ->read () & MSTATUS_MIE;
86
+ if (prv == PRV_M && !mstatus_mie)
87
+ return false ;
88
+
89
+ const bool sstatus_sie = state->sstatus ->read () & MSTATUS_SIE;
90
+ const bool medeleg_breakpoint = (state->medeleg ->read () >> CAUSE_BREAKPOINT) & 1 ;
91
+ if (prv == PRV_S && !v && medeleg_breakpoint && !sstatus_sie)
92
+ return false ;
93
+
94
+ const bool vsstatus_sie = state->vsstatus ->read () & MSTATUS_SIE;
95
+ const bool hedeleg_breakpoint = (state->hedeleg ->read () >> CAUSE_BREAKPOINT) & 1 ;
96
+ if (prv == PRV_S && v && medeleg_breakpoint && hedeleg_breakpoint && !vsstatus_sie)
97
+ return false ;
98
+ } else {
99
+ // mte and mpte in tcontrol is implemented. medeleg [3] is hard-wired to 0.
100
+ if (prv == PRV_M && !(tcontrol_value (state) & CSR_TCONTROL_MTE))
101
+ return false ;
102
+ }
103
+ }
104
+
105
+ return true ;
64
106
}
65
107
66
108
bool trigger_t::mode_match (reg_t prv, bool v) const noexcept
@@ -110,21 +152,6 @@ bool trigger_t::textra_match(processor_t * const proc) const noexcept
110
152
return true ;
111
153
}
112
154
113
- bool trigger_t::allow_action (const state_t * const state) const
114
- {
115
- 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
- }
125
- return true ;
126
- }
127
-
128
155
reg_t disabled_trigger_t::tdata1_read (const processor_t * const proc) const noexcept
129
156
{
130
157
auto xlen = proc->get_xlen ();
@@ -235,7 +262,7 @@ std::optional<match_result_t> mcontrol_common_t::detect_memory_access_match(proc
235
262
value &= 0xffffffff ;
236
263
}
237
264
238
- if (simple_match (xlen, value) && allow_action (proc-> get_state ()) ) {
265
+ if (simple_match (xlen, value)) {
239
266
/* This is OK because this function is only called if the trigger was not
240
267
* inhibited by the previous trigger in the chain. */
241
268
set_hit (timing ? HIT_IMMEDIATELY_AFTER : HIT_BEFORE);
@@ -324,7 +351,7 @@ void mcontrol6_t::tdata1_write(processor_t * const proc, const reg_t val, const
324
351
325
352
std::optional<match_result_t > icount_t::detect_icount_fire (processor_t * const proc) noexcept
326
353
{
327
- if (!common_match (proc) || ! allow_action (proc-> get_state ()) )
354
+ if (!common_match (proc))
328
355
return std::nullopt;
329
356
330
357
std::optional<match_result_t > ret = std::nullopt;
@@ -339,7 +366,7 @@ std::optional<match_result_t> icount_t::detect_icount_fire(processor_t * const p
339
366
340
367
void icount_t::detect_icount_decrement (processor_t * const proc) noexcept
341
368
{
342
- if (!common_match (proc) || ! allow_action (proc-> get_state ()) )
369
+ if (!common_match (proc))
343
370
return ;
344
371
345
372
if (count >= 1 ) {
@@ -431,7 +458,7 @@ std::optional<match_result_t> trap_common_t::detect_trap_match(processor_t * con
431
458
bool interrupt = (t.cause () & ((reg_t )1 << (xlen - 1 ))) != 0 ;
432
459
reg_t bit = t.cause () & ~((reg_t )1 << (xlen - 1 ));
433
460
assert (bit < xlen);
434
- if (simple_match (interrupt, bit) && allow_action (proc-> get_state ()) ) {
461
+ if (simple_match (interrupt, bit)) {
435
462
hit = true ;
436
463
return match_result_t (TIMING_AFTER, action);
437
464
}
0 commit comments