In SystemVerilog, the wait fork
statement is an essential tool that helps the main process wait until all forked processes are completed. This feature is particularly useful when the main process needs to spawn multiple threads and perform tasks before waiting for those threads to finish.
In this article, we will explore how wait fork
works in SystemVerilog with examples, focusing on how it allows synchronization between the main process and forked sub-processes.
What is systemVerilog Wait Fork
?
The wait fork
statement is used to pause the main process until all the forked processes (threads) are finished. It is commonly used after the fork
statement to ensure that the main thread waits until the completion of all parallel tasks.
The typical scenario for using wait fork
is when you have multiple threads running in parallel, and the main thread needs to wait for all of them to complete before continuing.
Basic Example: Using systemVerilog Wait Fork
with 3 Threads
Let’s walk through a simple example where we spawn three threads in parallel, and the main thread waits for all of them to finish.
module tb_top;
initial begin
// Fork 3 sub-threads in parallel
// The main thread will finish when all sub-threads have completed
fork
// Thread 1: Finishes first at 40ns
#40 $display ("[%0t ns] Show #40 $display statement", $time);
// Thread 2: Finishes at 70ns
begin
#20 $display ("[%0t ns] Show #20 $display statement", $time);
#50 $display ("[%0t ns] Show #50 $display statement", $time);
end
// Thread 3: Finishes at 60ns
#60 $display ("[%0t ns] TIMEOUT", $time);
join_any
// Display when fork join is completed
$display ("[%0t ns] Fork join is done, wait fork to end", $time);
// Wait until all forked processes finish
wait fork;
$display ("[%0t ns] Fork join is over", $time);
end
endmodule
Simulation Log:
ncsim> run
[20 ns] Show #20 $display statement
[40 ns] Show #40 $display statement
[40 ns] Fork join is done, wait fork to end
[60 ns] TIMEOUT
[70 ns] Show #50 $display statement
[70 ns] Fork join is over
ncsim: *W,RNQUIE: Simulation is complete.
How wait fork
Synchronizes Multiple Threads
In the example above, we see that the fork
statement starts three threads in parallel. The join_any
ensures the main thread will continue as soon as any one of the threads finishes. After that, the wait fork
command ensures the main process will pause until all the threads finish.
Key Points:
- Forking Threads: You can start multiple threads using the
fork
statement. - Main Thread Continuation: With
join_any
, the main thread can continue after any thread finishes. - Waiting for Completion: The
wait fork
command ensures that the main thread waits until all the threads have completed.
Extended Example: Forking Two Additional Threads
To see how this works with more threads, let’s modify the example to fork two more threads and make the main process wait for the completion of all of them.
module tb_top;
initial begin
// Fork 3 sub-threads in parallel
// The main thread will finish when any of the sub-threads have completed
fork
// Thread 1: Finishes first at 40ns
#40 $display ("[%0t ns] Show #40 $display statement", $time);
// Thread 2: Finishes at 70ns
begin
#20 $display ("[%0t ns] Show #20 $display statement", $time);
#50 $display ("[%0t ns] Show #50 $display statement", $time);
end
// Thread 3: Finishes at 60ns
#60 $display ("[%0t ns] TIMEOUT", $time);
join_any
// Display when fork join is completed
$display ("[%0t ns] Fork join is done, wait fork to end", $time);
// Fork two additional processes
fork
#10 $display ("[%0t ns] Wait for 10", $time);
#20 $display ("[%0t ns] Wait for 20", $time);
join_any
// Wait until all forked processes finish
wait fork;
$display ("[%0t ns] Fork join is over", $time);
end
endmodule
Simulation Log:
ncsim> run
[20 ns] Show #20 $display statement
[40 ns] Show #40 $display statement
[40 ns] Fork join is done, wait fork to end
[50 ns] Wait for 10
[60 ns] TIMEOUT
[60 ns] Wait for 20
[70 ns] Show #50 $display statement
[70 ns] Fork join is over
ncsim: *W,RNQUIE: Simulation is complete.
Comparison of Forked Processes:
To understand the behavior better, here’s a table comparing the different threads and their finish times in both examples.
Thread | Finish Time (Example 1) | Finish Time (Example 2) |
---|---|---|
Thread 1 | 40ns | 40ns |
Thread 2 | 70ns | 70ns |
Thread 3 | 60ns | 60ns |
Thread 4 | N/A | 50ns |
Thread 5 | N/A | 60ns |
As you can see from the table, the main thread continues its execution once any thread finishes in Example 1, but in Example 2, it waits until all the threads, including the two new ones, are done.
Conclusion: Effective Use of systemVerilog Wait Fork
The wait fork
statement is a powerful tool in SystemVerilog for managing multiple threads. By using this command, you can ensure that the main process waits for all forked processes to complete before continuing its execution. This allows for better synchronization in testbenches where parallel execution is crucial.
When working with multiple threads, always remember to use wait fork
for proper synchronization, ensuring that the main process only continues after all forked threads have finished their tasks.