Confusion regarding get_ap of TLM FIFO

Hi all ,

I was going through Class Reference Manual 1.2 uvm_tlm_fifo_base

(I) get_ap :: Transactions passed via get, try_get, peek, or try_peek (via any port connected to the get_peek_export) are sent out this port via its write method.

But when I went through Library Code 1.2 I see that ::

 get_ap.write(t) gets Called in for get() and try_get() Calls . 

Even the Simulators Output match the library Code . I am confused regarding this .



  class Component_fifo extends uvm_component ;

  `uvm_component_utils(Component_fifo)

   // We are creating a blocking TLM get port which will fetch a "simple_packet" type of data
   uvm_tlm_fifo #(simple_packet) fifo ; // Constructed in build_phase
   
   ....
  endclass
      class ComponentB extends uvm_component ;

  `uvm_component_utils(ComponentB)

   // We are creating a blocking TLM get port which will fetch a "simple_packet" type of data
   uvm_blocking_get_port #(simple_packet) get_port; // Created in build_phase
   simple_packet  pkt;
 
   function new (string name , uvm_component parent);
      super.new(name, parent);
   endfunction
   
   virtual task run_phase (uvm_phase phase); 
      
       forever 
	begin
         
           #5;
	   get_port.peek(pkt); // Doesn't call Subs2.write . Why ??
          `uvm_info ("COMPB", "Packet peeked at CompB", UVM_LOW)
	   get_port.get(pkt); // Calls Subs2.write as Expected .  
          `uvm_info ("COMPB", "Packet received at CompB", UVM_LOW)
        
	end

   endtask

    class Subs2 extends uvm_subscriber #(simple_packet) ; 

  `uvm_component_utils(Subs2)
   
   function new(string name, uvm_component parent);
      super.new(name, parent);
   endfunction: new
 
   function void write(simple_packet t ); 
          `uvm_info ("SUBS1", "Packet received at Subs1", UVM_LOW)
   endfunction

  endclass

  class my_env extends uvm_env;
   `uvm_component_utils (my_env)
      
       Component_fifo comp_fifo ; // Created in build_phase 
       Subs2          subs2;     //  Created in build_phase . Calls write()
   ComponentA     compA ; // Created in build_phase . Does the put()
   ComponentB     compB ; // Created in build_phase . Does the get()
 

virtual function void connect_phase (uvm_phase phase);
      
      compA.put_port.connect (comp_fifo.fifo.put_export);  

      compB.get_port.connect (comp_fifo.fifo.get_peek_export);  
      
      comp_fifo.fifo.put_ap.connect ( subs1.analysis_export );
      comp_fifo.fifo.get_ap.connect ( subs2.analysis_export );

   endfunction




Is this an issue in Library Code OR Class Reference Manual ?

(II) In uvm_tlm_fifo Class I see flush() Function Implemented as follows ::


  virtual function void flush();
    T t;
    bit r;

    r = 1; 
    while( r ) r = try_get( t ) ;
    
    if( m.num() > 0 && m_pending_blocked_gets != 0 ) begin
      uvm_report_error("flush failed" ,
		       "there are blocked gets preventing the flush", UVM_NONE);
    end
  
  endfunction

I believe the try_get() Calls recursively till all elements are removed from Mailbox ( inside tlm_fifo ) .

My doubt is regarding the uvm_error’s Condition .

When would it be true ? i.e

 if( m.num() > 0 && m_pending_blocked_gets != 0 )  

m_num() is an int same as the size argument passed to new() and m_pending_blocked_gets is Simply a Counter that Increments on calls to get() and on getting a transaction decrements its count back to 0

Thanks in advance ,

ABD

In reply to ABD_91:

The first issue is fixed in the IEEE 1800.2 LRM, however I think it is a bug in the library that flush() should indirectly call write(). I’ve filed a bug report.

The second issue is already filed as a bug(s).