Skip to content
Vinaydampuru edited this page Nov 3, 2022 · 12 revisions

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.

UVM provides default extensions of this class for the standard runtime phases. VIP Providers can likewise extend this class to define the phase functor for a particular component context as required.

Phase Definition

Singleton instances of those extensions are provided as package variables. 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.

It is the base class for phase functors, for both predefined and user-defined phases. Per-component overrides can use a customized imp. To create custom phases, do not extend uvm_phase directly: see the three predefined extended classes below which encapsulate behavior for different phase types: task, bottom-up function and top-down function.

Extend the appropriate one of these to create a uvm_YOURNAME_phase class for each phase, containing the default implementation of the new phase, which must be a uvm_component-compatible delegate, and which may be a null implementation. Instantiate a singleton instance of that class for your code to use when a phase handle is required. If your custom phase depends on methods that are not in uvm_component, but are within an extended class, then extend the base YOURPREFIX_NAME_phase class with parameterized component class context as required, to create a specialized functor which calls your extended component class methods. This scheme ensures compile-safety for your extended component classes while providing homogeneous base types for APIs and underlying data structures.

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.

Structure is a DAG (Directed Acyclic Graph).

Each instance is a node connected to others to form the graph. Hierarchy is overlaid with m_parent. 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.

Phase Handle

Handles of this type uvm_phase are used frequently in the API, both by the user, to access phasing-specific API, and also as a parameter to some APIs. In many cases, the singleton phase handles can be used (eg. <uvm_run_phase::get()>) in APIs. For those APIs that need to look up that phase in the graph, his is done automatically.

syntax:

class uvm_phase extends uvm_object;

uvm_object_utils(uvm_phase) uvm_register_cb(uvm_phase, uvm_phase_cb)

endclass

Phasing Interface

These methods implement an interface which allows all components to step through a standard schedule of phases, or a customized schedule, and also an API to allow independent phase domains which can jump like state machines to reflect behavior e.g. power domains on the DUT in different portions of the testbench. The phase tasks and functions are the phase name with the _phase suffix. For example, the build phase function is <build_phase>.

All processes associated with a task-based phase are killed when the phase ends. See <uvm_task_phase> for more details.

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 : output for build phase.

Github lab link: https://github.com/muneeb-mbytes/UVM_Course/blob/b7_Team_BJT/phases/build_phase/uvm_build_phase.sv

Github log file link: https://github.com/muneeb-mbytes/UVM_Course/blob/b7_Team_BJT/phases/build_phase/uvm_build_phase.log

connect_phase

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 : output for connect phase.

Github lab link: https://github.com/muneeb-mbytes/UVM_Course/blob/b7_Team_BJT/phases/connect_phase/uvm_connect_phase.sv

Github log file link: https://github.com/muneeb-mbytes/UVM_Course/blob/b7_Team_BJT/phases/connect_phase/uvm_connect_phase.log

Clone this wiki locally