Hi,
I came across problem where stop_sequences function of leaf level sequencer is terminating virtual sequence which is running on virtual sequencer.
Let me more elaborate on this.
Here ,
- my_seqr - leaf level sequencer
- my_vir_seqr - virtual sequencer
- my_vir_seq - virtual sequence
- my_tr - leaf level transaction
Where my_tr transaction is sent from virtual sequence (i.e. my_vir_seq) by using `uvm_do_on() macro to leaf level sequencer and it has been driven successfully and driver has done item_done, then after certain delay , reset is being applied and leaf level sequencer (my_seqr) is calling stop_sequences function to kill sequence if any sequence is running on it. But at time of reset , there is no sequence running on leaf level sequencer. Only running sequence is virtual sequence which is running of virtual sequencer (my_vir_seqr) and it is not generating any kind of traffic on my_seqr (leaf level sequencer), though stop_sequences() is killing my_vir_seq.
Snippet:
Transaction Class:
class my_tr extends uvm_transaction;
function new (string name = "my_tr");
super.new(name);
endfunction : new
`uvm_object_utils(my_tr)
endclass : my_tr
Leaf level Sequencer:
class my_seqr extends uvm_sequencer#(my_tr);
virtual my_if my_vif;
function new (string name = "my_seqr" , uvm_component parent = null);
super.new(name,parent);
endfunction : new
function void build_phase(uvm_phase phase);
// get virtual interface by using uvm_config_db
endfunction : build_phase
task run_phase (uvm_phase phase);
forever
begin
wait (my_vif.reset == 0);// wait for reset to be asserted.
stop_sequences();
wait (my_vif.reset == 1);// wait for reset to be de-asserted
end
endtask : run_phase
`uvm_component_utils(my_seqr)
endclass : my_seqr
Leaf level driver:
class my_drv extends uvm_driver#(my_tr);
// ------- --- build_phase
// ----- ---- connect phase
task run_phase(uvm_phase phase);
forever
begin
seq_item_port.get_next_item(req);
#10; // some delay
seq_item_port.item_done();
end
endtask : run_phase
endclass : my_drv
Virtual Sequencer (top level sequencer):
class my_vir_seqr extends uvm_sequencer;
my_seqr my_seqr_h; // handle of leaf level sequencer
function new (string name = "my_vir_seqr",uvm_component parent = null);
super.new(name,parent);
endfunction : new
`uvm_component_utils(my_vir_seqr)
endclass : my_vir_seqr
Virtual sequence:
class my_vir_seq extends uvm_sequence;
`uvm_object_utils(my_vir_seq)
`uvm_declare_p_sequencer(my_vir_seq)
process p_seq;
function new (string name = "my_vir_seq" );
super.new(name);
endfunction : new
task body();
my_tr tr;
p_seq = process :: self();
`uvm_info(get_name(),"sequence is running",UVM_LOW)
`uvm_do_on( tr, p_sequencer.my_seqr_h); // send transaction on leaf level sequencer
#1000; // Added delay to execute this sequence longer time
`uvm_info(get_name(),"sequence is completed",UVM_LOW)
endtask : body
endclass : my_vir_seq
UVM Test:
class my_test extends uvm_test;
task run_phase (uvm_phase phase);
my_vir_seq vir_seq = my_vir_seq :: type_id :: create("vir_seq");
// raise objection Here
//-------
// start sequence on virtual sequencer
vir_seq.start(env.my_vir_sqr_h);
`uvm_info("PROCESS_STATE",$sformatf("%0s",vir_seq.p_seq.state()),UVM_LOW)
// -------
// drop objection here
endtask : run_phase
endclass : my_test
TOP file:
module top;
bit reset;
// interface declaration and connection
initial
begin
reset = 1;
#80; // adding delay
reset = 0 ; // reset is applied
#10;
reset = 1;
end
initial
run_test();
endmodule : top
OUTPUT:
UVM_INFO@80[PROCESS_STATE]: KILLED
I checked UVM code of uvm_sequencer and found that whenever **start_item** is being called (through `uvm_do_on()) that time , sequencer is storing parent sequence pointer inside reg_sequences[] associative array, Thus here my_vir_seq's pointer would be stored inside this array. But at time of **finish_item**, UVM is not un-registering that sequence pointer inside this array.
Thus I needed to unregister my virtual sequence pointer explicitly by calling below function after `uvm_do_on()
// m_unregister_sequence
// ---------------------
function void uvm_sequencer_base::m_unregister_sequence(int sequence_id);
if (!reg_sequences.exists(sequence_id))
return;
reg_sequences.delete(sequence_id);
endfunction
So i dont understand why finish_item is not un-registering sequence pointer of parent sequence. Is there aBUG in UVM?
Should i consider that we should not generate/send leaf level transaction by using virtual sequence?