What is Semaphore in sv?

A semaphore allows you to control access to a resource.

Conceptually, a semaphore is a bucket. When a semaphore is allocated, a bucket that contains a fixed number of keys is created. Processes using semaphores must first procure a key from the bucket before they can continue to execute.

 If a specific process requires a key, only a fixed number of occurrences of that process can be in progress simultaneously. All others must wait until a sufficient number of keys are returned to the bucket.

Semaphores are typically used for mutual exclusion, access control to shared resources, and basic synchronization.

Imagine that you and your spouse share a car. Obviously, only one person can drive it at a time. You can manage this situation by agreeing that whoever has the key can drive it. 

When you are done with the car, you give up the car so that the other person can use it. The key is the semaphore that makes sure only one person has access to the car.

In operating system terminology, this is known as “mutually exclusive access,” so a semaphore is known as a “mutex” and is used to control access to a resource.

Semaphores can be used in a testbench when you have a resource, such as a bus, that may have multiple requestors from inside the testbench but, as part of the physical design, can only have one driver.

In SystemVerilog, a thread that requests a key when it is not available always blocks the execution of that particular thread. Multiple blocking threads are queued in FIFO order.

Semaphore is a built-in class that provides the following methods:

— Create a semaphore with a specified number of keys: new()

— Obtain one or more keys from the bucket: get()

— Return one or more keys into the bucket: put()

— Try to obtain one or more keys without blocking: try_get()

The default value for keyCount is 0.

If the specified number of keys is not available, the get() method blocks process until the keys become available.

If the specified number of keys is not available, the try_get() method returns 0.

Types of Semaphores

  1. Binary Semaphore:
    • Also known as a mutex (mutual exclusion).
    • Can take values 0 or 1.
    • Used to ensure that only one thread can access a resource at any given time.
  2. Counting Semaphore:
    • Can take any non-negative integer value.
    • Used to control access to a pool of resources (e.g., a limited number of identical resources).

Uses of Semaphores

  1. Mutual Exclusion: Semaphores can be used to protect critical sections of code, ensuring that only one thread can execute that section at a time. This is essential for maintaining data consistency when multiple threads access shared data.
  2. Resource Management: Counting semaphores are useful for managing a finite number of resources, such as connections to a database or slots in a thread pool. They help keep track of available resources and allow processes to wait when resources are unavailable.
  3. Event Counting: Semaphores can be used to signal the occurrence of events. For instance, one thread can signal a semaphore when a specific condition is met, allowing other waiting threads to continue execution.
  4. Producer-Consumer Problems: In scenarios where one process produces data and another consumes it, semaphores help manage the synchronization between the producer and consumer, preventing race conditions and ensuring that the consumer waits when there is no data available.
  5. Deadlock Prevention: Although semaphores can introduce complexity, they can also be part of strategies to prevent deadlocks when used thoughtfully with appropriate resource allocation protocols.

Example Use Case

Consider a simple example of a producer-consumer scenario:

  • Producer: Adds items to a shared buffer.
  • Consumer: Removes items from the buffer.

Using semaphores, we can ensure that the consumer waits if the buffer is empty and the producer waits if the buffer is full.

module top();
semaphore sema = new(1); // Create semaphore with 1 key.

initial begin
repeat(3) begin
fork
////////// PROCESS 1 ////////////////
begin
$display(“1: Waiting for key, time=%0t”, $time);
sema.get(1);
$display(“1: Got the Key, time=%0t”, $time);
#(10);// Do some work
sema.put(1);
$display(“1: Returning back key, time=%0t”, $time);
#(10);
end
////////// PROCESS 2 ////////////////
begin
#1;
$display(“2: Waiting for Key, time=%0t”, $time);
sema.get(1);
$display(“2: Got the Key, time=%0t”, $time);
#(10);//Do some work
sema.put(1);
$display(“2: Returning back key, time=%0t”, $time);
#(10);
end
join
$display();
end
#1000;
end
endmodule : top

//Output:
// 1: Waiting for key, time=0
// 1: Got the Key, time=0
// 2: Waiting for Key, time=1
// 1: Returning back key, time=10
// 2: Got the Key, time=10
// 2: Returning back key, time=20
//
// 1: Waiting for key, time=30
// 1: Got the Key, time=30
// 2: Waiting for Key, time=31
// 1: Returning back key, time=40
// 2: Got the Key, time=40
// 2: Returning back key, time=50
//
// 1: Waiting for key, time=60
// 1: Got the Key, time=60
// 2: Waiting for Key, time=61
// 1: Returning back key, time=70
// 2: Got the Key, time=70
// 2: Returning back key, time=80

Semaphores with Multiple Keys:

You can put more keys back than you took out. Suddenly you may have two keys but only one car!

Be careful if your testbench needs to get and put multiple keys. Perhaps you have one key left, and a thread requests two, causing it to block. Now a second thread requests a single semaphore – what should happen? In SystemVerilog the second request, get(1) , sneaks ahead of the earlier get(2) , bypassing the FIFO ordering.

 

1 thought on “What is Semaphore in sv?”

  1. you’rе actսally a just right ԝebmaster.
    The wеb site loаding pace is incredible. It kind of feels that you’re doing any
    unique trіck. Also, The contents are masterpiece.

    you have peгformed a wonderfսl activity in tһis topic!

Leave a Comment

Your email address will not be published. Required fields are marked *

error: Content is protected !!
Scroll to Top