In a testbench, semaphores are used to manage access to shared resources such as a bus that can have multiple requestors but only one driver at a time.
- A thread that calls
get()when no key is available blocks until one is returned. - Multiple waiting threads are queued in FIFO (first-in, first-out) order.
7.5.1 Semaphore Operations
A semaphore supports three main operations:
| Operation | Description |
|---|---|
new(n) |
Creates a semaphore with n keys |
get(n) |
Acquires n keys (blocks if not enough keys) |
put(n) |
Returns n keys back to the pool |
try_get(n) |
Tries to acquire n keys without blocking — returns 1 on success, 0 on failure |
🧩 Semaphores Controlling Access to a Hardware Resource
program automatic test;
semaphore sem; // Declare a semaphore
// Create semaphore and spawn threads
initial begin
sem = new(1); // Allocate semaphore with 1 key
fork
sequencer; // Thread 1
sequencer; // Thread 2
join
end
// Each sequencer repeatedly performs transactions
task sequencer;
repeat ($urandom % 10) // Random wait (0–9 cycles)
@bus.cb;
sendTrans; // Execute the transaction
endtask
// Task to perform transaction with controlled access
task sendTrans;
sem.get(1); // Acquire the key (enter critical section)
@bus.cb; // Drive signals onto the bus
bus.cb.addr <= t.addr;
...
sem.put(1); // Release the key when done
endtask
endprogram
🧮 Behavior Summary
- Only one thread can access the bus at a time.
- Other threads wait (block) until the semaphore key is released.
- This ensures safe, synchronized access to the shared hardware resource.
Semaphores with Multiple Keys
When using multiple keys, there are two important caveats:
-
⚠️ Over-releasing keys
You can accidentally put more keys back than you took out, leading to “extra” resources (e.g., two keys but only one car!). -
⚠️ Blocking due to FIFO ordering
Suppose:- 1 key remains.
- Thread A requests 2 keys → blocks.
- Thread B requests 1 key → also blocks (because A is ahead in the FIFO queue).
Even though there are enough keys for B, it must wait behind A.