What are UVM phases ?

All testbench components are derived from uvm_component and are aware of the phase concept. Each component goes through a pre-defined set of phases, and it cannot proceed to the next phase until all components finish their execution in the current phase. So UVM phases act as a synchronizing mechanism in the life cycle of a simulation.

Because phases are defined as callbacks, classes derived from uvm_component can perform useful work in the callback phase method. Methods that do not consume simulation time are functions and methods that consume simulation time are tasks. All phases can be grouped into three categories:

  1. Build time phases
  2. Run time phases
  3. Clean-Up phases

UVM phases

Note that run_phase is launched in parallel with other run-time phases.

Main UVM Phases

Phase CategoryUVM Phase NameMethod TypeDescription
Buildbuild_phasefunctionUsed to build testbench components and create their instances
connect_phasefunctionUsed to connect between different testbench components via TLM ports
end_of_elaboration_phasefunctionUsed to display UVM topology and other functions required to be done after connection
start_of_simulation_phasefunctionUsed to set initial run-time configuration or display topology
Runrun_phasetaskActual simulation that consumes time happens in this UVM phase and runs parallel to other UVM run-time phases.
Cleanextract_phasefunctionUsed to extract and compute expected data from scoreboard, an
check_phasefunctionUsed to perform scoreboard tasks that check for errors between expected and actual values from design
report_phasefunctionUsed to display result from checkers, or summary of other test objectives
final_phasefunctionTypically used to do last minute operations before exiting the simulation

Logically, the first thing to be done is to create testbench component objects so that they can be connected together. This is the reason for the build_phase. It is better to not start connecting them while other testbench components are still building their sub-components. So we have connect_phase which will connect all the components that were built in the previous phase. Although the next two phases are rarely used or are typically used to display UVM hierhachy information. Test stimulus is driven to the design during the run_phase which is launched in parallel with other run-time phases that are described shown below.

Why is build done top to bottom ?

Verification environment usually looks like a nested structure as shown in the image below. In order to build the agent, UVM environment is required to be defined and similarly in order to build the environment, the test class has to be defined. Hence, we can only go from top to bottom.

To add more flexibility, there are pre and post callbacks to all the runtime phases.

UVM run time phases

Why doesn't Verilog testbench need phases ?

A Verilog testbench would have all its components made of static containers or modules. So each module will have a set of ports or signals that it can utilize to communicate with other testbench components. Since a module is static, all modules will be created at beginning of the simulation and we won't have to worry about any component getting called without it being created or initialized. It would be useful to have some run-time phases for resetting DUT, driving the actual stimulus and maybe another phase to enable and run checkers.


	module driver (...);
		task reset_phase (...);
		task run_phase (...);
		task check_phase (...);
		
		initial begin
			reset_phase ();
			run_phase ();
			check_phase ();
		end
	endmodule

	module tb_top;
		dut       d0   (...);
		driver    drvr (...);
		checker1  chk0 (...);
		checker2  chk1 (...);
	endmodule

Verilog testbenches are limited in functionality and are not scalable.

Why SystemVerilog testbench require phases ?

SystemVerilog changes the whole game with the introduction of OOP (Object Oriented Programming) features. This enables the creation of well structured entities that can be reused and deployed when required. These entities are class objects, and it is possible to create a brand new object in the middle of the entire simulation, say at time Xns. What this means is that testbench components can be created at different times, and hence you could end up calling a component while it hasn't been initialized yet leading to wrong testbench outputs. Also, different companies maintain their own hierarchy and arrangement of testbench environments and takes a lot of effort to plug in different verification IPs from other companies. So, synchronization between testbench components is a key requirement.


	typedef class driver;
	typedef class monitor;
	
	class env;
		driver  d0;
		monitor mon0;
		
		function init_drvr ();
			d0 = new ();
			// initialize
		endfunction
		
		function init_mon ();
			mon0 = new ();
			// initialize
		endfunction
	endclass

What should be done in each UVM Phase ?

The table below summarizes the intent, expectation and result of each phase as documented in the UVM reference manual.

PhaseUpon EntryTypical UsesExit Criteria
buildTop-Level components are instantiated under uvm_root
  • Instantiate sub-components
  • Instantiate register model
  • Get configuration values for components being built
  • Set configuration values for sub-components
  • All uvm_components have been instantiated.
connectAll components have been instantiated
  • Connect TLM ports and exports, initiator sockets and target sockets
  • Connect register model to adapter components
  • Setup explicit phase domains
  • Connections between various components have been established
  • All independent phase domains are set
end_of_elaborationVerification environment has been assembled
  • Display environment topology
  • Open files
  • Define additional configuration settings
None
start_of_simulation
  • External tools/simulation engines have started and synced
  • Verification environment is configured and ready to be started
  • Display environment topology
  • Set debugger breakpoint
  • Set initial run-time configuration values
None
run
  • Indicates that power has been applied
  • No active edges of clock should have happened before (x->1)
Components run over various run-time phases
  • DUT no longer needs to be simulated
  • post_shutdown_phase is ready to end
extract
  • DUT no longer needs to be simulated
  • Simulation time will no longer advance
  • Extract data/final state information from scoreboard/testbench components
  • Probe the DUT (hierarchical reference/backdoor access)
  • Calculate statistics and summaries
  • Display final state information
  • Close files
All data has been collected and summarized
checkAll data has been collectedCheck that no unaccounted for data remainTest is known to have passed or failed
reportTest is known to have passed or failed
  • Report test results
  • Write results to file
End of test
finalAll test-related activity has completed
  • Close files
  • Terminate co-simulation engines
Ready to exit simulator