Events & Barriers

Orchestrating parallel processes: uvm_event for triggers and uvm_barrier for rendezvous.

Class-Based Synchronization

While SystemVerilog native event types are useful for simple thread triggers, they are transient and difficult to share across OVM/UVM hierarchies. uvm_event is a class-based wrapper that transforms a simple trigger into a powerful communication object.

Why use uvm_event?

  • Persistence: The event is an object. Its state (triggered or not) can be checked at any time.
  • Payload Sharing: You can attach any uvm_object as data to the trigger.
  • Callback Hooks: You can trigger logic automatically when an event occurs.

The Event Pool Pattern

In a complex SoC testbench, a Monitor on one side of the chip might need to trigger a Sequence on the other side. Connecting them via ports is messy. uvm_event_pool provides a Global Singleton hub where components can share events by string name.

Loosely Coupled Sync

// In Monitor: Broadcast a custom event
uvm_event e = uvm_event_pool::get_global("interrupt_occurred");
e.trigger(data_obj); // Trigger with data
// In Sequence: Wait for that specific event
uvm_event e = uvm_event_pool::get_global("interrupt_occurred");
e.wait_trigger();
// Optional: Retrieve the data
$cast(my_data, e.get_trigger_data());
                            

uvm_barrier: The Rendezvous

A Barrier is used when you have multiple parallel processes that must all reach a specific point before any of them are allowed to continue. This is critical for synchronizing many-core stimulus.

How it Works:

You set a threshold (number of processes). Every process that calls wait_for() will block until the total number of waiting processes equals the threshold. At that exact moment, UVM releases all of them simultaneously.

Test: Coordinating 4 CPUs

uvm_barrier b;
// 1. Setup in Env/Test
b = new("soc_barrier");
b.set_threshold(4); // Wait for 4 CPUs
// 2. Inside each CPU Sequence
task body();
    init_cpu_registers();
    `uvm_info("CPU", "Init done, waiting at barrier...", UVM_LOW)
    b.wait_for(); 
    // Everyone starts traffic at the same simulation time
    start_main_traffic();
endtask