sv里面fork...join_none的一段错误分析!
i=0send(i)--->into waiting queue
i++;
i=1send(i)---->into waiting queue
i++;
i=2send(i)------>intowaitingqueue
................
.................
i=16;ready queue 执行完 开始执行waiting queue
i=16$display().....
i=16$display().....
16次
就出现打印结果了,因为16个sendtask引用的是一个地址(*i);而且由于你是join none 的,所以你的所有send会在for循环结束后开始执行
首先是SV中static与automatic的区别。一个任务如果没有被标示为automatic,则默认为static,在这个任务的调用过程中就只会分配一块内存空间,所以每一次该任务的调用都会导致上一次任务的内存被重写。你的例子中就是说send被调用了许多次,但是send任务里面的int j 这个变量其实共用了同一个地址。
再看join_none语句。它指示父线程不会被阻塞,而会继续执行,子线程会加入等待队列。也就是说i会一直被加到15跳出循环后,才会执行循环中产生的16个send任务(线程),而此时i的值已经是15了,按前面说的这个任务是static的,所以再执行display只会打印出15.
如果将task send; 改为task automatic send 就可以实现15-0的打印。
或者在send任务中用automatic定义一个变量,如automatic int temp;然后先将j存放在temp中,打印temp。如下
task send(int j);
automatic int temp;
temp = j;
fork
$display("%0d",temp);
#0;
join_none
endtask
结果应该是一样的。
为什么打印的不是 16 而是 15?在for 跳出后, i 应该是16了.
是这样的,在program里面,task默认是static的,所以将for循环展开是
send(0);
send(1);
。
send(15);
由于send task是static的,也就是在内存中只有一个send,且由于fork join_none的缘故,send的执行会在下一个timeslot才开始,所以后面的send的数字会override前面的,也就是在内存中的send的输入值是15, 最后就是执行16遍内存中唯一的static的task send。
program test -->program automatic test
GOOD! 六楼说的也对。
都好厉害
绿皮书上有说明
厉害厉害,看了一下,有点理解了
换成function 就是15 to 0