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.
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
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.
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.
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.
Fig-4: The output of fork-join_any block.
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.
Fig-6: The output of the fork-join_none block.
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
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.
Fig-8: The output of wait fork process control statement.
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.
Fig-10: The output of disable fork process control statement.
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 |