-
Notifications
You must be signed in to change notification settings - Fork 49
/
cv32e40x_debug_triggers.sv
522 lines (447 loc) · 24.4 KB
/
cv32e40x_debug_triggers.sv
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
// Copyright 2022 Silicon Labs, Inc.
//
// This file, and derivatives thereof are licensed under the
// Solderpad License, Version 2.0 (the "License").
//
// Use of this file means you agree to the terms and conditions
// of the license and are in full compliance with the License.
//
// You may obtain a copy of the License at:
//
// https://solderpad.org/licenses/SHL-2.0/
//
// Unless required by applicable law or agreed to in writing, software
// and hardware implementations thereof distributed under the License
// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS
// OF ANY KIND, EITHER EXPRESSED OR IMPLIED.
//
// See the License for the specific language governing permissions and
// limitations under the License.
////////////////////////////////////////////////////////////////////////////////
// Engineer: Oystein Knauserud - oystein.knauserud@silabs.com //
// //
// Design Name: Debug triggers //
// Project Name: CV32E40X //
// Language: SystemVerilog //
// //
// Description: Module containing 0-4 triggers for debug //
// //
////////////////////////////////////////////////////////////////////////////////
module cv32e40x_debug_triggers
import cv32e40x_pkg::*;
#(
parameter int DBG_NUM_TRIGGERS = 1,
parameter a_ext_e A_EXT = A_NONE
)
(
input logic clk,
input logic rst_n,
// CSR inputs write inputs
input logic [31:0] csr_wdata_i,
input logic tselect_we_i,
input logic tdata1_we_i,
input logic tdata2_we_i,
input logic tinfo_we_i,
// CSR read data outputs
output logic [31:0] tselect_rdata_o,
output logic [31:0] tdata1_rdata_o,
output logic [31:0] tdata2_rdata_o,
output logic [31:0] tinfo_rdata_o,
// IF stage inputs
input logic [31:0] pc_if_i,
input logic ptr_in_if_i,
input privlvl_t priv_lvl_if_i,
// EX stage / LSU inputs
input logic lsu_valid_ex_i,
input logic [31:0] lsu_addr_ex_i,
input logic lsu_we_ex_i,
input logic [3:0] lsu_be_ex_i,
input privlvl_t priv_lvl_ex_i,
input lsu_atomic_e lsu_atomic_ex_i,
// WB stage inputs
input privlvl_t priv_lvl_wb_i,
// Controller inputs
input ctrl_fsm_t ctrl_fsm_i,
// Trigger match outputs
output logic [31:0] trigger_match_if_o, // Instruction address match
output logic [31:0] trigger_match_ex_o, // Load/Store address match
output logic etrigger_wb_o // Exception trigger match
);
// CSR write data
logic [31:0] tselect_n;
logic [31:0] tdata2_n;
logic [31:0] tinfo_n;
// RVFI only signals
logic [31:0] tdata1_n_r;
logic [31:0] tdata2_n_r;
logic tdata1_we_r;
logic tdata2_we_r;
// Signal for or'ing unused signals for easier lint
logic unused_signals;
generate
if (DBG_NUM_TRIGGERS > 0) begin : gen_triggers
// Internal CSR write enables
logic [DBG_NUM_TRIGGERS-1 : 0] tdata1_we_int;
logic [DBG_NUM_TRIGGERS-1 : 0] tdata1_we_hit;
logic [DBG_NUM_TRIGGERS-1 : 0] tdata2_we_int;
// Next-values for tdata1
logic [31:0] tdata1_n[DBG_NUM_TRIGGERS];
// CSR instance outputs
logic [31:0] tdata1_q[DBG_NUM_TRIGGERS];
logic [31:0] tdata2_q[DBG_NUM_TRIGGERS];
logic [31:0] tselect_q;
// CSR read data, possibly WARL resolved
logic [31:0] tdata1_rdata[DBG_NUM_TRIGGERS];
logic [31:0] tdata2_rdata[DBG_NUM_TRIGGERS];
// IF, EX and WB stages trigger match
logic [DBG_NUM_TRIGGERS-1 : 0] trigger_match_if;
logic [DBG_NUM_TRIGGERS-1 : 0] trigger_match_ex;
logic [DBG_NUM_TRIGGERS-1 : 0] etrigger_wb;
// Instruction address match
logic [DBG_NUM_TRIGGERS-1 : 0] if_addr_match;
// LSU address match signals
logic [DBG_NUM_TRIGGERS-1 : 0] lsu_addr_match_en;
logic [DBG_NUM_TRIGGERS-1 : 0] lsu_addr_match;
logic [3:0] lsu_byte_addr_match[DBG_NUM_TRIGGERS];
// Enable matching based on privilege level per trigger
logic [DBG_NUM_TRIGGERS-1 : 0] priv_lvl_match_en_if;
logic [DBG_NUM_TRIGGERS-1 : 0] priv_lvl_match_en_ex;
logic [DBG_NUM_TRIGGERS-1 : 0] priv_lvl_match_en_wb;
logic [1:0] lsu_addr_low_lsb; // Lower two bits of the lowest accessed address
logic [1:0] lsu_addr_high_lsb; // Lower two bits of the highest accessed address
logic [31:0] lsu_addr_low; // The lowest accessed address of an LSU transaction
logic [31:0] lsu_addr_high; // The highest accessed address of an LSU transaction
// Exception trigger code match
logic [31:0] exception_match[DBG_NUM_TRIGGERS];
// Resolve hit1+hit0 of mcontrol6
logic [1:0] mcontrol6_hit_resolved[DBG_NUM_TRIGGERS];
// Write data
// tdata1 has one _n value per implemented trigger to enable updating all hit-fields of
// mcontrol6 at the same time.
for (genvar idx=0; idx<DBG_NUM_TRIGGERS; idx++) begin : tdata1_wdata
always_comb begin
tdata1_n[idx] = tdata1_rdata[idx];
tdata1_we_hit[idx] = 1'b0;
mcontrol6_hit_resolved[idx] = mcontrol6_hit_resolve({tdata1_rdata[idx][MCONTROL_6_HIT1], tdata1_rdata[idx][MCONTROL_6_HIT0]},
{csr_wdata_i[MCONTROL_6_HIT1], csr_wdata_i[MCONTROL_6_HIT0]});
if (tdata1_we_i && (tselect_rdata_o == idx)) begin
if (csr_wdata_i[TDATA1_TTYPE_HIGH:TDATA1_TTYPE_LOW] == TTYPE_MCONTROL) begin
// Mcontrol supports any value in tdata2, no need to check tdata2 before writing tdata1
tdata1_n[idx] = {
TTYPE_MCONTROL, // type : address/data match
1'b1, // dmode : access from D mode only
6'b000000, // maskmax : hardwired to zero
1'b0, // hit : hardwired to zero
1'b0, // select : hardwired to zero, only address matching
1'b0, // timing : hardwired to zero, only 'before' timing
2'b00, // sizelo : hardwired to zero, match any size
4'b0001, // action : enter debug on match
1'b0, // chain : hardwired to zero
mcontrol2_6_match_resolve(csr_wdata_i[MCONTROL2_6_MATCH_HIGH:MCONTROL2_6_MATCH_LOW]), // match, WARL(0,2,3) 10:7
csr_wdata_i[6], // m : match in machine mode
1'b0, // : hardwired to zero
1'b0, // s : hardwired to zer0
mcontrol2_6_u_resolve(csr_wdata_i[MCONTROL2_6_U]), // zero, U 3
csr_wdata_i[2], // EXECUTE 2
csr_wdata_i[1], // STORE 1
csr_wdata_i[0] // LOAD 0
};
end else if (csr_wdata_i[TDATA1_TTYPE_HIGH:TDATA1_TTYPE_LOW] == TTYPE_MCONTROL6) begin
// Mcontrol6 supports any value in tdata2, no need to check tdata2 before writing tdata1
tdata1_n[idx] = {
TTYPE_MCONTROL6, // type : address/data match
1'b1, // dmode : access from D mode only
mcontrol6_uncertain_resolve(csr_wdata_i[MCONTROL_6_UNCERTAIN]), // uncertain 26
mcontrol6_hit_resolved[idx][1], // hit1: 25
2'b00, // zero, vs, vu
mcontrol6_hit_resolved[idx][0], // hit0: 22
1'b0, // zero, select 21
2'b00, // zero, 20:19
3'b000, // zero, size (match any size) 18:16
4'b0001, // action, WARL(1), enter debug 15:12
1'b0, // zero, chain 11
mcontrol2_6_match_resolve(csr_wdata_i[MCONTROL2_6_MATCH_HIGH:MCONTROL2_6_MATCH_LOW]), // match, WARL(0,2,3) 10:7
csr_wdata_i[6], // M 6
mcontrol6_uncertainen_resolve(csr_wdata_i[MCONTROL_6_UNCERTAINEN]), // uncertainen 5
1'b0, // zero, S 4
mcontrol2_6_u_resolve(csr_wdata_i[MCONTROL2_6_U]), // zero, U 3
csr_wdata_i[2], // EXECUTE 2
csr_wdata_i[1], // STORE 1
csr_wdata_i[0] // LOAD 0
};
end else if (csr_wdata_i[TDATA1_TTYPE_HIGH:TDATA1_TTYPE_LOW] == TTYPE_ETRIGGER) begin
// Etrigger can only support a subset of possible values in tdata2, only update tdata1 if
// tdata2 contains a legal value for etrigger.
// Detect if any cleared bits in ETRIGGER_TDATA2_MASK are set in tdata2
if (|(tdata2_rdata_o & (~ETRIGGER_TDATA2_MASK))) begin
// Unsupported exception codes enabled, default to disabled trigger.
tdata1_n[idx] = {TTYPE_DISABLED, 1'b1, {27{1'b0}}};
end else begin
tdata1_n[idx] = {
TTYPE_ETRIGGER, // type : exception trigger
1'b1, // dmode : access from D mode only 27
1'b0, // hit : WARL(0) 26
13'h0, // zero : tied to zero 25:13
1'b0, // vs : WARL(0) 12
1'b0, // vu : WARL(0) 11
1'b0, // zero : tied to zero 10
csr_wdata_i[9], // m : Match in machine mode 9
1'b0, // zero : tied to zero 8
1'b0, // s : WARL(0) 7
etrigger_u_resolve(csr_wdata_i[ETRIGGER_U]), // u : Match in user mode 6
6'b000001 // action : WARL(1), enter debug on match
};
end
end else if (csr_wdata_i[TDATA1_TTYPE_HIGH:TDATA1_TTYPE_LOW] == TTYPE_DISABLED) begin
// All tdata2 values are legal for a disabled trigger, no WARL on tdata1.
tdata1_n[idx] = {TTYPE_DISABLED, 1'b1, {27{1'b0}}};
end else begin
// No legal trigger type, set disabled trigger type 0xF
tdata1_n[idx] = {TTYPE_DISABLED, 1'b1, {27{1'b0}}};
end
end // tdata1_we_i
// SW writes and writes from controller cannot happen at the same time.
// Update bits {hit1, hit0} (WARL 0x0, 0x1)
if (ctrl_fsm_i.debug_trigger_hit_update) begin
if (tdata1_rdata[idx][TDATA1_TTYPE_HIGH:TDATA1_TTYPE_LOW] == TTYPE_MCONTROL6) begin
if (ctrl_fsm_i.debug_trigger_hit[idx]) begin
tdata1_n[idx][MCONTROL_6_HIT1] = 1'b0;
tdata1_n[idx][MCONTROL_6_HIT0] = 1'b1;
tdata1_we_hit[idx] = 1'b1;
end
end
end
end
end //for
// Write data for tdata2 and tselect
always_comb begin
// Tselect is WARL (0 -> DBG_NUM_TRIGGERS-1)
tselect_n = (csr_wdata_i < DBG_NUM_TRIGGERS) ? csr_wdata_i : tselect_rdata_o;
tdata2_n = tdata2_rdata_o;
// tdata2
if (tdata2_we_i) begin
if ((tdata1_rdata_o[TDATA1_TTYPE_HIGH:TDATA1_TTYPE_LOW] == TTYPE_DISABLED) ||
(tdata1_rdata_o[TDATA1_TTYPE_HIGH:TDATA1_TTYPE_LOW] == TTYPE_MCONTROL) ||
(tdata1_rdata_o[TDATA1_TTYPE_HIGH:TDATA1_TTYPE_LOW] == TTYPE_MCONTROL6)) begin
// Disabled trigger, mcontrol and mcontrol6 can have any value in tdata2
tdata2_n = csr_wdata_i;
end else begin
// Exception trigger, only allow implemented exception codes to be used
tdata2_n = csr_wdata_i & ETRIGGER_TDATA2_MASK;
end
end // tdata2_we_i
tinfo_n = tinfo_rdata_o; // Read only
end
// Calculate highest and lowest value of address[1:0] based on lsu_be_ex_i
always_comb begin
lsu_addr_high_lsb = 2'b00;
lsu_addr_low_lsb = 2'b00;
// Find highest accessed byte
for (int b=0; b<4; b++) begin : gen_high_byte_checks
if (lsu_be_ex_i[b]) begin
lsu_addr_high_lsb = 2'(b);
end // if
end // for
// Find lowest accessed byte
for (int b=3; b>=0; b--) begin : gen_low_byte_checks
if (lsu_be_ex_i[b]) begin
lsu_addr_low_lsb = 2'(b);
end // if
end // for
end // always
assign lsu_addr_high = {lsu_addr_ex_i[31:2], lsu_addr_high_lsb};
assign lsu_addr_low = {lsu_addr_ex_i[31:2], lsu_addr_low_lsb};
// Generate DBG_NUM_TRIGGERS instances of tdata1, tdata2 and match checks
for (genvar idx=0; idx<DBG_NUM_TRIGGERS; idx++) begin : tmatch_csr
////////////////////////////////////
// Instruction address match (IF)
////////////////////////////////////
// With timing=0 we enter debug before executing the instruction at the match address. We use the IF stage PC
// for comparison, and any trigger match will cause the instruction to act as a NOP with no side effects until it
// reaches WB where debug mode is entered.
//
// Trigger match is disabled while in debug mode.
//
// Trigger CSRs can only be written from debug mode, writes from any other privilege level are ignored.
// Thus we do not have an issue where a write to the tdata2 CSR immediately before the matched instruction
// could be missed since we must write in debug mode, then dret to machine mode (kills pipeline) before
// returning to dpc.
// No instruction address match on any pointer type (CLIC and Zc tablejumps).
// Check for address match using tdata2.match for checking rule
assign if_addr_match[idx] = (tdata1_rdata[idx][MCONTROL2_6_MATCH_HIGH:MCONTROL2_6_MATCH_LOW] == 4'h0) ? (pc_if_i == tdata2_rdata[idx]) :
(tdata1_rdata[idx][MCONTROL2_6_MATCH_HIGH:MCONTROL2_6_MATCH_LOW] == 4'h2) ? (pc_if_i >= tdata2_rdata[idx]) : (pc_if_i < tdata2_rdata[idx]);
// Check if matching is enabled for the current privilege level from IF
assign priv_lvl_match_en_if[idx] = (tdata1_rdata[idx][MCONTROL2_6_M] && (priv_lvl_if_i == PRIV_LVL_M)) ||
(tdata1_rdata[idx][MCONTROL2_6_U] && (priv_lvl_if_i == PRIV_LVL_U));
// Check for trigger match from IF
assign trigger_match_if[idx] = ((tdata1_rdata[idx][TDATA1_TTYPE_HIGH:TDATA1_TTYPE_LOW] == TTYPE_MCONTROL) ||
(tdata1_rdata[idx][TDATA1_TTYPE_HIGH:TDATA1_TTYPE_LOW] == TTYPE_MCONTROL6)) &&
tdata1_rdata[idx][MCONTROL2_6_EXECUTE] && priv_lvl_match_en_if[idx] && !ctrl_fsm_i.debug_mode && !ptr_in_if_i &&
if_addr_match[idx];
///////////////////////////////////////
// Load/Store address match (EX)
///////////////////////////////////////
// todo: LSU address matching must be revisited once the atomics are implemented
// As for instruction address match, the load/store address match happens before the a bus transaction is visible on the OBI bus.
// For split misaligned transfers, each transfer is checked separately. This means that half a store may be visible externally even if
// the second part matches tdata2 and debug is entered. For loads the RF write will not happen until the last part finished anyway, so no state update
// will happen regardless of which transaction matches.
// The BE of the transaction is used to determine which bytes of a word is being accessed.
// Check if any accessed byte matches the lower two bits of tdata2
always_comb begin
for (int b=0; b<4; b++) begin
if (lsu_be_ex_i[b] && (2'(b) == tdata2_rdata[idx][1:0])) begin
lsu_byte_addr_match[idx][b] = 1'b1;
end else begin
lsu_byte_addr_match[idx][b] = 1'b0;
end
end
end
// Check address matches for (==), (>=) and (<)
// For ==, check that we match the 32-bit aligned word and that any of the accessed bytes matches tdata2[1:0]
// For >=, check that the highest accessed address is greater than or equal to tdata2. If this fails, no bytes within the access are >= tdata2
// For <, check that the lowest accessed address is less than tdata2. If this fails, no bytes within the access are < tdata2.
assign lsu_addr_match[idx] = (tdata1_rdata[idx][MCONTROL2_6_MATCH_HIGH:MCONTROL2_6_MATCH_LOW] == 4'h0) ? ((lsu_addr_ex_i[31:2] == tdata2_rdata[idx][31:2]) && (|lsu_byte_addr_match[idx])) :
(tdata1_rdata[idx][MCONTROL2_6_MATCH_HIGH:MCONTROL2_6_MATCH_LOW] == 4'h2) ? (lsu_addr_high >= tdata2_rdata[idx]) :
(lsu_addr_low < tdata2_rdata[idx]) ;
// Check if matching is enabled for the current privilege level from EX
assign priv_lvl_match_en_ex[idx] = (tdata1_rdata[idx][MCONTROL2_6_M] && (priv_lvl_ex_i == PRIV_LVL_M)) ||
(tdata1_rdata[idx][MCONTROL2_6_U] && (priv_lvl_ex_i == PRIV_LVL_U));
// Enable LSU address matching
// AMO transactions have lsu_we_ex_i == 1'b1, but also perform a read. Thus AMOs will also match loads regardless of the lsu_we_we bit.
assign lsu_addr_match_en[idx] = lsu_valid_ex_i && ((tdata1_rdata[idx][MCONTROL2_6_LOAD] && (!lsu_we_ex_i || (lsu_atomic_ex_i == AT_AMO))) || (tdata1_rdata[idx][MCONTROL2_6_STORE] && lsu_we_ex_i));
// Signal trigger match for LSU address
assign trigger_match_ex[idx] = ((tdata1_rdata[idx][TDATA1_TTYPE_HIGH:TDATA1_TTYPE_LOW] == TTYPE_MCONTROL) ||
(tdata1_rdata[idx][TDATA1_TTYPE_HIGH:TDATA1_TTYPE_LOW] == TTYPE_MCONTROL6)) &&
priv_lvl_match_en_ex[idx] && lsu_addr_match_en[idx] && lsu_addr_match[idx] && !ctrl_fsm_i.debug_mode;
/////////////////////////////
// Exception trigger
/////////////////////////////
always_comb begin
exception_match[idx] = 32'd0;
for (int i=0; i<32; i++) begin
exception_match[idx][i] = tdata2_rdata[idx][i] && ctrl_fsm_i.exception_in_wb && (ctrl_fsm_i.exception_cause_wb == 11'(i));
end
end
assign priv_lvl_match_en_wb[idx] = (tdata1_rdata[idx][ETRIGGER_M] && (priv_lvl_wb_i == PRIV_LVL_M)) ||
(tdata1_rdata[idx][ETRIGGER_U] && (priv_lvl_wb_i == PRIV_LVL_U));
assign etrigger_wb[idx] = (tdata1_rdata[idx][TDATA1_TTYPE_HIGH:TDATA1_TTYPE_LOW] == TTYPE_ETRIGGER) && priv_lvl_match_en_wb[idx] &&
(|exception_match[idx]) && !ctrl_fsm_i.debug_mode;
cv32e40x_csr
#(
.WIDTH (32),
.RESETVALUE (TDATA1_RST_VAL)
)
tdata1_csr_i
(
.clk ( clk ),
.rst_n ( rst_n ),
.wr_data_i ( tdata1_n[idx] ),
.wr_en_i ( tdata1_we_int[idx] ),
.rd_data_o ( tdata1_q[idx] )
);
cv32e40x_csr
#(
.WIDTH (32),
.RESETVALUE (32'd0)
)
tdata2_csr_i
(
.clk ( clk ),
.rst_n ( rst_n ),
.wr_data_i ( tdata2_n ),
.wr_en_i ( tdata2_we_int[idx] ),
.rd_data_o ( tdata2_q[idx] )
);
// Set write enables
assign tdata1_we_int[idx] = (tdata1_we_i && (tselect_rdata_o == idx)) || tdata1_we_hit[idx];
assign tdata2_we_int[idx] = tdata2_we_i && (tselect_rdata_o == idx);
// Assign read data
assign tdata1_rdata[idx] = tdata1_q[idx];
assign tdata2_rdata[idx] = tdata2_q[idx];
end // for
// CSR instance for tselect
cv32e40x_csr
#(
.WIDTH (32),
.RESETVALUE (32'd0)
)
tselect_csr_i
(
.clk ( clk ),
.rst_n ( rst_n ),
.wr_data_i ( tselect_n ),
.wr_en_i ( tselect_we_i ),
.rd_data_o ( tselect_q )
);
// Assign CSR read data outputs
always_comb begin
tdata1_rdata_o = tdata1_rdata[0];
tdata2_rdata_o = tdata2_rdata[0];
// Iterate through triggers and set tdata1/tdata2 rdata for the currently selected trigger
for (int i=0; i<DBG_NUM_TRIGGERS; i++) begin
if(tselect_rdata_o == i) begin
tdata1_rdata_o = tdata1_rdata[i];
tdata2_rdata_o = tdata2_rdata[i];
end
end
end
// RVFI only
// assign _we_r and wdata_n_r values
always_comb begin
tdata1_we_r = tdata1_we_i || tselect_we_i;
tdata2_we_r = tdata2_we_i || tselect_we_i;
tdata1_n_r = tdata1_n[0];
tdata2_n_r = tdata2_n;
// Iterate over all triggers and pick tdata1_n_r and tdata1_we_r for the
// currently selected trigger.
for (int i=0; i<DBG_NUM_TRIGGERS; i++) begin
if(tselect_rdata_o == i) begin
tdata1_n_r = tdata1_n[i];
// Using tdata1_we_int to include HW writes to mcontrol6
tdata1_we_r = tdata1_we_int[i] || tselect_we_i;
end
end
// Make sure to update SW visible trigger CSRs on RVFI
// when tselect is written
if (tselect_we_i) begin
for (int i=0; i<DBG_NUM_TRIGGERS; i++) begin
if(tselect_n == i) begin
tdata1_n_r = tdata1_rdata[i];
tdata2_n_r = tdata2_rdata[i];
end
end
end
end
assign tselect_rdata_o = tselect_q;
assign tinfo_rdata_o = 32'h01008064; // Supported types 0x2, 0x5, 0x6 and 0xF, tinfo.version=1
// Set trigger match for IF
assign trigger_match_if_o = {{(32-DBG_NUM_TRIGGERS){1'b0}}, trigger_match_if};
// Set trigger match for EX
assign trigger_match_ex_o = {{(32-DBG_NUM_TRIGGERS){1'b0}}, trigger_match_ex};
// Set trigger match for WB
assign etrigger_wb_o = |etrigger_wb;
assign unused_signals = tinfo_we_i | (|tinfo_n) | (|tdata1_n_r) | (|tdata2_n_r) | tdata1_we_r | tdata2_we_r;
end else begin : gen_no_triggers
// Tie off outputs
assign tdata1_rdata_o = '0;
assign tdata2_rdata_o = '0;
assign tselect_rdata_o = '0;
assign tinfo_rdata_o = '0;
assign trigger_match_if_o = '0;
assign trigger_match_ex_o = '0;
assign etrigger_wb_o = '0;
assign tdata1_n = '0;
assign tdata2_n = '0;
assign tselect_n = '0;
assign tinfo_n = '0;
assign tdata1_n_r = '0;
assign tdata2_n_r = '0;
assign tdata1_we_r = 1'b0;
assign tdata2_we_r = 1'b0;
assign unused_signals = (|tdata1_n) | (|tdata2_n) | (|tselect_n) | (|tinfo_n) |
(|csr_wdata_i) | tdata1_we_i | tdata2_we_i | tselect_we_i | tinfo_we_i |
(|tdata1_n_r) | (|tdata2_n_r) | tdata1_we_r | tdata2_we_r;
end
endgenerate
endmodule