03 · SoC synchronization
Broadcast Control Plane & Global TB Messaging
Coordinate chip-wide commands and testbench reactions without point-to-point hierarchy wiring, while preserving payload, acknowledgement, and same-cycle intent.
A typed control-plane message fans out without hierarchy wiring, and the coordinator tracks recipient epochs so stale or duplicate acknowledgements cannot release the test.
release when unique acknowledged recipients = required mask for the current message epoch
Why it matters
- A 64-core SoC may need every core to enter low-power mode or invalidate its cache together.
- The verification goal is not only delivery. The command must reach every destination and take effect in the required cycle relationship.
- A scalable testbench needs a global notification mechanism so deeply nested agents can synchronize without a web of upward and downward pointers.
What is difficult
- UVM hierarchy makes direct Agent A to Agent B communication awkward without routing through the environment.
- A broadcast may need to notify 100 agents without scattering uvm_config_db paths or explicit component handles.
- Timing-only events are simple, but data-heavy commands also carry frequency, power state, or other configuration payload.
- The test must know when every subscriber has completed its reaction before proceeding.
Failure signatures
- One or more agents miss the global event and retain stale state.
- Agents react in different cycles even though the architectural command requires simultaneous effect.
- A timing event arrives but its associated configuration payload is stale.
- The test proceeds before all listeners flush or enter their synchronized state.
- An overly broad global event name collides with unrelated hierarchy behavior.
- Point-to-point handles make the environment fragile when agents are added or relocated.
Two viable approaches—and their cost
Global UVM event pool
Every agent subscribes to a named event obtained from uvm_event_pool.
- Strong hierarchy decoupling.
- New listeners can subscribe without changing the broadcaster.
- Delivery acknowledgement is not automatic.
- Payload and event-name ownership need a deliberate convention.
Shared global configuration object
Every agent holds a handle to one state object that carries the current global command data.
- Carries complex values such as a new frequency or power state.
- All listeners observe the same object without copying configuration fields.
- A field mutation alone does not provide an ordered notification or completion acknowledgement.
- Readers need synchronization so they do not observe a partially updated state.
Interview answer, built from the mechanism
- I avoid point-to-point connections for an SoC-wide control plane. A named event from uvm_event_pool acts as the testbench messaging bus.
- When the virtual sequence sends a global command, such as cache invalidate, it triggers the event. Each subscriber enters its sync state or flushes its scoreboard regardless of hierarchy depth.
- For data-heavy broadcasts, I put the payload in a shared typed configuration object and use the event as the publication boundary.
- A uvm_barrier or explicit acknowledgement tracker prevents the test from continuing until the required listener count has completed its reaction.
Component responsibility contract
| Component | Responsibility | Required change |
|---|---|---|
| Environment | Central dispatch | Create the uvm_event or publish the shared configuration object. |
| Agent | Listener | In run_phase, use wait_trigger() or a synchronized loop on a configuration state. |
| Virtual Sequence | Trigger | Trigger the notification when the broadcast packet is sent to the DUT. |
Implementation patterns
// --- Inside the Virtual Sequence (The Broadcaster) ---
task body();
uvm_event e = uvm_event_pool::get_global("PORESET_EVT");
send_broadcast_packet();
e.trigger(); // Notify everyone the reset has started
endtask
// --- Inside every Agent/Monitor (The Subscriber) ---
task run_phase(uvm_phase phase);
uvm_event e = uvm_event_pool::get_global("PORESET_EVT");
forever begin
e.wait_trigger();
`uvm_info(
"AGT",
"Global Reset Observed! Flushing...",
UVM_LOW
)
this.flush();
end
endtaskThe broadcaster and every subscriber resolve the same global event name. The event follows the DUT broadcast packet, and each listener flushes local state.
Stress recipe
- Instantiate the representative 64-core topology or 100 listener agents.
- Send a global cache-invalidate or low-power packet to the DUT.
- Trigger the matching testbench event only at the defined packet milestone.
- Record the cycle at which every listener enters Sync State or flushes its scoreboard.
- Require every listener to acknowledge through a barrier before normal stimulus resumes.
- Repeat with a data-heavy frequency or power-state update and prove listeners observe one coherent payload version.
- Start one subscriber late in a negative test to expose event-persistence and missed-trigger assumptions.
Follow-up questions
How do you ensure all agents finished their reaction before the test continues?
Use a uvm_barrier with the required listener threshold. Every participating agent waits or acknowledges at the barrier, and the test proceeds only after the threshold is satisfied.
What is the difference between a local and global event pool?
A global pool is accessible throughout the testbench. A local pool is owned by a particular hierarchy or object context. Use global naming sparingly for true SoC-level reset and power events.
How do you handle data in a broadcast?
Use a shared, typed Global Config Object for data-heavy state and an event for the timing or publication boundary.
