Skip to content

07. Phases

muneebullashariff edited this page Jan 4, 2024 · 4 revisions

1. uvm_phase

This is a base_class defines everything about a phase: behavior, state, and context.
To define behavior, it is extended by UVM or the user to create singleton objects which capture the definition of what the phase does and how it does it. These are then cloned to produce multiple nodes which are hooked up in a graph structure to provide context: which phases follow which, and to hold the state of the phase throughout its lifetime.

Phase Definition

These instances define the attributes of the phase (not what state it is in) They are then cloned into schedule nodes which point back to one of these implementations, and calls its virtual task or function methods on each participating component.

Phase Context

A schedule is a coherent group of one or more phase/state nodes linked together by a graph structure, allowing arbitrary linear/parallel relationships to be specified, and executed by stepping through them in the graph order. Each schedule node points to a phase and holds the execution state of that phase, and has optional links to other nodes for synchronization.

The main operations are: construct, add phases, and instantiate hierarchically within another schedule.

Each instance is a node connected to others to form the graph. Each node in the graph has zero or more successors, and zero or more predecessors. No nodes are completely isolated from others. Exactly one node has zero predecessors. This is the root node. Also the graph is acyclic, meaning for all nodes in the graph, by following the forward arrows you will never end up back where you started but you will eventually reach a node that has no successors.

Phase State

A given phase may appear multiple times in the complete phase graph, due to the multiple independent domain feature, and the ability for different VIP to customize their own phase schedules perhaps reusing existing phases. Each node instance in the graph maintains its own state of execution.

Key points that we have to know for understand working of all phases

  • Each testbench component is derived from uvm_component that has predefined phases. They are represented as callback methods.
  • Each component can not move to the next phase unless the current phase execution is completed for all the components. This provides proper synchronization between all the components. UVM phases are executed in a certain order and all are virtual methods.
  • Few phases that consume simulation time for execution are implemented as tasks and other phases that do not consume any simulation time are implemented as functions.
    Main categories in UVM phases.
    a. Build phases: Used to configure or construct the testbench.
    b. Run-time phases: Time-consuming testbench activity like running the test case.
    c. Clean up phases: Collect and report the results of the simulation.

syntax:

class uvm_phase extends uvm_object;

   `uvm_object_utils(uvm_phase)

endclass

new phase

                Fig-1: Categories of UVM phases

BUILD_PHASE

UVM Phases are a synchronizing mechanism for the environment. Phases are represented by callback methods, A set of predefined phases and corresponding callbacks are provided in uvm_component. The Method can be either a function or task.
Any class deriving from uvm_component may implement any or all of these callbacks, which are executed in a particular order

The top-level is a test and that test builds the testbench. In order to do this, the build_phase is necessary. The build_phase is the first phase in the flow and is the one of the phase that is called in a top-down manner starting with the test. Its purpose is to create all of the UVM components.
There are a few key points you need to remember for this phase.

  1. Every build_phase function should call super.build_phase first so that the build_phase function in the parent class is executed.
  2. Configuration for a component should be done before a component is created.
  3. All UVM components should be created in this phase.

The uvm_build_phase phase implementation method.

  1. Any override should call super.build_phase(phase) to execute the automatic configuration of fields registered in the component by calling <apply_config_settings>.
  2. To turn off automatic configuration for a component, do not call super.build_phase(phase).

syntax:

virtual function void build_phase(uvm_phase phase);

code snippet:

`include "uvm_macros.svh"
import uvm_pkg::*;

class object extends uvm_object;
   `uvm_object_utils(object)
   
   rand int a;
   rand int b;
  
   function new(string name = "object");
      super.new(name);
   endfunction
endclass

class test extends uvm_test;
   `uvm_component_utils(test)

   object obj;

   function new(string name = "test",uvm_component parent = null);
      super.new(name,parent);
   endfunction
   
   function void build_phase(uvm_phase phase);
      super.build_phase(phase);

      if(obj == null)
         `uvm_info(get_type_name(),"object for the class was not created",UVM_NONE)
      else
         `uvm_info(get_type_name(),"object for the class was created",UVM_NONE)

      obj = object::type_id::create("obj");
    
      if(obj == null)
         `uvm_info(get_type_name(),"object for the class was not created",UVM_NONE)
      else
         `uvm_info(get_type_name(),"object for the class was created",UVM_NONE)
  endfunction
endclass

module top;
   initial begin
      run_test("test");
   end
endmodule

output:

build

                Fig-2: output for build phase.

Github lab link: https://github.com/mbits-mirafra/UVMCourse/blob/b7_Team_BJT/phases/build_phase/uvm_build_phase.sv

Github log file link: https://github.com/mbits-mirafra/UVMCourse/blob/b7_Team_BJT/phases/build_phase/uvm_build_phase.log

connect_phase

Connect phase is used to establish the TLM connections between two components or one object and one component.

The <uvm_connect_phase> phase implementation method. This method should never be called directly.

syntax:

virtual function void connect_phase(uvm_phase phase);

code snippet:

code for objects

`include "uvm_macros.svh"
import uvm_pkg::*;

class object extends uvm_sequence_item;
   rand int a;

   `uvm_object_utils_begin(object)
      `uvm_field_int(a,UVM_DEFAULT)
   `uvm_object_utils_end

   function new(string name = "object");
      super.new(name);
   endfunction
endclass

class object1 extends uvm_sequence#(object);
   `uvm_object_utils(object1)

   object obj;

   function new(string name = "object1");
      super.new(name);
   endfunction

   task body();
      obj = object::type_id::create("obj");
      start_item(obj);
      assert(obj.randomize() with {a inside {1,2,3,4,5};});
      `uvm_info(get_type_name(),$sformatf("a = %0d",obj.a),UVM_NONE)
      finish_item(obj);
   endtask
endclass

code for components

class transmitter extends uvm_sequencer#(object);
   `uvm_component_utils(transmitter)

   object obj;
  
   function new(string name = "transmitter",uvm_component parent = null);
      super.new(name,parent); 
   endfunction
endclass

class reciever extends uvm_driver#(object);
   `uvm_component_utils(reciever)

   object obj;

   function new(string name = "reciever",uvm_component parent = null);
      super.new(name,parent);
   endfunction

   function void build_phase(uvm_phase phase);
      super.build_phase(phase);
      obj = object::type_id::create("obj");
   endfunction

   task run_phase(uvm_phase phase);
      forever begin
         seq_item_port.get_next_item(obj);
         `uvm_info(get_type_name(),$sformatf("a = %0d",obj.a),UVM_NONE)
         seq_item_port.item_done();
      end
   endtask
endclass

class agent extends uvm_agent;
   `uvm_component_utils(agent)
  
   transmitter trans;
   reciever rec;
  
   function new(string name = "agent",uvm_component parent = null);
      super.new(name,parent);
   endfunction
  
   function void build_phase(uvm_phase phase);
      super.build_phase(phase);
      trans = transmitter::type_id::create("trans",this);
      rec = reciever::type_id::create("rec",this);
   endfunction
  
   function void connect_phase(uvm_phase phase);
      rec.seq_item_port.connect(trans.seq_item_export);
   endfunction
endclass

class test extends uvm_test;
   `uvm_component_utils(test)
  
   object1 obj1;
   agent a;
  
   function new(string name = "test",uvm_component parent = null);
      super.new(name,parent);
   endfunction
  
   function void build_phase(uvm_phase phase);
      super.build_phase(phase);
      obj1 = object1::type_id::create("obj1");
      a = agent::type_id::create("a",this);
   endfunction
  
   task run_phase(uvm_phase phase);
      phase.raise_objection(this);
      obj1.start(a.trans);
      phase.drop_objection(this);
   endtask
endclass

module top;
   initial begin
      run_test("test");
   end
endmodule

output:

connect

              Fig-3 : output for connect phase.

Github lab link: https://github.com/mbits-mirafra/UVMCourse/blob/b7_Team_BJT/phases/connect_phase/uvm_connect_phase.sv

Github log file link: https://github.com/mbits-mirafra/UVMCourse/blob/b7_Team_BJT/phases/connect_phase/uvm_connect_phase.log

End of elaboration phase

Basically phases are used for synchronization between testbench components. These phases are nothing but predefined functions and tasks provided in uvm_component. Each component will goes through these predefined phases and it proceed to next phase only when current phase gets executed.
End of elaboration phase is a function which executes at 0 simulation time. It comes under BUILD phase.In the predefined order this phase comes before start of simulation phase and comes after connect phase. End of elaboration phase executes in bottom to top methodology. In End of elaboration phase verification environment has been assembled.
Functions of End of elaboration phase:

  1. It displays uvm topology it means structure of the design which is hierarchical information.
  2. It is used to make final time adjustments and changes to structure, configuration in testbench architecture before simulation.
  3. It opens the files and define additional configuration settings
  4. It is used to display startup simulation messages.
    Class Hierarchy:
    The complete phasing mechanism is subdivided into 3 phases: uvm_topdown_phase, uvm_bottomup_phase and uvm_task_phase.
    uvm_void
    uvm_object
    uvm_phase
    uvm_bottom_up phase
    Class Declaration:
    class uvm_end_of_elaboration_phase extends uvm_bottomup_phase

Syntax:-

virtual function void end_of_elaboration_phase(uvm_phase phase);

Code snippet:-

`include "uvm_macros.svh"
import uvm_pkg::*;

class test extends uvm_test;

  int a;

  `uvm_component_utils_begin(test)
    `uvm_field_int(a,UVM_DEFAULT)
  `uvm_component_utils_end

  function new(string name = "test", uvm_component parent = null);
    super.new(name,parent);
    a = 10;
    `uvm_info("new",$sformatf("a = %0d",a),UVM_LOW)
  endfunction:new

  virtual function void build_phase(uvm_phase phase);
    super.build_phase(phase);
    a = 20;
    `uvm_info("build",$sformatf("a = %0d",a),UVM_LOW)
  endfunction:build_phase

  virtual function void end_of_elaboration_phase(uvm_phase phase);
    super.end_of_elaboration_phase(phase);
    a = 30;
    `uvm_info("EOE",$sformatf("a = %0d",a),UVM_LOW)
  endfunction:end_of_elaboration_phase

  virtual task run_phase(uvm_phase phase);
      super.run_phase(phase);
      phase.raise_objection(this);
      `uvm_info("run",$sformatf("a = %0d",a),UVM_LOW)
      phase.drop_objection(this);
  endtask:run_phase

endclass:test

module top;

  initial begin

    run_test("test");

  end

endmodule:top 

Output

eoe

Github Lablink:- https://github.com/mbits-mirafra/UVMCourse/blob/b7_Team_BJT/phases/end_of_elaboration/uvm_eoe.sv

Github Logfile link:- https://github.com/mbits-mirafra/UVMCourse/blob/b7_Team_BJT/phases/end_of_elaboration/eoe.log

Start of simulation phase

Start of simulation phase is also a function in which simulation takes place at 0ns.This phase comes before actual simulation that is before RUN phase. Start of simulation phase is also a bottom to top methodology. Both End of elaboration and Start of simulation phase executes in bottom to top methodology because for printing topology, adjusting of the environment, accessing configuration information and this can only be possible in hierarchical fashion in bottom up only after build phase finish its execution. It belongs to run time phase so run phase will get executed from start of simulation phase .Generally both End of elaboration and Start of simulation phase are used for displaying uvm hierarchy information.
Functions in Start of simulation phase:
1.It displays environment topology this is also done in End of elaboration phase but any changes and additional modification settings are displayed in start of simulation phase.
2.set debugger breakpoint
3.set initial run time configuration values.
4.In this phase simulation engines ,debuggers, runtime tools have started and synced
5.verification environment is configured and ready to be started
Class Hierarchy:
The complete phasing mechanism is subdivided into 3 phases: uvm_topdown_phase, uvm_bottomup_phase and uvm_task_phase.
uvm_void
uvm_object
uvm_phase
uvm_bottom_up phase
Class Declaration:
class uvm_start_of_simulation_phase extends uvm_bottomup_phase

Syntax:-

virtual function void start_of_simulation_phase(uvm_phase phase);

Code snippet:-

`include "uvm_macros.svh"
import uvm_pkg::*;

class test extends uvm_test;

  int a;

  `uvm_component_utils_begin(test)
    `uvm_field_int(a,UVM_DEFAULT)
  `uvm_component_utils_end

  function new(string name = "test", uvm_component parent = null);
    super.new(name,parent);
    a = 10;
    `uvm_info("new",$sformatf("a = %0d",a),UVM_LOW)
  endfunction:new

  virtual function void build_phase(uvm_phase phase);
    super.build_phase(phase);
    a = 20;
    `uvm_info("build",$sformatf("a = %0d",a),UVM_LOW)
  endfunction:build_phase

  virtual function void end_of_elaboration_phase(uvm_phase phase);
    super.end_of_elaboration_phase(phase);
    a = 30;
    `uvm_info("EOE",$sformatf("a = %0d",a),UVM_LOW)
  endfunction:end_of_elaboration_phase

  virtual function void start_of_simulation_phase(uvm_phase phase);
    super.start_of_simulation_phase(phase);
    `uvm_info("SOS","now i am in start of simulation phase",UVM_LOW)
    `uvm_info("SOS","next going to run phase",UVM_LOW)
  endfunction:start_of_simulation_phase

  virtual task run_phase(uvm_phase phase);
      super.run_phase(phase);
      phase.raise_objection(this);
      `uvm_info("run",$sformatf("a = %0d",a),UVM_LOW)
      phase.drop_objection(this);
  endtask:run_phase

endclass:test

module top;

  initial begin

    run_test("test");

  end

endmodule:top

Output:-

sos

Github Lablink:- https://github.com/mbits-mirafra/UVMCourse/blob/b7_Team_BJT/phases/start_of_simulation/uvm_sos.sv

Github Logfile link:- https://github.com/mbits-mirafra/UVMCourse/blob/b7_Team_BJT/phases/start_of_simulation/sos.log

2. Run-phase

Run-phase is the phase that attains after the start of simulation and this is where it actually consumes time since there are tasks involved as mentioned below.

run phase

      Fig-4 : Categories of Run phase  

Note: The codes written below are just for the purpose of understanding if the pre-defined methods can be overwritten and are executed automatically by run_test.

pre_reset_phase:

It takes care of activities to be processed before reset.

  task pre_reset_phase(uvm_phase phase);
   
    `uvm_info(get_full_name(), {" Inside pre_reset__phase ", get_full_name()}, UVM_LOW);
 
  endtask:pre_reset_phase  

reset_phase:

This is used to generate a reset and put an interface into its default state.

 task reset_phase(uvm_phase phase);

    `uvm_info(get_full_name(), {" Inside reset__phase ", get_full_name()}, UVM_LOW);
     
  endtask:reset_phase

post_reset_phase:

It process activities that are required to be done immediately after reset.

 task  post_reset_phase(uvm_phase phase);

    `uvm_info(get_full_name(), {" Inside post_reset__phase ", get_full_name()}, UVM_LOW);
   
  endtask: post_reset_phase

pre_configure_phase:

This process is used after the reset is completed, this phase is used to prepare DUT for configuration programming.

 task  pre_configure_phase(uvm_phase phase);
   
    `uvm_info(get_full_name(), {" Inside pre_configure__phase ", get_full_name()}, UVM_LOW);
   
  endtask: pre_configure_phase

configure_phase:

It is used to program the design and keep it ready for the test cases to be tested on.

  task  configure_phase(uvm_phase phase);

    `uvm_info(get_full_name(), {" Inside configure__phase ", get_full_name()}, UVM_LOW);

  endtask: configure_phase

post_configure_phase:

This process is used to program the DUT and any memories in the testbench to keep it ready for the start of the test case.

  task  post_configure_phase(uvm_phase phase);
   
    `uvm_info(get_full_name(), {" Inside Post_configure__phase ", get_full_name()}, UVM_LOW);

  endtask: post_configure_phase

pre_main_phase:

It ensures if all required components are ready to start generating stimulus so that it can be applied on the design under test.

task  pre_main_phase(uvm_phase phase);
   
    `uvm_info(get_full_name(), {" Inside Pre_main__phase ", get_full_name()}, UVM_LOW);

  endtask: pre_main_phase
 

main_phase:

Here, the stimulus specified by the test case is generated and applied on the design. It completes when either all stimulus is exhausted or a timeout occurs.

  task main_phase(uvm_phase phase);
   
    `uvm_info(get_full_name(), {" Inside main__phase ", get_full_name()}, UVM_LOW);

  endtask: main_phase

post_main_phase:

This process is used to take care of any finalization of the main phase

  task post_main_phase(uvm_phase phase);
   
    `uvm_info(get_full_name(), {" Inside Post_main__phase ", get_full_name()}, UVM_LOW);

  endtask: post_main_phase

pre_shutdown_phase:

This phase is acts like a buffer to apply any stimulus before the shutdown phase starts.

task  pre_shut_down_phase(uvm_phase phase);
   
    `uvm_info(get_full_name(), {" Inside Pre_shutdown_phase ", get_full_name()}, UVM_LOW);

  endtask: pre_shut_down_phase

shutdown_phase:

This process drains out the resultant data which is propagated in main phase and also executes the any time-consuming sequences that read status registers.

   task  shut_down_phase(uvm_phase phase);
   
    `uvm_info(get_full_name(), {" Inside shutdown_phase ", get_full_name()}, UVM_LOW);

   endtask: shut_down_phase

post_shutdown_phase:

It performs any final activities before exiting the active simulation phases. At the end of the post_shutdown phase, the execution process starts the cleanup phase.

   task  Post_shut_down_phase(uvm_phase phase);
   
    `uvm_info(get_full_name(), {" Inside shutdown_phase ", get_full_name()}, UVM_LOW);

   endtask: Post_shut_down_phase

Output

run-phase-output

      Fig-5: output of run phase

GitHub Code link: https://github.com/mbits-mirafra/UVMCourse/blob/b7_Team_BJT/phases/run_phases/run_phases.sv

GitHub log file: https://github.com/mbits-mirafra/UVMCourse/blob/b7_Team_BJT/phases/run_phases/run_phases.log

Note:

1.UVM_phases are derived from the uvm_phase class.

2.We can also write a task run_phase instead of writing all the methods mentioned above. In that case, all the pre-defined methods are called by default and executed in the background.

3.Even if we write these tasks(sub_phases) randomly,automatically it will runs in the order as mentiond above.

4.However all of the sub-phases execute in serial order,we would not use the run_phase together with sub_phases.

5.The uvm_phase checks if any objections are raised by the components. The phase_done is the uvm_objection object that the uvm_phase keeps track of the number of objections with. When we called phase.raise_objection() from inside the run_phase of the perticular class, phase_done.raise_objection() is called in the uvm_phase under the hood.

3. Clean up phase

The clean-up phases are used to collect information from functional coverage monitors and scoreboards to see whether the coverage goal has been reached or the test case has passed. All the results are collected and reported in this phase, like for example the number of error’s during the simulation can be reported. The cleanup phases will start once the run phases are completed. They are implemented as functions and work from the bottom to the top of the component hierarchy.

cleanuphases

      Fig-6: Categories of clean up phases.

Cheat sheet of clean up phases

Sr No. Arrays Types Description Execution Approach Phase type
1 Extract phase Extracts data and final state information from scoreboard and testbench components. Bottom to Top Function
2 Check phase Checks DUT behavior and identity for any error that occurred during the execution of the testbench. Bottom to Top Function
3 Report phase Used to display simulation results. It can also write results to the file. Bottom to Top Function
4 Final phase Used to complete any outstanding actions that are yet to be completed in the testbench. Top to Bottom Function
      Table-1 Cheat Sheet   

Extract phase

This phase is used to retrieve and process the information from functional coverage monitors and scoreboards. This phase may also calculate any statistical information that will be used by report phase.

Code snippet:-

virtual function void extract_phase (uvm_phase phase);
   super.extract_phase(phase);
   `uvm_info("extract",$sformatf("All values of y in queue q are %0p",q),UVM_LOW)
   
endfunction

Check phase

This phase is used to check that the DUT behaved correctly and to identify any errors that may have occurred during the execution of the test bench.

Code snippet:-

virtual function void check_phase(uvm_phase phase);

   super.check_phase(phase);
   if(count_for_randomization == req.value)
      `uvm_info("check","All randomized values recieved",UVM_LOW)
   else
      `uvm_info("check","Some randomized values are missing",UVM_LOW)

endfunction

Report phase

This phase is used to display the results of the simulation or to write the results to file.

Code snippet:-

virtual function void report_phase(uvm_phase phase);

   super.report_phase(phase);
   file = $fopen("report_for_driver","w");
   $fdisplay(file,"Total no of randomizations happend are %0d",count_for_randomization);
   $fdisplay(file,"All randomized values of a are %0d",req.a);
   $fdisplay(file,"All randomized values of b are %0d",req.b);
   $fdisplay(file,"Outputs of y are %0p",q);
   $fclose(file);

endfunction

Final phase

Used to complete any outstanding actions(like closing files and terminate co-simulation engines) that are yet to be completed in the testbench.

Code snippet:-

virtual function void final_phase(uvm_phase phase);
    	
   super.final_phase(phase);
   `uvm_info("final","final phase is working",UVM_LOW)
    
endfunction  

Example

Code snippet:-

`include "uvm_macros.svh"
import uvm_pkg::*;

class seq_item extends uvm_sequence_item;
   rand bit [2:0] a;
   rand bit [2:0] b;
   bit [3:0] y;
   int value = 5;
  
   function new (string name = "seq_item");
      super.new(name);
   endfunction
    
   `uvm_object_utils_begin(seq_item)
   `uvm_field_int(a,UVM_DEFAULT)
   `uvm_field_int(b,UVM_DEFAULT)
   `uvm_field_int(y,UVM_DEFAULT)
   `uvm_object_utils_end

endclass:seq_item


class seq extends uvm_sequence#(seq_item);
   `uvm_object_utils(seq);
   seq_item st;
  	
   function new(string name = "seq");
      super.new(name);
   endfunction
  
   virtual task body();
      st = seq_item::type_id::create("seq_item");
      `uvm_info(get_type_name(), "Randomizing the values", UVM_MEDIUM)
      repeat(st.value)
      begin
         `uvm_do(st);
      end 
      `uvm_info(get_type_name(), "Randomization done", UVM_MEDIUM)      
   endtask:body
  
endclass:seq


class sequencer extends uvm_sequencer #(seq_item);

   `uvm_component_utils(sequencer)
    
   function new(string name = "sequencer", uvm_component parent=null);
      super.new(name, parent);
   endfunction
           
endclass


class driver extends uvm_driver#(seq_item);
   `uvm_component_utils(driver)
   int q[$];
   int count_for_randomization;
   int file;
  
   function new(string name = "driver", uvm_component parent=null);
      super.new(name,parent);
   endfunction
  
//build phase
   virtual function void build_phase(uvm_phase phase);
      super.build_phase(phase);
      req = seq_item::type_id::create("seq_item");
   endfunction
    
//run phase
   virtual task run_phase(uvm_phase phase);
      super.run_phase(phase);
      forever
      begin
         seq_item_port.get_next_item(req);
         `uvm_info(get_type_name(),$sformatf(" value of a:%0d , b:%0d" ,req.a,req.b),UVM_LOW)
         count_for_randomization++;
         req.y = (req.a)+(req.b);
         q.push_back(req.y);
         `uvm_info(get_type_name(),$sformatf(" value of y:%0d" ,req.y),UVM_LOW)
seq_item_port.item_done();
end
endtask
              
//Extract phase
              
   virtual function void extract_phase (uvm_phase phase);
      
      super.extract_phase(phase);
      `uvm_info("extract",$sformatf("All values of y in queue q are %0p",q),UVM_LOW)

endfunction
  
//check phase
  
   virtual function void check_phase(uvm_phase phase);

      super.check_phase(phase);
      if(count_for_randomization == req.value)
         `uvm_info("check","All randomized values recieved",UVM_LOW)
      else
         `uvm_info("check","Some randomized values are missing",UVM_LOW)
   endfunction
      
//report phase
      
   virtual function void report_phase(uvm_phase phase);
   
      super.report_phase(phase);
      file = $fopen("report_for_driver","w");
      $fdisplay(file,"Total no of randomizations happend are %0d",count_for_randomization);
      $fdisplay(file,"All randomized values of a are %0d",req.a);
      $fdisplay(file,"All randomized values of b are %0d",req.b);
      $fdisplay(file,"Outputs of y are %0p",q);
      $fclose(file);

   endfunction
      
// final phase
      
   virtual function void final_phase(uvm_phase phase);

      super.final_phase(phase);
      `uvm_info("final","final phase is working",UVM_LOW)
   endfunction
  
endclass      


class agent extends uvm_agent;

   `uvm_component_utils(agent)
   sequencer s;
   driver d;
  
   function new(string name = "agent", uvm_component parent=null);
      super.new(name,parent);  	
   endfunction
  
//build phase

   virtual function void build_phase(uvm_phase phase);

      super.build_phase(phase);
      s = sequencer::type_id::create("sequencer",this);
      d = driver::type_id::create("driver",this);
   endfunction
  
//connect phase 
   function void connect_phase(uvm_phase phase); 
      
      super.connect_phase(phase);
      d.seq_item_port.connect(s.seq_item_export);
   endfunction

endclass
  
class test extends uvm_test;

   `uvm_component_utils(test);
   seq se;
   agent a;

   function new(string name = "test", uvm_component parent=null) 	
      super.new(name,parent);
   endfunction
  
//build phase
   virtual function void build_phase(uvm_phase phase);

      super.build_phase(phase);
      se = seq::type_id::create("seq");
      a = agent::type_id::create("agent",this);

   endfunction
  
//run phase
   virtual task run_phase(uvm_phase phase);

      super.run_phase(phase);
      phase.raise_objection(this);
      se.start(a.s);
      phase.drop_objection(this);
   endtask
              
endclass
  
module top;

   initial begin
      run_test("test");
   end

endmodule

Output:-

op_cl_ph

      Fig-7: Output of all clean up phases

GitHub lab link:- https://github.com/mbits-mirafra/UVMCourse/tree/b7_Team_BJT/phases/clean_up_phase
Github Logfile link:-https://github.com/mbits-mirafra/UVMCourse/blob/b7_Team_BJT/phases/clean_up_phase/top_op.log

4. User defined phase

UVM supports user defined phases that are customizable by the user.These can be inserted anywhere.
Steps to create a custom phase :

Define phase

We create a phase by extending it from appropriate base class uvm_task_phase,uvm_topdown_phase, uvm_bottomup_phase. If your phase consumes time extend it from uvm_task_phase else go with the requirement.Implement exec_task or exec_func.

    class u_phase extends uvm_topdown_phase;                                                            
     static local u_phase up;                                                                          
     function new(string n="u_phase");                                                                 
       super.new(n);                                                                                   
     endfunction                                                                                       
                                                                                                      
     virtual function string get_type_name();                                                          
     return "user_defined_phase";                                                                      
     endfunction                                                                                       
                                                                                                       
     static function u_phase get();                                                                    
     if (up==null) begin                                                                               
      up=new();                                                                                        
     end                                                                                               
     return up;                                                                                        
     endfunction                                                                                       
                                                                                                       
     virtual function void exec_func(uvm_component comp,uvm_phase phase);                              
     comp.parent=null;                                                                                 
     //display("in the function");                                                                     
     `uvm_info(get_full_name(),$sformatf("in %s phase",phase.get_name()),UVM_MEDIUM);                  
     endfunction                                                                                       
    endclass

Here we extended a user defined phase from uvm_topdown_phase base class. And in the exec_func which is the predefined function that is to be overridden so that the defined function is done as per requirement,we are just printing an info regarding phase.

Insert into a schedule

Inorder to execute a phase it must be added into a domain and that domain is inserted into a schedule.A domain is a phasing schedule node representing an independent branch of schedule.We can insert the new user defined phase in between any of the existing phases. And to do so we need to create a handle for the uvm phase scheduler or domain.
We can do that in the following ways:
By using the handles of domain and phase.

uvm_domain d=uvm_domain::get_common_domain();                                                     
uvm_phase up=d.find(uvm_build_phase::get());  
d.add(user_phase::get(),null,up,null);   

In this we use handles for uvm_domain and uvm_phase for adding the user defined phase u_phase into the domain.In add, The first field is 'instance_field',that should return an instance of a phase,second field is 'with_field',that should represent a phase along with which the user phase should be run,third and fourth fields are 'after and before_fields', to specify the phase after and before which the user phase should be run/inserted respectively. Here the user phase is inserted after build_phase as specified.

  • Both 'with_field' and 'after and before_fields' cannot be given at the same time as they lead to contradiction. So one should be null for other to happen.

Without any handles

uvm_domain::get_common_domain().add(u_phase::get(),null,uvm_build_phase::get(),null);  

Here without any handles we are adding the user defined phase into the domain.

Use the defined phase

     class test extends uvm_test;                                                                        
     `uvm_component_utils(test)                                                                        
     function new(string n="test",uvm_component p=null);                                               
     super.new(n,p);                                                                                                                                                                  
     endfunction                                                                                       
                                                                              
     virtual task run_phase(uvm_phase phase);                                                          
     `uvm_info(get_type_name(),$sformatf("in %s phase",phase.get_name()),UVM_MEDIUM);                  
     endtask                                                                                           
                                                                                                    
     virtual function void build_phase(uvm_phase phase);    
     //uvm_domain u=uvm_domain::get_common_domain();                                                   
     //uvm_phase up=u.find(uvm_build_phase::get());                                                    
     uvm_domain::get_common_domain().add(u_phase::get(),null,uvm_build_phase::get(),null);                                                                                                                                                            
     `uvm_info(get_type_name(),$sformatf("in %s phase",phase.get_name()),UVM_LOW);                     
     endfunction                                                                                       
                                                                                                    
     virtual function void connect_phase(uvm_phase phase);                                              
     `uvm_info(get_type_name(),$sformatf("in %s phase",phase.get_name()),UVM_LOW);                     
     endfunction                                                                                                 
    endclass    

Output:

image

      Fig-8: output of user defined phase

Here we created a user defined phase u_phase and inserted it after build_phase, as we did mention before_field to null,the u_phase will be executed just after build_phase.

Github Lablink:- https://github.com/mbits-mirafra/UVMCourse/blob/b7_Team_BJT/phases/user_def_phase/UDphase/forwiki.sv

Github Logfile:- https://github.com/mbits-mirafra/UVMCourse/blob/b7_Team_BJT/phases/user_def_phase/UDphase/transcript

Clone this wiki locally