12.Fine Grain Process Control - vineethkumarv/SystemVerilog_Course GitHub Wiki
Fine Grain Process Control
Systemverilog has a built in class named Process that allows one process(i.e, like fork_join) to access and control the processes/threads. When we fork off any thread, a new object of process class is created at that time. This object contains status information about that thread.
Fig-1: These are all the pre-defined methods which are available in fine grain process control.
Cheat sheet of different fine-grain process control:
S.no | Tasks | Description |
---|---|---|
1. | self() | Used to create the ID/object of the process. |
2. | status() | Used to return the mode of the current Thread. |
3. | kill() | Used to kill the Thread. |
4. | await() | Used to wait the current Thread for some other Thread to complete. |
5. | suspend() | Used to suspend the Thread for some indefinite time. |
6. | resume() | Used to resume the Thread from suspended state. |
1.self()
It creates the object/ID for process class. The object is used to access all the pre-defined methods of the process class.
The object contains the Status information of all the Threads.
Syntax:-
process p_handle1,p_handle2;
initial begin
p_handle1 = process :: self();
p_handle2 = process :: self();
end
code snippet:-
fork:FORK_F1
$display("[%0t] Entered into fork-join and started first check for the process",$time);
#1 ->e1;
begin:BEGIN_B2
wait(e1.triggered);
if(p1 == null)
$display("[%0t] Not created",$time);
else
$display("[%0t] Created",$time);
->e3;
#1 ->e2;
end:BEGIN_B2
#2 p1 = process :: self();
begin:BEGIN_B3
wait(e2.triggered);
$display("[%0t] Started second check for the process",$time);
if(p1 == null)
$display("[%0t] Not created",$time);
else
$display("[%0t] Created",$time);
->e4;
end:BEGIN_B3
fork:FORK_F2
begin:BEGIN_B4
wait(e3.triggered);
$display("[%0t] first check for the process done",$time);
end:BEGIN_B4
begin:BEGIN_B5
wait(e4.triggered);
$display("[%0t] Second check for the process done",$time);
end:BEGIN_B5
join:FORK_F2
join:FORK_F1
In the above code snippet you can see that At #0 simulation time the handle for the process class was declared.
In the below Fig-2,
- At #1 simulation time we are checking whether an object p1 was created or not then it was displaying Not created.
- At #2 simulation time we are creating an object for the process p1.
- At #3 simulation time we are checking for the object p1 it was displaying Created.
Fig-2: The output of the self() method.
Fig-3: scheduler Schematic for self() method.
Github lab link-https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/b7_Team_BJT/fine_grain_process_control/fine_self/fine_self.sv
Github log_file link-https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/b7_Team_BJT/fine_grain_process_control/fine_self/fine_self.log
2.Status()
It will shows the status/mode of the process ID. There are different modes like Finished, Running, Waiting, Suspended, Killed.
Syntax:-
process p_handle;
initial begin
begin
p_handle = process :: self();
$display("status : %s",p_handle.status());
end
end
code snippet:-
$display("[%0t] Seeking status:",$time);
fork:FORK_F1
begin:BEGIN_B2
p1 = process :: self();
#1 $display("[%0t] I am in process p1",$time);
$display("[%0t] Initial status of p1: %s",$time,p1.status());
#1 $display("[%0t] Still working in p1",$time);
->e1;
->e2;
end:BEGIN_B2
begin:BEGIN_B3
p2 = process :: self();
wait(e2.triggered);
#1 $display("[%0t] I am in process p2",$time);
$display("[%0t] Initial status of p2: %s",$time,p2.status());
$display("[%0t] Still working in p2",$time);
->e3;
end:BEGIN_B3
begin:BEGIN_B4
wait(e1.triggered);
$display("[%0t] Final status of p1: %s",$time,p1.status());
end:BEGIN_B4
begin:BEGIN_B5
wait(e3.triggered);
$display("[%0t] Final status of p2: %s",$time,p2.status());
end:BEGIN_B5
fork:FORK_F2
p3 = process :: self();
#1 $display("[%0t] I am in process p3",$time);
#1 $display("[%0t] status of p3: %s",$time,p3.status());
#1 ->e4;
join:FORK_F2
join_any:FORK_F1
wait(e4.triggered);
#1 $display("[%0t] Final status of p3: %s",$time,p3.status());
In the below Fig-4,
- you can see that there are some strings which are in upper-case those are the status of a process p1 and p2.
- At different simulation times the status of the processes/Threads will be changing depending on their execution.
Fig-4: The output of the status() method.
Fig-5: scheduler Schematic for status() method.
Github lab link-https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/b7_Team_BJT/fine_grain_process_control/fine_status/fine_status.sv
Github log_file link-https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/b7_Team_BJT/fine_grain_process_control/fine_status/fine_status.log
3.kill()
The kill () function terminates the process and all its sub-processes. If the process is not blocked (due to wait statement, delay or waiting for an event to trigger), then it will be terminated in the current timestamp.
Syntax:-
Process p_handle1;
initial begin
fork
p_handle1 = process :: self();
p_handle1.kill();
join_any
end
code snippet:-
$display("[%0t] Seeking status:",$time);
fork:FORK_F1
begin:BEGIN_B2
p1 = process :: self();
#1 $display("[%0t] I am in process p1",$time);
$display("[%0t] Initial status check of p1: %s",$time,p1.status);
->e1;
if(p1.status() != process :: FINISHED)
p1.kill();
$display("hi i am working");
$display("what about you?");
end:BEGIN_B2
begin:BEGIN_B3
wait(e1.triggered);
#1 $display("[%0t] Status of p1 before killing: %s",$time,p1.status());
end:BEGIN_B3
join:FORK_F1
In the above code snippet you can see that process p1 At #0 simulation time process class object was created.
In the below Fig-6,
- At #1 simulation time the status of p1 was RUNNING.
- At #2 simulation time after using kill() method the status of p1 was KILLED.
Fig-6: The output of the kill() method.
Fig-7: scheduler Schematic for kill() method.
Github lab link-https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/b7_Team_BJT/fine_grain_process_control/fine_kill/fine_kill.sv
Github log_file link- https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/b7_Team_BJT/fine_grain_process_control/fine_kill/fine_kill.log
4.await()
This method is used to allows one process to wait for another process/Thread to complete.
Syntax:-
Process p_handle1,p_handle2;
initial begin
fork
begin
p_handle1 = process :: self();
p_handle2.await();
end
begin
p_handle2 = process :: self();
end
join
end
code snippet:-
$display("[%0t] Seeking status:",$time);
fork:FORK_F1
begin:BEGIN_B2
p1 = process :: self();
#1 $display("[%0t] I am in process p1",$time);
$display("[%0t] Initial status of p1: %s",$time,p1.status());
$display("[%0t] Status of p1 before await: %s",$time,p1.status());
if(p1.status() != process :: FINISHED)
p2.await();
end:BEGIN_B2
#2 $display("[%0t] Status of p1 after await: %s",$time,p1.status());
begin:BEGIN_B4
p2 = process :: self();
#1 $display("[%0t] I am in process p2",$time);
$display("[%0t] Initial status of p2: %s",$time,p2.status());
#2 ->e2;
end:BEGIN_B4
begin:BEGIN_B5
wait(e2.triggered);
$display("[%0t] Final status of p2: %s",$time,p2.status());
->e1;
end:BEGIN_B5
begin:BEGIN_B6
wait(e1.triggered);
$display("[%0t] Final status of p1: %s",$time,p1.status());
end:BEGIN_B6
join_any:FORK_F1
In the above code snippet we are trying to make process p1 to wait until the process p2 was finished.
In below Fig-8, you can see
- At #1 simulation time before using await() method the status of p1 was RUNNING.
- At #2 simulation time after using await() method the status of p1 was WAITING.
- At #3 simulation time once the status of p2 was FINISHED then the status of p1 also FINISHED.
Fig-8: The output of the await() method.
Fig-9: scheduler Schematic for await () method.
Github lab link-https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/b7_Team_BJT/fine_grain_process_control/fine_await/fine_await.sv
Github log_file link-https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/b7_Team_BJT/fine_grain_process_control/fine_await/fine_await.log
5.suspend()
This method is used to suspend the execution of the process/Thread. It can suspend its own or other process’s execution. The execution is suspended until a resume() method is encountered.
If the process is not blocked (due to wait statement, delay or waiting for an event to trigger), then it will be suspended in the current timestamp.
Syntax:-
Process p_handle1;
initial begin
fork
begin
p_handle1 = process :: self();
p_handle1.suspend();
end
join_none
end
code snippet:-
$display("[%0t] Seeking status:",$time);
fork:FORK_F1
begin:BEGIN_B2
p1 = process :: self();
#1 $display("[%0t] I am in process p1",$time);
$display("[%0t] Initial status of p1: %s",$time,p1.status());
->e1;
if(p1.status() != process :: FINISHED)
begin:BEGIN_B3
#1 $display("[%0t] Status of p1 before suspending: %s",$time,p1.status());
p1.suspend();
$display("[%0t] Status of p2 in p1 block: %s",$time,p2.status());
end:BEGIN_B3
end:BEGIN_B2
begin:BEGIN_B4
wait(e1.triggered);
p2 = process :: self();
#1 $display("[%0t] I am in process p2",$time);
$display("[%0t] Initial status of p2: %s",$time,p2.status());
#1 $display("[%0t] status of p1 after suspended: %s",$time,p1.status());
->e2;
end:BEGIN_B4
begin:BEGIN_B5
wait(e2.triggered);
$display("[%0t] Final status of p2: %s",$time,p2.status());
end:BEGIN_B5
join:FORK_F1
In the above code snippet we are trying to make process p1 to suspend permanently.
In the below Fig-10, you can see
- At #1 simulation time before suspending the status of p1 was RUNNING.
- At #3 simulation time after suspending the status of p1 was SUSPENDED.
Fig-10: The output of the suspend() method.
Fig-11: scheduler Schematic for suspend () method.
Github lab link-https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/b7_Team_BJT/fine_grain_process_control/fine_suspend/fine_suspend.sv
Github log_file link- https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/b7_Team_BJT/fine_grain_process_control/fine_suspend/fine_suspend.log
6.resume()
This method is used to restart the process that was suspended. Resuming a process that was suspended while being blocked (due to wait statement, delay or waiting for an event to trigger) shall reinitialize that process to the event expression or wait for the wait condition to be true or for the delay to expire.
Syntax:-
Process p_handle1,p_handle2;
initial begin
fork
begin
p_handle1 = process :: self();
p_handle1.suspend();
end
begin
p_handle2 = process :: self();
p_handle1.resume();
end
join_none
end
code snippet:-
$display("[%0t] Seeking status:",$time);
fork:FORK_F1
begin:BEGIN_B2
p1 = process :: self();
#1 $display("[%0t] I am in process p1",$time);
$display("[%0t] Initial status of p1: %s",$time,p1.status());
->e1;
if(p1.status() != process :: FINISHED)
begin:BEGIN_B3
#1 $display("[%0t] Status of p1 before suspending: %s",$time,p1.status());
p1.suspend();
$display("[%0t] Status of p2 in p1 block: %s",$time,p2.status());
end:BEGIN_B3
end:BEGIN_B2
begin:BEGIN_B4
wait(e2.triggered);
$display("[%0t] Status of p1 before resuming: %s",$time,p1.status());
p1.resume();
#1 $display("[%0t] Status of p1 after resuming: %s",$time,p1.status());
->e3;
end:BEGIN_B4
begin:BEGIN_B6
p2 = process :: self();
#1 $display("[%0t] I am in process p2",$time);
$display("[%0t] Initial status of p2: %s",$time,p2.status());
if(p1.status() == process :: SUSPENDED)
#1 ->e2;
end:BEGIN_B6
begin:BEGIN_B7
wait(e3.triggered);
#1 $display("[%0t] Final status of p1: %s",$time,p1.status());
$display("[%0t] Final status of p2: %s",$time,p2.status());
end:BEGIN_B7
join:FORK_F1
Here in the above code snippet we are trying to resume the process p1 in the process p2.
In the below Fig-12, you can see
- At #1 simulation time the status of p1 was RUNNING.
- At #2 simulation time before using resume() method the status of p1 was SUSPENDED.
- At #3 simulation time after using resume() method the status of p1 was FINISHED.
Fig-12: The output of the resume() method.
Fig-13: scheduler Schematic for resume() method.
Github lab link-https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/b7_Team_BJT/fine_grain_process_control/fine_resume/fine_resume.sv
Github log_file link-https://github.com/muneeb-mbytes/SystemVerilog_Course/blob/b7_Team_BJT/fine_grain_process_control/fine_resume/fine_resume.log