[dv/lc_ctrl] enhance smoke test These PR did a few enhancement for the lc_ctrl smoke test: 1. Move the constraints to next_valid_lc_state request to `lc_ctrl_env_pkg.sv` so we can reuse that in scb. Thanks weicai for the help and suggestions. We found for an associative array, index cannot be randomized with constraint, so we spilt it into a separate randomize function within the sequence. 2. Minor clean up and add some comments. 3. Use all three registers for lc input token instead of one. Signed-off-by: Cindy Chen <chencindy@google.com>
diff --git a/hw/ip/lc_ctrl/dv/env/lc_ctrl_env_pkg.sv b/hw/ip/lc_ctrl/dv/env/lc_ctrl_env_pkg.sv index a4347a0..f49aac7 100644 --- a/hw/ip/lc_ctrl/dv/env/lc_ctrl_env_pkg.sv +++ b/hw/ip/lc_ctrl/dv/env/lc_ctrl_env_pkg.sv
@@ -20,11 +20,32 @@ `include "dv_macros.svh" // parameters - // TODO: add the names of alerts in order parameter string LIST_OF_ALERTS[] = {"lc_programming_failure", "lc_state_failure"}; parameter uint NUM_ALERTS = 2; parameter uint CLAIM_TRANS_VAL = 'ha5; + // associative array cannot declare parameter here, so we used const instead + const dec_lc_state_e VALID_NEXT_STATES [dec_lc_state_e][$] = '{ + DecLcStRma: {DecLcStScrap}, + DecLcStProdEnd: {DecLcStScrap}, + DecLcStProd: {DecLcStScrap, DecLcStRma}, + DecLcStDev: {DecLcStScrap, DecLcStRma}, + DecLcStTestUnlocked3: {DecLcStScrap, DecLcStRma, DecLcStProdEnd, DecLcStProd, DecLcStDev}, + DecLcStTestUnlocked2: {DecLcStScrap, DecLcStProdEnd, DecLcStProd, DecLcStDev, + DecLcStTestLocked2}, + DecLcStTestUnlocked1: {DecLcStScrap, DecLcStRma, DecLcStProdEnd, DecLcStProd, DecLcStDev, + DecLcStTestLocked2, DecLcStTestLocked1}, + DecLcStTestUnlocked0: {DecLcStScrap, DecLcStRma, DecLcStProdEnd, DecLcStProd, DecLcStDev, + DecLcStTestLocked2, DecLcStTestLocked1, DecLcStTestLocked0}, + DecLcStTestLocked2: {DecLcStScrap, DecLcStProdEnd, DecLcStProd, + DecLcStDev, DecLcStTestUnlocked3}, + DecLcStTestLocked1: {DecLcStScrap, DecLcStProdEnd, DecLcStProd, DecLcStDev, + DecLcStTestUnlocked3, DecLcStTestUnlocked2}, + DecLcStTestLocked0: {DecLcStScrap, DecLcStProdEnd, DecLcStProd, DecLcStDev, + DecLcStTestUnlocked3, DecLcStTestUnlocked2, DecLcStTestUnlocked1}, + DecLcStRaw: {DecLcStScrap, DecLcStTestUnlocked2, DecLcStTestUnlocked1, DecLcStTestUnlocked0} + }; + // types typedef enum bit [1:0] { LcPwrInitReq, @@ -37,6 +58,33 @@ typedef virtual lc_ctrl_if lc_ctrl_vif; // functions + function automatic bit valid_state_for_trans(lc_state_e curr_state); + valid_state_for_trans = 0; + if (curr_state inside {LcStRma, LcStProdEnd, LcStProd, LcStDev, LcStTestUnlocked3, + LcStTestUnlocked2, LcStTestUnlocked1, LcStTestUnlocked0, + LcStTestLocked2, LcStTestLocked1, LcStTestLocked0, LcStRaw}) begin + valid_state_for_trans = 1; + end + endfunction + + function automatic dec_lc_state_e dec_lc_state(lc_state_e curr_state); + case (curr_state) + LcStRaw: return DecLcStRaw; + LcStTestUnlocked0: return DecLcStTestUnlocked0; + LcStTestLocked0: return DecLcStTestLocked0; + LcStTestUnlocked1: return DecLcStTestUnlocked1; + LcStTestLocked1: return DecLcStTestLocked1; + LcStTestUnlocked2: return DecLcStTestUnlocked2; + LcStTestLocked2: return DecLcStTestLocked2; + LcStTestUnlocked3: return DecLcStTestUnlocked3; + LcStDev: return DecLcStDev; + LcStProd: return DecLcStProd; + LcStProdEnd: return DecLcStProdEnd; + LcStRma: return DecLcStRma; + LcStScrap: return DecLcStScrap; + default: `uvm_fatal("lc_env_pkg", $sformatf("unknown lc_state 0x%0h", curr_state)) + endcase + endfunction // package sources `include "lc_ctrl_env_cfg.sv"
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 417c234..cd6e9f7 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
@@ -47,10 +47,12 @@ cfg.pwr_lc_vif.drive_pin(LcPwrInitReq, 0); endtask - virtual task sw_transition_req(bit [TL_DW-1:0] next_lc_state, bit [TL_DW-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); 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); + 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); endtask
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 9a2f940..ed97b34 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
@@ -8,62 +8,35 @@ `uvm_object_new - rand dec_lc_state_e next_lc_state; + dec_lc_state_e next_lc_state; constraint lc_cnt_c { lc_state != LcStRaw -> lc_cnt != LcCntRaw; } - constraint valid_next_lc_state_c { - // TODO: temp constraint, did not enable ram interface - next_lc_state != DecLcStRma; - lc_state == LcStRma -> next_lc_state inside {DecLcStScrap}; - lc_state == LcStProdEnd -> next_lc_state inside {DecLcStScrap}; - lc_state == LcStProd -> next_lc_state inside {DecLcStScrap, DecLcStRma}; - lc_state == LcStDev -> next_lc_state inside {DecLcStScrap, DecLcStRma}; - - lc_state == LcStTestUnlocked3 -> next_lc_state inside - {DecLcStScrap, DecLcStRma, DecLcStProdEnd, DecLcStProd, DecLcStDev}; - - lc_state == LcStTestLocked2 -> next_lc_state inside - {DecLcStScrap, DecLcStProdEnd, DecLcStProd, DecLcStDev, DecLcStTestUnlocked3}; - - lc_state == LcStTestUnlocked2 -> next_lc_state inside - {DecLcStScrap, DecLcStProdEnd, DecLcStProd, DecLcStDev, DecLcStTestLocked2}; - - lc_state == LcStTestLocked1 -> next_lc_state inside - {DecLcStScrap, DecLcStProdEnd, DecLcStProd, DecLcStDev, DecLcStTestUnlocked3, - DecLcStTestUnlocked2}; - - lc_state == LcStTestUnlocked1 -> next_lc_state inside - {DecLcStScrap, DecLcStRma, DecLcStProdEnd, DecLcStProd, DecLcStDev, - DecLcStTestLocked2, DecLcStTestLocked1}; - - lc_state == LcStTestLocked0 -> next_lc_state inside - {DecLcStScrap, DecLcStProdEnd, DecLcStProd, DecLcStDev, DecLcStTestUnlocked3, - DecLcStTestUnlocked2, DecLcStTestUnlocked1}; - - lc_state == LcStTestUnlocked0 -> next_lc_state inside - {DecLcStScrap, DecLcStRma, DecLcStProdEnd, DecLcStProd, DecLcStDev, - DecLcStTestLocked2, DecLcStTestLocked1, DecLcStTestLocked0}; - - lc_state == LcStRaw -> next_lc_state inside - {DecLcStScrap, DecLcStTestUnlocked2, DecLcStTestUnlocked1, DecLcStTestUnlocked0}; - } - task body(); for (int i = 1; i <= num_trans; i++) begin if (i != 1) dut_init(); - `uvm_info(`gfn, $sformatf("starting seq %0d/%0d, init LC_state is %0s, LC_cnt is %0s", i, num_trans, lc_state.name, lc_cnt.name), UVM_MEDIUM) // SW transition request - if (lc_state != LcStScrap && lc_cnt != LcCnt16) begin - bit [TL_DW-1:0] token_val = $urandom(); + if (valid_state_for_trans(lc_state) && lc_cnt != LcCnt16) begin + bit [TL_DW*3-1:0] token_val = {$urandom(), $urandom(), $urandom()}; + 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); end end endtask : body + // smoke test will always return valid next_lc_state + // need to randomize here because associative array's index cannot be a rand input in constraint + virtual function void randomize_next_lc_state(dec_lc_state_e curr_lc_state); + `DV_CHECK_STD_RANDOMIZE_WITH_FATAL(next_lc_state, + // TODO: temp constraint for no DecLcStRma + next_lc_state inside {VALID_NEXT_STATES[curr_lc_state]}; next_lc_state != DecLcStRma;) + endfunction + endclass : lc_ctrl_smoke_vseq
diff --git a/hw/ip/lc_ctrl/dv/tb.sv b/hw/ip/lc_ctrl/dv/tb.sv index a150bcf..80cc4b1 100644 --- a/hw/ip/lc_ctrl/dv/tb.sv +++ b/hw/ip/lc_ctrl/dv/tb.sv
@@ -21,6 +21,7 @@ // TODO: use push-pull agent wire lc_otp_token_rsp_t lc_rsp; assign lc_rsp.ack = 1; + // TODO: temp constraint to 0 because it has to equal to otp_lc_data_i tokens assign lc_rsp.hashed_token = 0; // interfaces