| // 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'b1; |
| |
| // knobs to enable post_start routines |
| bit do_dut_shutdown = 1'b1; |
| |
| `uvm_object_new |
| |
| task pre_start(); |
| super.pre_start(); |
| cfg = p_sequencer.cfg; |
| cov = p_sequencer.cov; |
| ral = cfg.ral; |
| 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); |
| endtask |
| |
| virtual task apply_reset(string kind = "HARD"); |
| if (kind == "HARD") cfg.clk_rst_vif.apply_reset(); |
| if (cfg.has_ral) ral.reset(kind); |
| endtask |
| |
| virtual task wait_for_reset(string reset_kind = "HARD"); |
| `uvm_info(`gfn, "waiting for rst_n assertion...", UVM_MEDIUM) |
| @(negedge cfg.clk_rst_vif.rst_n); |
| `uvm_info(`gfn, "waiting for rst_n de-assertion...", UVM_MEDIUM) |
| @(posedge cfg.clk_rst_vif.rst_n); |
| `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(); |
| // TODO(sriyerg): wait for pending items in tl agent to clear up |
| 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 way aditional 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_fatal(`gfn, "this method is not supposed to be called directly!") |
| 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)); |
| |
| // add csr exclusions before running the csr seq |
| csr_excl = csr_excl_item::type_id::create("csr_excl"); |
| add_csr_exclusions(csr_test_type, csr_excl); |
| csr_excl.print_exclusions(); |
| |
| // 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); |
| 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") begin |
| string reset_type = "HARD"; |
| csr_write_seq m_csr_write_seq; |
| |
| // 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.push_back(ral); |
| m_csr_write_seq.set_csr_excl_item(csr_excl); |
| m_csr_write_seq.external_checker = cfg.en_scb; |
| 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); |
| end |
| |
| // create base csr seq and pass our ral |
| m_csr_seq = csr_base_seq::type_id::create("m_csr_seq"); |
| m_csr_seq.num_test_csrs = num_test_csrs; |
| m_csr_seq.models.push_back(ral); |
| m_csr_seq.set_csr_excl_item(csr_excl); |
| m_csr_seq.external_checker = cfg.en_scb; |
| m_csr_seq.start(null); |
| endtask |
| |
| endclass |