Jump to content
Sign in to follow this  
qinhailiang

what is the intend of uvm_wait_for_nba_region?

Recommended Posts

Hi, All

 

there is a task as follow in uvm_globals.sv file.

 

 

//----------------------------------------------------------------------------
//
// Task: uvm_wait_for_nba_region
//
// Callers of this task will not return until the NBA region, thus allowing
// other processes any number of delta cycles (#0) to settle out before
// continuing. See <uvm_sequencer_base::wait_for_sequences> for example usage.
//
//----------------------------------------------------------------------------

task uvm_wait_for_nba_region;

  string s;

  int nba;
  int next_nba;

  //If `included directly in a program block, can't use a non-blocking assign,
  //but it isn't needed since program blocks are in a seperate region.
`ifndef UVM_NO_WAIT_FOR_NBA
  next_nba++;
  nba <= next_nba;
  @(nba);
`else
  repeat(`UVM_POUND_ZERO_COUNT) #0;
`endif


endtask
 

For example, it is used in the task wait_for_sequences in uvm_sequencer_base.sv file

 

Who would like to explain the function of the uvm_wait_for_nba_region in details?

 

Best Regards

 

QIN

 

 

 

Share this post


Link to post
Share on other sites

This is really a workaround for the fact that earlier versions of SystemVerilog did not support non-blocking assignments to class variables. When you have many different processes simultaneously writing and reading the same variable, you need a way to prevent races between the indeterminate ordering between the reads and the writes. In the case of the UVM sequencer, you want all the sequences to have a chance to write their requests to the sequencer before arbitration kicks in to select a sequence. Without some kind of blocking mechanism, its possible that a single sequence can "hog" the sequencer, not giving the other sequences a change to put in their requests. In the past, this was done by adding #0 delays, a highly discouraged practice. A #0 simply means go to the end of the queue of things currently executing. A single #0 is sometime unavoidable, but once you start adding more #0's you are simply postponing race conditions for later in the queue. The UVM originally tried to solve this by adding a repeat (some_large_enough_number) #0; hoping that that number was larger than anyone else would have used. The NBA region solves this by creating a separate queue of updates to execute after all the activity at the current time has settled out. If the sequences had used NBAs to write their requests, this wait functionality would not be needed.

 

And the comment about if the UVM library was `included in a program block instead of a package is false in so many ways

  1. Scheduling semantics of program blocks has nothing to do with where the code is declared, only where the process is initiated when calling run_test().
  2. You certainly are allowed to have nonblocking assignments in a program block.
  3. You certainly do need this functionality because you can have the same races within a program block between reads and writes as you can within a module.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  

×