[dv/pwrmgr] Fix reset coverage
Fix sampling while sleeping.
Don't send rstmgr sw reset while sleeping, since they are not realistic.
Break covergroups to be clearly per reset.
Signed-off-by: Guillermo Maturana <maturana@google.com>
diff --git a/hw/ip/pwrmgr/dv/env/pwrmgr_env_cov.sv b/hw/ip/pwrmgr/dv/env/pwrmgr_env_cov.sv
index 068d845..bc07f3a 100644
--- a/hw/ip/pwrmgr/dv/env/pwrmgr_env_cov.sv
+++ b/hw/ip/pwrmgr/dv/env/pwrmgr_env_cov.sv
@@ -87,25 +87,34 @@
control_cross: cross core_cp, io_cp, usb_lp_cp, usb_active_cp, main_pd_n_cp, sleep_cp;
endgroup
- covergroup reset_cg with function sample (
- resets_t hw_resets,
- resets_t hw_resets_en,
- logic sw_rst,
- logic main_pwr_rst,
- logic esc_rst,
- bit sleep
- );
- hw_resets_cp: coverpoint hw_resets;
- sw_rst_cp: coverpoint sw_rst;
- main_pwr_rst_cp: coverpoint main_pwr_rst;
- esc_rst_cp: coverpoint esc_rst;
- hw_resets_en_cp: coverpoint hw_resets_en;
+ covergroup hw_reset_0_cg with function sample (logic reset, logic enable, bit sleep);
+ reset_cp: coverpoint reset;
+ enable_cp: coverpoint enable;
sleep_cp: coverpoint sleep;
+ reset_cross: cross reset, enable, sleep;
+ endgroup
- hw_resets_cross: cross hw_resets_cp, hw_resets_en_cp, sleep_cp;
- esc_rst_cross: cross esc_rst_cp, sleep_cp;
- main_pwr_rst_cross: cross main_pwr_rst_cp, sleep_cp;
- sw_rst_cross: cross sw_rst_cp, sleep_cp;
+ covergroup hw_reset_1_cg with function sample (logic reset, logic enable, bit sleep);
+ reset_cp: coverpoint reset;
+ enable_cp: coverpoint enable;
+ sleep_cp: coverpoint sleep;
+ reset_cross: cross reset_cp, enable_cp, sleep_cp;
+ endgroup
+
+ covergroup rstmgr_sw_reset_cg with function sample (logic sw_reset);
+ sw_reset_cp: coverpoint sw_reset;
+ endgroup
+
+ covergroup main_power_reset_cg with function sample (logic main_power_reset, bit sleep);
+ main_power_reset_cp: coverpoint main_power_reset;
+ sleep_cp: coverpoint sleep;
+ reset_cross: cross main_power_reset_cp, sleep_cp;
+ endgroup
+
+ covergroup esc_reset_cg with function sample (logic esc_reset, bit sleep);
+ esc_reset_cp: coverpoint esc_reset;
+ sleep_cp: coverpoint sleep;
+ reset_cross: cross esc_reset_cp, sleep_cp;
endgroup
function new(string name, uvm_component parent);
@@ -116,7 +125,11 @@
wakeup_intr_cg_wrap[i] = new({wakeup.name, "_intr_cg"});
end
control_cg = new();
- reset_cg = new();
+ hw_reset_0_cg = new();
+ hw_reset_1_cg = new();
+ rstmgr_sw_reset_cg = new();
+ main_power_reset_cg = new();
+ esc_reset_cg = new();
endfunction : new
virtual function void build_phase(uvm_phase phase);
diff --git a/hw/ip/pwrmgr/dv/env/pwrmgr_scoreboard.sv b/hw/ip/pwrmgr/dv/env/pwrmgr_scoreboard.sv
index eb2d377..3feba31 100644
--- a/hw/ip/pwrmgr/dv/env/pwrmgr_scoreboard.sv
+++ b/hw/ip/pwrmgr/dv/env/pwrmgr_scoreboard.sv
@@ -74,29 +74,42 @@
end
endtask
- // Resets are triggered without deep sleep at this point.
- // TODO(maturana) Figure out how to determine a reset triggered while in sleep mode.
+ local task sample_reset_coverage(bit sleep);
+ cov.hw_reset_0_cg.sample(cfg.pwrmgr_vif.rstreqs_i[0], cfg.pwrmgr_vif.reset_en[0], sleep);
+ cov.hw_reset_1_cg.sample(cfg.pwrmgr_vif.rstreqs_i[1], cfg.pwrmgr_vif.reset_en[1], sleep);
+ cov.rstmgr_sw_reset_cg.sample(cfg.pwrmgr_vif.sw_rst_req_i == prim_mubi_pkg::MuBi4True);
+ cov.main_power_reset_cg.sample(cfg.pwrmgr_vif.pwr_rst_req.rstreqs[pwrmgr_pkg::ResetMainPwrIdx],
+ sleep);
+ cov.esc_reset_cg.sample(cfg.pwrmgr_vif.pwr_rst_req.rstreqs[pwrmgr_pkg::ResetEscIdx], sleep);
+ `uvm_info(`gfn, $sformatf(
+ {
+ "reset_cg sample with hw_resets=%b, hw_resets_en=%b, ",
+ "esc_rst=%b, main_pwr_rst=%b, sw_rst=%b, sleep=%b"
+ },
+ cfg.pwrmgr_vif.rstreqs_i,
+ cfg.pwrmgr_vif.reset_en,
+ cfg.pwrmgr_vif.pwr_rst_req.rstreqs[pwrmgr_pkg::ResetEscIdx],
+ cfg.pwrmgr_vif.pwr_rst_req.rstreqs[pwrmgr_pkg::ResetMainPwrIdx],
+ cfg.pwrmgr_vif.sw_rst_req_i == prim_mubi_pkg::MuBi4True,
+ sleep
+ ), UVM_MEDIUM)
+ endtask
+
task reset_coverage_collector();
- forever
- @(posedge cfg.pwrmgr_vif.pwr_rst_req.reset_cause == pwrmgr_pkg::HwReq) begin
- if (cfg.en_cov) begin
- cov.reset_cg.sample(
- .hw_resets(cfg.pwrmgr_vif.rstreqs_i), .hw_resets_en(cfg.pwrmgr_vif.reset_en),
- .esc_rst(cfg.pwrmgr_vif.pwr_rst_req.rstreqs[pwrmgr_pkg::ResetEscIdx]),
- .main_pwr_rst(cfg.pwrmgr_vif.pwr_rst_req.rstreqs[pwrmgr_pkg::ResetMainPwrIdx]),
- .sw_rst(cfg.pwrmgr_vif.sw_rst_req_i == prim_mubi_pkg::MuBi4True), .sleep(1'b0));
+ fork
+ forever
+ @(posedge cfg.pwrmgr_vif.pwr_rst_req.reset_cause == pwrmgr_pkg::HwReq) begin
+ if (cfg.en_cov) begin
+ sample_reset_coverage(.sleep(1'b0));
+ end
end
- end
- forever
- @(posedge cfg.pwrmgr_vif.slow_state == pwrmgr_pkg::SlowPwrStateLowPower) begin
- if (cfg.en_cov) begin
- cov.reset_cg.sample(
- .hw_resets(cfg.pwrmgr_vif.rstreqs_i), .hw_resets_en(cfg.pwrmgr_vif.reset_en),
- .esc_rst(cfg.pwrmgr_vif.pwr_rst_req.rstreqs[pwrmgr_pkg::ResetEscIdx]),
- .main_pwr_rst(cfg.pwrmgr_vif.pwr_rst_req.rstreqs[pwrmgr_pkg::ResetMainPwrIdx]),
- .sw_rst(cfg.pwrmgr_vif.sw_rst_req_i == prim_mubi_pkg::MuBi4True), .sleep(1'b1));
+ forever
+ @(posedge cfg.pwrmgr_vif.slow_state == pwrmgr_pkg::SlowPwrStateLowPower) begin
+ if (cfg.en_cov) begin
+ sample_reset_coverage(.sleep(1'b1));
+ end
end
- end
+ join_none
endtask
virtual task process_tl_access(tl_seq_item item, tl_channels_e channel, string ral_name);
diff --git a/hw/ip/pwrmgr/dv/env/seq_lib/pwrmgr_base_vseq.sv b/hw/ip/pwrmgr/dv/env/seq_lib/pwrmgr_base_vseq.sv
index a90c9f0..a87b97d 100644
--- a/hw/ip/pwrmgr/dv/env/seq_lib/pwrmgr_base_vseq.sv
+++ b/hw/ip/pwrmgr/dv/env/seq_lib/pwrmgr_base_vseq.sv
@@ -21,12 +21,12 @@
localparam int MaxCyclesBeforeEnable = 6;
// Random wakeups and resets.
- rand wakeups_t wakeups;
- rand wakeups_t wakeups_en;
- rand resets_t resets;
- rand resets_t resets_en;
- rand bit power_glitch_reset;
- rand bit escalation_reset;
+ rand wakeups_t wakeups;
+ rand wakeups_t wakeups_en;
+ rand resets_t resets;
+ rand resets_t resets_en;
+ rand bit power_glitch_reset;
+ rand bit escalation_reset;
// TODO(maturana) Enable escalation resets once there is support for driving them.
constraint escalation_reset_c {escalation_reset == 1'b0;}
diff --git a/hw/ip/pwrmgr/dv/env/seq_lib/pwrmgr_lowpower_wakeup_race_vseq.sv b/hw/ip/pwrmgr/dv/env/seq_lib/pwrmgr_lowpower_wakeup_race_vseq.sv
index 5f37b78..67157cb 100644
--- a/hw/ip/pwrmgr/dv/env/seq_lib/pwrmgr_lowpower_wakeup_race_vseq.sv
+++ b/hw/ip/pwrmgr/dv/env/seq_lib/pwrmgr_lowpower_wakeup_race_vseq.sv
@@ -87,7 +87,7 @@
// Now bring it back.
cfg.clk_rst_vif.wait_clks(cycles_before_wakeup);
- // Check wake_status prior to wakeup, or the unit requesting wakeup will have been reset.
+ // Check wake_status prior to wakeup, or the unit requesting wakeup will have been reset.
// This read will not work in the chip, since the processor will be asleep.
cfg.slow_clk_rst_vif.wait_clks(4);
csr_rd_check(.ptr(ral.wake_status[0]), .compare_value(wakeups & wakeups_en),
diff --git a/hw/ip/pwrmgr/dv/env/seq_lib/pwrmgr_wakeup_reset_vseq.sv b/hw/ip/pwrmgr/dv/env/seq_lib/pwrmgr_wakeup_reset_vseq.sv
index 81cf49f..d5808f4 100644
--- a/hw/ip/pwrmgr/dv/env/seq_lib/pwrmgr_wakeup_reset_vseq.sv
+++ b/hw/ip/pwrmgr/dv/env/seq_lib/pwrmgr_wakeup_reset_vseq.sv
@@ -61,18 +61,24 @@
set_nvms_idle();
// Wait for the slow state machine to be in low power.
- wait (cfg.pwrmgr_vif.slow_state == pwrmgr_pkg::SlowPwrStateLowPower);
+ wait(cfg.pwrmgr_vif.slow_state == pwrmgr_pkg::SlowPwrStateLowPower);
// This will send the wakeup and reset so they almost coincide.
fork
begin
cfg.clk_rst_vif.wait_clks(cycles_before_reset);
cfg.pwrmgr_vif.update_resets(resets);
- cfg.pwrmgr_vif.update_sw_rst_req(sw_rst_from_rstmgr);
+ if (power_glitch_reset) begin
+ `uvm_info(`gfn, "Sending power glitch", UVM_MEDIUM)
+ cfg.pwrmgr_vif.glitch_power_reset();
+ end
+ `uvm_info(`gfn, $sformatf("Sending reset=%b, power_glitch=%b", resets, power_glitch_reset
+ ), UVM_MEDIUM)
end
begin
cfg.clk_rst_vif.wait_clks(cycles_before_wakeup);
cfg.pwrmgr_vif.update_wakeups(wakeups);
+ `uvm_info(`gfn, $sformatf("Sending wakeup=%b", wakeups), UVM_MEDIUM)
end
join
@@ -92,8 +98,7 @@
.err_msg("failed reset_status check"));
check_wake_info(.reasons(enabled_wakeups), .prior_reasons(1'b0), .fall_through(1'b0),
- .prior_fall_through(1'b0), .abort(1'b0),
- .prior_abort(1'b0));
+ .prior_fall_through(1'b0), .abort(1'b0), .prior_abort(1'b0));
// This is the expected side-effect of the low power entry reset, since the source of the
// non-aon wakeup sources will deassert it as a consequence of their reset.