../src/lowrisc_ip_alert_handler_component_0.1/rtl/alert_handler.sv Cov: 100%
1: // Copyright lowRISC contributors.
2: // Licensed under the Apache License, Version 2.0, see LICENSE for details.
3: // SPDX-License-Identifier: Apache-2.0
4: //
5: // Alert handler top.
6: //
7: // Note that the alert_pkg, the regfile and alert_handler_reg_wrap
8: // have to be generated using the reg_alert_handler.py script.
9: //
10:
11: `include "prim_assert.sv"
12:
13: module alert_handler
14: import alert_pkg::*;
15: import prim_alert_pkg::*;
16: import prim_esc_pkg::*;
17: (
18: input clk_i,
19: input rst_ni,
20: // Bus Interface (device)
21: input tlul_pkg::tl_h2d_t tl_i,
22: output tlul_pkg::tl_d2h_t tl_o,
23: // Interrupt Requests
24: output logic intr_classa_o,
25: output logic intr_classb_o,
26: output logic intr_classc_o,
27: output logic intr_classd_o,
28: // State information for HW crashdump
29: output alert_crashdump_t crashdump_o,
30: // Entropy Input from TRNG
31: input entropy_i,
32: // Alert Sources
33: input alert_tx_t [NAlerts-1:0] alert_tx_i,
34: output alert_rx_t [NAlerts-1:0] alert_rx_o,
35: // Escalation outputs
36: input esc_rx_t [N_ESC_SEV-1:0] esc_rx_i,
37: output esc_tx_t [N_ESC_SEV-1:0] esc_tx_o
38: );
39:
40: //////////////////////////////////
41: // Regfile Breakout and Mapping //
42: //////////////////////////////////
43:
44: logic [N_CLASSES-1:0] irq;
45: hw2reg_wrap_t hw2reg_wrap;
46: reg2hw_wrap_t reg2hw_wrap;
47:
48: // TODO: make this fully parametric at some point
49: assign {intr_classd_o,
50: intr_classc_o,
51: intr_classb_o,
52: intr_classa_o} = irq;
53:
54: alert_handler_reg_wrap i_reg_wrap (
55: .clk_i,
56: .rst_ni,
57: .tl_i,
58: .tl_o,
59: .irq_o ( irq ),
60: .crashdump_o,
61: .hw2reg_wrap,
62: .reg2hw_wrap
63: );
64:
65: ////////////////
66: // Ping Timer //
67: ////////////////
68:
69: logic [N_LOC_ALERT-1:0] loc_alert_trig;
70:
71: logic [NAlerts-1:0] alert_ping_en;
72: logic [NAlerts-1:0] alert_ping_ok;
73: logic [N_ESC_SEV-1:0] esc_ping_en;
74: logic [N_ESC_SEV-1:0] esc_ping_ok;
75:
76: alert_handler_ping_timer i_ping_timer (
77: .clk_i,
78: .rst_ni,
79: .entropy_i,
80: // we enable ping testing as soon as the config
81: // regs have been locked
82: .en_i ( reg2hw_wrap.config_locked ),
83: .alert_en_i ( reg2hw_wrap.alert_en ),
84: .ping_timeout_cyc_i ( reg2hw_wrap.ping_timeout_cyc ),
85: // this determines the range of the randomly generated
86: // wait period between ping. maximum mask width is PING_CNT_DW.
87: .wait_cyc_mask_i ( PING_CNT_DW'(24'hFFFFFF) ),
88: .alert_ping_en_o ( alert_ping_en ),
89: .esc_ping_en_o ( esc_ping_en ),
90: .alert_ping_ok_i ( alert_ping_ok ),
91: .esc_ping_ok_i ( esc_ping_ok ),
92: .alert_ping_fail_o ( loc_alert_trig[0] ),
93: .esc_ping_fail_o ( loc_alert_trig[1] )
94: );
95:
96: /////////////////////
97: // Alert Receivers //
98: /////////////////////
99:
100: logic [NAlerts-1:0] alert_integfail;
101: logic [NAlerts-1:0] alert_trig;
102:
103: // Target interrupt notification
104: for (genvar k = 0 ; k < NAlerts ; k++) begin : gen_alerts
105: prim_alert_receiver #(
106: .AsyncOn(AsyncOn[k])
107: ) i_alert_receiver (
108: .clk_i ,
109: .rst_ni ,
110: .ping_en_i ( alert_ping_en[k] ),
111: .ping_ok_o ( alert_ping_ok[k] ),
112: .integ_fail_o ( alert_integfail[k] ),
113: .alert_o ( alert_trig[k] ),
114: .alert_rx_o ( alert_rx_o[k] ),
115: .alert_tx_i ( alert_tx_i[k] )
116: );
117: end
118:
119: assign loc_alert_trig[2] = |(reg2hw_wrap.alert_en & alert_integfail);
120:
121: ///////////////////////////////////////
122: // Set alert cause bits and classify //
123: ///////////////////////////////////////
124:
125: alert_handler_class i_class (
126: .alert_trig_i ( alert_trig ),
127: .loc_alert_trig_i ( loc_alert_trig ),
128: .alert_en_i ( reg2hw_wrap.alert_en ),
129: .loc_alert_en_i ( reg2hw_wrap.loc_alert_en ),
130: .alert_class_i ( reg2hw_wrap.alert_class ),
131: .loc_alert_class_i ( reg2hw_wrap.loc_alert_class ),
132: .alert_cause_o ( hw2reg_wrap.alert_cause ),
133: .loc_alert_cause_o ( hw2reg_wrap.loc_alert_cause ),
134: .class_trig_o ( hw2reg_wrap.class_trig )
135: );
136:
137: ////////////////////////////////////
138: // Escalation Handling of Classes //
139: ////////////////////////////////////
140:
141: logic [N_CLASSES-1:0] class_accum_trig;
142: logic [N_CLASSES-1:0][N_ESC_SEV-1:0] class_esc_sig_en;
143:
144: for (genvar k = 0; k < N_CLASSES; k++) begin : gen_classes
145: alert_handler_accu i_accu (
146: .clk_i,
147: .rst_ni,
148: .class_en_i ( reg2hw_wrap.class_en[k] ),
149: .clr_i ( reg2hw_wrap.class_clr[k] ),
150: .class_trig_i ( hw2reg_wrap.class_trig[k] ),
151: .thresh_i ( reg2hw_wrap.class_accum_thresh[k] ),
152: .accu_cnt_o ( hw2reg_wrap.class_accum_cnt[k] ),
153: .accu_trig_o ( class_accum_trig[k] )
154: );
155:
156: alert_handler_esc_timer i_esc_timer (
157: .clk_i,
158: .rst_ni,
159: .en_i ( reg2hw_wrap.class_en[k] ),
160: // this clear does not apply to interrupts
161: .clr_i ( reg2hw_wrap.class_clr[k] ),
162: // an interrupt enables the timeout
163: .timeout_en_i ( irq[k] ),
164: .accum_trig_i ( class_accum_trig[k] ),
165: .timeout_cyc_i ( reg2hw_wrap.class_timeout_cyc[k] ),
166: .esc_en_i ( reg2hw_wrap.class_esc_en[k] ),
167: .esc_map_i ( reg2hw_wrap.class_esc_map[k] ),
168: .phase_cyc_i ( reg2hw_wrap.class_phase_cyc[k] ),
169: .esc_trig_o ( hw2reg_wrap.class_esc_trig[k] ),
170: .esc_cnt_o ( hw2reg_wrap.class_esc_cnt[k] ),
171: .esc_state_o ( hw2reg_wrap.class_esc_state[k] ),
172: .esc_sig_en_o ( class_esc_sig_en[k] )
173: );
174: end
175:
176: ////////////////////////
177: // Escalation Senders //
178: ////////////////////////
179:
180: logic [N_ESC_SEV-1:0] esc_sig_en;
181: logic [N_ESC_SEV-1:0] esc_integfail;
182: logic [N_ESC_SEV-1:0][N_CLASSES-1:0] esc_sig_en_trsp;
183:
184: for (genvar k = 0; k < N_ESC_SEV; k++) begin : gen_esc_sev
185: for (genvar j = 0; j < N_CLASSES; j++) begin : gen_transp
186: assign esc_sig_en_trsp[k][j] = class_esc_sig_en[j][k];
187: end
188:
189: assign esc_sig_en[k] = |esc_sig_en_trsp[k];
190:
191: prim_esc_sender i_esc_sender (
192: .clk_i,
193: .rst_ni,
194: .ping_en_i ( esc_ping_en[k] ),
195: .ping_ok_o ( esc_ping_ok[k] ),
196: .integ_fail_o ( esc_integfail[k] ),
197: .esc_en_i ( esc_sig_en[k] ),
198: .esc_rx_i ( esc_rx_i[k] ),
199: .esc_tx_o ( esc_tx_o[k] )
200: );
201: end
202:
203: assign loc_alert_trig[3] = |esc_integfail;
204:
205: ////////////////
206: // Assertions //
207: ////////////////
208:
209: // check whether all outputs have a good known state after reset
210: `ASSERT_KNOWN(TlDValidKnownO_A, tl_o.d_valid)
211: `ASSERT_KNOWN(TlAReadyKnownO_A, tl_o.a_ready)
212: `ASSERT_KNOWN(IrqAKnownO_A, intr_classa_o)
213: `ASSERT_KNOWN(IrqBKnownO_A, intr_classb_o)
214: `ASSERT_KNOWN(IrqCKnownO_A, intr_classc_o)
215: `ASSERT_KNOWN(IrqDKnownO_A, intr_classd_o)
216: `ASSERT_KNOWN(CrashdumpKnownO_A, crashdump_o)
217: `ASSERT_KNOWN(AckPKnownO_A, alert_rx_o)
218: `ASSERT_KNOWN(EscPKnownO_A, esc_tx_o)
219:
220: // this restriction is due to specifics in the ping selection mechanism
221: `ASSERT_INIT(CheckNAlerts, NAlerts < (256 - N_CLASSES))
222: `ASSERT_INIT(CheckEscCntDw, EscCntDw <= 32)
223: `ASSERT_INIT(CheckAccuCntDw, AccuCntDw <= 32)
224: `ASSERT_INIT(CheckNClasses, N_CLASSES <= 8)
225: `ASSERT_INIT(CheckNEscSev, N_ESC_SEV <= 8)
226:
227: endmodule
228: