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:

  1. Main Thread Execution: The main thread runs the initial block and finds a fork join_any block.
  2. Forking Threads: The main thread creates three threads to run in parallel.
  3. Thread Completion: It waits for any one of the threads to finish execution.
  4. Main Thread Resumes: The first thread finishes (Thread1), and the main thread resumes execution.
  5. 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

Featurefork joinfork join with disable fork
Threads ExecutionThreads continue after the main thread finishesThreads are killed as soon as the main thread finishes
Control over ThreadsNo control after fork joinAllows control over remaining threads with disable fork
Use CaseParallel execution without interruptionControl 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.

Scroll to Top