Question regarding Phasing N TLM Port with max_size 2

Hi ,

While trying to learn via trying out different stuff related to phases and TLM , I ended up coding the following .



class componentA extends uvm_component;
   `uvm_component_utils (componentA)
 
 
  uvm_blocking_put_port #(int) m_put_port;
  uvm_tlm_fifo #(int) m_fifo_export;
  uvm_blocking_put_imp #(int,componentA) m_put_imp;
 
   function new (string name = "componentA", uvm_component parent= null);
      super.new (name, parent);
   endfunction

   
   virtual function void build_phase (uvm_phase phase);
       // super.build_phase (phase) ; // Learnt recently here !! 
      m_put_port    = new("m_put_port", this,1,2); // By default max_size is 1 so we would get an Error since we want it to connect to export as well as imp !!
      m_fifo_export = new("m_fifo_export", this ,0); // 0 indicates Unbounded , so can store infinite elements 
      m_put_imp     = new("m_put_imp", this);
   
   endfunction

   virtual function void connect_phase (uvm_phase phase);
      m_put_port.connect(m_fifo_export.put_export);  
      m_put_port.connect(m_put_imp);  
   
   endfunction
   
   virtual task run_phase (uvm_phase phase);

	   phase.raise_objection(this `ifdef M2 ,,2 `endif );
	   for ( int i = 1 ; i < 6 ; i++ ) 
	       begin 
                 m_put_port.put(i);        
	       end     
          `uvm_info ("COMPA", " All put Done ", UVM_LOW)
	   phase.drop_objection(this`ifdef M2 ,,1 `endif);

   endtask

   virtual task main_phase (uvm_phase phase);    
	   int ii ;
	   phase.raise_objection(this);
           
            while ( m_fifo_export.is_empty() != 1 ) // is_empty() returns 1 when empty , so we fetch till Not Empty 
	      begin
	         m_fifo_export.get(ii);
                `uvm_info ("GET_PEEK_EXPORT", $sformatf(" Got %0d ",ii), UVM_LOW) 
			   # 2 ; 
             end
	   
	   phase.drop_objection(this `ifdef M2 ,,2 `endif );

   endtask

   task put ( int INT ) ;

  
    `uvm_info ("PUT_IMP", $sformatf(" Got %0d ",INT), UVM_LOW)

   endtask

endclass 

// Inside module

componentA compA ;

initial begin

compA = new("compA",null);

run_test();

end



I get following Output [ Without +define+M2 ] ::
**
UVM_INFO @ 0: reporter [RNTST] Running test …
UVM_INFO EX.sv(56) @ 0: compA [COMPA] All put Done
UVM_INFO /asiclibs/libraries/uvm/uvm-1.1d/src/base/uvm_objection.svh(1267) @ 0: reporter [TEST_DONE] ‘run’ phase is ready to proceed to the ‘extract’ phase
UVM_INFO EX.sv(71) @ 0: compA [GET_PEEK_EXPORT] Got 1
UVM_INFO EX.sv(71) @ 2: compA [GET_PEEK_EXPORT] Got 2
UVM_INFO EX.sv(71) @ 4: compA [GET_PEEK_EXPORT] Got 3
UVM_INFO EX.sv(71) @ 6: compA [GET_PEEK_EXPORT] Got 4
UVM_INFO EX.sv(71) @ 8: compA [GET_PEEK_EXPORT] Got 5
**

[Q1] I am confused how I get msg from reporter before all the get() calls ? .
Is it cos the run_phase() objection Count is 0 ? in that case then how do I still manage to get displays from get() call ?

[Q2] I know that run_phase() executes in parallel to main_phase() , so in this code will both objections be raised at Time 0 ?

With +define+M2 , I get an Error ::

UVM_FATAL @ 10: main_objection [OBJTN_ZERO] Object “compA” attempted to drop objection ‘main_objection’ count below zero

[Q3] Would it make a difference if put() is done in main_phase while get() is done in run_phase ?

[Q4] Why the error ? Won’t the raise and drop objections in run_phase and main_phase be additive ? I raised 2 objections in run_phase while dropping only 1 . Since I raise 1 again in main_phase ( total 2 ) , I drop 2 objections in main_phase

[Q5] I notice that I don’t get the previous message in this case ( reporter [TEST_DONE] ‘run’ phase is ready to proceed to the ‘extract’ phase ) , why so ?

[Q6] Why no output from task put() ? Does it have to do with set_if() && get_if() of uvm_port_base class ?

In reply to MICRO_91:

  1. Your problems stem from the fact that there are no delays in the run_phase between the raise and drop. The run_phase is over at time 0 and ready to proceed, but the extract_phase won’t begin until the main phase ends.
  2. There’s a requirement that there must be some blocking delay between the raise and drop. Otherwise you get this kind of error message.
  3. We recommend just using the run_phase which avoids many issues including the ones you see here.
  4. Same as Q2
  5. Same as Q2
  6. Sorry, uncharted territory.

In reply to dave_59:

Hi Dave ,

I went through LRM 1800.2 and different websites for (6) .

Since “m_fifo_export” occurs before “m_put_imp” lexicographically [ LRM 7.8.2 ] , put() always call the port connected at Index 0 which is fifo in the above case .

If I want to call “m_put_imp” after “m_fifo_export” with existing code , I need to call set_if(Index) . [ Where valid Index is from 0 to 1 , 0 points to handle “m_fifo_export” while index 1 is “m_put_imp” ]