Creation of user-defined phases in UVM is a possibility although it may hinder in complete re-usability of the testbench. There are chances for components to go out of sync and cause errors related to null pointer handles. But, in case you decide that you have to use one for your project, keep reading.
Some of the main steps to using a custom phase are:
- Create and define a new phase class
- Add the new phase to an existing schedule
- Use the new phase in a component that supports this phase
Create custom phase class1. Extend appropriate base class for your phase type
class my_PHASE_phase extends uvm_task_phase; class my_PHASE_phase extends uvm_topdown_phase; class my_PHASE_phase extends uvm_bottomup_phase;2. Implement
exec_funcmethod based on whether this phase consumes simulation time.
task exec_task (uvm_component comp, uvm_phase schedule); function void exec_func (uvm_component comp, uvm_phase schedule);
Here's the complete example of a new phase class definition.
class uvm_user_phase extends uvm_task_phase; // Define the new method; set the name without "uvm" and "phase" protected function new(string name="post_run"); super.new(name); endfunction // Create a function to return the type name static const string type_name = "uvm_user_phase"; virtual function string get_type_name(); return type_name; endfunction // If this phase is a task that requires simulation time, you need to // define "exec_task" method virtual task exec_task(uvm_component comp, uvm_phase phase); my_test TEST; if ($cast(TEST, comp)) TEST.post_run_phase (phase); endtask // Create a singleton object that can be accessed elsewhere local static uvm_user_phase m_inst; // Create a method to return the singleton object static function uvm_user_phase get(); if(m_inst == null) m_inst = new; return m_inst; endfunction endclass
Insert new phase into schedule
UVM has a certain sequence of executing phases which you can review in Phases . We can insert the new phase in between any of the existing phases for which we have to obtain the handle to the UVM phase scheduler or domain. A domain is a phasing schedule node that represents and independent branch of the schedule. Individual phases are added to a domain which will be inserted into the required schedule.1. Get handle to the appropriate domain
// Use this if you want to insert in between the common phases // build, connect, end_of_elaboration, start_of_simulation, run, extract, check, report, final uvm_domain dm = uvm_domain::get_common_domain (); // Use this if you want to insert in between run-time phases // reset, configure, main, shutdown uvm_domain dm = uvm_domain::get_uvm_domain ();2. Get a handle to the phase after which you want to insert
uvm_phase ph = dm.find (uvm_connect_phase::get()); // Or whichever phase; substitute phase_name with actual phase name like build, reset, etc uvm_phase ph = dm.find (uvm_[phase_name]_phase::get());3. Insert phase into the domain
dm.add (uvm_user_phase::get(), null, ph, null);
Here's the complete example and for our purpose it has been included as part of the testcase.
class my_test extends uvm_test; ... virtual function void add_my_phase (); uvm_domain dm = uvm_domain::get_common_domain (); uvm_phase ph = dm.find (uvm_connect_phase::get()); dm.add (uvm_user_phase::get(), null, ph, null); endfunction function new (string name = "my_test", uvm_component parent); super.new (name, parent); add_my_phase(); endfunction ... // Define what needs to be done when the new phase is executed virtual task user_phase (uvm_phase phase); `uvm_info ("TEST", $sformatf ("In %s phase", phase.get_name()), UVM_MEDIUM) endtask endclass
Go to Downloads and search for tag "uvm-user-phase" to get the source code.
---------------------------------------------------------------- (C) 2007-2013 Mentor Graphics Corporation (C) 2007-2013 Cadence Design Systems, Inc. (C) 2006-2013 Synopsys, Inc. (C) 2011-2013 Cypress Semiconductor Corp. ---------------------------------------------------------------- UVM_INFO @ 0: reporter [RNTST] Running test my_test... UVM_INFO ./tb_top.sv(42) @ 0: uvm_test_top [TEST] In build_phase UVM_INFO ./tb_top.sv(47) @ 0: uvm_test_top [TEST] In connect_phase UVM_INFO ./tb_top.sv(66) @ 0: uvm_test_top [TEST] In user_phase UVM_INFO ./tb_top.sv(57) @ 0: uvm_test_top [TEST] In run_phase UVM_INFO ./tb_top.sv(62) @ 0: uvm_test_top [TEST] In extract_phase UVM_INFO ./tb_top.sv(71) @ 0: uvm_test_top [TEST] In final_phase --- UVM Report catcher Summary --- Number of demoted UVM_FATAL reports : 0 Number of demoted UVM_ERROR reports : 0 Number of demoted UVM_WARNING reports: 0 Number of caught UVM_FATAL reports : 0 Number of caught UVM_ERROR reports : 0 Number of caught UVM_WARNING reports : 0 --- UVM Report Summary ---
user_phase was inserted after the
connect_phase as expected.