I have developed this small tb.
/*transaction class */
import uvm_pkg::*;
`include "uvm_macros.svh";
class configuration extends uvm_sequence_item;
`uvm_object_utils(configuration)
bit [7:0] data_width;
int unsigned no_of_trans;
function new(string name = "configuration");
super.new(name);
endfunction
function void set_cfg();
if( ! $value$plusargs ("data_width=%d",data_width ))
data_width = 32;
if(!$value$plusargs ("no_of_trans=%d",no_of_trans ))
no_of_trans = 10;
endfunction
endclass
class transaction extends uvm_sequence_item;
`uvm_object_utils(transaction)
bit [3:0] data;
function new(string name = "transaction");
super.new(name);
endfunction
endclass
interface data_if(input clk);
bit [5:0] data;
endinterface
/* sequence class*/
class my_sequence extends uvm_sequence#(transaction);
`uvm_object_utils(my_sequence)
transaction req;
int LIMIT;
task body();
for (int i = 0; i < LIMIT; i++) begin
req= new("req");
req.data = 1;
start_item(req);
// req.data = 1;
// #60;
// req.randomize();
finish_item(req);
end
endtask
endclass
/* sequencer*/
class sequencer extends uvm_sequencer#(transaction);
`uvm_component_utils(sequencer)
//constructor
function new(string name, uvm_component parent);
super.new(name,parent);
endfunction
endclass
/* driver class*/
class driver extends uvm_driver#(transaction);
// Virtual Interface
virtual data_if vif;
transaction req;
`uvm_component_utils(driver)
// Constructor
function new (string name, uvm_component parent);
super.new(name, parent);
endfunction : new
function void build_phase(uvm_phase phase);
super.build_phase(phase);
if(!uvm_config_db#(virtual data_if)::get(this, "", "vif", vif))
`uvm_fatal("NO_VIF",{"virtual interface must be set for: ",get_full_name(),".vif"});
req = new("req");
endfunction: build_phase
// run phase
virtual task run_phase(uvm_phase phase);
forever begin
seq_item_port.get_next_item(req);
drive();
seq_item_port.item_done();
end
endtask : run_phase
// drive
virtual task drive();
// req.print();
$display("%0t:req.data=%d",$time, req.data);
@(posedge vif.clk);
vif.data<= req.data;
endtask : drive
endclass : driver
/*agent class*/
class agent extends uvm_agent;
driver drv;
sequencer seqr;
// UVM automation macros for general components
`uvm_component_utils(agent)
// constructor
function new (string name, uvm_component parent);
super.new(name, parent);
endfunction : new
// build_phase
function void build_phase(uvm_phase phase);
super.build_phase(phase);
drv= driver::type_id::create("drv", this);
seqr = sequencer::type_id::create("seqr", this);
endfunction : build_phase
function void connect_phase(uvm_phase phase);
drv.seq_item_port.connect(seqr.seq_item_export);
// m_drv0.seq_item_port.connect (m_seqr0.seq_item_export);
endfunction
endclass : agent
/*env class*/
class my_env extends uvm_env;
`uvm_component_utils(my_env)
agent agt;
function new (string name, uvm_component parent);
super.new(name, parent);
endfunction : new
function void build_phase(uvm_phase phase);
agt= agent::type_id::create("agt",this);
endfunction
task run_phase(uvm_phase phase);
phase.raise_objection(this);
$display("%0t",$time);
#10;
phase.drop_objection(this);
endtask
endclass
class my_test extends uvm_test;
`uvm_component_utils(my_test)
my_sequence seq;
my_env env;
configuration cfg;
function new (string name, uvm_component parent);
super.new(name, parent);
endfunction : new
function void build_phase(uvm_phase phase);
env = my_env::type_id::create("env", this);
seq = my_sequence::type_id::create("seq");
cfg = configuration ::type_id :: create("cfg");
cfg.set_cfg();
seq.LIMIT=10;
endfunction
task main_phase(uvm_phase phase);
seq.start(env.agt.seqr);
endtask
endclass
module tb_top;
bit clk;
//clock generation
always #5 clk = ~clk;
//creatinng instance of interface, inorder to connect DUT and testcase
data_if intf(clk);
//enabling the wave dump
initial begin
uvm_config_db#(virtual data_if)::set(uvm_root::get(),"*","vif",intf);
$dumpfile("dump.vcd"); $dumpvars;
end
initial begin
run_test("my_test");
end
endmodule
Output:
# UVM_INFO verilog_src/questa_uvm_pkg-1.2/src/questa_uvm_pkg.sv(277) @ 0: reporter [Questa UVM] QUESTA_UVM-1.2.3
# UVM_INFO verilog_src/questa_uvm_pkg-1.2/src/questa_uvm_pkg.sv(278) @ 0: reporter [Questa UVM] questa_uvm::init(+struct)
# UVM_INFO @ 0: reporter [RNTST] Running test my_test...
# 0
# 0:req.data= 1
# UVM_INFO verilog_src/uvm-1.1d/src/base/uvm_objection.svh(1267) @ 10: reporter [TEST_DONE] 'run' phase is ready to proceed to the 'extract' phase
#
# --- UVM Report Summary ---
#
# ** Report counts by severity
# UVM_INFO : 4
# UVM_WARNING : 0
# UVM_ERROR : 0
# UVM_FATAL : 0
# ** Report counts by id
# [Questa UVM] 2
# [RNTST] 1
# [TEST_DONE] 1
# ** Note: $finish : /usr/share/questa/questasim/linux_x86_64/../verilog_src/uvm-1.1d/src/base/uvm_root.svh(430)
# Time: 10 ns Iteration: 55 Instance: /tb_top
Here, objection is raise inside run_phase of env and in main_phase of test, their is no objection, still as per output objection in run_phase, let main_phase of test executes and once that objection is dropped , simulation ends. Isn’t it wrong? how can objection of env can control test 's phase?