细粒度进程控制

SystemVerilog有一个内置的名为Process的类,允许一个进程(例如,像fork_join)访问和控制进程/线程。当我们分叉出任何线程时,会在那时创建Process类的新对象。该对象包含有关该线程的状态信息。

Untitled Diagram drawio (5)

序号任务描述
1.self()用于创建进程的ID/对象。
2.status()用于返回当前线程的模式。
3.kill()用于终止线程。
4.await()用于等待当前线程完成其他线程。
5.suspend()用于暂停线程一段时间。
6.resume()用于从暂停状态恢复线程。

1.self()#

它为Process类创建对象/ID。该对象用于访问Process类的所有预定义方法。对象包含所有线程的状态信息。

语法:-

process p_handle1,p_handle2;  
initial begin 
   p_handle1 = process :: self();  
   p_handle2 = process :: self(); 
end  

代码片段:-

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

在上面的代码片段中,您可以看到在#0模拟时间时声明了进程类的句柄。在下面的图中,

  • 在#1模拟时间时,我们正在检查是否创建了对象p1,然后它显示“未创建”。
  • 在#2模拟时间时,我们为进程p1创建一个对象。
  • 在#3模拟时间时,我们检查对象p1,显示“已创建”。

fine_self_output

fork join_any _self _kill-Page-2 drawio (3)

2.Status()#

它将显示进程ID的状态/模式。有不同的模式,如已完成(Finished)、运行中(Running)、等待中(Waiting)、已挂起(Suspended)、已终止(Killed)。

语法:-

process p_handle;
initial begin
   begin  
      p_handle = process :: self();  
      $display("status : %s",p_handle.status());  
   end
end 

代码片段:-

$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());  

在下图中,

  • 您可以看到一些字符串是大写的,这些是进程p1和p2的状态。
  • 在不同的模拟时间,进程/线程的状态将根据它们的执行而改变。 fine_status_output

status drawio (1)

3.kill()#

kill()函数终止进程及其所有子进程。如果进程没有被阻塞(由于等待语句、延迟或等待事件触发),则它将在当前时间戳被终止。

语法:-

Process p_handle1; 
initial begin 
   fork 
      p_handle1 = process :: self();  
      p_handle1.kill(); 
   join_any  
end 

代码片段:-

$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  

在上述代码片段中,您可以看到在#0模拟时间时创建了进程p1的进程类对象。 在下图中,

  • 在#1模拟时间时,进程p1的状态为RUNNING
  • 在使用kill()方法后的#2模拟时间时,进程p1的状态为KILLED

fine_kill_output

fork join_any _self _kill-Page-3 drawio

4.await()#

这种方法用于允许一个进程等待另一个进程/线程完成。

语法:-

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

代码片段:-

$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  

在上述代码片段中,我们试图使进程p1等待直到进程p2完成。 在下面的图8中,您可以看到:

  • 在#1模拟时间之前使用await()方法之前,p1的状态为RUNNING
  • 在使用await()方法后的#2模拟时间时,p1的状态为WAITING
  • 一旦p2的状态为FINISHED,则p1的状态也为FINISHED

fine_await_output

await drawio

5.suspend()#

这个方法用于暂停进程/线程的执行。它可以暂停自己或其他进程的执行。执行将暂停,直到遇到resume()方法。 如果进程没有被阻塞(由于等待语句、延迟或等待事件触发),则它将在当前时间戳被暂停。

语法:-

Process p_handle1;  
initial begin  
   fork 
      begin
         p_handle1 = process :: self();
         p_handle1.suspend();  
      end
   join_none 
end 

代码片段:-

$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  

在上述代码片段中,我们试图使进程p1永久暂停。 在下面的图10中,您可以看到:

  • 在#1模拟时间之前,暂停p1的状态为RUNNING
  • 在#3模拟时间之后,暂停p1的状态为SUSPENDED

fine_suspend_output

Untitled Diagram drawio (5)

6.resume()#

这个方法用于重新启动被暂停的进程。如果暂停的进程在被阻塞时(由于等待语句、延迟或等待事件触发),则恢复该进程将重新初始化到事件表达式或等待条件为真,或等待延迟到期。

语法:-

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

代码片段:-

$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

在上述代码片段中,我们试图在进程p2中恢复进程p1。 在下面的图12中,您可以看到:

  • 在#1模拟时间时,p1的状态为RUNNING
  • 在使用resume()方法之前的#2模拟时间时,p1的状态为SUSPENDED
  • 在使用resume()方法后的#3模拟时间时,p1的状态为FINISHED

fine_resume_output

resume drawio