Regarding get_next_item implementation in uvm_sequencer base class

task uvm_sequencer::get_next_item(output REQ t);
REQ req_item;

// If a sequence_item has already been requested, then get_next_item()
// should not be called again until item_done() has been called.

if (get_next_item_called == 1)
uvm_report_error(get_full_name(),
“Get_next_item called twice without item_done or get in between”, UVM_NONE);

if (!sequence_item_requested)
m_select_sequence();

// Set flag indicating that the item has been requested to ensure that item_done or get
// is called between requests
sequence_item_requested = 1;
get_next_item_called = 1;
m_req_fifo.peek(t);
endtask

The above task is implemented in the baseclass of uvm_sequencer. they have implemented the get_next_item method using peek method(if you see the above code). peek is a method which gives the copy of the value and the value will be remained in the mailbox. the size of req_fifo is 1. once a packet has been put inside the req_fifo until i get the packet out i cannot put any other packet. if this is the case, how the hand shaking between driver and sequencer is happening for multiple packets. can anyone give me clarity.?

In reply to Salman devarenti :

Read the UVM Cookbook chapter on pipelined drivers on how to handle multiple packets simultaneously.

In reply to cgales:

No, my question is how the driver getting the next packet when the previous packet still there in req_fifo. Peek is a mailbox method. Peek method will give copy of the packet but the packet will be left there inside req_fifo. When a packet is already there inside the req_fifo, how the driver is getting another new packet (using peek method we can’t get the packet out. It’s just takes the copy of packet).

In reply to Salman devarenti :

As the Cookbook chapter points out, you don’t use get_next_item() when you want to get multiple sequence items. You use get() which will remove the item from the queue.

If you use get_next_item(), you need to use item_done() to remove the item from the queue.

In reply to cgales:
Thanks mate…! It is helpful.

quick question, if get_next_item is a task inside uvm_sequencer. then how can we address it as seq_item_export.get_next_item(). This is the way we use get-next_item() in most cases ie normal cases that are non pipelined.

This because the uvm_sequencer ha a ‘seq_item_export’ as an interface. We are calling in the driver exactly seq_item_export.get_next_item(req) to retrieve a sequence_item from the sequencer.

I am not exactly following what you meant. seq_item_export is a pull port (as shown below). if get_next_item is a task inside uvm_sequencer then shouldnt get_next_item be called as sequencer.get_next_item(), why does seq_item_export.get_next_item() work correctly as well?

Sequencer Interface

This is an interface for communicating with sequencers.

The interface is defined as

Requests: virtual task get_next_item (output REQ request); virtual task try_next_item (output REQ request); virtual task get (output REQ request); virtual task peek (output REQ request); Responses: virtual function void item_done (input RSP response=null); virtual task put (input RSP response); Sync Control: virtual task wait_for_sequences (); virtual function bit has_do_available ();

See uvm_sqr_if_base #(REQ,RSP) for information about this interface.

seq_item_export

uvm_seq_item_pull_imp #(
REQ,
RSP,
this_type
) seq_item_export

This export provides access to this sequencer’s implementation of the sequencer interface.

Looks like you are not familiar with TL communication. Units play different roles. The sequencer is a pssive unit and cannot act, but the driver is an active unit and will retrieve a sequence_item from the sequencer calling seq_item_export.get_next_item(req).

so how is seq_item_export.get_next_item(req) different to sequencer.get_next_item(req) functionally. can we use them interchangeably

The driver does not have a handle to the sequencer. TLM is layer of abstraction that provides a standard way for components to communicate without any knowledge of the component they are communicating with. A “port” is the initiator or caller, and the “export” is the provider, or callee. In this scenario the sequencer is providing the implementation of get_next_item() and exporting a handle to the port in the driver through the seq_item_export

Hi Dave, thanks for the reply. I am referencing to the concept of sequence layering in UVM. where we use translator sequence for establishing the layer.
In non-layering scenario we use seq_item_export.get_next_iyem(), thats okay but in translator seq we use get_next_item differently. as in the snip shown. What i dont get is how can get_next_item be used differently in layering vs non-layering scenarios.