[dv/lc_ctrl] Add lc_ctrl sequence to trigger otp_prog_failure alert This PR adds a lc_ctrl sequence to test scoreboard alert checkings. The sequence will be optmized further once the push-pull agent support data constraints. The purpose of this commit is to create a testcase for cip_base_scb alert checking. Signed-off-by: Cindy Chen <chencindy@google.com>
diff --git a/hw/ip/lc_ctrl/data/lc_ctrl_testplan.hjson b/hw/ip/lc_ctrl/data/lc_ctrl_testplan.hjson index abec17e..1471060 100644 --- a/hw/ip/lc_ctrl/data/lc_ctrl_testplan.hjson +++ b/hw/ip/lc_ctrl/data/lc_ctrl_testplan.hjson
@@ -65,7 +65,7 @@ - Check if lc_state moves to escalation state ''' milestone: V2 - tests: [] + tests: ["lc_ctrl_prog_failure"] } { name: lc_state_failure
diff --git a/hw/ip/lc_ctrl/dv/env/lc_ctrl_env.core b/hw/ip/lc_ctrl/dv/env/lc_ctrl_env.core index 73ab837..89cd570 100644 --- a/hw/ip/lc_ctrl/dv/env/lc_ctrl_env.core +++ b/hw/ip/lc_ctrl/dv/env/lc_ctrl_env.core
@@ -22,6 +22,7 @@ - seq_lib/lc_ctrl_base_vseq.sv: {is_include_file: true} - seq_lib/lc_ctrl_common_vseq.sv: {is_include_file: true} - seq_lib/lc_ctrl_smoke_vseq.sv: {is_include_file: true} + - seq_lib/lc_ctrl_prog_failure_vseq.sv: {is_include_file: true} file_type: systemVerilogSource generate:
diff --git a/hw/ip/lc_ctrl/dv/env/lc_ctrl_if.sv b/hw/ip/lc_ctrl/dv/env/lc_ctrl_if.sv index b18e7a4..df4db66 100644 --- a/hw/ip/lc_ctrl/dv/env/lc_ctrl_if.sv +++ b/hw/ip/lc_ctrl/dv/env/lc_ctrl_if.sv
@@ -10,6 +10,7 @@ import otp_ctrl_part_pkg::*; logic tdo_oe; // TODO: add assertions + logic prog_err; // TODO: remove once push-pull can constrain data otp_ctrl_pkg::otp_lc_data_t otp_i; otp_ctrl_part_pkg::otp_hw_cfg_t otp_hw_cfg_i; @@ -54,6 +55,7 @@ clk_byp_ack_i = clk_byp_ack; flash_rma_ack_i = flash_rma_ack; + prog_err = 0; endtask task automatic set_clk_byp_ack(lc_ctrl_pkg::lc_tx_t val);
diff --git a/hw/ip/lc_ctrl/dv/env/lc_ctrl_scoreboard.sv b/hw/ip/lc_ctrl/dv/env/lc_ctrl_scoreboard.sv index b49ad8a..9d22a29 100644 --- a/hw/ip/lc_ctrl/dv/env/lc_ctrl_scoreboard.sv +++ b/hw/ip/lc_ctrl/dv/env/lc_ctrl_scoreboard.sv
@@ -40,6 +40,7 @@ super.run_phase(phase); fork check_lc_output(); + process_otp_prog_rsp(); join_none endtask @@ -70,6 +71,17 @@ end endtask + virtual task process_otp_prog_rsp(); + forever begin + push_pull_item#(.HostDataWidth(OTP_PROG_HDATA_WIDTH), + .DeviceDataWidth(OTP_PROG_DDATA_WIDTH)) item_rcv; + otp_prog_fifo.get(item_rcv); + if (cfg.lc_ctrl_vif.prog_err == 1) begin + void'(set_exp_alert(.alert_name("lc_programming_failure"), .max_delay(0), .always_on(1))); + end + end + endtask + // check lc outputs, default all off virtual function void check_lc_outputs(lc_outputs_t exp_o = '{default:lc_ctrl_pkg::Off}, string msg = "expect all output OFF");
diff --git a/hw/ip/lc_ctrl/dv/env/seq_lib/lc_ctrl_base_vseq.sv b/hw/ip/lc_ctrl/dv/env/seq_lib/lc_ctrl_base_vseq.sv index 343d48a..c304599 100644 --- a/hw/ip/lc_ctrl/dv/env/seq_lib/lc_ctrl_base_vseq.sv +++ b/hw/ip/lc_ctrl/dv/env/seq_lib/lc_ctrl_base_vseq.sv
@@ -96,14 +96,24 @@ join_none endtask - virtual task sw_transition_req(bit [TL_DW-1:0] next_lc_state, bit [TL_DW*3-1:0] token_val); + virtual task sw_transition_req(bit [TL_DW-1:0] next_lc_state, + bit [TL_DW*3-1:0] token_val, + bit trans_success = 1); csr_wr(ral.claim_transition_if, CLAIM_TRANS_VAL); csr_wr(ral.transition_target, next_lc_state); csr_wr(ral.transition_token_0, token_val[TL_DW-1:0]); csr_wr(ral.transition_token_1, token_val[TL_DW*2-1:TL_DW]); csr_wr(ral.transition_token_2, token_val[TL_DW*3-1:TL_DW*2]); csr_wr(ral.transition_cmd, 'h01); - csr_spinwait(ral.status.transition_successful, 1); + if (trans_success) begin + csr_spinwait(ral.status.transition_successful, 1); + end else begin + // TODO: temp support only for otp_error + csr_spinwait(ral.status.otp_error, 1); + // always on alert, set time delay to make sure alert triggered for at least for one + // handshake cycle + cfg.clk_rst_vif.wait_clks($urandom_range(20, 50)); + end endtask // checking of these two CSRs are done in scb
diff --git a/hw/ip/lc_ctrl/dv/env/seq_lib/lc_ctrl_prog_failure_vseq.sv b/hw/ip/lc_ctrl/dv/env/seq_lib/lc_ctrl_prog_failure_vseq.sv new file mode 100644 index 0000000..37e0bd7 --- /dev/null +++ b/hw/ip/lc_ctrl/dv/env/seq_lib/lc_ctrl_prog_failure_vseq.sv
@@ -0,0 +1,44 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +// This sequence triggers prog_failure alert by setting the error bit in otp_program_rsp +// Then check in scb if the alert is triggered correctly +class lc_ctrl_prog_failure_vseq extends lc_ctrl_smoke_vseq; + `uvm_object_utils(lc_ctrl_prog_failure_vseq) + + `uvm_object_new + + virtual function void configure_vseq(); + this.trans_success_c.constraint_mode(0); + endfunction + + virtual task body(); + fork + super.body(); + set_prog_failure(); + join_any + disable fork; + endtask + + virtual task post_start(); + super.post_start(); + // trigger dut_init to make sure always on alert is not firing forever + dut_init(); + endtask + + task set_prog_failure(); + forever begin + wait(cfg.m_otp_prog_pull_agent_cfg.vif.req == 1); + if (trans_success) begin + cfg.lc_ctrl_vif.prog_err = 0; + end else begin + cfg.lc_ctrl_vif.prog_err = 1; + end + wait (cfg.m_otp_prog_pull_agent_cfg.vif.req == 0); + cfg.clk_rst_vif.wait_clks(2); + cfg.lc_ctrl_vif.prog_err = 0; + end + endtask + +endclass
diff --git a/hw/ip/lc_ctrl/dv/env/seq_lib/lc_ctrl_smoke_vseq.sv b/hw/ip/lc_ctrl/dv/env/seq_lib/lc_ctrl_smoke_vseq.sv index 1a1f56e..aea9243 100644 --- a/hw/ip/lc_ctrl/dv/env/seq_lib/lc_ctrl_smoke_vseq.sv +++ b/hw/ip/lc_ctrl/dv/env/seq_lib/lc_ctrl_smoke_vseq.sv
@@ -10,17 +10,18 @@ rand bit clk_byp_error_rsp; rand bit flash_rma_error_rsp; + rand bit trans_success; dec_lc_state_e next_lc_state; - constraint lc_cnt_c { - lc_state != LcStRaw -> lc_cnt != LcCntRaw; - } - constraint no_err_rsps_c { clk_byp_error_rsp == 0; flash_rma_error_rsp == 0; } + constraint trans_success_c { + trans_success == 1; + } + task body(); run_clk_byp_rsp_nonblocking(clk_byp_error_rsp); run_flash_rma_rsp_nonblocking(flash_rma_error_rsp); @@ -41,7 +42,7 @@ randomize_next_lc_state(dec_lc_state(lc_state)); `uvm_info(`gfn, $sformatf("next_LC_state is %0s, input token is %0h", next_lc_state.name, token_val), UVM_DEBUG) - sw_transition_req(next_lc_state, token_val); + sw_transition_req(next_lc_state, token_val, trans_success); end else begin // wait at least two clks for scb to finish checking lc outputs cfg.clk_rst_vif.wait_clks($urandom_range(2, 10));
diff --git a/hw/ip/lc_ctrl/dv/env/seq_lib/lc_ctrl_vseq_list.sv b/hw/ip/lc_ctrl/dv/env/seq_lib/lc_ctrl_vseq_list.sv index 237a209..1322696 100644 --- a/hw/ip/lc_ctrl/dv/env/seq_lib/lc_ctrl_vseq_list.sv +++ b/hw/ip/lc_ctrl/dv/env/seq_lib/lc_ctrl_vseq_list.sv
@@ -5,3 +5,4 @@ `include "lc_ctrl_base_vseq.sv" `include "lc_ctrl_smoke_vseq.sv" `include "lc_ctrl_common_vseq.sv" +`include "lc_ctrl_prog_failure_vseq.sv"
diff --git a/hw/ip/lc_ctrl/dv/lc_ctrl_sim_cfg.hjson b/hw/ip/lc_ctrl/dv/lc_ctrl_sim_cfg.hjson index d97aa54..95c5a31 100644 --- a/hw/ip/lc_ctrl/dv/lc_ctrl_sim_cfg.hjson +++ b/hw/ip/lc_ctrl/dv/lc_ctrl_sim_cfg.hjson
@@ -51,7 +51,11 @@ uvm_test_seq: lc_ctrl_smoke_vseq } - // TODO: add more tests here + { + name: lc_ctrl_prog_failure + uvm_test_seq: lc_ctrl_prog_failure_vseq + } + ] // List of regressions.
diff --git a/hw/ip/lc_ctrl/dv/tb.sv b/hw/ip/lc_ctrl/dv/tb.sv index 1ac9db1..b8a7c87 100644 --- a/hw/ip/lc_ctrl/dv/tb.sv +++ b/hw/ip/lc_ctrl/dv/tb.sv
@@ -39,7 +39,7 @@ `DV_ALERT_IF_CONNECT // TODO: remove once OTP_PROG_DDATA_WIDTH is set to 1 - assign otp_prog_rsp.err = 0; + assign otp_prog_rsp.err = lc_ctrl_if.prog_err; assign otp_prog_rsp.ack = otp_prog_if.ack; assign otp_token_rsp.ack = otp_token_if.ack; // TODO: temp constraint to 0 because it has to equal to otp_lc_data_i tokens