-
Notifications
You must be signed in to change notification settings - Fork 752
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[sram_ctrl,dv] Add sec_cm_mem_readback test
This commit provides a new sec_cm_readback test that tests the SRAM readback FI countermeasure. In the test, a fault is injected during one of the read/write SRAM requests. The test checks, whether the expected alert fires. Closes #23322. Signed-off-by: Pascal Nasahl <[email protected]>
- Loading branch information
Showing
8 changed files
with
170 additions
and
9 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
139 changes: 139 additions & 0 deletions
139
hw/ip/sram_ctrl/dv/env/seq_lib/sram_ctrl_readback_err_vseq.sv
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,139 @@ | ||
// Copyright lowRISC contributors (OpenTitan project). | ||
// Licensed under the Apache License, Version 2.0, see LICENSE for details. | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
// readback_err_vseq | ||
class sram_ctrl_readback_err_vseq extends sram_ctrl_base_vseq; | ||
`uvm_object_utils(sram_ctrl_readback_err_vseq) | ||
|
||
`uvm_object_new | ||
|
||
// Indicates the number of memory accesses to be performed in this test. | ||
rand int num_ops; | ||
|
||
// Indicates at which memory access the fault is injected. | ||
rand int do_fi_op; | ||
|
||
constraint num_ops_c { | ||
num_ops inside {[10 : 200]}; | ||
} | ||
|
||
constraint do_fi_op_c { | ||
do_fi_op inside {[10 : num_ops]}; | ||
} | ||
|
||
int fi_iteration_position = 0; | ||
|
||
task drive_reqs(int iterations); | ||
// Perform random read/write operations. | ||
bit [TL_AW-1:0] addr; | ||
bit [TL_AW-1:0] sram_addr_mask = cfg.ral_models[cfg.sram_ral_name].get_addr_mask(); | ||
bit [TL_AW-1:0] max_offset = {sram_addr_mask[TL_AW-1:2], 2'd0}; | ||
logic [TL_DW-1:0] rdata; | ||
for (int iteration = 0; iteration < iterations; iteration++) begin | ||
bit write = $urandom_range(0, 1); | ||
`DV_CHECK_STD_RANDOMIZE_WITH_FATAL(addr, (addr & sram_addr_mask) < max_offset;) | ||
if (write) begin | ||
do_single_write(.addr(addr), .data(iteration), .mask('1), .blocking(0)); | ||
end else begin | ||
do_single_read(.addr(addr), .mask('1), .check_rdata(0), .blocking(0), .rdata(rdata)); | ||
end | ||
end | ||
endtask | ||
|
||
task inject_fault(int iterations, int iteration_fi_position, string fi_path, | ||
string tlul_req_path); | ||
// Inject a fault into the signal indicated by fi_path. | ||
bit req; | ||
for (int iteration = 0; iteration < iterations; iteration++) begin | ||
// Wait until the TL-UL request arrives in the SRAM module. | ||
`DV_SPINWAIT( | ||
do begin | ||
#1ps; | ||
uvm_hdl_read(tlul_req_path, req); | ||
end while(!req); | ||
) | ||
|
||
// Check if it is time to inject a fault. | ||
if (iteration == iteration_fi_position) begin | ||
`uvm_info(`gfn, $sformatf( | ||
"Injecting fault into %s in memory operation %d", | ||
fi_path, iteration_fi_position), | ||
UVM_LOW) | ||
`DV_CHECK(uvm_hdl_force(fi_path, 'hbeef)) | ||
// Release the faulty signal after one clock cycle. | ||
cfg.clk_rst_vif.wait_clks(1); | ||
`DV_CHECK(uvm_hdl_release(fi_path)) | ||
end | ||
cfg.clk_rst_vif.wait_clks(1); | ||
end | ||
endtask | ||
|
||
task monitor_response(int iterations, int iteration_fi_position, string alert_signal, | ||
string tlul_req_path); | ||
// Monitor whether the alert_signal was triggered. | ||
bit req; | ||
for (int iteration = 0; iteration < iterations; iteration++) begin | ||
// Wait until the TL-UL request arrives in the SRAM module. | ||
`DV_SPINWAIT( | ||
do begin | ||
#1ps; | ||
uvm_hdl_read(tlul_req_path, req); | ||
end while(!req); | ||
) | ||
// Check if it is time to monitor the response. | ||
if (iteration == iteration_fi_position) begin | ||
`uvm_info(`gfn, $sformatf("Checking the %s alert", alert_signal), UVM_LOW) | ||
// Check if alert_signal was triggered. | ||
cfg.scb.set_exp_alert(alert_signal, .is_fatal(1'b1), .max_delay(20)); | ||
wait_alert_trigger (alert_signal, .max_wait_cycle(20), .wait_complete(0)); | ||
// Reset to get the DUT out of terminal state. | ||
apply_resets_concurrently(); | ||
end | ||
cfg.clk_rst_vif.wait_clks(1); | ||
end | ||
endtask | ||
|
||
task body(); | ||
// Used as a FI target. | ||
// TODO: add list of signals instead of using a single signal. Currently only | ||
// the read or write address is faulted. | ||
string fi_path = "tb.dut.sram_addr"; | ||
// Used to keep track of the incoming TL-UL requests. | ||
string tlul_req_path = "tb.dut.ram_tl_i.a_valid"; | ||
// The readback feature raises the fatal_error alert on a mismatch. | ||
string alert_signal = "fatal_error"; | ||
|
||
// Disable certain checks for FI. | ||
cfg.is_fi_test = 1'b1; | ||
|
||
`DV_CHECK_MEMBER_RANDOMIZE_FATAL(num_ops) | ||
`DV_CHECK_MEMBER_RANDOMIZE_FATAL(do_fi_op) | ||
|
||
// Request memory init & enable SRAM readback feature. | ||
req_mem_init(); | ||
csr_wr(.ptr(ral.readback), .value(MuBi4True)); | ||
|
||
// Sanity check some static paths we use in this test. | ||
`DV_CHECK(uvm_hdl_check_path(fi_path), | ||
$sformatf("Hierarchical path %0s appears to be invalid.", fi_path)) | ||
`DV_CHECK(uvm_hdl_check_path(tlul_req_path), | ||
$sformatf("Hierarchical path %0s appears to be invalid.", tlul_req_path)) | ||
|
||
// As we have at least 10 memory requests, correct the offset. | ||
fi_iteration_position = do_fi_op - 10; | ||
|
||
// Start the parallel threads. | ||
fork | ||
// Driver task. | ||
drive_reqs(num_ops); | ||
|
||
// Fault injector task. | ||
inject_fault(num_ops, fi_iteration_position, fi_path, tlul_req_path); | ||
|
||
// Monitoring task. | ||
monitor_response(num_ops, fi_iteration_position, alert_signal, tlul_req_path); | ||
join_any | ||
endtask : body | ||
|
||
endclass : sram_ctrl_readback_err_vseq |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters