UVM Objections
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
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
- 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.
- 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:
- Objections are generally used in components and sequences.
- 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.
- With set_starting_phase and get_starting_phase methods
- 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.
UVM Tutorials