Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[dv] Minor improvements to cip_base_vseq and rv_dm TB #21282

Merged
merged 5 commits into from
Feb 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 21 additions & 1 deletion hw/dv/sv/cip_lib/seq_lib/cip_base_vseq.sv
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The changes to wait_to_issue_reset() seem sensible to me, but I do see there are two derived classes (hmac_common_vseq.sv/otp_ctrl_common_vseq.sv) who override the method and call super.wait_to_issue_reset(). Is it worth running a little regression locally just to check for any breakage there? I may be wrong, but I'm not sure the CI testcases would get those.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not too concerned: this change can only ever cause us to wait a bit of extra time. And any test that causes it to fire would have failed unconditionally without this change. So I think this is guaranteed to be safe :-)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fair enough! :)

Original file line number Diff line number Diff line change
Expand Up @@ -707,14 +707,20 @@ class cip_base_vseq #(
end
begin : issue_rand_reset
wait_to_issue_reset(reset_delay_bound);

// Check that there are no CSR requests in flight as we trigger the reset. If any
// exist, they won't manage to complete (because apply_resets_concurrently will kill
// the task that is driving them) and everything will end up out of sync.
`DV_CHECK(!has_outstanding_access(),
"Trying to trigger a reset with outstanding CSR items.")

ongoing_reset = 1'b1;
`uvm_info(`gfn, $sformatf("\nReset is issued for run %0d/%0d", i, num_times), UVM_LOW)
apply_resets_concurrently();
do_read_and_check_all_csrs = 1'b1;
ongoing_reset = 1'b0;
end
join_any
`DV_CHECK_EQ(has_outstanding_access(), 0, "No CSR outstanding items after reset!")
disable fork;
`uvm_info(`gfn, $sformatf("\nStress w/ reset is done for run %0d/%0d", i, num_times),
UVM_LOW)
Expand All @@ -737,7 +743,21 @@ class cip_base_vseq #(
rand_reset_delay inside {[1:reset_delay_bound]};
)

// Wait a random number of cycles (up to reset_delay_bound) before triggering the reset.
cfg.clk_rst_vif.wait_clks(rand_reset_delay);

// If there is an outstanding access, wait up to 1000 more cycles to allow it to clear. If it
// doesn't clear, something has gone wrong: we don't expect there to permanently be CSR
// accesses.
for (int i = 0; i < 1000; i++) begin
if (!has_outstanding_access()) break;
cfg.clk_rst_vif.wait_clks(1);
end
`DV_CHECK(!has_outstanding_access(),
"Outstanding access never cleared to allow us to reset.")

// Wait a portion of the clock period, to avoid the reset being synchronised with an edge of the
// clock.
#($urandom_range(0, cfg.clk_rst_vif.clk_period_ps) * 1ps);
endtask

Expand Down
94 changes: 55 additions & 39 deletions hw/ip/rv_dm/dv/env/seq_lib/rv_dm_smoke_vseq.sv
Original file line number Diff line number Diff line change
Expand Up @@ -15,50 +15,66 @@ class rv_dm_smoke_vseq extends rv_dm_base_vseq;
scanmode == prim_mubi_pkg::MuBi4False;
}

task body();
// Read the JTAG IDCODE register and verify that it matches the expected value.
// Read the JTAG IDCODE register and verify that it matches the expected value.
task check_idcode();
uvm_reg_data_t data;
repeat ($urandom_range(1, 10)) begin
`DV_CHECK_STD_RANDOMIZE_FATAL(data)
csr_wr(.ptr(jtag_dtm_ral.idcode), .value(data));
csr_rd(.ptr(jtag_dtm_ral.idcode), .value(data));
`DV_CHECK_EQ(data, RV_DM_JTAG_IDCODE)
end
repeat ($urandom_range(1, 10)) begin
data = $urandom_range(0, 1);
// Verify that writing to haltreq results in debug_req output to be set.
csr_wr(.ptr(jtag_dmi_ral.dmcontrol.haltreq), .value(data));
cfg.clk_rst_vif.wait_clks($urandom_range(0, 1000));
`DV_CHECK_EQ(cfg.rv_dm_vif.cb.debug_req, data)
cfg.clk_rst_vif.wait_clks($urandom_range(1, 10));
end
repeat ($urandom_range(1, 10)) begin
data = $urandom_range(0, 1);
// Verify that writing to ndmreset results in ndmreset output to be set.
csr_wr(.ptr(jtag_dmi_ral.dmcontrol.ndmreset), .value(data));
cfg.clk_rst_vif.wait_clks($urandom_range(0, 1000));
`DV_CHECK_EQ(cfg.rv_dm_vif.cb.ndmreset_req, data)
cfg.clk_rst_vif.wait_clks($urandom_range(1, 10));
end
repeat ($urandom_range(1, 10)) begin
data = $urandom_range(0, 1);
// Verify that the dmstatus[*unavail] field tracks the unavailable_i input.
cfg.rv_dm_vif.cb.unavailable <= data;
csr_rd(.ptr(jtag_dmi_ral.dmstatus), .value(data));
`DV_CHECK_EQ(cfg.rv_dm_vif.unavailable,
get_field_val(jtag_dmi_ral.dmstatus.anyunavail, data))
`DV_CHECK_EQ(cfg.rv_dm_vif.unavailable,
get_field_val(jtag_dmi_ral.dmstatus.allunavail, data))
`DV_CHECK_STD_RANDOMIZE_FATAL(data)
csr_wr(.ptr(jtag_dtm_ral.idcode), .value(data));
csr_rd(.ptr(jtag_dtm_ral.idcode), .value(data));
`DV_CHECK_EQ(data, RV_DM_JTAG_IDCODE)
endtask

// Verify that writing to haltreq causes debug_req output to be set.
task check_haltreq();
uvm_reg_data_t data = $urandom_range(0, 1);
csr_wr(.ptr(jtag_dmi_ral.dmcontrol.haltreq), .value(data));
cfg.clk_rst_vif.wait_clks($urandom_range(0, 1000));
`DV_CHECK_EQ(cfg.rv_dm_vif.cb.debug_req, data)
endtask

// Verify that writing to ndmreset causes ndmreset output to be set.
task check_ndmreset();
uvm_reg_data_t data = $urandom_range(0, 1);
csr_wr(.ptr(jtag_dmi_ral.dmcontrol.ndmreset), .value(data));
cfg.clk_rst_vif.wait_clks($urandom_range(0, 1000));
`DV_CHECK_EQ(cfg.rv_dm_vif.cb.ndmreset_req, data)
endtask

// Verify that the dmstatus[*unavail] field tracks the unavailable_i input.
task check_unavailable();
uvm_reg_data_t data = $urandom_range(0, 1);
cfg.rv_dm_vif.cb.unavailable <= data;
csr_rd(.ptr(jtag_dmi_ral.dmstatus), .value(data));
`DV_CHECK_EQ(cfg.rv_dm_vif.unavailable,
get_field_val(jtag_dmi_ral.dmstatus.anyunavail, data))
`DV_CHECK_EQ(cfg.rv_dm_vif.unavailable,
get_field_val(jtag_dmi_ral.dmstatus.allunavail, data))
endtask

// Verify that writing to dmactive causes dmactive output to be set.
task check_dmactive();
uvm_reg_data_t data = $urandom_range(0, 1);
csr_wr(.ptr(jtag_dmi_ral.dmcontrol.dmactive), .value(data));
cfg.clk_rst_vif.wait_clks($urandom_range(0, 1000));
`DV_CHECK_EQ(cfg.rv_dm_vif.cb.dmactive, data)
endtask

task body();
repeat ($urandom_range(20, 50)) begin
randcase
1: check_idcode();
1: check_haltreq();
1: check_ndmreset();
1: check_unavailable();
endcase
cfg.clk_rst_vif.wait_clks($urandom_range(1, 10));
end
repeat ($urandom_range(1, 10)) begin
data = $urandom_range(0, 1);
// Verify that writing to dmactive results in dmactive output to be set.
csr_wr(.ptr(jtag_dmi_ral.dmcontrol.dmactive), .value(data));
cfg.clk_rst_vif.wait_clks($urandom_range(0, 1000));
`DV_CHECK_EQ(cfg.rv_dm_vif.cb.dmactive, data)

repeat ($urandom_range(1, 5)) begin
check_dmactive();
cfg.clk_rst_vif.wait_clks($urandom_range(1, 10));
end

endtask : body

endclass : rv_dm_smoke_vseq
Loading