../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: