Day 99: Inter-process communication: mailboxes and semaphores
Mailboxes and semaphores
A testbench is concurrent: generator, driver, and monitor run as parallel processes (fork...join). They coordinate with two primitives. A mailbox is a thread-safe FIFO for passing transactions between processes (generator → driver). A semaphore guards a shared resource — a process get()s a key before using it and put()s it back, so only N processes access it at once.
mailbox #(uart_txn) mb = new();
// generator process
task gen();
repeat (100) begin
uart_txn t = new();
assert(t.randomize());
mb.put(t); // blocking put
end
endtask
// driver process (runs in parallel)
task drv();
forever begin
uart_txn t;
mb.get(t); // blocks until a transaction is available
drive(t);
end
endtaskThe producer/consumer backbone
Mailbox-connected generator and driver is the producer/consumer pattern — the plumbing of every class-based testbench (and, later, UVM's sequencer→driver via a TLM port). Building it by hand now means UVM's version reads as 'oh, that's this, standardized'. Semaphores matter when, e.g., two sequences must not drive the same bus simultaneously.
Key terms
- Mailbox
- A thread-safe queue for passing transactions between concurrent testbench processes.
- Semaphore
- A counting lock (get/put keys) that limits concurrent access to a shared resource.
- fork...join
- SystemVerilog construct spawning parallel processes for concurrent testbench components.
- Producer/consumer
- The pattern where one process generates work and another consumes it, connected by a mailbox.
Before moving on, you should be able to
What is a mailbox used for in a SystemVerilog testbench?