blob: ccad56f4f070881f98f3ff6d8e1588d51dff6215 [file] [log] [blame]
// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
//
// The test to create transition to invalid state from any lowpower transitions.
class pwrmgr_lowpower_invalid_vseq extends pwrmgr_base_vseq;
`uvm_object_utils(pwrmgr_lowpower_invalid_vseq)
`uvm_object_new
// Create enum to map rtl local sparse state
// to continuous dv state.
typedef enum bit [3:0] {
DVWaitDisClks = 0,
DVWaitFallThrough = 1,
DVWaitNvmIdleChk = 2,
DVWaitLowPowerPrep = 3,
DVWaitReqPwrDn = 4,
DVWaitLowPower = 5,
DVWaitEnableClocks = 6,
DVWaitReleaseLcRst = 7,
DVWaitOtpInit = 8,
DVWaitLcInit = 9,
DVWaitAckPwrUp = 10,
DVWaitRomCheck = 11,
DVWaitStrap = 12,
DVWaitActive = 13,
DVWaitInvalid = 14
} reset_index_e;
constraint wakeups_c {wakeups != 0;}
constraint wakeup_en_c {
solve wakeups before wakeups_en;
|(wakeups_en & wakeups) == 1'b1;
}
task body();
reset_index_e reset_index;
resets_t enabled_resets;
string path = "tb.dut.u_fsm.fsm_invalid_i";
int num_of_target_states = 4;
// Spurious interrupt check can be executed by
// residue of lowpower task. Since we cannot kill csr op
// by disable fork, we have to disable spurious interrup check.
cfg.invalid_st_test = 1;
wait_for_fast_fsm_active();
`uvm_info(`gfn, "At body start", UVM_MEDIUM)
check_wake_status('0);
reset_index = DVWaitFallThrough;
for (int i = 0; i < num_of_target_states; ++i) begin
`uvm_info(`gfn, $sformatf("Starting new round%0d %s", i, reset_index.name), UVM_MEDIUM)
`DV_CHECK_RANDOMIZE_FATAL(this)
setup_interrupt(.enable(en_intr));
fork
start_lowpower_transition();
begin
int wait_time_ns = 10000;
`DV_SPINWAIT(wait(cfg.pwrmgr_vif.fast_state == dv2rtl_st(reset_index));, $sformatf(
"Timed out waiting for state %s", reset_index.name), wait_time_ns)
@cfg.clk_rst_vif.cbn;
`DV_CHECK(uvm_hdl_force(path, 1))
`uvm_info(`gfn, "Injected invalid slow state", UVM_MEDIUM)
@cfg.clk_rst_vif.cb;
end
join_any
@cfg.clk_rst_vif.cb;
`DV_CHECK(uvm_hdl_release(path))
`DV_CHECK(cfg.pwrmgr_vif.fast_state, pwrmgr_pkg::FastPwrStateInvalid)
repeat (10) @cfg.clk_rst_vif.cb;
apply_reset();
reset_index++;
wait_for_fast_fsm_active();
end // for (int i = 0; i < 4; ++i)
endtask
task start_lowpower_transition();
wakeups_t enabled_wakeups = wakeups_en & wakeups;
`DV_CHECK(enabled_wakeups, $sformatf(
"Some wakeup must be enabled: wkups=%b, wkup_en=%b", wakeups, wakeups_en))
`uvm_info(`gfn, $sformatf("Enabled wakeups=0x%x", enabled_wakeups), UVM_MEDIUM)
csr_wr(.ptr(ral.wakeup_en[0]), .value(wakeups_en));
low_power_hint = 1;
update_control_csr();
wait_for_csr_to_propagate_to_slow_domain();
`uvm_info(`gfn, $sformatf("Enabled wakeups=0x%x", enabled_wakeups), UVM_MEDIUM)
// Initiate low power transition.
cfg.pwrmgr_vif.update_cpu_sleeping(1'b1);
set_nvms_idle();
`DV_WAIT(cfg.pwrmgr_vif.fast_state != pwrmgr_pkg::FastPwrStateActive)
if (ral.control.main_pd_n.get_mirrored_value() == 1'b0) begin
wait_for_reset_cause(pwrmgr_pkg::LowPwrEntry);
end
// Now bring it back.
cfg.clk_rst_vif.wait_clks(cycles_before_wakeup);
cfg.pwrmgr_vif.update_wakeups(wakeups);
wait(cfg.pwrmgr_vif.pwr_clk_req.main_ip_clk_en == 1'b1);
// wakeups should be registered.
cfg.pwrmgr_vif.update_wakeups('1);
wait_for_fast_fsm_active();
`uvm_info(`gfn, "Back from wakeup", UVM_MEDIUM)
endtask : start_lowpower_transition
function pwrmgr_pkg::fast_pwr_state_e dv2rtl_st(reset_index_e idx);
case (idx)
DVWaitDisClks: return pwrmgr_pkg::FastPwrStateDisClks;
DVWaitFallThrough: return pwrmgr_pkg::FastPwrStateFallThrough;
DVWaitNvmIdleChk: return pwrmgr_pkg::FastPwrStateNvmIdleChk;
DVWaitLowPowerPrep: return pwrmgr_pkg::FastPwrStateLowPowerPrep;
DVWaitReqPwrDn: return pwrmgr_pkg::FastPwrStateReqPwrDn;
DVWaitLowPower: return pwrmgr_pkg::FastPwrStateLowPower;
DVWaitEnableClocks: return pwrmgr_pkg::FastPwrStateEnableClocks;
DVWaitReleaseLcRst: return pwrmgr_pkg::FastPwrStateReleaseLcRst;
DVWaitOtpInit: return pwrmgr_pkg::FastPwrStateOtpInit;
DVWaitLcInit: return pwrmgr_pkg::FastPwrStateLcInit;
DVWaitAckPwrUp: return pwrmgr_pkg::FastPwrStateAckPwrUp;
DVWaitRomCheck: return pwrmgr_pkg::FastPwrStateRomCheckDone;
DVWaitStrap: return pwrmgr_pkg::FastPwrStateStrap;
DVWaitActive: return pwrmgr_pkg::FastPwrStateActive;
DVWaitInvalid: return pwrmgr_pkg::FastPwrStateInvalid;
default: begin
`uvm_error("dv2rma_st", $sformatf("unknown index:%0d", idx))
end
endcase
endfunction : dv2rtl_st
endclass : pwrmgr_lowpower_invalid_vseq