@@ -14,6 +14,7 @@ class chip_sw_rv_core_ibex_lockstep_glitch_vseq extends chip_sw_base_vseq;
1414 int unsigned width; // >0: take this as width; 0: use width from parameter
1515 string width_parameter_name;
1616 int unsigned unpacked_dim_width;
17+ int unsigned offset;
1718 } port_t ;
1819
1920 typedef logic [255 : 0 ] val_t ;
@@ -205,70 +206,85 @@ class chip_sw_rv_core_ibex_lockstep_glitch_vseq extends chip_sw_base_vseq;
205206 " Could not read LockstepOffset parameter." );
206207
207208 // List of all ports and their bit widths (or the name of the parameter that defines the width
208- // and/or the unpacked dimension).
209+ // and/or the unpacked dimension). The fourth field allows enabling an offset from where the
210+ // fault will be injected.
209211 ports = new [45 ];
210212 ports = '{
211213 // `hart_id_i` and `boot_addr_i` are not glitch-protected by the lockstep core.
212- // '{"hart_id_i", 1, "", 0},
213- // '{"boot_addr_i", 1, "", 0},
214- '{ " instr_req_o" , 1 , " " , 0 } ,
215- '{ " instr_gnt_i" , 1 , " " , 0 } ,
216- '{ " instr_rvalid_i" , 1 , " " , 0 } ,
217- '{ " instr_addr_o" , 32 , " " , 0 } ,
218- '{ " instr_rdata_i" , 0 , " MemDataWidth" , 0 } ,
219- '{ " instr_err_i" , 1 , " " , 0 } ,
220- '{ " data_req_o" , 1 , " " , 0 } ,
221- '{ " data_gnt_i" , 1 , " " , 0 } ,
222- '{ " data_rvalid_i" , 1 , " " , 0 } ,
223- '{ " data_we_o" , 1 , " " , 0 } ,
224- '{ " data_be_o" , 1 , " " , 0 } ,
225- '{ " data_addr_o" , 32 , " " , 0 } ,
226- '{ " data_wdata_o" , 0 , " MemDataWidth" , 0 } ,
227- '{ " data_rdata_i" , 0 , " MemDataWidth" , 0 } ,
228- '{ " data_err_i" , 1 , " " , 0 } ,
229- '{ " dummy_instr_id_o" , 1 , " " , 0 } ,
230- '{ " rf_raddr_a_o" , 5 , " " , 0 } ,
231- '{ " rf_raddr_b_o" , 5 , " " , 0 } ,
232- '{ " rf_waddr_wb_o" , 5 , " " , 0 } ,
233- '{ " rf_we_wb_o" , 1 , " " , 0 } ,
234- '{ " rf_wdata_wb_ecc_o" , 0 , " RegFileDataWidth" , 0 } ,
235- '{ " rf_rdata_a_ecc_i" , 0 , " RegFileDataWidth" , 0 } ,
236- '{ " rf_rdata_b_ecc_i" , 0 , " RegFileDataWidth" , 0 } ,
237- '{ " ic_tag_req_o" , ibex_pkg :: IC_NUM_WAYS , " " , 0 } ,
238- '{ " ic_tag_write_o" , 1 , " " , 0 } ,
239- '{ " ic_tag_addr_o" , ibex_pkg :: IC_INDEX_W , " " , 0 } ,
240- '{ " ic_tag_wdata_o" , 0 , " TagSizeECC" , 0 } ,
241- '{ " ic_tag_rdata_i" , 0 , " TagSizeECC" , ibex_pkg :: IC_NUM_WAYS } ,
242- '{ " ic_data_req_o" , ibex_pkg :: IC_NUM_WAYS , " " , 0 } ,
243- '{ " ic_data_write_o" , 1 , " " , 0 } ,
244- '{ " ic_data_addr_o" , ibex_pkg :: IC_INDEX_W , " " , 0 } ,
245- '{ " ic_data_wdata_o" , 0 , " LineSizeECC" , 0 } ,
246- '{ " ic_data_rdata_i" , 0 , " LineSizeECC" , ibex_pkg :: IC_NUM_WAYS } ,
247- '{ " ic_scr_key_valid_i" , 1 , " " , 0 } ,
248- '{ " ic_scr_key_req_o" , 1 , " " , 0 } ,
249- '{ " irq_software_i" , 1 , " " , 0 } ,
250- '{ " irq_timer_i" , 1 , " " , 0 } ,
251- '{ " irq_external_i" , 1 , " " , 0 } ,
252- '{ " irq_fast_i" , 15 , " " , 0 } ,
253- '{ " irq_nm_i" , 1 , " " , 0 } ,
254- '{ " irq_pending_o" , 1 , " " , 0 } ,
255- '{ " debug_req_i" , 1 , " " , 0 } ,
256- '{ " crash_dump_o" , $bits(ibex_pkg :: crash_dump_t), " " , 0 } ,
257- '{ " double_fault_seen_o" , 1 , " " , 0 } ,
214+ // '{"hart_id_i", 1, "", 0, 0},
215+ // '{"boot_addr_i", 1, "", 0, 0},
216+ '{ " instr_req_o" , 1 , " " , 0 , 0 } ,
217+ '{ " instr_gnt_i" , 1 , " " , 0 , 0 } ,
218+ '{ " instr_rvalid_i" , 1 , " " , 0 , 0 } ,
219+ '{ " instr_addr_o" , 32 , " " , 0 , 0 } ,
220+ '{ " instr_rdata_i" , 0 , " MemDataWidth" , 0 , 0 } ,
221+ '{ " instr_err_i" , 1 , " " , 0 , 0 } ,
222+ '{ " data_req_o" , 1 , " " , 0 , 0 } ,
223+ '{ " data_gnt_i" , 1 , " " , 0 , 0 } ,
224+ '{ " data_rvalid_i" , 1 , " " , 0 , 0 } ,
225+ '{ " data_we_o" , 1 , " " , 0 , 0 } ,
226+ '{ " data_be_o" , 1 , " " , 0 , 0 } ,
227+ '{ " data_addr_o" , 32 , " " , 0 , 0 } ,
228+ '{ " data_wdata_o" , 0 , " MemDataWidth" , 0 , 0 } ,
229+ '{ " data_rdata_i" , 0 , " MemDataWidth" , 0 , 0 } ,
230+ '{ " data_err_i" , 1 , " " , 0 , 0 } ,
231+ '{ " dummy_instr_id_o" , 1 , " " , 0 , 0 } ,
232+ '{ " rf_raddr_a_o" , 5 , " " , 0 , 0 } ,
233+ '{ " rf_raddr_b_o" , 5 , " " , 0 , 0 } ,
234+ '{ " rf_waddr_wb_o" , 5 , " " , 0 , 0 } ,
235+ '{ " rf_we_wb_o" , 1 , " " , 0 , 0 } ,
236+ '{ " ic_tag_req_o" , ibex_pkg :: IC_NUM_WAYS , " " , 0 , 0 } ,
237+ '{ " ic_tag_write_o" , 1 , " " , 0 , 0 } ,
238+ '{ " ic_tag_addr_o" , ibex_pkg :: IC_INDEX_W , " " , 0 , 0 } ,
239+ '{ " ic_tag_wdata_o" , 0 , " TagSizeECC" , 0 , 0 } ,
240+ '{ " ic_tag_rdata_i" , 0 , " TagSizeECC" , ibex_pkg :: IC_NUM_WAYS , 0 } ,
241+ '{ " ic_data_req_o" , ibex_pkg :: IC_NUM_WAYS , " " , 0 , 0 } ,
242+ '{ " ic_data_write_o" , 1 , " " , 0 , 0 } ,
243+ '{ " ic_data_addr_o" , ibex_pkg :: IC_INDEX_W , " " , 0 , 0 } ,
244+ '{ " ic_data_wdata_o" , 0 , " LineSizeECC" , 0 , 0 } ,
245+ '{ " ic_data_rdata_i" , 0 , " LineSizeECC" , ibex_pkg :: IC_NUM_WAYS , 0 } ,
246+ '{ " ic_scr_key_valid_i" , 1 , " " , 0 , 0 } ,
247+ '{ " ic_scr_key_req_o" , 1 , " " , 0 , 0 } ,
248+ '{ " irq_software_i" , 1 , " " , 0 , 0 } ,
249+ '{ " irq_timer_i" , 1 , " " , 0 , 0 } ,
250+ '{ " irq_external_i" , 1 , " " , 0 , 0 } ,
251+ '{ " irq_fast_i" , 15 , " " , 0 , 0 } ,
252+ '{ " irq_nm_i" , 1 , " " , 0 , 0 } ,
253+ '{ " irq_pending_o" , 1 , " " , 0 , 0 } ,
254+ '{ " debug_req_i" , 1 , " " , 0 , 0 } ,
255+ '{ " crash_dump_o" , $bits(ibex_pkg :: crash_dump_t), " " , 0 , 0 } ,
256+ '{ " double_fault_seen_o" , 1 , " " , 0 , 0 } ,
258257 // `fetch_enable_i` is a multi-bit signal, and multi-bit FI is outside the threat model.
259- // '{"fetch_enable_i", 1, "", 0},
258+ // '{"fetch_enable_i", 1, "", 0, 0 },
260259 // The `alert_*` output signals are not compared between the regular core and the lockstep
261260 // core. Thus, those outputs are not protected against glitches. This is intentional because
262261 // an alert is raised in reaction to a glitch (potentially an injected fault) inside the core.
263262 // To then also glitch the `alert_*` outputs, the attacker would need to be able to glitch two
264263 // signals at the same time, which is outside the threat model. Thus, these signals are
265264 // excluded from the list of outputs in order to prevent false negative test results.
266- // '{"alert_minor_o", 1, "", 0},
267- // '{"alert_major_internal_o", 1, "", 0},
268- // '{"alert_major_bus_o", 1, "", 0},
269- '{ " core_busy_o" , 1 , " " , 0 }
265+ // '{"alert_minor_o", 1, "", 0, 0 },
266+ // '{"alert_major_internal_o", 1, "", 0, 0 },
267+ // '{"alert_major_bus_o", 1, "", 0, 0 },
268+ '{ " core_busy_o" , 1 , " " , 0 , 0 }
270269 } ;
271270
271+ glitch_lockstep_core = $urandom_range (1 );
272+ // The main core uses a register file data width of RegFileDataWidth and the
273+ // shadow core uses RegFileDataEccWidth. Assemble the ports array
274+ // accordingly.
275+ if (glitch_lockstep_core) begin
276+ // Although the shadow core drives all RegFileDataEccWidth bits of rf_wdata_wb_ecc_o, only
277+ // bits RegFileDataEccWidth-1:RegFileDataWidth are forwarded to the shadow register file.
278+ // As a fault in the lower bits have no effect, use an offset of RegFileDataWidth.
279+ ports[42 ] = '{ " rf_wdata_wb_ecc_o" , 0 , " RegFileDataEccWidth" , 0 , " RegFileDataWidth" } ;
280+ ports[43 ] = '{ " rf_rdata_a_ecc_i" , 0 , " RegFileDataEccWidth" , 0 , 0 } ;
281+ ports[44 ] = '{ " rf_rdata_b_ecc_i" , 0 , " RegFileDataEccWidth" , 0 , 0 } ;
282+ end else begin
283+ ports[42 ] = '{ " rf_wdata_wb_ecc_o" , 0 , " RegFileDataWidth" , 0 , 0 } ;
284+ ports[43 ] = '{ " rf_rdata_a_ecc_i" , 0 , " RegFileDataWidth" , 0 , 0 } ;
285+ ports[44 ] = '{ " rf_rdata_b_ecc_i" , 0 , " RegFileDataWidth" , 0 , 0 } ;
286+ end
287+
272288 // Randomly pick a port (of either the lockstep core or the regular core) to glitch.
273289 port_idx = $urandom_range (ports.size () - 1 );
274290 if (ports[port_idx].width > 0 ) begin
@@ -280,7 +296,6 @@ class chip_sw_rv_core_ibex_lockstep_glitch_vseq extends chip_sw_base_vseq;
280296 " Could not obtain port width from parameter value." );
281297 `DV_CHECK_FATAL (port_width > 0 , " Read zero port width from parameter value." )
282298 end
283- glitch_lockstep_core = $urandom_range (1 );
284299 glitch_core_path = glitch_lockstep_core ? lockstep_core_path : core_path;
285300 port_name = ports[port_idx].name;
286301 glitch_path = $sformatf (" %s .%s " , glitch_core_path, port_name);
@@ -296,7 +311,7 @@ class chip_sw_rv_core_ibex_lockstep_glitch_vseq extends chip_sw_base_vseq;
296311 end
297312
298313 // Pick one bit to glitch in the port.
299- bit_idx = $urandom_range (port_width - 1 ) ;
314+ bit_idx = $urandom_range (port_width - 1 - ports[port_idx].offset) + ports[port_idx].offset ;
300315
301316 // Wait until the CPU is executing code, except if glitching the I$ scramble key valid port.
302317 // The reason is that the scramble key is provided shortly after reset and then not again until
0 commit comments