blob: ff7d3066f35a8bd727f1f0a3737d533bd6b876dc [file] [log] [blame]
// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
class dv_base_vseq #(type RAL_T = dv_base_reg_block,
type CFG_T = dv_base_env_cfg,
type COV_T = dv_base_env_cov,
type VIRTUAL_SEQUENCER_T = dv_base_virtual_sequencer) extends uvm_sequence;
`uvm_object_param_utils(dv_base_vseq #(RAL_T, CFG_T, COV_T, VIRTUAL_SEQUENCER_T))
`uvm_declare_p_sequencer(VIRTUAL_SEQUENCER_T)
// number of iterations to run the test seq - please override constraint in extended vseq
// randomization for this is disabled in pre_start since we don't want to re-randomize it again
rand uint num_trans;
constraint num_trans_c {
num_trans inside {[1:20]};
}
// handles for ease of op
CFG_T cfg;
RAL_T ral;
COV_T cov;
// knobs to enable pre_start routines
bit do_dut_init = 1'b1;
bit do_apply_reset = 1'b1;
bit do_wait_for_reset = 1'b0;
// knobs to enable post_start routines
bit do_dut_shutdown = 1'b1;
// various knobs to enable certain routines
// this knob allows user to disable assertions in csr_hw_reset before random write sequence,
// the assertions will turn back on after the hw reset deasserted
bit enable_asserts_in_hw_reset_rand_wr = 1'b1;
`uvm_object_new
virtual function void set_handles();
`DV_CHECK_NE_FATAL(p_sequencer, null, "Did you forget to call `set_sequencer()`?")
cfg = p_sequencer.cfg;
cov = p_sequencer.cov;
ral = cfg.ral;
endfunction
// This function is invoked in pre_randomize(). Override it in the extended classes to configure
// / control the randomization of this sequence.
virtual function void configure_vseq();
endfunction
function void pre_randomize();
// Set the handles in pre_randomize(), so that the knobs in cfg are available during sequence
// randomization. This forces `p_sequencer` handle to be set before the randomization - users
// are required to call `set_sequencer()` right after creating the sequence and before
// randomizing it.
if (cfg == null) set_handles();
configure_vseq();
endfunction
task pre_start();
super.pre_start();
if (cfg == null) set_handles();
if (do_dut_init) dut_init("HARD");
num_trans.rand_mode(0);
endtask
task body();
`uvm_fatal(`gtn, "Need to override this when you extend from this class!")
endtask : body
task post_start();
super.post_start();
if (do_dut_shutdown) dut_shutdown();
endtask
/*
* startup, reset and shutdown related tasks
*/
virtual task dut_init(string reset_kind = "HARD");
if (do_apply_reset) apply_reset(reset_kind);
else if (do_wait_for_reset) wait_for_reset(reset_kind);
// delay after reset for tl agent check seq_item_port empty
#1ps;
endtask
virtual task apply_reset(string kind = "HARD");
if (kind == "HARD") begin
cfg.clk_rst_vif.apply_reset();
end
if (cfg.has_ral) begin
foreach (cfg.ral_models[i]) cfg.ral_models[i].reset(kind);
end
endtask
virtual task wait_for_reset(string reset_kind = "HARD",
bit wait_for_assert = 1,
bit wait_for_deassert = 1);
if (wait_for_assert) begin
`uvm_info(`gfn, "waiting for rst_n assertion...", UVM_MEDIUM)
@(negedge cfg.clk_rst_vif.rst_n);
end
if (wait_for_deassert) begin
`uvm_info(`gfn, "waiting for rst_n de-assertion...", UVM_MEDIUM)
@(posedge cfg.clk_rst_vif.rst_n);
end
`uvm_info(`gfn, "wait_for_reset done", UVM_HIGH)
endtask
// dut shutdown - this is called in post_start if do_dut_shutdown bit is set
virtual task dut_shutdown();
csr_utils_pkg::wait_no_outstanding_access();
endtask
// function to add csr exclusions of the given type using the csr_excl_item item
// arg csr_test_type: this the the type of csr test run - we may want additional exclusions
// depending on what test seq we are running
// arg csr_excl: this is the csr exclusion object that maintains the list of exclusions
// the same object handle is to be passed to csr sequences in csr_seq_lib so that they can query
// those exclusions
virtual function void add_csr_exclusions(string csr_test_type,
csr_excl_item csr_excl,
string scope = "ral");
`uvm_info(`gfn, "no exclusion item added from this function", UVM_DEBUG)
endfunction
// TODO: temp support, can delete this once all IPs update their exclusion in hjson
virtual function csr_excl_item add_and_return_csr_excl(string csr_test_type);
add_csr_exclusions(csr_test_type, ral.csr_excl);
ral.csr_excl.print_exclusions();
return ral.csr_excl;
endfunction
// wrapper task around run_csr_vseq - the purpose is to be able to call this directly for actual
// csr tests (as opposed to higher level stress test that could also run csr seq as a fork by
// calling run_csr_vseq(..) task)
virtual task run_csr_vseq_wrapper(int num_times = 1);
string csr_test_type;
csr_excl_item csr_excl;
// env needs to have a ral instance
`DV_CHECK_EQ_FATAL(cfg.has_ral, 1'b1)
// get csr_test_type from plusarg
void'($value$plusargs("csr_%0s", csr_test_type));
// create csr exclusions before running the csr seq
csr_excl = add_and_return_csr_excl(csr_test_type);
// run the csr seq
for (int i = 1; i <= num_times; i++) begin
`uvm_info(`gfn, $sformatf("running csr %0s vseq iteration %0d/%0d",
csr_test_type, i, num_times), UVM_LOW)
run_csr_vseq(.csr_test_type(csr_test_type), .csr_excl(csr_excl));
end
endtask
// capture the entire csr seq as a task that can be overridden if desired
// arg csr_test_type: what csr test to run {hw_reset, rw, bit_bash, aliasing}
// arg csr_excl: csr exclusion object - needs to be created and exclusions set before call
// arg num_test_csrs:instead of testing the entire ral model or passing test chunk info via
// plusarg, provide ability to set a random number of csrs to test from higher level sequence
virtual task run_csr_vseq(string csr_test_type = "",
csr_excl_item csr_excl = null,
int num_test_csrs = 0,
bit do_rand_wr_and_reset = 1);
csr_base_seq m_csr_seq;
// env needs to have a ral instance
`DV_CHECK_EQ_FATAL(cfg.has_ral, 1'b1)
// check which csr test type
case (csr_test_type)
"hw_reset": csr_base_seq::type_id::set_type_override(csr_hw_reset_seq::get_type());
"rw" : csr_base_seq::type_id::set_type_override(csr_rw_seq::get_type());
"bit_bash": csr_base_seq::type_id::set_type_override(csr_bit_bash_seq::get_type());
"aliasing": csr_base_seq::type_id::set_type_override(csr_aliasing_seq::get_type());
"mem_walk": csr_base_seq::type_id::set_type_override(csr_mem_walk_seq::get_type());
default : `uvm_fatal(`gfn, $sformatf("specified opt is invalid: +csr_%0s", csr_test_type))
endcase
// if hw_reset test, then write all CSRs first and reset the whole dut
if (csr_test_type == "hw_reset" && do_rand_wr_and_reset) begin
string reset_type = "HARD";
csr_write_seq m_csr_write_seq;
// Writing random values to CSRs might trigger assertion errors. So we disable in the entire
// DUT hierarchy and re-enable after resetting the DUT. See DV_ASSERT_CTRL macro defined in
// hw/dv/sv/dv_utils/dv_macros.svh for more details.
if (!enable_asserts_in_hw_reset_rand_wr) begin
`DV_ASSERT_CTRL_REQ("dut_assert_en", 1'b0)
end
// run write-only sequence to randomize the csr values
m_csr_write_seq = csr_write_seq::type_id::create("m_csr_write_seq");
m_csr_write_seq.models = cfg.ral_models;
m_csr_write_seq.external_checker = cfg.en_scb;
m_csr_write_seq.en_rand_backdoor_write = 1'b1;
m_csr_write_seq.set_csr_excl_item(csr_excl);
m_csr_write_seq.start(null);
// run dut_shutdown before asserting reset
dut_shutdown();
// issue reset
void'($value$plusargs("do_reset=%0s", reset_type));
dut_init(reset_type);
if (!enable_asserts_in_hw_reset_rand_wr) begin
`DV_ASSERT_CTRL_REQ("dut_assert_en", 1'b1)
end
end
// create base csr seq and pass our ral
m_csr_seq = csr_base_seq::type_id::create("m_csr_seq");
m_csr_seq.models = cfg.ral_models;
m_csr_seq.external_checker = cfg.en_scb;
m_csr_seq.num_test_csrs = num_test_csrs;
m_csr_seq.set_csr_excl_item(csr_excl);
m_csr_seq.start(null);
endtask
// enable/disable csr_assert
virtual function void set_csr_assert_en(bit enable, string path = "*");
uvm_config_db#(bit)::set(null, path, "csr_assert_en", enable);
endfunction
endclass