In the previous article, we explored different methods for launching parallel threads in SystemVerilog. Now, let’s focus on how to disable threads that were created using a fork join block.
SystemVerilog provides a simple way to kill all active threads that were launched using the fork join
construct. This can be done by calling disable fork
. This allows for better control when working with multiple threads.
Key Points: How the SystemVerilog Disable Fork Join Works
Here’s what happens when the simulation starts with the given example:
- Main Thread Execution: The main thread runs the initial block and finds a
fork join_any
block. - Forking Threads: The main thread creates three threads to run in parallel.
- Thread Completion: It waits for any one of the threads to finish execution.
- Main Thread Resumes: The first thread finishes (Thread1), and the main thread resumes execution.
- Other Threads: Thread2 and Thread3 are still running even though the main thread has exited the
fork join_any
block.
SystemVerilog Example Without Disable Fork
Let’s first see the standard code for launching multiple threads in parallel.
module tb_top;
initial begin
// Fork off 3 sub-threads in parallel and the currently executing main thread
// will finish when any of the 3 sub-threads have finished.
fork
// Thread1 : Will finish first at time 40ns
#40 $display ("[%0t ns] Show #40 $display statement", $time);
// Thread2 : Will finish at time 70ns
begin
#20 $display ("[%0t ns] Show #20 $display statement", $time);
#50 $display ("[%0t ns] Show #50 $display statement", $time);
end
// Thread3 : Will finish at time 60ns
#60 $display ("[%0t ns] TIMEOUT", $time);
join_any
// Display as soon as the fork is done
$display ("[%0t ns] Fork join is done", $time);
end
endmodule
Simulation Log Without Disable Fork
When running the above code, the simulation output will look like this:
[20 ns] Show #20 $display statement
[40 ns] Show #40 $display statement
[40ns] Fork join is done
[60 ns] TIMEOUT
[70 ns] Show #50 $display statement
ncsim: *W,RNQUIE: Simulation is complete.
ncsim> exit
As seen in the log, Thread2 and Thread3 continue running even after the main thread finishes executing. Now, let’s see how to control this by using disable fork
.
SystemVerilog Example With Disable Fork
In this updated version, we use disable fork
to terminate all the threads after the main thread finishes.
module tb_top;
initial begin
// Fork off 3 sub-threads in parallel and the currently executing main thread
// will finish when any of the 3 sub-threads have finished.
fork
// Thread1 : Will finish first at time 40ns
#40 $display ("[%0t ns] Show #40 $display statement", $time);
// Thread2 : Will finish at time 70ns
begin
#20 $display ("[%0t ns] Show #20 $display statement", $time);
#50 $display ("[%0t ns] Show #50 $display statement", $time);
end
// Thread3 : Will finish at time 60ns
#60 $display ("[%0t ns] TIMEOUT", $time);
join_any
// Display as soon as the fork is done
$display ("[%0t ns] Fork join is done, let's disable fork", $time);
// Disable the fork, killing all remaining threads
disable fork;
end
endmodule
Simulation Log With Disable Fork
When you run the simulation with disable fork
, you will see the following output:
[20 ns] Show #20 $display statement
[40 ns] Show #40 $display statement
[40ns] Fork join is done, let's disable fork
ncsim: *W,RNQUIE: Simulation is complete.
ncsim> exit
In this case, as soon as the main thread completes, the disable fork
command is issued. This causes Thread2 and Thread3 to be terminated, which prevents them from executing further.
Comparison Table: Fork Join vs Fork Join with Disable Fork
Feature | fork join | fork join with disable fork |
---|---|---|
Threads Execution | Threads continue after the main thread finishes | Threads are killed as soon as the main thread finishes |
Control over Threads | No control after fork join | Allows control over remaining threads with disable fork |
Use Case | Parallel execution without interruption | Control and terminate threads after execution |
Why Use Disable Fork?
Using disable fork
is especially useful when you want to terminate any running threads immediately after a certain point in the simulation. This is helpful in scenarios where you need to clean up resources or prevent threads from consuming unnecessary simulation time. By adding disable fork
, you can maintain tighter control over the flow of your simulation.
Conclusion
In summary, SystemVerilog’s disable fork
provides a powerful way to control threads in a simulation. By calling disable fork
, you can terminate threads that are no longer needed, providing better resource management. This is particularly useful in scenarios where you want to ensure that all threads are properly managed, preventing unnecessary computation after the main task is completed.