Hi,
I was studying some code and led to some questions. Can two sequences communicate with each other using a sequencer? i.e., sequence A will add items using start_item while sequencer B read them using sequencer.get function?.
Hi,
I was studying some code and led to some questions. Can two sequences communicate with each other using a sequencer? i.e., sequence A will add items using start_item while sequencer B read them using sequencer.get function?.
Hi Rajmuk01,
Actually I didn’t get your complete question, but as per my understanding from your question, a sequence can call another sequence. Let me try to explain through following example.
class sub_seqs extends uvm_sequence #(xtn);
// Factory registration $ constructor
virtual task body();
req = xtn_item::type_id::create("req");
start_item(req);
assert(req.randomize());
finish_item(req);
endtask : body
endclass : sub_seqs
class main_seqs extends uvm_sequence#(xtn);
// Factory registration $ constructor
sub_seqs seqs; // created handle for sub_seqs
virtual task body;
repeat(10)
begin
seqs = sub_seqs::type_id::create("seqs");
seqs.start(m_sequencer); // In-built handle
end
endtask : body
endclass : main_seqs
So, in the above code, when you call the main_seqs from driver through get_next_item via sequencer, main_seqs’s body task calls sub_seqs for 10 times and hence randomizes it for 10 times.
I hope, this clears your doubt.
Thanks & Regards,
Sachin
No. I did not mean that. Its more like one sequence sending to data to another via a sequencer. I have the put code to explain it better. I always thought get_next_item/try_next_item can be accessed only by drivers. But then UVM class library says that seq_item_export variable present in uvm_sequencer provides access to these methods. And it seems driver can access these methods only because seq_item_export is connected to seq_item_port and as such these methods are actually part of sequencer, hence this example holds good. Wanted to confirm if this is the case
class external_sequence extends uvm_sequence #(trans_item);
virtual task body();
req = trans_item::type_id::create("req");
start_item(req);
assert(req.randomize());
finish_item(req);
endtask : body
endclass
class transaction_sequence extends uvm_sequence #(uvm_sequence_item);
uvm_sequencer #(trans_item) sequencer;
virtual function
void initialize(uvm_sequencer #(trans_item) sqr);
sequencer = sqr;
endfunction : initialize
virtual task
body();
trans_item item
sequencer.try_next_item(item);
// Rest of the code
endtask
endclass
class my_agent extends uvm_agent;
`uvm_component_utils(my_agent)
// Variable: sequencer
uvm_sequencer #(trans_item) sequencer;
transaction_sequence trans_seq;
virtual function
void build_phase(uvm_phase phase);
super.build_phase(phase);
sequencer = uvm_sequencer #(trans_item)::type_id::create("sequencer", this);
trans_seq = transaction_sequence sequence::type_id::create("trans_seq", this);
endfunction : build_phase
virtual task
run_phase(uvm_phase phase);
trans_seq.initialize(sequencer);
trans_seq.start(null);
endtask : run_phase
endclass
class my_env extends uvm_env;
my_agent agentA;
external_sequence ext_seq;
void build_phase(uvm_phase phase);
super.build_phase(phase);
ext_seq = external_sequence::type_id::create("ext_seq", this);
endfunction
virtual task
run_phase(uvm_phase phase);
ext_seq.start(agentA.sequencer);
endtask : run_phase
endclass
Hi Rajesh,
You are correct that the sequencer provides the implementation of get_next_item/try_next_item, so technically what you propose would work. However, I’m not sure why you would want to do such a thing. The get/try_next_item methods will return a transaction from the sequencer’s internal fifo. The sequence puts the transaction in the fifo via start_item(). Having both sequences executing on env.agentA.sequencer [and by the way, you forgot to create/instantiate agentA in the env] serves no useful purpose, since trans_seq still needs to do something with the transaction. Anything it would do could just as easily be done in ext_seq. Even worse, there’s now no transaction left in the fifo for the driver to get. It would make no sense for trans_seq to call start_item() to send it to the driver, since that would just be putting the item back into the same fifo.
The only time we recommend calling the sequencer methods directly is from a translation sequence when you are implementing a layered protocol. See the Cookbook for more details.
Good luck,
-Tom