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 class
1. 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_task
or exec_func
method 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
----------------------------------------------------------------
(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 ---
Note that user_phase
was inserted after the connect_phase
as expected.