blob: 880bd9e60d13232a479e8756b080613ff64e5989 [file] [log] [blame]
// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
// This sequence sends read traffic with error injection
// at the output of read_buffer.
// Read response will trigger fatal_err.storage_err.
class flash_ctrl_rd_path_intg_vseq extends flash_ctrl_legacy_base_vseq;
`uvm_object_utils(flash_ctrl_rd_path_intg_vseq)
`uvm_object_new
task body();
int idx1, idx2;
string path1, path2;
int state_timeout_ns = 100000; // 100us
repeat(5) begin
flash_op_t host;
bit [TL_AW-1:0] tl_addr;
bit saw_err, completed;
data_4s_t rdata;
// Enable ecc for all regions
flash_otf_region_cfg(.scr_mode(scr_ecc_cfg), .ecc_mode(OTFCfgTrue));
idx1 = $urandom_range(0, 63);
idx2 = $urandom_range(0, 63);
path1 = {"tb.dut.u_eflash.gen_flash_cores[0].u_core",
$sformatf(".u_rd.gen_bufs[0].u_rd_buf.data_i[%0d]", idx1)};
path2 = {"tb.dut.u_eflash.gen_flash_cores[1].u_core",
$sformatf(".u_rd.gen_bufs[0].u_rd_buf.data_i[%0d]", idx2)};
cfg.clk_rst_vif.wait_clks(10);
`uvm_info(`gfn, $sformatf("Assert read path err idx1:%0d idx2:%0d", idx1, idx2), UVM_LOW)
`DV_CHECK(uvm_hdl_force(path1, 1'b0))
`DV_CHECK(uvm_hdl_force(path2, 1'b0))
cfg.scb_h.expected_alert["fatal_err"].expected = 1;
cfg.scb_h.expected_alert["fatal_err"].max_delay = 2000;
cfg.scb_h.exp_alert_contd["fatal_err"] = 10000;
cfg.scb_h.exp_tl_rsp_intg_err = 1;
tl_addr[OTFHostId-2:0] = $urandom();
tl_addr[1:0] = 'h0;
tl_addr[OTFBankId] = $urandom_range(0, 1);
for (int i = 0; i < cfg.otf_num_hr; ++i) begin
bit local_saw_err;
// fatal_err.phy_storage_err
tl_access_w_abort(
.addr(tl_addr), .write(1'b0), .completed(completed),
.saw_err(local_saw_err),
.tl_access_timeout_ns(cfg.seq_cfg.erase_timeout_ns),
.data(rdata), .check_rsp(1'b0), .blocking(1),
.tl_sequencer_h(p_sequencer.tl_sequencer_hs[cfg.flash_ral_name]));
saw_err |= local_saw_err;
if ((i % 2)== 1) tl_addr += 4;
end
csr_utils_pkg::wait_no_outstanding_access();
`DV_CHECK_EQ(saw_err, 1)
// Check fault_status register and err_code register to make sure
// host read only triggers fault_status.phy_storage_err
collect_err_cov_status(ral.fault_status);
csr_rd_check(.ptr(ral.fault_status.phy_storage_err), .compare_value(1));
csr_rd_check(.ptr(ral.err_code), .compare_value(0));
`uvm_info(`gfn, "Wait until all drain", UVM_LOW)
cfg.clk_rst_vif.wait_clks(100);
`DV_CHECK(uvm_hdl_release(path1))
`DV_CHECK(uvm_hdl_release(path2))
// reset for the next round
cfg.seq_cfg.disable_flash_init = 1;
cfg.seq_cfg.en_init_keys_seeds = 0;
apply_reset();
csr_wr(.ptr(ral.init), .value(1));
`uvm_info("Test","OTP",UVM_LOW)
otp_model();
`DV_SPINWAIT(wait(cfg.flash_ctrl_vif.rd_buf_en == 1);,
"Timed out waiting for rd_buf_en",
state_timeout_ns)
cfg.clk_rst_vif.wait_clks(10);
end
// disable tlul_err_cnt check
cfg.tlul_core_obs_cnt = cfg.tlul_core_exp_cnt;
endtask
endclass