Here, we will take few more examples to understand Semaphore thoroughly.
Example 1:
Assume that we have 3 processes, second process starts only after completing the first and 3rd starts only after completing the 2nd process. Let’s see how we can implement the situation using semaphore.
module test;
// Declare a semaphore
semaphore sem;
// Task for the first process
task process_1();
$display("[%0t] Process 1 started.", $time);
#10; // Simulate process execution time
$display("[%0t] Process 1 completed.", $time);
sem.put(1); // Release one semaphore token for the next process
endtask
// Task for the second process
task process_2();
sem.get(1); // Acquire a semaphore token (wait for Process 1 to complete)
$display("[%0t] Process 2 started.", $time);
#15; // Simulate process execution time
$display("[%0t] Process 2 completed.", $time);
sem.put(1); // Release one semaphore token for the next process
endtask
// Task for the third process
task process_3();
sem.get(1); // Acquire a semaphore token (wait for Process 2 to complete)
$display("[%0t] Process 3 started.", $time);
#20; // Simulate process execution time
$display("[%0t] Process 3 completed.", $time);
endtask
// Initial block to initialize semaphore and start the tasks
initial begin
sem = new(0); // Initialize semaphore with 0 tokens
fork
process_1();
process_2();
process_3();
join
$display("[%0t] All processes completed.", $time);
$finish;
end
endmodule
Explanation
- Semaphore:
- A semaphore is initialized with
0tokens. This ensures that the second and third processes cannot proceed until the first process provides a token, and similarly, the third process waits for the second.
- A semaphore is initialized with
- Tasks:
process_1():- Starts execution.
- Once completed, it calls
sem.put(1)to release one token, signaling that the second process can proceed.
process_2():- Calls
sem.get(1)to wait until it gets a token (fromprocess_1()). - Once completed, it releases a token for the third process using
sem.put(1).
- Calls
process_3():- Waits for a token from
process_2()and then executes.
- Waits for a token from
- Fork-Join:
forkallows all tasks to start concurrently, but the semaphore ensures proper synchronization.
- Simulation Output:
[0] Process 1 started.
[10] Process 1 completed.
[10] Process 2 started.
[25] Process 2 completed.
[25] Process 3 started.
[45] Process 3 completed.
[45] All processes completed.