Uvm_wait_for_nba_region , #0 , wait(0) difference

Hi there,
I’m curious that are “uvm_wait_for_nba_region” and “#0” and “wait(0)” used in uvm source code trying to achieve same result?
All of them are used inside source code, for example , in following code from uvm_phase.svh


1368     // STARTED:                                                                 
1369     //---------                                                                 
1370     state_chg.m_prev_state = m_state;                                           
1371     m_state = UVM_PHASE_STARTED;                                                
1372     `uvm_do_callbacks(uvm_phase, uvm_phase_cb, phase_state_change(this, state_chg))
1373                                                                                 
1374     m_imp.traverse(top,this,UVM_PHASE_STARTED);                                 
1375     m_ready_to_end_count = 0 ; // reset the ready_to_end count when phase starts
1376     #0; // LET ANY WAITERS WAKE UP                                              
1377                                                                                 
1378                                                                                 
1379     //if (m_imp.get_phase_type() != UVM_PHASE_TASK) begin                       
1380     if (!$cast(task_phase,m_imp)) begin                                         
1381                                                                                 
1382       //-----------                                                             
1383       // EXECUTING: (function phases)                                           
1384       //-----------                                                             
1385       state_chg.m_prev_state = m_state;                                         
1386       m_state = UVM_PHASE_EXECUTING;                                            
1387       `uvm_do_callbacks(uvm_phase, uvm_phase_cb, phase_state_change(this, state_chg))
1388                                                                                 
1389       #0; // LET ANY WAITERS WAKE UP                                           
1390       m_imp.traverse(top,this,UVM_PHASE_EXECUTING);                             
1391                                                                                 
1392     end                                                                         
1393     else begin                                                                  
1394         m_executing_phases[this] = 1;                                           
1395                                                                                 
1396         state_chg.m_prev_state = m_state;                                       
1397         m_state = UVM_PHASE_EXECUTING;                                          
1398         `uvm_do_callbacks(uvm_phase, uvm_phase_cb, phase_state_change(this, state_chg))
1399                                                                                 
1400         fork : master_phase_process                                             
1401           begin                                                                 
1402                                                                                 
1403             m_phase_proc = process::self();                                     
1404                                                                                 
1405             //-----------                                                       
1406             // EXECUTING: (task phases)                                         
1407             //-----------                                                       
1408             task_phase.traverse(top,this,UVM_PHASE_EXECUTING);                  
1409                                                                                 
1410             wait(0); // stay alive for later kill                               
1411                                                                                 
1412           end                                                                   
1413         join_none                                                               
1414                                                                                 
1415         uvm_wait_for_nba_region(); //Give sequences, etc. a chance to object    
1416                                                                                 
1417         // Now wait for one of three criterion for end-of-phase.                
1418         fork                                                                    
1419           begin // guard                                                        
1420                                                                                 
1421            fork                                                                 
1422              // JUMP                                                            
1423              begin                                                              
1424                 wait (m_premature_end);                                         
1425                 `UVM_PH_TRACE("PH/TRC/EXE/JUMP","PHASE EXIT ON JUMP REQUEST",this,UVM_DEBUG)
1426              end                                                                
1427                                                                                 


Another question, for above code, are “#0” and “uvm_wait_for_nba_region” and “wait(0)” interchangeable?
(I don’t know how to highlight in original above context, so I listed below.


1389       #0; // LET ANY WAITERS WAKE UP 
1410             wait(0); // stay alive for later kill  
1415         uvm_wait_for_nba_region(); //Give sequences, etc. a chance to object  

Thanks in advance,
Jeff

In reply to Jeff_Li_90:

The wait(0) is a permanent suspension of a process. They could have used m_phase_proc.suspend() to achieve the same behavior. Why they needed to do this is not documented.

This is very different from what the other 2 constructs are trying to achieve. #0 in procedural code is a poor attempt at addressing race conditions between processes. Unfortunately #0 delays can accumulate and the race re-appears. The uvm_wait_for_nba_region routine is a more deterministic way of eliminating races. But since it was a latter addition to the UVM, no-one has gone back and retrofitted to remove all the #0’s

In reply to dave_59:

In reply to Jeff_Li_90:
The wait(0) is a permanent suspension of a process. They could have used m_phase_proc.suspend() to achieve the same behavior. Why they needed to do this is not documented.
This is very different from what the other 2 constructs are trying to achieve. #0 in procedural code is a poor attempt at addressing race conditions between processes. Unfortunately #0 delays can accumulate and the race re-appears. The uvm_wait_for_nba_region routine is a more deterministic way of eliminating races. But since it was a latter addition to the UVM, no-one has gone back and retrofitted to remove all the #0’s

Hi Dave,

per SV LRM 4.4.2.3 Inactive events region :
If events are being executed in the active region set, an explicit #0 delay control requires the process to be
suspended and an event to be scheduled into the Inactive region of the current time slot so that the process
can be resumed in the next Inactive to Active iteration.

So technically speaking, #0 won’t put me inside NBA region, but rather Inactive region, this is not exactly same as uvm_wait_foir_nba_region in that upon return of uvm_wait_foir_nba_region I’m inside NBA region.

Am i correct?

Thanks,
Jeff