In System Verilog UVM, the interface present in TLM ports for communication between sequences and drivers (uvm_sqr_if_base
) offers flexibility. For pulling requests, I'll summarize the four options in this table:
blocking item_done
get_next_item() yes no
try_next_item() no no
get() yes yes
peek() yes no
... where blocking indicates that if you call the method, but no sequence is ready to provide data, then the task will BLOCK and wait until data is ready and can and will be returned.
... where item_done indicates that the method also calls item_done()
after successfully pulling an item from the sequence.
What's the difference between peek()
and get_next_item()
then?
Consider these two code snippets from two imaginary drivers ...
while(1) begin: loop1 while(1) begin: loop2
seq_item_port.get_next_item(req); seq_item_port.peek(req);
process(req); process(req);
seq_item_port.item_done(); seq_item_port.item_done();
end: loop1 end: loop2
What's the difference? Why are there two methods for accomplishing the same thing? It doesn't seem to be TLM1 vs TLM2 styles.
EDIT:
To answer the point below. I had looked at the source code before asking this question. In fact, the LANGUAGE differs only slightly, the code seems to do exactly the same thing. What's the point? What am I missing?
// Task: get_next_item
//
// Retrieves the next available item from a sequence. The call will block
// until an item is available. The following steps occur on this call:
//
// 1 - Arbitrate among requesting, unlocked, relevant sequences - choose the
// highest priority sequence based on the current sequencer arbitration
// mode. If no sequence is available, wait for a requesting unlocked
// relevant sequence, then re-arbitrate.
// 2 - The chosen sequence will return from wait_for_grant
// 3 - The chosen sequence <uvm_sequence_base::pre_do> is called
// 4 - The chosen sequence item is randomized
// 5 - The chosen sequence <uvm_sequence_base::post_do> is called
// 6 - Return with a reference to the item
//
// Once <get_next_item> is called, <item_done> must be called to indicate the
// completion of the request to the sequencer. This will remove the request
// item from the sequencer FIFO.
vs.
// Task: peek
//
// Returns the current request item if one is in the sequencer FIFO. If no
// item is in the FIFO, then the call will block until the sequencer has a new
// request. The following steps will occur if the sequencer FIFO is empty:
//
// 1 - Arbitrate among requesting, unlocked, relevant sequences - choose the
// highest priority sequence based on the current sequencer arbitration mode.
// If no sequence is available, wait for a requesting unlocked relevant
// sequence, then re-arbitrate.
//
// 2 - The chosen sequence will return from <uvm_sequence_base::wait_for_grant>
// 3 - The chosen sequence <uvm_sequence_base::pre_do> is called
// 4 - The chosen sequence item is randomized
// 5 - The chosen sequence <uvm_sequence_base::post_do> is called
//
// Once a request item has been retrieved and is in the sequencer FIFO,
// subsequent calls to peek will return the same item. The item will stay in
// the FIFO until either get or <item_done> is called.