Jump to content

jeremyr

Members
  • Posts

    1
  • Joined

  • Last visited

jeremyr's Achievements

Member

Member (1/2)

0

Reputation

  1. 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
×
×
  • Create New...