Module Definition
dashboard | hierarchy | modlist | groups | tests | asserts



Module Instance : tb.dut.u_ping_timer

Instance :
SCORELINECONDTOGGLEFSMBRANCHASSERT
99.46 100.00 97.30 100.00 100.00 100.00


Instance's subtree :
SCORELINECONDTOGGLEFSMBRANCHASSERT
99.57 100.00 97.44 100.00 100.00 100.00 100.00


Parent :
SCORELINECONDTOGGLEFSMBRANCHASSERTNAME
99.96 100.00 99.87 100.00 dut


Subtrees :
NAMESCORELINECONDTOGGLEFSMBRANCHASSERT
u_prim_buf_spurious_alert_ping 100.00 100.00
u_prim_buf_spurious_esc_ping 100.00 100.00
u_prim_count_cnt 100.00 100.00
u_prim_count_esc_cnt 100.00 100.00
u_prim_double_lfsr 100.00 100.00 100.00 100.00 100.00
u_state_regs 100.00 100.00 100.00 100.00

Line Coverage for Module : alert_handler_ping_timer
Line No.TotalCoveredPercent
TOTAL6262100.00
CONT_ASSIGN7811100.00
CONT_ASSIGN8111100.00
CONT_ASSIGN8211100.00
ALWAYS8533100.00
CONT_ASSIGN9911100.00
CONT_ASSIGN13411100.00
ALWAYS14144100.00
CONT_ASSIGN15211100.00
CONT_ASSIGN15611100.00
CONT_ASSIGN19611100.00
CONT_ASSIGN23311100.00
CONT_ASSIGN23411100.00
CONT_ASSIGN26411100.00
CONT_ASSIGN26511100.00
CONT_ASSIGN26811100.00
CONT_ASSIGN27811100.00
CONT_ASSIGN27911100.00
ALWAYS3313737100.00
ALWAYS42633100.00

77 78 1/1 assign reseed_timer_d = (reseed_timer_q > '0) ? reseed_timer_q - 1'b1 : Tests: T1 T2 T3  79 (reseed_en) ? {wait_cyc_mask_i, 80 {ReseedLfsrExtraBits{1'b1}}} : '0; 81 1/1 assign edn_req_o = (reseed_timer_q == '0); Tests: T1 T2 T3  82 1/1 assign reseed_en = edn_req_o & edn_ack_i; Tests: T1 T2 T3  83 84 always_ff @(posedge clk_i or negedge rst_ni) begin : p_regs 85 1/1 if (!rst_ni) begin Tests: T1 T2 T3  86 1/1 reseed_timer_q <= '0; Tests: T1 T2 T3  87 end else begin 88 1/1 reseed_timer_q <= reseed_timer_d; Tests: T1 T2 T3  89 end 90 end 91 92 /////////////////////////// 93 // Tandem LFSR Instances // 94 /////////////////////////// 95 96 logic cnt_set, lfsr_err; 97 logic [LfsrWidth-1:0] entropy; 98 logic [PING_CNT_DW + IdDw - 1:0] lfsr_state; 99 1/1 assign entropy = (reseed_en) ? edn_data_i[LfsrWidth-1:0] : '0; Tests: T1 T2 T3  100 101 // SEC_CM: PING_TIMER.LFSR.REDUN 102 // We employ two redundant LFSRs to guard against FI attacks. 103 // If any of the two is glitched and the two LFSR states do not agree, 104 // the FSM below is moved into a terminal error state and all ping alerts 105 // are permanently asserted. 106 prim_double_lfsr #( 107 .LfsrDw ( LfsrWidth ), 108 .EntropyDw ( LfsrWidth ), 109 .StateOutDw ( PING_CNT_DW + IdDw ), 110 .DefaultSeed ( RndCnstLfsrSeed ), 111 .StatePermEn ( 1'b1 ), 112 .StatePerm ( RndCnstLfsrPerm ), 113 .MaxLenSVA ( MaxLenSVA ), 114 .LockupSVA ( LockupSVA ), 115 .ExtSeedSVA ( 1'b0 ), // ext seed is unused 116 .EnableAlertTriggerSVA ( 1'b0 ) 117 ) u_prim_double_lfsr ( 118 .clk_i, 119 .rst_ni, 120 .seed_en_i ( 1'b0 ), 121 .seed_i ( '0 ), 122 .lfsr_en_i ( reseed_en || cnt_set ), 123 .entropy_i ( entropy ), 124 .state_o ( lfsr_state ), 125 .err_o ( lfsr_err ) 126 ); 127 128 logic [IdDw-1:0] id_to_ping_d, id_to_ping_q; 129 // The subtraction below ensures that the alert ID is always in range. If 130 // all alerts are enabled, an alert ID drawn in this way will always be 131 // valid. This comes at the cost of a bias towards certain alert IDs that 132 // will be pinged twice as often on average - but it ensures that we have 133 // less alert IDs that need to be skipped since they are invalid. 134 1/1 assign id_to_ping_d = (lfsr_state[PING_CNT_DW +: IdDw] >= NAlerts) ? Tests: T1 T2 T3  135 lfsr_state[PING_CNT_DW +: IdDw] - NAlerts : 136 lfsr_state[PING_CNT_DW +: IdDw]; 137 138 // we need to hold the ID stable while the ping is ongoing since this will result in 139 // spurious ping responses otherwise. 140 always_ff @(posedge clk_i or negedge rst_ni) begin : p_id_reg 141 1/1 if (!rst_ni) begin Tests: T1 T2 T3  142 1/1 id_to_ping_q <= '0; Tests: T1 T2 T3  143 end else begin 144 1/1 if (cnt_set) begin Tests: T1 T2 T3  145 1/1 id_to_ping_q <= id_to_ping_d; Tests: T4 T5 T6  146 end MISSING_ELSE 147 end 148 end 149 150 // align the enable mask with powers of two for the indexing operation below. 151 logic [2**IdDw-1:0] enable_mask; 152 1/1 assign enable_mask = (2**IdDw)'(alert_ping_en_i); Tests: T1 T2 T3  153 154 // check if the randomly drawn alert ID is actually valid and the alert is enabled 155 logic id_vld; 156 1/1 assign id_vld = enable_mask[id_to_ping_q]; Tests: T1 T2 T3  157 158 ////////////////////////////////// 159 // Escalation Counter Instances // 160 ////////////////////////////////// 161 162 // As opposed to the alert ID, the escalation sender ID to be pinged is not drawn at random. 163 // Rather, we cycle through the escalation senders one by one in a deterministic fashion. 164 // This allows us to provide guarantees needed for the ping timeout / auto escalation feature 165 // implemented at the escalation receiver side. 166 // 167 // In particular, with N_ESC_SEV escalation senders in the design, we can guarantee 168 // that each escalation channel will be pinged at least once every 169 // 170 // N_ESC_SEV x (NUM_WAIT_COUNT + NUM_TIMEOUT_COUNT) x 2**PING_CNT_DW 171 // 172 // cycles - independently of the reseeding operation. 173 // 174 // - N_ESC_SEV: # escalation channels to ping. 175 // - NUM_WAIT_COUNT: # wait counts between subsequent escalation channel pings. 176 // - NUM_TIMEOUT_COUNT: # timeout counts between subsequent escalation channel pings. 177 // - 2**PING_CNT_DW: # maximum counter value. 178 // 179 // This guarantee is used inside the escalation receivers to monitor the pings sent out by the 180 // alert handler. I.e., once the alert handler has started to send out pings, each escalation 181 // receiver employs a timeout window within which it expects the next ping to arrive. If 182 // escalation pings cease to arrive at an escalation receiver for any reason, this will 183 // automatically trigger the associated escalation countermeasure. 184 // 185 // In order to have enough margin, the escalation receiver timeout counters use a threshold that 186 // is 4x higher than the value calculated above. With N_ESC_SEV = 4, PING_CNT_DW = 16 and 187 // NUM_WAIT_COUNT = NUM_TIMEOUT_COUNT = 2 this amounts to a 22bit timeout threshold. 188 // 189 // We employ two redundant counters to guard against FI attacks. 190 // If any of the two is glitched and the two counter states do not agree, 191 // the FSM below is moved into a terminal error state and all ping alerts 192 // are permanently asserted. 193 194 logic esc_cnt_en, esc_cnt_clr, esc_cnt_error; 195 logic [EscSenderIdxWidth-1:0] esc_cnt; 196 1/1 assign esc_cnt_clr = (esc_cnt >= EscSenderIdxWidth'(N_ESC_SEV-1)) && esc_cnt_en; Tests: T1 T2 T3  197 198 // SEC_CM: PING_TIMER.CTR.REDUN 199 prim_count #( 200 .Width(EscSenderIdxWidth), 201 // The alert handler behaves differently than other comportable IP. I.e., instead of sending out 202 // an alert signal, this condition is handled internally in the alert handler. 203 .EnableAlertTriggerSVA(0), 204 // Pass a parameter to disable coverage for some assertions that are unreachable because set_i 205 // and decr_en_i are tied to zero. 206 .PossibleActions(prim_count_pkg::Clr | 207 prim_count_pkg::Incr) 208 ) u_prim_count_esc_cnt ( 209 .clk_i, 210 .rst_ni, 211 .clr_i(esc_cnt_clr), 212 .set_i(1'b0), 213 .set_cnt_i('0), 214 .incr_en_i(esc_cnt_en), 215 .decr_en_i(1'b0), 216 .step_i(EscSenderIdxWidth'(1)), 217 .commit_i(1'b1), 218 .cnt_o(esc_cnt), 219 .cnt_after_commit_o(), 220 .err_o(esc_cnt_error) 221 ); 222 223 ///////////////////////////// 224 // Timer Counter Instances // 225 ///////////////////////////// 226 227 // We employ two redundant counters to guard against FI attacks. 228 // If any of the two is glitched and the two counter states do not agree, 229 // the FSM below is moved into a terminal error state and all ping alerts 230 // are permanently asserted. 231 logic [PING_CNT_DW-1:0] cnt, cnt_setval; 232 logic wait_cnt_set, timeout_cnt_set, timer_expired, cnt_error; 233 1/1 assign timer_expired = (cnt == '0); Tests: T1 T2 T3  234 1/1 assign cnt_set = wait_cnt_set || timeout_cnt_set; Tests: T1 T2 T3  235 236 // SEC_CM: PING_TIMER.CTR.REDUN 237 prim_count #( 238 .Width(PING_CNT_DW), 239 // The alert handler behaves differently than other comportable IP. I.e., instead of sending out 240 // an alert signal, this condition is handled internally in the alert handler. 241 .EnableAlertTriggerSVA(0), 242 // Pass a parameter to disable coverage for some assertions that are unreachable because clr_i 243 // and incr_en_i are tied to zero. 244 .PossibleActions(prim_count_pkg::Set | 245 prim_count_pkg::Decr) 246 ) u_prim_count_cnt ( 247 .clk_i, 248 .rst_ni, 249 .clr_i(1'b0), 250 .set_i(cnt_set), 251 .set_cnt_i(cnt_setval), 252 .incr_en_i(1'b0), 253 .decr_en_i(1'b1), // we are counting down here. 254 .step_i(PING_CNT_DW'(1'b1)), 255 .commit_i(1'b1), 256 .cnt_o(cnt), 257 .cnt_after_commit_o(), 258 .err_o(cnt_error) 259 ); 260 261 // the constant offset ensures a minimum cycle spacing between pings. 262 logic unused_bits; 263 logic [PING_CNT_DW-1:0] wait_cyc; 264 1/1 assign wait_cyc = (lfsr_state[PING_CNT_DW-1:0] | PING_CNT_DW'(3'b100)); Tests: T1 T2 T3  265 1/1 assign unused_bits = lfsr_state[2]; Tests: T1 T2 T3  266 267 // note that the masks are used for DV/FPV only in order to reduce the state space. 268 1/1 assign cnt_setval = (wait_cnt_set) ? (wait_cyc & wait_cyc_mask_i) : ping_timeout_cyc_i; Tests: T1 T2 T3  269 270 //////////////////////////// 271 // Ping and Timeout Logic // 272 //////////////////////////// 273 274 logic alert_ping_en, esc_ping_en; 275 logic spurious_alert_ping, spurious_esc_ping; 276 277 // generate ping enable vector 278 1/1 assign alert_ping_req_o = NAlerts'(alert_ping_en) << id_to_ping_q; Tests: T1 T2 T3  279 1/1 assign esc_ping_req_o = EscSenderIdxWidth'(esc_ping_en) << esc_cnt; Tests: T1 T2 T3  280 281 // under normal operation, these signals should never be asserted. 282 // we place hand instantiated buffers here such that these signals are not 283 // optimized away during synthesis (these buffers will receive a keep or size_only 284 // attribute in our Vivado and DC synthesis flows). 285 prim_buf u_prim_buf_spurious_alert_ping ( 286 .in_i(|(alert_ping_ok_i & ~alert_ping_req_o)), 287 .out_o(spurious_alert_ping) 288 ); 289 prim_buf u_prim_buf_spurious_esc_ping ( 290 .in_i(|(esc_ping_ok_i & ~esc_ping_req_o)), 291 .out_o(spurious_esc_ping) 292 ); 293 294 // SEC_CM: PING_TIMER.FSM.SPARSE 295 // Encoding generated with: 296 // $ ./util/design/sparse-fsm-encode.py -d 5 -m 6 -n 9 \ 297 // -s 728582219 --language=sv 298 // 299 // Hamming distance histogram: 300 // 301 // 0: -- 302 // 1: -- 303 // 2: -- 304 // 3: -- 305 // 4: -- 306 // 5: |||||||||||||||||||| (60.00%) 307 // 6: ||||||||||||| (40.00%) 308 // 7: -- 309 // 8: -- 310 // 9: -- 311 // 312 // Minimum Hamming distance: 5 313 // Maximum Hamming distance: 6 314 // Minimum Hamming weight: 2 315 // Maximum Hamming weight: 6 316 // 317 localparam int StateWidth = 9; 318 typedef enum logic [StateWidth-1:0] { 319 InitSt = 9'b011001011, 320 AlertWaitSt = 9'b110000000, 321 AlertPingSt = 9'b101110001, 322 EscWaitSt = 9'b010110110, 323 EscPingSt = 9'b000011101, 324 FsmErrorSt = 9'b101101110 325 } state_e; 326 327 state_e state_d, state_q; 328 329 always_comb begin : p_fsm 330 // default 331 1/1 state_d = state_q; Tests: T1 T2 T3  332 1/1 wait_cnt_set = 1'b0; Tests: T1 T2 T3  333 1/1 timeout_cnt_set = 1'b0; Tests: T1 T2 T3  334 1/1 esc_cnt_en = 1'b0; Tests: T1 T2 T3  335 1/1 alert_ping_en = 1'b0; Tests: T1 T2 T3  336 1/1 esc_ping_en = 1'b0; Tests: T1 T2 T3  337 // this captures spurious ping responses 338 1/1 alert_ping_fail_o = spurious_alert_ping; Tests: T1 T2 T3  339 1/1 esc_ping_fail_o = spurious_esc_ping; Tests: T1 T2 T3  340 341 1/1 unique case (state_q) Tests: T1 T2 T3  342 // wait until activated 343 // we never return to this state 344 // once activated! 345 InitSt: begin 346 1/1 if (en_i) begin Tests: T1 T2 T3  347 1/1 state_d = AlertWaitSt; Tests: T4 T5 T6  348 1/1 wait_cnt_set = 1'b1; Tests: T4 T5 T6  349 end MISSING_ELSE 350 end 351 // wait for random amount of cycles 352 AlertWaitSt: begin 353 1/1 if (timer_expired) begin Tests: T4 T5 T6  354 1/1 state_d = AlertPingSt; Tests: T4 T5 T7  355 1/1 timeout_cnt_set = 1'b1; Tests: T4 T5 T7  356 end MISSING_ELSE 357 end 358 // SEC_CM: ALERT_RX.INTERSIG.BKGN_CHK 359 // send out an alert ping request and wait for a ping 360 // response or a ping timeout (whatever comes first). 361 // if the alert ID is not valid, we drop the request and 362 // proceed to the next ping. 363 AlertPingSt: begin 364 1/1 alert_ping_en = id_vld; Tests: T4 T5 T7  365 1/1 if (timer_expired || |(alert_ping_ok_i & alert_ping_req_o) || !id_vld) begin Tests: T4 T5 T7  366 1/1 state_d = EscWaitSt; Tests: T4 T5 T7  367 1/1 wait_cnt_set = 1'b1; Tests: T4 T5 T7  368 1/1 if (timer_expired) begin Tests: T4 T5 T7  369 1/1 alert_ping_fail_o = 1'b1; Tests: T19 T20 T21  370 end MISSING_ELSE 371 end MISSING_ELSE 372 end 373 // wait for random amount of cycles 374 EscWaitSt: begin 375 1/1 if (timer_expired) begin Tests: T4 T5 T7  376 1/1 state_d = EscPingSt; Tests: T4 T5 T7  377 1/1 timeout_cnt_set = 1'b1; Tests: T4 T5 T7  378 end MISSING_ELSE 379 end 380 // SEC_CM: ESC_TX.INTERSIG.BKGN_CHK 381 // send out an escalation ping request and wait for a ping 382 // response or a ping timeout (whatever comes first) 383 EscPingSt: begin 384 1/1 esc_ping_en = 1'b1; Tests: T4 T5 T7  385 1/1 if (timer_expired || |(esc_ping_ok_i & esc_ping_req_o)) begin Tests: T4 T5 T7  386 1/1 state_d = AlertWaitSt; Tests: T4 T5 T7  387 1/1 wait_cnt_set = 1'b1; Tests: T4 T5 T7  388 1/1 esc_cnt_en = 1'b1; Tests: T4 T5 T7  389 1/1 if (timer_expired) begin Tests: T4 T5 T7  390 1/1 esc_ping_fail_o = 1'b1; Tests: T19 T20 T21  391 end MISSING_ELSE 392 end MISSING_ELSE 393 end 394 // SEC_CM: PING_TIMER.FSM.LOCAL_ESC 395 // terminal FSM error state. 396 // if we for some reason end up in this state (e.g. malicious glitching) 397 // we are going to assert both ping fails continuously 398 FsmErrorSt: begin 399 1/1 alert_ping_fail_o = 1'b1; Tests: T6 T8 T9  400 1/1 esc_ping_fail_o = 1'b1; Tests: T6 T8 T9  401 end 402 default: begin 403 state_d = FsmErrorSt; 404 alert_ping_fail_o = 1'b1; 405 esc_ping_fail_o = 1'b1; 406 end 407 endcase 408 409 // SEC_CM: PING_TIMER.FSM.LOCAL_ESC 410 // if the two LFSR or counter states do not agree, 411 // we move into the terminal state. 412 1/1 if (lfsr_err || cnt_error || esc_cnt_error) begin Tests: T1 T2 T3  413 1/1 state_d = FsmErrorSt; Tests: T6 T8 T9  414 1/1 alert_ping_fail_o = 1'b1; Tests: T6 T8 T9  415 1/1 esc_ping_fail_o = 1'b1; Tests: T6 T8 T9  416 end MISSING_ELSE 417 end 418 419 /////////////////// 420 // FSM Registers // 421 /////////////////// 422 423 // The alert handler behaves differently than other comportable IP. I.e., instead of sending out 424 // an alert signal, this condition is handled internally in the alert handler. The 425 // EnableAlertTriggerSVA parameter is therefore set to 0. 426 3/3 `PRIM_FLOP_SPARSE_FSM(u_state_regs, state_d, state_q, state_e, InitSt, clk_i, rst_ni, 0) Tests: T1 T2 T3  | T1 T2 T3  | T1 T2 T3 
PRIM_FLOP_SPARSE_FSM(u_state_regs, state_d, state_q, state_e, InitSt, clk_i, rst_ni, 0): 426.1 `ifdef SIMULATION 426.2 prim_sparse_fsm_flop #( 426.3 .StateEnumT(state_e), 426.4 .Width($bits(state_e)), 426.5 .ResetValue($bits(state_e)'(InitSt)), 426.6 .EnableAlertTriggerSVA(0), 426.7 .CustomForceName("state_q") 426.8 ) u_state_regs ( 426.9 .clk_i ( clk_i ), 426.10 .rst_ni ( rst_ni ), 426.11 .state_i ( state_d ), 426.12 .state_o ( ) 426.13 ); 426.14 always_ff @(posedge clk_i or negedge rst_ni) begin 426.15 1/1 if (!rst_ni) begin Tests: T1 T2 T3  426.16 1/1 state_q <= InitSt; Tests: T1 T2 T3  426.17 end else begin 426.18 1/1 state_q <= state_d; Tests: T1 T2 T3  426.19 end 426.20 end 426.21 u_state_regs_A: assert property (@(posedge clk_i) disable iff ((!rst_ni) !== '0) (state_q === u_state_regs.state_o)) 426.22 else begin 426.23 `ifdef UVM 426.24 uvm_pkg::uvm_report_error("ASSERT FAILED", "u_state_regs_A", uvm_pkg::UVM_NONE, 426.25 "../src/lowrisc_ip_alert_handler_component_0.1/rtl/alert_handler_ping_timer.sv", 426, "", 1); 426.26 `else 426.27 $error("%0t: (%0s:%0d) [%m] [ASSERT FAILED] %0s", $time, `__FILE__, `__LINE__, 426.28 `PRIM_STRINGIFY(u_state_regs_A)); 426.29 `endif 426.30 end 426.31 `else 426.32 prim_sparse_fsm_flop #( 426.33 .StateEnumT(state_e), 426.34 .Width($bits(state_e)), 426.35 .ResetValue($bits(state_e)'(InitSt)), 426.36 .EnableAlertTriggerSVA(0) 426.37 ) u_state_regs ( 426.38 .clk_i ( clk_i ), 426.39 .rst_ni ( rst_ni ), 426.40 .state_i ( state_d ), 426.41 .state_o ( state_q ) 426.42 ); 426.43 `endif

Cond Coverage for Module : alert_handler_ping_timer
TotalCoveredPercent
Conditions373697.30
Logical373697.30
Non-Logical00
Event00

 LINE       78
 EXPRESSION ((reseed_timer_q > '0) ? ((reseed_timer_q - 1'b1)) : (reseed_en ? ({wait_cyc_mask_i, {ReseedLfsrExtraBits {1'b1}}}) : '0))
             ----------1----------
-1-StatusTests
0CoveredT1,T2,T3
1CoveredT1,T2,T3

 LINE       78
 SUB-EXPRESSION (reseed_en ? ({wait_cyc_mask_i, {ReseedLfsrExtraBits {1'b1}}}) : '0)
                 ----1----
-1-StatusTests
0CoveredT1,T2,T3
1CoveredT1,T2,T3

 LINE       81
 EXPRESSION (reseed_timer_q == '0)
            -----------1----------
-1-StatusTests
0CoveredT1,T2,T3
1CoveredT1,T2,T3

 LINE       82
 EXPRESSION (edn_req_o & edn_ack_i)
             ----1----   ----2----
-1--2-StatusTests
01Not Covered
10CoveredT1,T2,T3
11CoveredT1,T2,T3

 LINE       99
 EXPRESSION (reseed_en ? edn_data_i[(alert_pkg::LfsrWidth - 1):0] : '0)
             ----1----
-1-StatusTests
0CoveredT1,T2,T3
1CoveredT1,T2,T3

 LINE       117
 EXPRESSION (reseed_en || cnt_set)
             ----1----    ---2---
-1--2-StatusTests
00CoveredT1,T2,T3
01CoveredT4,T5,T6
10CoveredT1,T2,T3

 LINE       134
 EXPRESSION 
 Number  Term
      1  (lfsr_state[alert_pkg::PING_CNT_DW+:IdDw] >= alert_pkg::NAlerts) ? ((lfsr_state[alert_pkg::PING_CNT_DW+:IdDw] - alert_pkg::NAlerts)) : lfsr_state[alert_pkg::PING_CNT_DW+:IdDw])
-1-StatusTests
0CoveredT4,T10,T5
1CoveredT1,T2,T3

 LINE       196
 EXPRESSION ((esc_cnt >= 2'((alert_pkg::N_ESC_SEV - 1))) && esc_cnt_en)
             ---------------------1---------------------    -----2----
-1--2-StatusTests
01CoveredT4,T5,T7
10CoveredT4,T5,T8
11CoveredT4,T5,T7

 LINE       233
 EXPRESSION (cnt == '0)
            -----1-----
-1-StatusTests
0CoveredT1,T2,T3
1CoveredT1,T2,T3

 LINE       234
 EXPRESSION (wait_cnt_set || timeout_cnt_set)
             ------1-----    -------2-------
-1--2-StatusTests
00CoveredT1,T2,T3
01CoveredT4,T5,T7
10CoveredT4,T5,T6

 LINE       268
 EXPRESSION (wait_cnt_set ? ((wait_cyc & wait_cyc_mask_i)) : ping_timeout_cyc_i)
             ------1-----
-1-StatusTests
0CoveredT1,T2,T3
1CoveredT4,T5,T6

 LINE       365
 EXPRESSION (timer_expired || ((|(alert_ping_ok_i & alert_ping_req_o))) || ((!id_vld)))
             ------1------    --------------------2--------------------    -----3-----
-1--2--3-StatusTests
000CoveredT4,T5,T7
001CoveredT4,T5,T7
010CoveredT4,T5,T7
100CoveredT19,T20,T21

 LINE       385
 EXPRESSION (timer_expired || ((|(esc_ping_ok_i & esc_ping_req_o))))
             ------1------    ------------------2------------------
-1--2-StatusTests
00CoveredT4,T5,T7
01CoveredT4,T5,T7
10CoveredT19,T20,T21

 LINE       412
 EXPRESSION (lfsr_err || cnt_error || esc_cnt_error)
             ----1---    ----2----    ------3------
-1--2--3-StatusTests
000CoveredT1,T2,T3
001CoveredT6,T8,T9
010CoveredT6,T8,T9
100CoveredT6,T8,T9

FSM Coverage for Module : alert_handler_ping_timer
Summary for FSM :: state_q
TotalCoveredPercent
States 6 6 100.00 (Not included in score)
Transitions 10 6 60.00
Sequences 0 0

State, Transition and Sequence Details for FSM :: state_q
statesLine No.CoveredTests
AlertPingSt 354 Covered T4,T5,T7
AlertWaitSt 347 Covered T4,T5,T6
EscPingSt 376 Covered T4,T5,T7
EscWaitSt 366 Covered T4,T5,T7
FsmErrorSt 413 Covered T6,T8,T9
InitSt 345 Covered T1,T2,T3


transitionsLine No.CoveredTests
AlertPingSt->EscWaitSt 366 Covered T4,T5,T7
AlertPingSt->FsmErrorSt 413 Not Covered
AlertWaitSt->AlertPingSt 354 Covered T4,T5,T7
AlertWaitSt->FsmErrorSt 413 Covered T6,T8,T9
EscPingSt->AlertWaitSt 386 Covered T4,T5,T7
EscPingSt->FsmErrorSt 413 Not Covered
EscWaitSt->EscPingSt 376 Covered T4,T5,T7
EscWaitSt->FsmErrorSt 413 Not Covered
InitSt->AlertWaitSt 347 Covered T4,T5,T6
InitSt->FsmErrorSt 413 Not Covered



Branch Coverage for Module : alert_handler_ping_timer
Line No.TotalCoveredPercent
Branches 32 32 100.00
TERNARY 78 3 3 100.00
TERNARY 99 2 2 100.00
TERNARY 134 2 2 100.00
TERNARY 268 2 2 100.00
IF 85 2 2 100.00
IF 141 3 3 100.00
CASE 341 14 14 100.00
IF 412 2 2 100.00
IF 426 2 2 100.00


78 assign reseed_timer_d = (reseed_timer_q > '0) ? reseed_timer_q - 1'b1 : -1- ==> 79 (reseed_en) ? {wait_cyc_mask_i, -2- ==> ==>

Branches:
-1--2-StatusTests
1 - Covered T1,T2,T3
0 1 Covered T1,T2,T3
0 0 Covered T1,T2,T3


99 assign entropy = (reseed_en) ? edn_data_i[LfsrWidth-1:0] : '0; -1- ==> ==>

Branches:
-1-StatusTests
1 Covered T1,T2,T3
0 Covered T1,T2,T3


134 assign id_to_ping_d = (lfsr_state[PING_CNT_DW +: IdDw] >= NAlerts) ? -1- ==> ==>

Branches:
-1-StatusTests
1 Covered T1,T2,T3
0 Covered T4,T10,T5


268 assign cnt_setval = (wait_cnt_set) ? (wait_cyc & wait_cyc_mask_i) : ping_timeout_cyc_i; -1- ==> ==>

Branches:
-1-StatusTests
1 Covered T4,T5,T6
0 Covered T1,T2,T3


85 if (!rst_ni) begin -1- 86 reseed_timer_q <= '0; ==> 87 end else begin 88 reseed_timer_q <= reseed_timer_d; ==>

Branches:
-1-StatusTests
1 Covered T1,T2,T3
0 Covered T1,T2,T3


141 if (!rst_ni) begin -1- 142 id_to_ping_q <= '0; ==> 143 end else begin 144 if (cnt_set) begin -2- 145 id_to_ping_q <= id_to_ping_d; ==> 146 end MISSING_ELSE ==>

Branches:
-1--2-StatusTests
1 - Covered T1,T2,T3
0 1 Covered T4,T5,T6
0 0 Covered T1,T2,T3


341 unique case (state_q) -1- 342 // wait until activated 343 // we never return to this state 344 // once activated! 345 InitSt: begin 346 if (en_i) begin -2- 347 state_d = AlertWaitSt; ==> 348 wait_cnt_set = 1'b1; 349 end MISSING_ELSE ==> 350 end 351 // wait for random amount of cycles 352 AlertWaitSt: begin 353 if (timer_expired) begin -3- 354 state_d = AlertPingSt; ==> 355 timeout_cnt_set = 1'b1; 356 end MISSING_ELSE ==> 357 end 358 // SEC_CM: ALERT_RX.INTERSIG.BKGN_CHK 359 // send out an alert ping request and wait for a ping 360 // response or a ping timeout (whatever comes first). 361 // if the alert ID is not valid, we drop the request and 362 // proceed to the next ping. 363 AlertPingSt: begin 364 alert_ping_en = id_vld; 365 if (timer_expired || |(alert_ping_ok_i & alert_ping_req_o) || !id_vld) begin -4- 366 state_d = EscWaitSt; 367 wait_cnt_set = 1'b1; 368 if (timer_expired) begin -5- 369 alert_ping_fail_o = 1'b1; ==> 370 end MISSING_ELSE ==> 371 end MISSING_ELSE ==> 372 end 373 // wait for random amount of cycles 374 EscWaitSt: begin 375 if (timer_expired) begin -6- 376 state_d = EscPingSt; ==> 377 timeout_cnt_set = 1'b1; 378 end MISSING_ELSE ==> 379 end 380 // SEC_CM: ESC_TX.INTERSIG.BKGN_CHK 381 // send out an escalation ping request and wait for a ping 382 // response or a ping timeout (whatever comes first) 383 EscPingSt: begin 384 esc_ping_en = 1'b1; 385 if (timer_expired || |(esc_ping_ok_i & esc_ping_req_o)) begin -7- 386 state_d = AlertWaitSt; 387 wait_cnt_set = 1'b1; 388 esc_cnt_en = 1'b1; 389 if (timer_expired) begin -8- 390 esc_ping_fail_o = 1'b1; ==> 391 end MISSING_ELSE ==> 392 end MISSING_ELSE ==> 393 end 394 // SEC_CM: PING_TIMER.FSM.LOCAL_ESC 395 // terminal FSM error state. 396 // if we for some reason end up in this state (e.g. malicious glitching) 397 // we are going to assert both ping fails continuously 398 FsmErrorSt: begin 399 alert_ping_fail_o = 1'b1; ==> 400 esc_ping_fail_o = 1'b1; 401 end 402 default: begin 403 state_d = FsmErrorSt; ==>

Branches:
-1--2--3--4--5--6--7--8-StatusTests
InitSt 1 - - - - - - Covered T4,T5,T6
InitSt 0 - - - - - - Covered T1,T2,T3
AlertWaitSt - 1 - - - - - Covered T4,T5,T7
AlertWaitSt - 0 - - - - - Covered T4,T5,T6
AlertPingSt - - 1 1 - - - Covered T19,T20,T21
AlertPingSt - - 1 0 - - - Covered T4,T5,T7
AlertPingSt - - 0 - - - - Covered T4,T5,T7
EscWaitSt - - - - 1 - - Covered T4,T5,T7
EscWaitSt - - - - 0 - - Covered T4,T5,T7
EscPingSt - - - - - 1 1 Covered T19,T20,T21
EscPingSt - - - - - 1 0 Covered T4,T5,T7
EscPingSt - - - - - 0 - Covered T4,T5,T7
FsmErrorSt - - - - - - - Covered T6,T8,T9
default - - - - - - - Covered T6,T8,T9


412 if (lfsr_err || cnt_error || esc_cnt_error) begin -1- 413 state_d = FsmErrorSt; ==> 414 alert_ping_fail_o = 1'b1; 415 esc_ping_fail_o = 1'b1; 416 end MISSING_ELSE ==>

Branches:
-1-StatusTests
1 Covered T6,T8,T9
0 Covered T1,T2,T3


426 `PRIM_FLOP_SPARSE_FSM(u_state_regs, state_d, state_q, state_e, InitSt, clk_i, rst_ni, 0) -1- ==> ==>

Branches:
-1-StatusTests
1 Covered T1,T2,T3
0 Covered T1,T2,T3


Assert Coverage for Module : alert_handler_ping_timer
TotalAttemptedPercentSucceeded/MatchedPercent
Assertions 7 7 100.00 7 100.00
Cover properties 0 0 0
Cover sequences 0 0 0
Total 7 7 100.00 7 100.00




Assertion Details

NameAttemptsReal SuccessesFailuresIncomplete
AlertPingOH_A 538552980 202063 0 0
EscPingOH_A 538552980 134545 0 0
MaxIdDw_A 617 617 0 0
PingOH0_A 538552980 538382136 0 0
WaitCycMaskIsRightAlignedMask_A 538552980 538382136 0 0
WaitCycMaskMin_A 538552980 538382136 0 0
u_state_regs_A 538552980 538382136 0 0


AlertPingOH_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 538552980 202063 0 0
T4 12866 2225 0 0
T5 17765 2515 0 0
T6 17214 0 0 0
T7 0 1251 0 0
T8 41292 0 0 0
T10 18028 0 0 0
T11 22732 0 0 0
T16 43811 0 0 0
T19 0 500 0 0
T22 0 2169 0 0
T23 0 1867 0 0
T24 0 2857 0 0
T25 0 2414 0 0
T26 0 2081 0 0
T27 0 5 0 0
T28 35331 0 0 0
T29 46058 0 0 0
T30 57586 0 0 0

EscPingOH_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 538552980 134545 0 0
T4 12866 2275 0 0
T5 17765 2520 0 0
T6 17214 0 0 0
T7 0 1230 0 0
T8 41292 0 0 0
T10 18028 0 0 0
T11 22732 0 0 0
T16 43811 0 0 0
T19 0 153 0 0
T22 0 2135 0 0
T23 0 1830 0 0
T24 0 2820 0 0
T25 0 2393 0 0
T26 0 2070 0 0
T28 35331 0 0 0
T29 46058 0 0 0
T30 57586 0 0 0
T31 0 5 0 0

MaxIdDw_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 617 617 0 0
T1 1 1 0 0
T2 1 1 0 0
T3 1 1 0 0
T4 1 1 0 0
T5 1 1 0 0
T6 1 1 0 0
T10 1 1 0 0
T11 1 1 0 0
T12 1 1 0 0
T28 1 1 0 0

PingOH0_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 538552980 538382136 0 0
T1 1561 1508 0 0
T2 4616 4541 0 0
T3 3651 3556 0 0
T4 12866 12673 0 0
T5 17765 17617 0 0
T6 17214 4563 0 0
T10 18028 17956 0 0
T11 22732 22647 0 0
T12 2597 2524 0 0
T28 35331 35232 0 0

WaitCycMaskIsRightAlignedMask_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 538552980 538382136 0 0
T1 1561 1508 0 0
T2 4616 4541 0 0
T3 3651 3556 0 0
T4 12866 12673 0 0
T5 17765 17617 0 0
T6 17214 4563 0 0
T10 18028 17956 0 0
T11 22732 22647 0 0
T12 2597 2524 0 0
T28 35331 35232 0 0

WaitCycMaskMin_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 538552980 538382136 0 0
T1 1561 1508 0 0
T2 4616 4541 0 0
T3 3651 3556 0 0
T4 12866 12673 0 0
T5 17765 17617 0 0
T6 17214 4563 0 0
T10 18028 17956 0 0
T11 22732 22647 0 0
T12 2597 2524 0 0
T28 35331 35232 0 0

u_state_regs_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 538552980 538382136 0 0
T1 1561 1508 0 0
T2 4616 4541 0 0
T3 3651 3556 0 0
T4 12866 12673 0 0
T5 17765 17617 0 0
T6 17214 4563 0 0
T10 18028 17956 0 0
T11 22732 22647 0 0
T12 2597 2524 0 0
T28 35331 35232 0 0

Line Coverage for Instance : tb.dut.u_ping_timer
Line No.TotalCoveredPercent
TOTAL6262100.00
CONT_ASSIGN7811100.00
CONT_ASSIGN8111100.00
CONT_ASSIGN8211100.00
ALWAYS8533100.00
CONT_ASSIGN9911100.00
CONT_ASSIGN13411100.00
ALWAYS14144100.00
CONT_ASSIGN15211100.00
CONT_ASSIGN15611100.00
CONT_ASSIGN19611100.00
CONT_ASSIGN23311100.00
CONT_ASSIGN23411100.00
CONT_ASSIGN26411100.00
CONT_ASSIGN26511100.00
CONT_ASSIGN26811100.00
CONT_ASSIGN27811100.00
CONT_ASSIGN27911100.00
ALWAYS3313737100.00
ALWAYS42633100.00

77 78 1/1 assign reseed_timer_d = (reseed_timer_q > '0) ? reseed_timer_q - 1'b1 : Tests: T1 T2 T3  79 (reseed_en) ? {wait_cyc_mask_i, 80 {ReseedLfsrExtraBits{1'b1}}} : '0; 81 1/1 assign edn_req_o = (reseed_timer_q == '0); Tests: T1 T2 T3  82 1/1 assign reseed_en = edn_req_o & edn_ack_i; Tests: T1 T2 T3  83 84 always_ff @(posedge clk_i or negedge rst_ni) begin : p_regs 85 1/1 if (!rst_ni) begin Tests: T1 T2 T3  86 1/1 reseed_timer_q <= '0; Tests: T1 T2 T3  87 end else begin 88 1/1 reseed_timer_q <= reseed_timer_d; Tests: T1 T2 T3  89 end 90 end 91 92 /////////////////////////// 93 // Tandem LFSR Instances // 94 /////////////////////////// 95 96 logic cnt_set, lfsr_err; 97 logic [LfsrWidth-1:0] entropy; 98 logic [PING_CNT_DW + IdDw - 1:0] lfsr_state; 99 1/1 assign entropy = (reseed_en) ? edn_data_i[LfsrWidth-1:0] : '0; Tests: T1 T2 T3  100 101 // SEC_CM: PING_TIMER.LFSR.REDUN 102 // We employ two redundant LFSRs to guard against FI attacks. 103 // If any of the two is glitched and the two LFSR states do not agree, 104 // the FSM below is moved into a terminal error state and all ping alerts 105 // are permanently asserted. 106 prim_double_lfsr #( 107 .LfsrDw ( LfsrWidth ), 108 .EntropyDw ( LfsrWidth ), 109 .StateOutDw ( PING_CNT_DW + IdDw ), 110 .DefaultSeed ( RndCnstLfsrSeed ), 111 .StatePermEn ( 1'b1 ), 112 .StatePerm ( RndCnstLfsrPerm ), 113 .MaxLenSVA ( MaxLenSVA ), 114 .LockupSVA ( LockupSVA ), 115 .ExtSeedSVA ( 1'b0 ), // ext seed is unused 116 .EnableAlertTriggerSVA ( 1'b0 ) 117 ) u_prim_double_lfsr ( 118 .clk_i, 119 .rst_ni, 120 .seed_en_i ( 1'b0 ), 121 .seed_i ( '0 ), 122 .lfsr_en_i ( reseed_en || cnt_set ), 123 .entropy_i ( entropy ), 124 .state_o ( lfsr_state ), 125 .err_o ( lfsr_err ) 126 ); 127 128 logic [IdDw-1:0] id_to_ping_d, id_to_ping_q; 129 // The subtraction below ensures that the alert ID is always in range. If 130 // all alerts are enabled, an alert ID drawn in this way will always be 131 // valid. This comes at the cost of a bias towards certain alert IDs that 132 // will be pinged twice as often on average - but it ensures that we have 133 // less alert IDs that need to be skipped since they are invalid. 134 1/1 assign id_to_ping_d = (lfsr_state[PING_CNT_DW +: IdDw] >= NAlerts) ? Tests: T1 T2 T3  135 lfsr_state[PING_CNT_DW +: IdDw] - NAlerts : 136 lfsr_state[PING_CNT_DW +: IdDw]; 137 138 // we need to hold the ID stable while the ping is ongoing since this will result in 139 // spurious ping responses otherwise. 140 always_ff @(posedge clk_i or negedge rst_ni) begin : p_id_reg 141 1/1 if (!rst_ni) begin Tests: T1 T2 T3  142 1/1 id_to_ping_q <= '0; Tests: T1 T2 T3  143 end else begin 144 1/1 if (cnt_set) begin Tests: T1 T2 T3  145 1/1 id_to_ping_q <= id_to_ping_d; Tests: T4 T5 T6  146 end MISSING_ELSE 147 end 148 end 149 150 // align the enable mask with powers of two for the indexing operation below. 151 logic [2**IdDw-1:0] enable_mask; 152 1/1 assign enable_mask = (2**IdDw)'(alert_ping_en_i); Tests: T1 T2 T3  153 154 // check if the randomly drawn alert ID is actually valid and the alert is enabled 155 logic id_vld; 156 1/1 assign id_vld = enable_mask[id_to_ping_q]; Tests: T1 T2 T3  157 158 ////////////////////////////////// 159 // Escalation Counter Instances // 160 ////////////////////////////////// 161 162 // As opposed to the alert ID, the escalation sender ID to be pinged is not drawn at random. 163 // Rather, we cycle through the escalation senders one by one in a deterministic fashion. 164 // This allows us to provide guarantees needed for the ping timeout / auto escalation feature 165 // implemented at the escalation receiver side. 166 // 167 // In particular, with N_ESC_SEV escalation senders in the design, we can guarantee 168 // that each escalation channel will be pinged at least once every 169 // 170 // N_ESC_SEV x (NUM_WAIT_COUNT + NUM_TIMEOUT_COUNT) x 2**PING_CNT_DW 171 // 172 // cycles - independently of the reseeding operation. 173 // 174 // - N_ESC_SEV: # escalation channels to ping. 175 // - NUM_WAIT_COUNT: # wait counts between subsequent escalation channel pings. 176 // - NUM_TIMEOUT_COUNT: # timeout counts between subsequent escalation channel pings. 177 // - 2**PING_CNT_DW: # maximum counter value. 178 // 179 // This guarantee is used inside the escalation receivers to monitor the pings sent out by the 180 // alert handler. I.e., once the alert handler has started to send out pings, each escalation 181 // receiver employs a timeout window within which it expects the next ping to arrive. If 182 // escalation pings cease to arrive at an escalation receiver for any reason, this will 183 // automatically trigger the associated escalation countermeasure. 184 // 185 // In order to have enough margin, the escalation receiver timeout counters use a threshold that 186 // is 4x higher than the value calculated above. With N_ESC_SEV = 4, PING_CNT_DW = 16 and 187 // NUM_WAIT_COUNT = NUM_TIMEOUT_COUNT = 2 this amounts to a 22bit timeout threshold. 188 // 189 // We employ two redundant counters to guard against FI attacks. 190 // If any of the two is glitched and the two counter states do not agree, 191 // the FSM below is moved into a terminal error state and all ping alerts 192 // are permanently asserted. 193 194 logic esc_cnt_en, esc_cnt_clr, esc_cnt_error; 195 logic [EscSenderIdxWidth-1:0] esc_cnt; 196 1/1 assign esc_cnt_clr = (esc_cnt >= EscSenderIdxWidth'(N_ESC_SEV-1)) && esc_cnt_en; Tests: T1 T2 T3  197 198 // SEC_CM: PING_TIMER.CTR.REDUN 199 prim_count #( 200 .Width(EscSenderIdxWidth), 201 // The alert handler behaves differently than other comportable IP. I.e., instead of sending out 202 // an alert signal, this condition is handled internally in the alert handler. 203 .EnableAlertTriggerSVA(0), 204 // Pass a parameter to disable coverage for some assertions that are unreachable because set_i 205 // and decr_en_i are tied to zero. 206 .PossibleActions(prim_count_pkg::Clr | 207 prim_count_pkg::Incr) 208 ) u_prim_count_esc_cnt ( 209 .clk_i, 210 .rst_ni, 211 .clr_i(esc_cnt_clr), 212 .set_i(1'b0), 213 .set_cnt_i('0), 214 .incr_en_i(esc_cnt_en), 215 .decr_en_i(1'b0), 216 .step_i(EscSenderIdxWidth'(1)), 217 .commit_i(1'b1), 218 .cnt_o(esc_cnt), 219 .cnt_after_commit_o(), 220 .err_o(esc_cnt_error) 221 ); 222 223 ///////////////////////////// 224 // Timer Counter Instances // 225 ///////////////////////////// 226 227 // We employ two redundant counters to guard against FI attacks. 228 // If any of the two is glitched and the two counter states do not agree, 229 // the FSM below is moved into a terminal error state and all ping alerts 230 // are permanently asserted. 231 logic [PING_CNT_DW-1:0] cnt, cnt_setval; 232 logic wait_cnt_set, timeout_cnt_set, timer_expired, cnt_error; 233 1/1 assign timer_expired = (cnt == '0); Tests: T1 T2 T3  234 1/1 assign cnt_set = wait_cnt_set || timeout_cnt_set; Tests: T1 T2 T3  235 236 // SEC_CM: PING_TIMER.CTR.REDUN 237 prim_count #( 238 .Width(PING_CNT_DW), 239 // The alert handler behaves differently than other comportable IP. I.e., instead of sending out 240 // an alert signal, this condition is handled internally in the alert handler. 241 .EnableAlertTriggerSVA(0), 242 // Pass a parameter to disable coverage for some assertions that are unreachable because clr_i 243 // and incr_en_i are tied to zero. 244 .PossibleActions(prim_count_pkg::Set | 245 prim_count_pkg::Decr) 246 ) u_prim_count_cnt ( 247 .clk_i, 248 .rst_ni, 249 .clr_i(1'b0), 250 .set_i(cnt_set), 251 .set_cnt_i(cnt_setval), 252 .incr_en_i(1'b0), 253 .decr_en_i(1'b1), // we are counting down here. 254 .step_i(PING_CNT_DW'(1'b1)), 255 .commit_i(1'b1), 256 .cnt_o(cnt), 257 .cnt_after_commit_o(), 258 .err_o(cnt_error) 259 ); 260 261 // the constant offset ensures a minimum cycle spacing between pings. 262 logic unused_bits; 263 logic [PING_CNT_DW-1:0] wait_cyc; 264 1/1 assign wait_cyc = (lfsr_state[PING_CNT_DW-1:0] | PING_CNT_DW'(3'b100)); Tests: T1 T2 T3  265 1/1 assign unused_bits = lfsr_state[2]; Tests: T1 T2 T3  266 267 // note that the masks are used for DV/FPV only in order to reduce the state space. 268 1/1 assign cnt_setval = (wait_cnt_set) ? (wait_cyc & wait_cyc_mask_i) : ping_timeout_cyc_i; Tests: T1 T2 T3  269 270 //////////////////////////// 271 // Ping and Timeout Logic // 272 //////////////////////////// 273 274 logic alert_ping_en, esc_ping_en; 275 logic spurious_alert_ping, spurious_esc_ping; 276 277 // generate ping enable vector 278 1/1 assign alert_ping_req_o = NAlerts'(alert_ping_en) << id_to_ping_q; Tests: T1 T2 T3  279 1/1 assign esc_ping_req_o = EscSenderIdxWidth'(esc_ping_en) << esc_cnt; Tests: T1 T2 T3  280 281 // under normal operation, these signals should never be asserted. 282 // we place hand instantiated buffers here such that these signals are not 283 // optimized away during synthesis (these buffers will receive a keep or size_only 284 // attribute in our Vivado and DC synthesis flows). 285 prim_buf u_prim_buf_spurious_alert_ping ( 286 .in_i(|(alert_ping_ok_i & ~alert_ping_req_o)), 287 .out_o(spurious_alert_ping) 288 ); 289 prim_buf u_prim_buf_spurious_esc_ping ( 290 .in_i(|(esc_ping_ok_i & ~esc_ping_req_o)), 291 .out_o(spurious_esc_ping) 292 ); 293 294 // SEC_CM: PING_TIMER.FSM.SPARSE 295 // Encoding generated with: 296 // $ ./util/design/sparse-fsm-encode.py -d 5 -m 6 -n 9 \ 297 // -s 728582219 --language=sv 298 // 299 // Hamming distance histogram: 300 // 301 // 0: -- 302 // 1: -- 303 // 2: -- 304 // 3: -- 305 // 4: -- 306 // 5: |||||||||||||||||||| (60.00%) 307 // 6: ||||||||||||| (40.00%) 308 // 7: -- 309 // 8: -- 310 // 9: -- 311 // 312 // Minimum Hamming distance: 5 313 // Maximum Hamming distance: 6 314 // Minimum Hamming weight: 2 315 // Maximum Hamming weight: 6 316 // 317 localparam int StateWidth = 9; 318 typedef enum logic [StateWidth-1:0] { 319 InitSt = 9'b011001011, 320 AlertWaitSt = 9'b110000000, 321 AlertPingSt = 9'b101110001, 322 EscWaitSt = 9'b010110110, 323 EscPingSt = 9'b000011101, 324 FsmErrorSt = 9'b101101110 325 } state_e; 326 327 state_e state_d, state_q; 328 329 always_comb begin : p_fsm 330 // default 331 1/1 state_d = state_q; Tests: T1 T2 T3  332 1/1 wait_cnt_set = 1'b0; Tests: T1 T2 T3  333 1/1 timeout_cnt_set = 1'b0; Tests: T1 T2 T3  334 1/1 esc_cnt_en = 1'b0; Tests: T1 T2 T3  335 1/1 alert_ping_en = 1'b0; Tests: T1 T2 T3  336 1/1 esc_ping_en = 1'b0; Tests: T1 T2 T3  337 // this captures spurious ping responses 338 1/1 alert_ping_fail_o = spurious_alert_ping; Tests: T1 T2 T3  339 1/1 esc_ping_fail_o = spurious_esc_ping; Tests: T1 T2 T3  340 341 1/1 unique case (state_q) Tests: T1 T2 T3  342 // wait until activated 343 // we never return to this state 344 // once activated! 345 InitSt: begin 346 1/1 if (en_i) begin Tests: T1 T2 T3  347 1/1 state_d = AlertWaitSt; Tests: T4 T5 T6  348 1/1 wait_cnt_set = 1'b1; Tests: T4 T5 T6  349 end MISSING_ELSE 350 end 351 // wait for random amount of cycles 352 AlertWaitSt: begin 353 1/1 if (timer_expired) begin Tests: T4 T5 T6  354 1/1 state_d = AlertPingSt; Tests: T4 T5 T7  355 1/1 timeout_cnt_set = 1'b1; Tests: T4 T5 T7  356 end MISSING_ELSE 357 end 358 // SEC_CM: ALERT_RX.INTERSIG.BKGN_CHK 359 // send out an alert ping request and wait for a ping 360 // response or a ping timeout (whatever comes first). 361 // if the alert ID is not valid, we drop the request and 362 // proceed to the next ping. 363 AlertPingSt: begin 364 1/1 alert_ping_en = id_vld; Tests: T4 T5 T7  365 1/1 if (timer_expired || |(alert_ping_ok_i & alert_ping_req_o) || !id_vld) begin Tests: T4 T5 T7  366 1/1 state_d = EscWaitSt; Tests: T4 T5 T7  367 1/1 wait_cnt_set = 1'b1; Tests: T4 T5 T7  368 1/1 if (timer_expired) begin Tests: T4 T5 T7  369 1/1 alert_ping_fail_o = 1'b1; Tests: T19 T20 T21  370 end MISSING_ELSE 371 end MISSING_ELSE 372 end 373 // wait for random amount of cycles 374 EscWaitSt: begin 375 1/1 if (timer_expired) begin Tests: T4 T5 T7  376 1/1 state_d = EscPingSt; Tests: T4 T5 T7  377 1/1 timeout_cnt_set = 1'b1; Tests: T4 T5 T7  378 end MISSING_ELSE 379 end 380 // SEC_CM: ESC_TX.INTERSIG.BKGN_CHK 381 // send out an escalation ping request and wait for a ping 382 // response or a ping timeout (whatever comes first) 383 EscPingSt: begin 384 1/1 esc_ping_en = 1'b1; Tests: T4 T5 T7  385 1/1 if (timer_expired || |(esc_ping_ok_i & esc_ping_req_o)) begin Tests: T4 T5 T7  386 1/1 state_d = AlertWaitSt; Tests: T4 T5 T7  387 1/1 wait_cnt_set = 1'b1; Tests: T4 T5 T7  388 1/1 esc_cnt_en = 1'b1; Tests: T4 T5 T7  389 1/1 if (timer_expired) begin Tests: T4 T5 T7  390 1/1 esc_ping_fail_o = 1'b1; Tests: T19 T20 T21  391 end MISSING_ELSE 392 end MISSING_ELSE 393 end 394 // SEC_CM: PING_TIMER.FSM.LOCAL_ESC 395 // terminal FSM error state. 396 // if we for some reason end up in this state (e.g. malicious glitching) 397 // we are going to assert both ping fails continuously 398 FsmErrorSt: begin 399 1/1 alert_ping_fail_o = 1'b1; Tests: T6 T8 T9  400 1/1 esc_ping_fail_o = 1'b1; Tests: T6 T8 T9  401 end 402 default: begin 403 state_d = FsmErrorSt; 404 alert_ping_fail_o = 1'b1; 405 esc_ping_fail_o = 1'b1; 406 end 407 endcase 408 409 // SEC_CM: PING_TIMER.FSM.LOCAL_ESC 410 // if the two LFSR or counter states do not agree, 411 // we move into the terminal state. 412 1/1 if (lfsr_err || cnt_error || esc_cnt_error) begin Tests: T1 T2 T3  413 1/1 state_d = FsmErrorSt; Tests: T6 T8 T9  414 1/1 alert_ping_fail_o = 1'b1; Tests: T6 T8 T9  415 1/1 esc_ping_fail_o = 1'b1; Tests: T6 T8 T9  416 end MISSING_ELSE 417 end 418 419 /////////////////// 420 // FSM Registers // 421 /////////////////// 422 423 // The alert handler behaves differently than other comportable IP. I.e., instead of sending out 424 // an alert signal, this condition is handled internally in the alert handler. The 425 // EnableAlertTriggerSVA parameter is therefore set to 0. 426 3/3 `PRIM_FLOP_SPARSE_FSM(u_state_regs, state_d, state_q, state_e, InitSt, clk_i, rst_ni, 0) Tests: T1 T2 T3  | T1 T2 T3  | T1 T2 T3 
PRIM_FLOP_SPARSE_FSM(u_state_regs, state_d, state_q, state_e, InitSt, clk_i, rst_ni, 0): 426.1 `ifdef SIMULATION 426.2 prim_sparse_fsm_flop #( 426.3 .StateEnumT(state_e), 426.4 .Width($bits(state_e)), 426.5 .ResetValue($bits(state_e)'(InitSt)), 426.6 .EnableAlertTriggerSVA(0), 426.7 .CustomForceName("state_q") 426.8 ) u_state_regs ( 426.9 .clk_i ( clk_i ), 426.10 .rst_ni ( rst_ni ), 426.11 .state_i ( state_d ), 426.12 .state_o ( ) 426.13 ); 426.14 always_ff @(posedge clk_i or negedge rst_ni) begin 426.15 1/1 if (!rst_ni) begin Tests: T1 T2 T3  426.16 1/1 state_q <= InitSt; Tests: T1 T2 T3  426.17 end else begin 426.18 1/1 state_q <= state_d; Tests: T1 T2 T3  426.19 end 426.20 end 426.21 u_state_regs_A: assert property (@(posedge clk_i) disable iff ((!rst_ni) !== '0) (state_q === u_state_regs.state_o)) 426.22 else begin 426.23 `ifdef UVM 426.24 uvm_pkg::uvm_report_error("ASSERT FAILED", "u_state_regs_A", uvm_pkg::UVM_NONE, 426.25 "../src/lowrisc_ip_alert_handler_component_0.1/rtl/alert_handler_ping_timer.sv", 426, "", 1); 426.26 `else 426.27 $error("%0t: (%0s:%0d) [%m] [ASSERT FAILED] %0s", $time, `__FILE__, `__LINE__, 426.28 `PRIM_STRINGIFY(u_state_regs_A)); 426.29 `endif 426.30 end 426.31 `else 426.32 prim_sparse_fsm_flop #( 426.33 .StateEnumT(state_e), 426.34 .Width($bits(state_e)), 426.35 .ResetValue($bits(state_e)'(InitSt)), 426.36 .EnableAlertTriggerSVA(0) 426.37 ) u_state_regs ( 426.38 .clk_i ( clk_i ), 426.39 .rst_ni ( rst_ni ), 426.40 .state_i ( state_d ), 426.41 .state_o ( state_q ) 426.42 ); 426.43 `endif

Cond Coverage for Instance : tb.dut.u_ping_timer
TotalCoveredPercent
Conditions373697.30
Logical373697.30
Non-Logical00
Event00

 LINE       78
 EXPRESSION ((reseed_timer_q > '0) ? ((reseed_timer_q - 1'b1)) : (reseed_en ? ({wait_cyc_mask_i, {ReseedLfsrExtraBits {1'b1}}}) : '0))
             ----------1----------
-1-StatusTests
0CoveredT1,T2,T3
1CoveredT1,T2,T3

 LINE       78
 SUB-EXPRESSION (reseed_en ? ({wait_cyc_mask_i, {ReseedLfsrExtraBits {1'b1}}}) : '0)
                 ----1----
-1-StatusTests
0CoveredT1,T2,T3
1CoveredT1,T2,T3

 LINE       81
 EXPRESSION (reseed_timer_q == '0)
            -----------1----------
-1-StatusTests
0CoveredT1,T2,T3
1CoveredT1,T2,T3

 LINE       82
 EXPRESSION (edn_req_o & edn_ack_i)
             ----1----   ----2----
-1--2-StatusTests
01Not Covered
10CoveredT1,T2,T3
11CoveredT1,T2,T3

 LINE       99
 EXPRESSION (reseed_en ? edn_data_i[(alert_pkg::LfsrWidth - 1):0] : '0)
             ----1----
-1-StatusTests
0CoveredT1,T2,T3
1CoveredT1,T2,T3

 LINE       117
 EXPRESSION (reseed_en || cnt_set)
             ----1----    ---2---
-1--2-StatusTests
00CoveredT1,T2,T3
01CoveredT4,T5,T6
10CoveredT1,T2,T3

 LINE       134
 EXPRESSION 
 Number  Term
      1  (lfsr_state[alert_pkg::PING_CNT_DW+:IdDw] >= alert_pkg::NAlerts) ? ((lfsr_state[alert_pkg::PING_CNT_DW+:IdDw] - alert_pkg::NAlerts)) : lfsr_state[alert_pkg::PING_CNT_DW+:IdDw])
-1-StatusTests
0CoveredT4,T10,T5
1CoveredT1,T2,T3

 LINE       196
 EXPRESSION ((esc_cnt >= 2'((alert_pkg::N_ESC_SEV - 1))) && esc_cnt_en)
             ---------------------1---------------------    -----2----
-1--2-StatusTests
01CoveredT4,T5,T7
10CoveredT4,T5,T8
11CoveredT4,T5,T7

 LINE       233
 EXPRESSION (cnt == '0)
            -----1-----
-1-StatusTests
0CoveredT1,T2,T3
1CoveredT1,T2,T3

 LINE       234
 EXPRESSION (wait_cnt_set || timeout_cnt_set)
             ------1-----    -------2-------
-1--2-StatusTests
00CoveredT1,T2,T3
01CoveredT4,T5,T7
10CoveredT4,T5,T6

 LINE       268
 EXPRESSION (wait_cnt_set ? ((wait_cyc & wait_cyc_mask_i)) : ping_timeout_cyc_i)
             ------1-----
-1-StatusTests
0CoveredT1,T2,T3
1CoveredT4,T5,T6

 LINE       365
 EXPRESSION (timer_expired || ((|(alert_ping_ok_i & alert_ping_req_o))) || ((!id_vld)))
             ------1------    --------------------2--------------------    -----3-----
-1--2--3-StatusTests
000CoveredT4,T5,T7
001CoveredT4,T5,T7
010CoveredT4,T5,T7
100CoveredT19,T20,T21

 LINE       385
 EXPRESSION (timer_expired || ((|(esc_ping_ok_i & esc_ping_req_o))))
             ------1------    ------------------2------------------
-1--2-StatusTests
00CoveredT4,T5,T7
01CoveredT4,T5,T7
10CoveredT19,T20,T21

 LINE       412
 EXPRESSION (lfsr_err || cnt_error || esc_cnt_error)
             ----1---    ----2----    ------3------
-1--2--3-StatusTests
000CoveredT1,T2,T3
001CoveredT6,T8,T9
010CoveredT6,T8,T9
100CoveredT6,T8,T9

FSM Coverage for Instance : tb.dut.u_ping_timer
Summary for FSM :: state_q
TotalCoveredPercent
States 6 6 100.00 (Not included in score)
Transitions 6 6 100.00
Sequences 0 0

State, Transition and Sequence Details for FSM :: state_q
statesLine No.CoveredTests
AlertPingSt 354 Covered T4,T5,T7
AlertWaitSt 347 Covered T4,T5,T6
EscPingSt 376 Covered T4,T5,T7
EscWaitSt 366 Covered T4,T5,T7
FsmErrorSt 413 Covered T6,T8,T9
InitSt 345 Covered T1,T2,T3


transitionsLine No.CoveredTestsExclude Annotation
AlertPingSt->EscWaitSt 366 Covered T4,T5,T7
AlertPingSt->FsmErrorSt 413 Excluded [LOW_RISK]: Forcing from any state other than IdleSt to FSMErrorSt is covered in FPV.
AlertWaitSt->AlertPingSt 354 Covered T4,T5,T7
AlertWaitSt->FsmErrorSt 413 Covered T6,T8,T9
EscPingSt->AlertWaitSt 386 Covered T4,T5,T7
EscPingSt->FsmErrorSt 413 Excluded [LOW_RISK]: Forcing from any state other than IdleSt to FSMErrorSt is covered in FPV.
EscWaitSt->EscPingSt 376 Covered T4,T5,T7
EscWaitSt->FsmErrorSt 413 Excluded [LOW_RISK]: Forcing from any state other than IdleSt to FSMErrorSt is covered in FPV.
InitSt->AlertWaitSt 347 Covered T4,T5,T6
InitSt->FsmErrorSt 413 Excluded [LOW_RISK]: Forcing from any state other than IdleSt to FSMErrorSt is covered in FPV.



Branch Coverage for Instance : tb.dut.u_ping_timer
Line No.TotalCoveredPercent
Branches 32 32 100.00
TERNARY 78 3 3 100.00
TERNARY 99 2 2 100.00
TERNARY 134 2 2 100.00
TERNARY 268 2 2 100.00
IF 85 2 2 100.00
IF 141 3 3 100.00
CASE 341 14 14 100.00
IF 412 2 2 100.00
IF 426 2 2 100.00


78 assign reseed_timer_d = (reseed_timer_q > '0) ? reseed_timer_q - 1'b1 : -1- ==> 79 (reseed_en) ? {wait_cyc_mask_i, -2- ==> ==>

Branches:
-1--2-StatusTests
1 - Covered T1,T2,T3
0 1 Covered T1,T2,T3
0 0 Covered T1,T2,T3


99 assign entropy = (reseed_en) ? edn_data_i[LfsrWidth-1:0] : '0; -1- ==> ==>

Branches:
-1-StatusTests
1 Covered T1,T2,T3
0 Covered T1,T2,T3


134 assign id_to_ping_d = (lfsr_state[PING_CNT_DW +: IdDw] >= NAlerts) ? -1- ==> ==>

Branches:
-1-StatusTests
1 Covered T1,T2,T3
0 Covered T4,T10,T5


268 assign cnt_setval = (wait_cnt_set) ? (wait_cyc & wait_cyc_mask_i) : ping_timeout_cyc_i; -1- ==> ==>

Branches:
-1-StatusTests
1 Covered T4,T5,T6
0 Covered T1,T2,T3


85 if (!rst_ni) begin -1- 86 reseed_timer_q <= '0; ==> 87 end else begin 88 reseed_timer_q <= reseed_timer_d; ==>

Branches:
-1-StatusTests
1 Covered T1,T2,T3
0 Covered T1,T2,T3


141 if (!rst_ni) begin -1- 142 id_to_ping_q <= '0; ==> 143 end else begin 144 if (cnt_set) begin -2- 145 id_to_ping_q <= id_to_ping_d; ==> 146 end MISSING_ELSE ==>

Branches:
-1--2-StatusTests
1 - Covered T1,T2,T3
0 1 Covered T4,T5,T6
0 0 Covered T1,T2,T3


341 unique case (state_q) -1- 342 // wait until activated 343 // we never return to this state 344 // once activated! 345 InitSt: begin 346 if (en_i) begin -2- 347 state_d = AlertWaitSt; ==> 348 wait_cnt_set = 1'b1; 349 end MISSING_ELSE ==> 350 end 351 // wait for random amount of cycles 352 AlertWaitSt: begin 353 if (timer_expired) begin -3- 354 state_d = AlertPingSt; ==> 355 timeout_cnt_set = 1'b1; 356 end MISSING_ELSE ==> 357 end 358 // SEC_CM: ALERT_RX.INTERSIG.BKGN_CHK 359 // send out an alert ping request and wait for a ping 360 // response or a ping timeout (whatever comes first). 361 // if the alert ID is not valid, we drop the request and 362 // proceed to the next ping. 363 AlertPingSt: begin 364 alert_ping_en = id_vld; 365 if (timer_expired || |(alert_ping_ok_i & alert_ping_req_o) || !id_vld) begin -4- 366 state_d = EscWaitSt; 367 wait_cnt_set = 1'b1; 368 if (timer_expired) begin -5- 369 alert_ping_fail_o = 1'b1; ==> 370 end MISSING_ELSE ==> 371 end MISSING_ELSE ==> 372 end 373 // wait for random amount of cycles 374 EscWaitSt: begin 375 if (timer_expired) begin -6- 376 state_d = EscPingSt; ==> 377 timeout_cnt_set = 1'b1; 378 end MISSING_ELSE ==> 379 end 380 // SEC_CM: ESC_TX.INTERSIG.BKGN_CHK 381 // send out an escalation ping request and wait for a ping 382 // response or a ping timeout (whatever comes first) 383 EscPingSt: begin 384 esc_ping_en = 1'b1; 385 if (timer_expired || |(esc_ping_ok_i & esc_ping_req_o)) begin -7- 386 state_d = AlertWaitSt; 387 wait_cnt_set = 1'b1; 388 esc_cnt_en = 1'b1; 389 if (timer_expired) begin -8- 390 esc_ping_fail_o = 1'b1; ==> 391 end MISSING_ELSE ==> 392 end MISSING_ELSE ==> 393 end 394 // SEC_CM: PING_TIMER.FSM.LOCAL_ESC 395 // terminal FSM error state. 396 // if we for some reason end up in this state (e.g. malicious glitching) 397 // we are going to assert both ping fails continuously 398 FsmErrorSt: begin 399 alert_ping_fail_o = 1'b1; ==> 400 esc_ping_fail_o = 1'b1; 401 end 402 default: begin 403 state_d = FsmErrorSt; ==>

Branches:
-1--2--3--4--5--6--7--8-StatusTests
InitSt 1 - - - - - - Covered T4,T5,T6
InitSt 0 - - - - - - Covered T1,T2,T3
AlertWaitSt - 1 - - - - - Covered T4,T5,T7
AlertWaitSt - 0 - - - - - Covered T4,T5,T6
AlertPingSt - - 1 1 - - - Covered T19,T20,T21
AlertPingSt - - 1 0 - - - Covered T4,T5,T7
AlertPingSt - - 0 - - - - Covered T4,T5,T7
EscWaitSt - - - - 1 - - Covered T4,T5,T7
EscWaitSt - - - - 0 - - Covered T4,T5,T7
EscPingSt - - - - - 1 1 Covered T19,T20,T21
EscPingSt - - - - - 1 0 Covered T4,T5,T7
EscPingSt - - - - - 0 - Covered T4,T5,T7
FsmErrorSt - - - - - - - Covered T6,T8,T9
default - - - - - - - Covered T6,T8,T9


412 if (lfsr_err || cnt_error || esc_cnt_error) begin -1- 413 state_d = FsmErrorSt; ==> 414 alert_ping_fail_o = 1'b1; 415 esc_ping_fail_o = 1'b1; 416 end MISSING_ELSE ==>

Branches:
-1-StatusTests
1 Covered T6,T8,T9
0 Covered T1,T2,T3


426 `PRIM_FLOP_SPARSE_FSM(u_state_regs, state_d, state_q, state_e, InitSt, clk_i, rst_ni, 0) -1- ==> ==>

Branches:
-1-StatusTests
1 Covered T1,T2,T3
0 Covered T1,T2,T3


Assert Coverage for Instance : tb.dut.u_ping_timer
TotalAttemptedPercentSucceeded/MatchedPercent
Assertions 7 7 100.00 7 100.00
Cover properties 0 0 0
Cover sequences 0 0 0
Total 7 7 100.00 7 100.00




Assertion Details

NameAttemptsReal SuccessesFailuresIncomplete
AlertPingOH_A 538552980 202063 0 0
EscPingOH_A 538552980 134545 0 0
MaxIdDw_A 617 617 0 0
PingOH0_A 538552980 538382136 0 0
WaitCycMaskIsRightAlignedMask_A 538552980 538382136 0 0
WaitCycMaskMin_A 538552980 538382136 0 0
u_state_regs_A 538552980 538382136 0 0


AlertPingOH_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 538552980 202063 0 0
T4 12866 2225 0 0
T5 17765 2515 0 0
T6 17214 0 0 0
T7 0 1251 0 0
T8 41292 0 0 0
T10 18028 0 0 0
T11 22732 0 0 0
T16 43811 0 0 0
T19 0 500 0 0
T22 0 2169 0 0
T23 0 1867 0 0
T24 0 2857 0 0
T25 0 2414 0 0
T26 0 2081 0 0
T27 0 5 0 0
T28 35331 0 0 0
T29 46058 0 0 0
T30 57586 0 0 0

EscPingOH_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 538552980 134545 0 0
T4 12866 2275 0 0
T5 17765 2520 0 0
T6 17214 0 0 0
T7 0 1230 0 0
T8 41292 0 0 0
T10 18028 0 0 0
T11 22732 0 0 0
T16 43811 0 0 0
T19 0 153 0 0
T22 0 2135 0 0
T23 0 1830 0 0
T24 0 2820 0 0
T25 0 2393 0 0
T26 0 2070 0 0
T28 35331 0 0 0
T29 46058 0 0 0
T30 57586 0 0 0
T31 0 5 0 0

MaxIdDw_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 617 617 0 0
T1 1 1 0 0
T2 1 1 0 0
T3 1 1 0 0
T4 1 1 0 0
T5 1 1 0 0
T6 1 1 0 0
T10 1 1 0 0
T11 1 1 0 0
T12 1 1 0 0
T28 1 1 0 0

PingOH0_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 538552980 538382136 0 0
T1 1561 1508 0 0
T2 4616 4541 0 0
T3 3651 3556 0 0
T4 12866 12673 0 0
T5 17765 17617 0 0
T6 17214 4563 0 0
T10 18028 17956 0 0
T11 22732 22647 0 0
T12 2597 2524 0 0
T28 35331 35232 0 0

WaitCycMaskIsRightAlignedMask_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 538552980 538382136 0 0
T1 1561 1508 0 0
T2 4616 4541 0 0
T3 3651 3556 0 0
T4 12866 12673 0 0
T5 17765 17617 0 0
T6 17214 4563 0 0
T10 18028 17956 0 0
T11 22732 22647 0 0
T12 2597 2524 0 0
T28 35331 35232 0 0

WaitCycMaskMin_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 538552980 538382136 0 0
T1 1561 1508 0 0
T2 4616 4541 0 0
T3 3651 3556 0 0
T4 12866 12673 0 0
T5 17765 17617 0 0
T6 17214 4563 0 0
T10 18028 17956 0 0
T11 22732 22647 0 0
T12 2597 2524 0 0
T28 35331 35232 0 0

u_state_regs_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 538552980 538382136 0 0
T1 1561 1508 0 0
T2 4616 4541 0 0
T3 3651 3556 0 0
T4 12866 12673 0 0
T5 17765 17617 0 0
T6 17214 4563 0 0
T10 18028 17956 0 0
T11 22732 22647 0 0
T12 2597 2524 0 0
T28 35331 35232 0 0

0% 10% 20% 30% 40% 50% 60% 70% 80% 90% 100%