为什么输出始终在fork join_none中输出j = 5?

为什么输出始终在fork join_none中输出j = 5?

问题描述:

我有一段代码表现出以下行为。我期望看到10个并行线程,例如第一个线程:j = 0和第五个线程:j = 4,全部在模拟时间0纳秒运行。此外,j = i和$ display并行运行,因此在$ display执行时,j仍然是x。为什么输出始终在fork join_none中输出j = 5?

module tb; 

integer i,j; 

initial 
for(i=0;i<5;i++) 
fork 
j = i; 
$display("Value of j is %d at time=%d \n", j, $time); 
join_none 

endmodule 

我收到以下输出。有人可以请解释。我在使用VCS的EDAPlayground上尝试过。

Value of j is   5 at time=     0 

Value of j is   5 at time=     0 

Value of j is   5 at time=     0 

Value of j is   5 at time=     0 

Value of j is   5 at time=     0 

你假设你的代码产生了10个并行线程是正确的。但是,直到父线程阻塞或终止之后,fork/join_none才会启动任何这些线程。在你的情况下,在initial块进程终止之后。到那时,在退出for循环后,i的值为5。

另外,10个线程没有定义的执行顺序 - 它们都在比赛中。 $显示或分配可以以任何顺序进行,所以有可能j显示x。您可能会从不同的工具获得不同的结果

要让您的代码显示0,1,...,4,您不能在j中使用静态变量。您需要为for循环的每次迭代使用automatic创建一个j的副本,该循环使用每个循环的当前值i进行初始化。 @埃曼已经表明了这样做的一种方式。

您可能需要在变量开始执行之前向变量添加一个“自动”,自动存储类变量映射到堆栈上。当函数被调用时,函数中声明的所有本地(非静态)变量都映射到堆栈中的各个位置。由于这些变量只存在于堆栈上,因此只要函数执行完成并且堆栈相应缩小,它们就不再存在。意义范围保持活跃,直到达到所有子进程的结束。

module tb; 
     integer i,j; 
     initial 
     for(i=0;i<5;i++) 
      fork 
      automatic int j=i; 
      begin 
       $display("Value of j is %d at time=%d \n", j, $time); 
      end 
      join_none 
    endmodule 
+0

感谢您的解释。但我的问题在于,不是如何避免这种输出,而是为什么在我的代码中看到这种行为,为什么j = x不打印5次? –

+0

默认情况下,模块或程序块变量是静态的,这意味着它的内存在仿真结束之前不会被解除分配。在你的情况下,因为for循环值更新为5首先j更新为5,因为我保持价值5,并从来没有解除分配导致5,但在这种情况下自动答案中提到的只有内存在所有过程完成后都会被取消分配。 – Emman