Jump to content

Register write() clobbers simultaneous access in multi-threaded testbench


Recommended Posts

Hi,

I am facing a threading issue when a single register instance is accessed multiple times simultaneously.  Given two separate threads scheduled at the same time and each calling the uvm_reg::write() task, I see the first one to execute the call does correctly take the semaphore on uvm_reg::write().XatomicX(1) task call, and the second thread correctly blocks when it attempts uvm_reg::write().XatomicX(1) task.  The first thread, in the uvm_reg::do_write() task safely immediately returns on its uvm-reg::do_write().XatomicX(1) task call and correctly executes the bus transaction.  The problem arises when the uvm_reg::do_write() task returns the semaphore in its XatomicX(0) call.  This:

1 - immediately wakes Thread2 which takes the semaphore and assigns its process to the local m_process variable, then continues into the uvm_reg::do_write() and correctly executes its bus transaction;

2 - once Thread2 blocks while its bus transaction takes place, Thread1 returns from uvm_reg::do_write() and hits its uvm_reg::write().XatomicX(0) task call. 

At this point in time, Thread2 correctly owns the semaphore and has its process reference stored in uvm_reg::m_process.  However, when Thread1 calls XatomicX(0) just before returning from uvm_reg::write(), there is no check on why the semaphore is owned.

From UVM-1.2 uvm_reg.svh:

task uvm_reg::XatomicX(bit on);
   process m_reg_process;
   m_reg_process=process::self();
   
   if (on) begin
      // we don't care about this branch right now
   end
   else begin
      // Maybe a key was put back in by a spurious call to reset()
      void'(m_atomic.try_get(1));
      m_atomic.put(1);
      m_process = null;
   end
endtask: XatomicX

Because Thread2 correctly owns the semaphore AND there no checking done on ownership when bit on == 0, Thread1 is able to incorrectly put back the semaphore and invalidate the m_process reference.  (The spurious reset comment does not apply).

Because of my testbench setup, my test has to immediate write this same register with another value.  So, Thread1 preforms a second write() call on the same register.

This causes warnings to be emitted from the field because the register is currently busy (in the bus transaction):

function void uvm_reg_field::set(...);
   ...
   if (m_parent.is_busy()) begin
      `uvm_warning("UVM/FLD/SET/BSY",
                   $sformatf("Setting the value of field \"%s\" while containing register \"%s\" is being accessed may result in loss of desired field value. A race condition between threads concurrently accessing the register model is the likely cause of the problem.",
                             get_name(), m_parent.get_full_name()))
   end
   ...
endfunction

and it clobbers the register value in the RAL model.  Because Thread2 is currently busy on bus transaction, when it returns it may perform the do_predict call while Thread1 is busy on its bus transaction for the same register.  I'm not sure what will happen here.

I am thinking that the XatomicX should have a check on the process when bit on == 0, similar to when the bit on == 1, to ensure the clearer of the semaphore is the same owner who claimed it.  However, I am not sure how this would affect other testbenches.  For example, is it possible to split the write() task into separate threads when the driver returns responses separately (i.e., the uvm_reg_adapater.provides_responses == 1).  Basically, is it possible to start a register transaction in one thread (taking the semaphore) and end it in another transaction?  

Also, I see that there is a similar, though different solution than I'm suggesting, already posted (with an approved but not fixed mantis bug):

I also see that in my release of UVM-IEEE, the uvm_reg class has the exact same XatomicX locking mechanism implemented.

The only current solution I see that handles this outside of UVM and enables multi-threading access of the same register is with, yet another, semaphore that makes the internal uvm_reg semaphore all but moot.  However, this is not desirable since I need to enforce a guideline on my team rather than have it built-in.

Am I missing something?  Better approaches?

 

Thanks for your feedback!

Jeremy Ridgeway

Link to comment
Share on other sites

  • 2 weeks later...

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...