Semaphore is a SystemVerilog built-in class, used for access control to shared resources, and for basic synchronization.
Think of a semaphore as a bucket of keys. Processes using semaphores need to grab a key from the bucket before proceeding with their execution. Meanwhile, other processes have to wait until enough keys are put back into the bucket.
Imagine a situation where two processes attempting to use the same chunk of shared memory—one writing, the other reading. This can cause unexpected outcomes. To avoid this, a semaphore can be employed.
Syntax:
semaphore semaphore_name;
Semaphore is a built-in class that provides the following methods,
• new(): Create a semaphore with a specified number of keys
• get(): Obtain one or more keys from the bucket
• put(): Return one or more keys into the bucket
• try_get(): Try to obtain one or more keys without blocking
The new() method is used to create the Semaphore.
semaphore_name = new(numbers_of_keys);
where
• number_of_keys is integer variable, the number of keys in the bucket.
• The default number of keys is ‘0’
• The new() method will return the semaphore handle or null if the semaphore cannot be created
1.2 get()
The semaphore get() method is used to get key/keys from a semaphore.
semaphore_name.get(number_of_keys); or semaphore_name.get();
When the semaphore_name.get() method is called,
• If the specified number of keys are available, then the method returns and execution continues
• If the specified number of keys are not available, then the process blocks until the keys become available
• The default number of keys requested is 1
1.3 put()
The semaphore put() method is used to return key/keys to a semaphore.
semaphore_name.put(number_of_keys); or semaphore_name.put();
When the semaphore_name.put() method is called,
• The specified number of keys are returned to the semaphore.
• The default number of keys returned is 1.
1.4 try_get()
The semaphore try_get() method is used to procure a specified number of keys from a semaphore, but without blocking.
semaphore_name.try_get(number_of_keys); or semaphore_name.try_get();
When the semaphore_name.try_get() method is called,
• If the specified number of keys are available, the method returns 1 and execution continues
• If the specified number of keys are not available, the method returns 0 and execution continues
• The default number of keys requested is 1
Example1: Two processes accessing the same resource
In the example below, semaphore sema is created with the 1 key, two processes are accessing the display method at the same time, but only one process will get the semaphore key and the other process will wait till it gets the key.
module semaphore_ex;
semaphore sema; //declaring semaphore sema
initial begin
sema=new(1); //creating sema with '1' key
fork
display(); //process-1
display(); //process-2
join
end
//display method
task automatic display();
sema.get(); //getting '1' key from sema
$display($time,"\tCurrent Simulation Time");
#30;
sema.put(); //putting '1' key to sema
endtask
endmodule
Output
0 Current Simulation Time
30 Current Simulation Time
Example 2: Semaphore with 4 keys
In the example below, creating semaphore with ‘4’ keys.
module semaphore_ex;
semaphore sema; //declaring semaphore sema
initial begin
sema=new(4); //creating sema with '4' keys
fork
display(); //process-1
display(); //process-2
join
end
//display method
task automatic display();
sema.get(4); //getting '4' keys from sema
$display($time,"\tCurent Simulation Time");
#30;
sema.put(4); //putting '4' keys to sema
endtask
endmodule
Output
0 Current Simulation Time
30 Current Simulation Time
Example 3: Putting back more keys
In the example below, creating semaphore with ‘1’ key, putting more number of keys back to the semaphore.
module semaphore_ex;
semaphore sema; //declaring semaphore sema
initial begin
sema=new(1); //creating sema with '1' keys
fork
display(1); //process-1
display(2); //process-2
display(3); //process-3
join
end
//display method
task automatic display(int key);
sema.get(key); //getting 'key' number of keys from sema
$display($time,"\tCurrent Simulation Time, Got %0d keys",key);
#30;
sema.put(key+1); //putting 'key' number of keys to sema
endtask
endmodule
Output:
0 Current Simulation Time, Got 1 keys
30 Current Simulation Time, Got 2 keys
60 Current Simulation Time, Got 3 keys
Example 4: using try_get
In the example below, creating semaphore with ‘4’ key, try_get() will check for the keys if the keys are not available simulation will proceed(non-blocking).
module semaphore_ex;
semaphore sema; //declaring semaphore sema
initial begin
sema=new(4); //creating sema with '4' keys
fork
display(4); //process-1
display(4); //process-2
join
end
//display method
task automatic display(int key);
sema.try_get(key); //getting 'key' number of keys from sema
$display($time,"\tCurrent Simulation Time, Got %0d keys",key);
#30;
sema.put(key); //putting 'key' number of keys to sema
endtask
endmodule
Output:
0 Current Simulation Time, Got 4 keys
0 Current Simulation Time, Got 4 keys