Tutorials

Learn More

The uvm_objection class provides a mechanism to coordinate status information between two or more components, objects. The uvm_objection class is extended from uvm_report_object.

Class hierarchy

uvm_objection hierarchy

Class Declaration

class uvm_objection extends uvm_report_object

The objection deals with the concept of raise and drop objection which means the internal counter is increment and decrement respectively. Each participating component and object may raise or drop objections asynchronously. When all objections are dropped, the counter value will become zero. The objection has to be raised before starting any process and drop it once it is completed.

UVM Objection Usage

  1. UVM phasing mechanism uses objections to coordinate with each other and the phase should be ended when all objections are dropped. They can be used in all UVM phases.
  2. It allows proceeding for the “End of test”. The simulation time-consuming activity happens in the run phase. If all objections dropped for run phases, it means simulation activity is completed. The test can be ended after executing clean up phases.
task reset_phase( uvm_phase phase);
  phase.raise_objection(this);
  ...
  phase.drop_objection(this);
endtask

task run_phase(uvm_phase phase);
  phase.raise_objection(this, "Raised Objection");
  ...
  phase.drop_objection(this, "Dropped Objection");
endtask

Note: 

  1. Objections are generally used in components and sequences.
  2. Other objects can also use them but they must use a component or sequence object context.

Methods in uvm_objection

Methods

Description

raise_objection (uvm_object obj = null, string description = ” “, int count = 1)

Raises number of objections for corresponding object with default count = 1

drop_objection (uvm_object obj = null, string description = ” “, int count = 1)

Drops number of objections for corresponding object with default count = 1

set_drain_time (uvm_object obj=null, time drain)

Sets drain time for corresponding objects.

Callback Hooks

The callback methods are defined in the uvm_objection_callback class which is derived from the uvm_callback class.

Callback Hooks

Description

raised

Called when an objection is raised for this component or its derived classes.

dropped

Called when an objection is dropped for this component or its derived classes.

all_dropped

Called when all objections are dropped for this component and its derived classes.

Drain Time

The amount of wait time between all objections has been dropped and calling all_dropped() callback is called drain time.

UVM Objections Examples

In the below example, complete driver, sequence, and sequencer communication are not established as an intention is to provide clarity for the objection mechanism.

An objection in the test component

The raise_objection is called prior to executing the run_phase. Once activities of run_phase are completed, the drop_objection is called. The run_phase of the test is mentioned below.

class seq_item extends uvm_sequence_item;
  rand bit[15:0] addr;
  rand bit[15:0] data;
  `uvm_object_utils(seq_item)
  
  function new(string name = "seq_item");
    super.new(name);
  endfunction
  
endclass

class base_seq extends uvm_sequence #(seq_item);
  seq_item req;
  `uvm_object_utils(base_seq)
  
  function new (string name = "base_seq");
    super.new(name);
  endfunction

  task body();
    `uvm_info(get_type_name(), "Base seq: Body started", UVM_LOW);
    req = seq_item::type_id::create("req");
    // send to the driver
    #20;
    `uvm_info(get_type_name(), "Base seq: Body completed", UVM_LOW);
  endtask
endclass


class base_test extends uvm_test;
  base_seq bseq;

  `uvm_component_utils(base_test)
  
  function new(string name = "base_test", uvm_component parent = null);
    super.new(name, parent);
  endfunction
  
  function void build_phase(uvm_phase phase);
    super.build_phase(phase);
  endfunction
 
  task run_phase(uvm_phase phase);
    super.run_phase(phase);
    phase.raise_objection(this, "Raise Objection");
    bseq = base_seq::type_id::create("bseq");    
    bseq.start(null);
    phase.drop_objection(this, "Drop Objection");
  endtask
endclass

module tb_top;
  initial begin
    run_test("base_test");
  end
endmodule

Output:

UVM_INFO testbench.sv(17) @ 0: reporter@@bseq [base_seq] Base seq: Body started
UVM_INFO testbench.sv(21) @ 20: reporter@@bseq [base_seq] Base seq: Body completed

An objection in the sequence

The objection can be raised and dropped either in body tasks or pre_body/ post_body tasks.

class base_seq extends uvm_sequence #(seq_item);
  ...
  task pre_body();
    if(starting_phase != null) starting_phase.raise_objection(this);
  endtask
 
  task body();
    req = seq_item::type_id::create("req");
    // send to the driver
    #20;
   ...
  endtask
 
  task post_body();
    if(starting_phase != null) starting_phase.drop_objection(this);
  endtask
endclass

The above code is not recommended to use with uvm1.2 as the starting_phase() method from uvm_sequence_base is deprecated in uvm1.2 

The objection mechanism in the sequence can be used with the below two approaches.

  1. With set_starting_phase and get_starting_phase methods
  2. With set_automatic_phase_objection method

With set_starting_phase and get_starting_phase methods

The two new methods set_starting_phase and get_starting_phase are added as a replacement.

As the name implies set_starting_phase and get_starting_phase are used to set and retrieve the phase. 

Note: If get_starting_phase returns null, then the sequence will not raise and drop objection.

class seq_item extends uvm_sequence_item;
  rand bit[15:0] addr;
  rand bit[15:0] data;
  `uvm_object_utils(seq_item)
  
  function new(string name = "seq_item");
    super.new(name);
  endfunction
  
endclass

class base_seq extends uvm_sequence #(seq_item);
  seq_item req;
  uvm_phase phase;
  `uvm_object_utils(base_seq)
  
  function new (string name = "base_seq");
    super.new(name);
  endfunction

  task pre_body();
    `uvm_info(get_type_name(), "Inside pre_body", UVM_LOW);
    phase = get_starting_phase; // Retrieve phase information
    if (phase != null) phase.raise_objection(this);
  endtask
  
  task body();
    `uvm_info(get_type_name(), "Base seq: Body started", UVM_LOW);
    req = seq_item::type_id::create("req");
    // send to the driver
    #20;
    `uvm_info(get_type_name(), "Base seq: Body completed", UVM_LOW);
  endtask
  
  task post_body();
    `uvm_info(get_type_name(), "Inside post_body", UVM_LOW);
    if (phase != null) phase.drop_objection(this);
  endtask
endclass


class base_test extends uvm_test;
  base_seq bseq;

  `uvm_component_utils(base_test)
  
  function new(string name = "base_test", uvm_component parent = null);
    super.new(name, parent);
  endfunction
  
  function void build_phase(uvm_phase phase);
    super.build_phase(phase);
  endfunction
 
  task run_phase(uvm_phase phase);
    super.run_phase(phase);
    bseq = base_seq::type_id::create("bseq");
    bseq.set_starting_phase(phase); // Set starting phase
    bseq.start(null);
  endtask
endclass

module tb_top;
  initial begin
    run_test("base_test");
  end
endmodule

Output:

UVM_INFO testbench.sv(18) @ 0: reporter@@bseq [base_seq] Inside pre_body
UVM_INFO testbench.sv(24) @ 0: reporter@@bseq [base_seq] Base seq: Body started
UVM_INFO testbench.sv(28) @ 20: reporter@@bseq [base_seq] Base seq: Body completed
UVM_INFO testbench.sv(32) @ 20: reporter@@bseq [base_seq] Inside post_body

With set_automatic_phase_objection method

The uvm1.2 also added the set_automatic_phase_objection method that automatically raises and drops the objection for the current sequence. Alternatively, there is no need to call raise_objection prior to executing the sequence and drop_objection once execution is completed.

Instead, make set_automatic_phase_objection(1) either in the new() method of the sequence or before starting the sequence.

class seq_item extends uvm_sequence_item;
  rand bit[15:0] addr;
  rand bit[15:0] data;

  `uvm_object_utils(seq_item)
  
  function new(string name = "seq_item");
    super.new(name);
  endfunction
  
endclass

class base_seq extends uvm_sequence #(seq_item);
  seq_item req;
  uvm_phase phase;
  `uvm_object_utils(base_seq)
  
  function new (string name = "base_seq");
    super.new(name);
  endfunction

  task pre_body();
    `uvm_info(get_type_name(), "Inside pre_body", UVM_LOW);
  endtask
  
  task body();
    `uvm_info(get_type_name(), "Base seq: Body started", UVM_LOW);
    req = seq_item::type_id::create("req");
    // send to the driver
    #20;
    `uvm_info(get_type_name(), "Base seq: Body completed", UVM_LOW);
  endtask
  
  task post_body();
    `uvm_info(get_type_name(), "Inside post_body", UVM_LOW);
  endtask
endclass

class base_test extends uvm_test;
  base_seq bseq;

  `uvm_component_utils(base_test)
  
  function new(string name = "base_test", uvm_component parent = null);
    super.new(name, parent);
  endfunction
  
  function void build_phase(uvm_phase phase);
    super.build_phase(phase);
  endfunction
 
  task run_phase(uvm_phase phase);
    super.run_phase(phase);
    bseq = base_seq::type_id::create("bseq");
    bseq.set_starting_phase(phase);
    bseq.set_automatic_phase_objection(1);
    bseq.start(null);
  endtask
endclass

module tb_top;
  initial begin
    run_test("base_test");
  end
endmodule

Output:

UVM_INFO testbench.sv(18) @ 0: reporter@@bseq [base_seq] Inside pre_body
UVM_INFO testbench.sv(22) @ 0: reporter@@bseq [base_seq] Base seq: Body started
UVM_INFO testbench.sv(26) @ 20: reporter@@bseq [base_seq] Base seq: Body completed
UVM_INFO testbench.sv(30) @ 20: reporter@@bseq [base_seq] Inside post_body

Note: Do not make set_automatic_phase_objection(1) if the sequence runs with a forever loop inside of the body, as the objection will never get dropped.