UVM_ERROR ONLY via try_next_item


  `include "uvm_pkg.sv"
  `include "uvm_macros.svh" 
  
   import  uvm_pkg::*;

   class user_seq_item  extends uvm_sequence_item ;
  
     //   Factory  Registration  N  Object  Constructor
  
  endclass   

  typedef  uvm_sequencer #(user_seq_item)  user_sequencer ;

  class  my_driver  extends  uvm_driver #(user_seq_item) ;

      //   Factory  Registration  N  Component  Constructor
     
      task   main_phase(  uvm_phase phase ) ;
             
           `ifdef TRY  
             seq_item_port.try_next_item(req) ;
           `else   
             seq_item_port.get_next_item(req) ;
           `endif

             seq_item_port.item_done() ;

      endtask

  endclass

  class  user_seq  extends uvm_sequence#(user_seq_item) ; 

     //   Factory  Registration  N  Object  Constructor

  `ifdef  PRE_DO
     virtual  task  pre_do (  bit  is_item  ) ; 
      #50 ;
     endtask
 `endif     

     task  body() ;
       
         req =  user_seq_item::type_id::create("req") ;  

            start_item(req); 
             
          `ifndef PRE_DO   
            #100 ;
          `endif   

            finish_item(req);  
           
           `uvm_info("body",$sformatf(" Task finish_item()  Unblocks "),UVM_NONE)

     endtask

  endclass   

  
  class  user_test extends  uvm_test ;

      //   Factory  Registration  N  Component  Constructor

      my_driver        drv  ;
  
      user_sequencer   seqr ;

      function  void  build_phase ( uvm_phase phase ) ;
       
              drv  =  my_driver::type_id::create("drv",this) ; 
              
             seqr  =  user_sequencer::type_id::create("seqr",this) ; 

      endfunction

      function  void  connect_phase ( uvm_phase phase ) ;
          drv.seq_item_port.connect( seqr.seq_item_export ) ;  
      endfunction
      
      task   main_phase(  uvm_phase phase ) ;
          user_seq   seq  ;

          phase.raise_objection(this);

                 seq  =  user_seq::type_id::create("seq");

                 seq.start(seqr);  

          phase.drop_objection(this);

      endtask

  endclass

  module  Top_TB ; 
   
      initial  run_test("user_test") ;
  
  endmodule


ONLY when using try_next_item I observe UVM_ERROR followed by UVM_FATAL .

//===========================================================================================
// OUTPUT with +define+TRY
//===========================================================================================
//
// UVM_INFO @ 0: reporter [RNTST] Running test user_test…
// UVM_ERROR @ 0: uvm_test_top.seqr [TRY_NEXT_BLOCKED] try_next_item: the selected sequence ‘uvm_test_top.seqr.seq’ did not produce an item within an NBA delay. Sequences should not consume time between calls to start_item and finish_item. Returning null item.
// UVM_FATAL @ 0: uvm_test_top.seqr [uvm_test_top.seqr] Item_done() called with no outstanding requests. Each call to item_done() must be paired with a previous call to get_next_item().
//
//===========================================================================================

//===========================================================================================
// OUTPUT with +define+TRY +define+PRE_DO
//===========================================================================================
//
// UVM_INFO @ 0: reporter [RNTST] Running test user_test…
// UVM_ERROR @ 0: uvm_test_top.seqr [TRY_NEXT_BLOCKED] try_next_item: the selected sequence ‘uvm_test_top.seqr.seq’ did not produce an item within an NBA delay. Sequences should not consume time between calls to start_item and finish_item. Returning null item.
// UVM_FATAL @ 0: uvm_test_top.seqr [uvm_test_top.seqr] Item_done() called with no outstanding requests. Each call to item_done() must be paired with a previous call to get_next_item().
//
//===========================================================================================

**[ Q ] Why is it that ONLY try_next_item gives the UVM_ERROR N UVM_FATAL whereas get_next_item works fine ?
**

In reply to MICRO_91:

Even though try_next_item() is declared as a task, there are checks to ensure that it does not block beyond a time unit. Unlike a function that has a return code, you have to check the req argument to make sure it has a non-null handle.

get_net_item() can block, so there can be a delay between start_item and finish_item. The problem with they wrote this protocol is you have no way of knowing whether the driver is using get_next_item or try_next_item, so you should not insert delays regardless.