4

I have a doubt regarding UVM. Let's think I have a DUT with two interfaces, each one with its agent, generating transactions with the same clock. These transactions are handled with analysis imports (and write functions) on the scoreboard. My problem is that both these transactions read/modify shared variables of the scoreboard.

My questions are:

1) Have I to guarantee mutual exclusion explicitly though a semaphore? (i suppose yes)

2) Is this, in general, a correct way to proceed?

3) and the main problem, can in some way the order of execution be fixed?

Depending on that order the values of shared variables can change, generating inconsistency. Moreover, that order is fixed by specifications.

Thanks in advance.

e19293001
  • 2,783
  • 9
  • 42
  • 54
arandomuser
  • 521
  • 1
  • 7
  • 22

4 Answers4

2

While SystemVerilog tasks and functions do run concurrently, they do not run in parallel. It is important to understand the difference between parallelism and concurrency and it has been explained well here.

So while a SystemVerilog task or function could be executing concurrently with another task or function, in reality it does not actually run at the same time (run time context). The SystemVerilog scheduler keeps a list of all the tasks and functions that need to run on the same simulation time and at that time it executes them one-by-one (sequentially) on the same processor (concurrency) and not together on multiple processors (parallelism). As a result mutual exclusion is implicit and you do not need to use semaphores on that account.

The sequence in which two such concurrent functions would be executed is not deterministic but it is repeatable. So when you execute a testbench multiple times on the same simulator, the sequence of execution would be same. But two different simulators (or different versions of the same simulator) could execute these functions in a different order.

If the specifications require a certain order of execution, you need to ensure that order by making one of these tasks/functions wait on the other. In your scoreboard example, since you are using analysis port, you will have two "write" functions (perhaps using uvm_analysis_imp_decl macro) executing concurrently. To ensure an order, (since functions can not wait) you can fork out join_none threads and make one of the threads wait on the other by introducing an event that gets triggered at the conclusion of the first thread and the other thread waits for this event at the start.

Community
  • 1
  • 1
Puneet Goel
  • 858
  • 5
  • 8
0

This is a pretty difficult problem to address. If you get 2 transactions in the same time step, you have to be able to process them regardless of the order in which they get sent to your scoreboard. You can't know for sure which monitor will get triggered first. The only thing you can do is collect the transactions and at the end of the time step do your modeling/checking/etc.

Semaphores only help you if you have concurrent threads that take (simulation) time that are trying to access a shared resource. If you get things from an analysis port, then you get them in 0 time, so semaphores won't help you here.

Tudor Timi
  • 7,453
  • 1
  • 24
  • 53
0

So to my understanding, the answer is: compiler/vendor/uvm cannot ensure the order of execution. If you need to ensure the order which actually happen in same time step, you need to use semaphore correctly to make it work the way you want. Another thing is, only you yourself know which one must execute after the other if they are in same simulation time.

awill
  • 135
  • 1
  • 4
  • 15
0

this is a classical race condition where the result depends upon the actual thread order...

  • first of all you have to decide if the write race is problematic for you and/or if there is a priority order in this case. if you dont care the last access would win.

  • if the access isnt atomic you might need a semaphore to ensure only one access is handled at a time and the next waits till the first has finished.

  • you can also try to control order by changing the structure or introducing thread ordering (wait_order) or if possible you remove timing at all (here instead of directly operating with the data you get you simply store the data for some time and then later you operate on it.

uwes
  • 11
  • 3