11.Processes - vineethkumarv/SystemVerilog_Course GitHub Wiki

Processes

A Processes or Thread is any piece of code that gets executed as a separate entity. A fork-join block creates the different threads that run in parallel.

In the below Fig-1 we can see that types of processes and the process controls.

Untitled Diagram drawio (4)

      Fig-1: The processes and process control blocks.

Cheat sheet for processes:

S.no Processes Description
1. fork-join Parent threads will be executed only when all child threads are executed.
2. fork-join_any Parent threads will be executed only when anyone of the child thread gets executed.
3. fork-join_none Parent threads will be executed parallel with the child threads.
4. wait fork It makes the parent Threads to wait until all the child threads are executed.
5. disable fork It will terminate the execution of all the child threads when disable fork is execute.
6. Fine Grain Process Control These are used to control the processes and it will provide the status of the process/Thread.

Processes or Threads

We have 3 types of Threads/Processes

  1. fork-join
  2. fork-join_any
  3. fork-join_none

1.fork-join

System Verilog provides support for parallel threads through fork-join construct. In fork-join process parent thread will execute only when all the child thread are finished their execution.

syntax:-

fork
Thread 1
Thread 2
Thread 3
join

code snippet:-

$display("[%0t] Thread_T1: Values of a= %0d,b= %0d, c= %0d,d= %0d",$time,a,b,c,d);

fork:FORK_F1  

   begin:BEGIN_B2  
      #1 a <= b;  
      b <= 7;  
      $monitor("[%0t] Thread-T2: Values of a= %0d,b= %0d, c= %0d,d= %0d",$time,a,b,c,d);  
      #1 ->e1;  
      c = b;  
   end:BEGIN_B2  

   begin:BEGIN_B3  
      wait(e1.triggered);  
      $display("[%0t] Event is triggered",$time);  

      begin:BEGIN_B4  
        #1 d = c;  
      end:BEGIN_B4  

   end:BEGIN_B3  

join:FORK_F1 

$display("[%0t] Thread_T3: value of a= %0d,b= %0d, c= %0d,d= %0d",$time,a,b,c,d); 

Output:-
In the below Fig-2 we can see that Thread_T1 is executed first at #0 simulation time but Thread_T3 will be executed after all the child threads are executed and the child threads will execute according to the time delays.

fork_join_output

      Fig-2: The output of fork join block.

In the below Fig-3 you can easily understand how the entire code for fork-join works with respect to schedule schematic regions.

  • where sampling of the variables will be done in preponed region.
  • All the blocking assignments will be executed and all non-blocking assignments was evaluated in active region.
  • Events will be executed in Active region.
  • $display statements will be executed in active region.
  • All #0 delays statements will be executed in inactive region.
  • The evaluated non-blocking assignments will be executed in NBA region.
  • $monitor statements will be executed in postponed region.

fork_join (1)

      Fig-3: scheduler Schematic for fork-join code.

Github lab link: https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/b7_Team_BJT/processes/fork_join/fork_join.sv

Github log_file link: https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/b7_Team_BJT/processes/fork_join/fork_join.log

2.fork-join_any

The parent threads will be execute when any one of the child thread finished their execution. It means if you have 2 or more thread in your fork-join_any block and each thread need different time to finish. In this case, whichever thread finished first, fork-join_any will comes out of the block and will start executing the next parent thread/statement in simulation.
It does not mean that the rest of the child threads will be automatically discarded by simulation. Those threads will be running in the background.

syntax:-
fork
Thread 1
Thread 2
Thread 3
join_any

code snippet:-

$display("[%0t] Thread_T1: Starting of fork_join_any",$time);

a = "Kapu";
c = "Malpe";

fork:FORK_F1  

   begin:BEGIN_B2  
      #0 $display("[%0t] Thread_T2: Values of a =%0s,b =%0s,c =%0s,d =%0s",$time,a,b,c,d);  

      begin:BEGIN_B3  
         b <= a;  
         #1 $display("[%0t] Thread_T3: Values of a =%0s,b =%0s,c =%0s,d =%0s",$time,a,b,c,d);  
      end:BEGIN_B3  

   end:BEGIN_B2  

   fork:FORK_F2  

      begin:BEGIN_B4  
         #3 -> e1;  
         $display("[%0t] Thread_T4: Values of a =%0s,b =%0s,c =%0s,d =%0s",$time,a,b,c,d);  
      end:BEGIN_B4  

   join:FORK_F2  
      
join_any:FORK_F1

#1 $display("[%0t] Thread_T5: Values of a =%0s,b =%0s,c =%0s,d =%0s",$time,a,b,c,d);
    
begin:BEGIN_B5
   wait(e1.triggered);
   d = "Kodi";
   $monitor("[%0t] Thread_T6: Values of a =%0s,b =%0s,c =%0s,d =%0s",$time,a,b,c,d);
end:BEGIN_B5

Output:-
In the below Fig-4 we can see that parent Thread_T1 is executed at #0 and the child Thread_T3 is executed at #1 then only the parent Thread_T5 will be executed at #2.

Untitled Diagram drawio (23)

      Fig-4: The output of fork-join_any block.

fork join_any

      Fig-5: scheduler Schematic for fork-join_any code.

Github lab link: https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/b7_Team_BJT/processes/fork_join_any/fork_join_any.sv

Github log_file link: https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/b7_Team_BJT/processes/fork_join_any/fork_join_any.log

3.fork-join_none

The parent threads are executed parallel with the child threads. This means the thread which is outside the fork-join_none, does not wait for the completion of any threads which is inside the fork-join_none, it just execute parallelly.
It does not mean that the rest of the child threads will be automatically discarded by simulation. Those threads will be running in the background.

syntax:-

fork
Thread 1
Thread 2
Thread 3
join_none

code snippet:-

$display("[%0t] Thread_T1: Starting of fork_join_none",$time);

a = "Kapu";
c = "Malpe";

fork:FORK_F1  

   begin:BEGIN_B2  
      #1 $display("[%0t] Thread_T2: Values of a =%0s,b =%0s,c =%0s,d =%0s",$time,a,b,c,d);      
      b <= a;  
      #1 $display("[%0t] Thread_T3: Values of a =%0s,b =%0s,c =%0s,d =%0s",$time,a,b,c,d);  
   end:BEGIN_B2  

   fork:FORK_F2  
      #1 -> e1;  
      $display("[%0t] Thread_T4: Values of a =%0s,b =%0s,c =%0s,d =%0s",$time,a,b,c,d);  
   join:FORK_F2  

join_none:FORK_F1

#1 $display("[%0t] Thread_T5: Values of a =%0s,b =%0s,c =%0s,d =%0s",$time,a,b,c,d);

wait(e1.triggered);
d = "Kodi";

$monitor("[%0t] Thread_T6: Values of a =%0s,b =%0s,c =%0s,d =%0s",$time,a,b,c,d);

Output:-
In the below Fig-6 At #0 the parent Thread_T1 and the child Thread_T4 is executed Then At #1 both parent Thread_T5 and child Thread_T2 will gets executed and so on.

Untitled Diagram drawio (28)

      Fig-6: The output of the fork-join_none block.

fork_join_none

      Fig-7 : scheduler Schematic for fork-join_none code.

Github lab link :https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/b7_Team_BJT/processes/fork_join_none/fork_join_none.sv

Github log_file link :https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/b7_Team_BJT/processes/fork_join_none/fork_join_none.log


Process control

System Verilog provides constructs that allow one process to terminate or wait for the completion of other processes.

  1. wait fork
  2. disable fork
  3. Fine grain process control

1.wait fork

The wait fork statement is used to ensure that all child processes (processes created by the calling process) have completed their execution. It will wait until all the fork processes complete the execution.

code snippet:-

#1 $display("[%0t] Thread_T1: values of a = %0s,b = %0s,c = %0s",$time,a,b,c);

fork:FORK_F1  

   #2 b <= "Delta";  
   #0 $display("[%0t] Thread_T2: values of a = %0s,b = %0s,c = %0s",$time,a,b,c);  

   begin:BEGIN_B2  
      #1 -> e1;  
      c = "Hoode";  
      #1 $display("[%0t] Thread_T3: values of a = %0s,b = %0s,c = %0s",$time,a,b,c);  
   end:BEGIN_B2  

   fork:FORK_F2  
      wait(e1.triggered);  
      #2 $display("[%0t] Thread_T4: values of a = %0s,b = %0s,c = %0s",$time,a,b,c);  
   join:FORK_F2  

   #1 $display("[%0t] Thread_T5: values of a = %0s,b = %0s,c = %0s",$time,a,b,c);  

join_none:FORK_F1  

wait fork;  
#0 $monitor("[%0t] Thread_T6: values of a = %0s,b = %0s,c = %0s",$time,a,b,c);  

Output:-
In the below Fig-8 we see that At #1 the parent Thread_T1 will get executed and there was a #0 statement which will be working in inactive region and the statements will be executed in the corresponding regions. Even though we are using fork-join_none the $monitor statement will be waiting till all the child Threads was executed.

Untitled Diagram drawio (26)

      Fig-8: The output of wait fork process control statement.

wait_fork

      Fig-9: scheduler Schematic for wait fork code.

Github lab link :https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/b7_Team_BJT/processes/wait_fork/wait_fork.sv

github log_file link :https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/b7_Team_BJT/processes/wait_fork/wait_fork.log

2.disable fork

On execution of the disable fork, all the active process will get terminated.

code snippet:-

#0 $display("[%0t] Thread_T1: Values of a = %0s,b = %0s,c = %0s",$time,a,b,c);

fork:FORK_F1  

   #3 b <= "Delta";  

   #4 $display("[%0t] Thread_T2: Values of a = %0s,b = %0s,c = %0s",$time,a,b,c);  
             
   begin:BEGIN_B2  
      #1 -> e1;  
      c = "Hoode";  
      #1 $display("[%0t] Thread_T3: Values of a = %0s,b = %0s,c = %0s",$time,a,b,c);  
   end:BEGIN_B2  
      
   fork:FORK_F2  
      @(e1.triggered);  
      #1 $display("[%0t] Thread_T4: Values of a = %0s,b = %0s,c = %0s",$time,a,b,c);  
   join:FORK_F2  
      
   #1 $display("[%0t] Thread_T5: Values of a = %0s,b = %0s,c = %0s",$time,a,b,c);  

join_any:FORK_F1  

disable fork;  
#1 $display("[%0t] Thread_T6: ending of fork-join",$time);   

Output:-
In the below Fig-10 At #0 we are waiting for the event to get triggered and the #0 statement will be executed in active region because it was the $display statement.
At #1 it was triggering the event e1 and a child Thread_T5 will get executed then due to using fork-join_any it will go to the parent Thread and hits disable fork statement then all the remaining child Threads will be terminated.

Untitled Diagram drawio (27)

      Fig-10: The output of disable fork process control statement.

disable_fork

      Fig-11: scheduler Schematic for disable fork code.

Github lab link :https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/b7_Team_BJT/processes/disable_fork/disable_fork.sv

Github log_file link :https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/b7_Team_BJT/processes/disable_fork/disable_fork.log

Interview Questions

1.Difference between fork_join,fork_join_any and fork_join_none ?

fork_join fork_join_any fok_join_none
In fork_join the main threads will execute after all the threads in the fork_join is executed In fork_join_any the main threads executes if any one of the child threads excecutes In fork_join_none child threads and main threads are executed parallely