SV中用的比较多的是fork…join_none,以及disable fork,wait fork;
其中,wait_fork会阻止当前线程,直到所有子线程完成;
disable fork会kill disable fork 所在的当前线程以及所有子线程;
具体可看文章disable label and disable fork
The parent process continues to execute concurrently with all the processes spawned by the fork. The spawned processes do not start executing until the parent thread executes a blocking statement.
from LRM父线程继续与fork产生的所有子线程同时执行; 生成的子线程不会开始执行,直到父线程执行阻塞语句或终止 。
上面那句话有两层含义:
automatic variables get created upon entry and initialized before executing any procedural statement within the block they are located in.
位于fork join_none中的 automatic变量的创建和初始化会比procedural statement 先执行,且与父线程同时执行。
Each statement within a fork/join_none becomes as new child process and execution of the child process does not begin until the current parent thread suspends.
位于fork join_none中的procedural statement 不会开始执行,直到父线程执行阻塞语句或终止。
sv为下列进程产生一个执行线程:
对于begin…end 而言,处于initial、fork…join(join_any, join_none)中是一个线程,除此之外不是线程~~
应用场景
initial
begin
N = $urandom_range(1,10);
for( int j = 1; j <= N; ++j )
fork
automatic int k = j; // local copy, k, for each value of j
start_a_thread(k);
join_none
end
注意以下几种场景的区别:
program automatic test; //declare automatic
initial begin
for(int i=0;i<16;i++)
send(i);
end
task send(int j);//int j 为automatic 变量,每次call send 均会为j分配新的存储空间
fork
begin
$display("Driving port %0d",j);
#1;
end
join_none
endtask
end
endprogram
result :
simulation ends at time 0.
Driving port 0
Driving port 1
Driving port 2
Driving port 3
...
program test;
initial begin
for(int i=0;i<16;i++)
send(i);
end
task send(int j); //int j 为static变量
fork
begin
$display("Driving port %0d",j);
#1;
end
join_none
endtask
end
endprogram
result :
simulation ends at time 0.
Driving port 15
Driving port 15
Driving port 15
Driving port 15
...
program中一个任务如果没有被标示为automatic,则默认为static。在这个任务的调用过程中就只会分配一块内存空间,所以每一次该任务的调用都会导致上一次任务的内存被重写。例子中send被调用了许多次,但是send任务里面的int j(static 变量) 这个变量其实共用了同一个地址。
再看join_none语句,它指示父线程不会被阻塞,而会继续执行,子线程会加入等待队列。也就是说i会一直被加到15跳出循环后,才会执行循环中产生的16个send任务(线程),而此时i的值已经是15了,按前面说的这个任务是static的,所以再执行display只会打印出15.
如果将task send; 改为task automatic send 就可以实现15-0的打印。
上面两个栗子是说明task中static变量 和automatic 变量的区别,下面的栗子是说明fork join_none执行的差异。
program automatic test;
initial begin
for(int i=0;i<16;i++)
fork
send(i);
join_none
end
task send(int j);
begin
$display("Driving port %0d",j);
#1;
end
endtask
end
endprogram
result :
simulation ends at time 0.
Driving port 16
Driving port 16
Driving port 16
Driving port 16
...
//case 1
program automatic test;
initial begin
for(int i=0;i<16;i++)
fork
int jj = i;//variable creation and initialization;and it occurs before spawning any process within the fork/join_none
send(jj);
join_none
end
task send(int j);
begin
$display("Driving port %0d",j);
#1;
end
endtask
end
endprogram
result :
simulation ends at time 0.
Driving port 0
Driving port 1
Driving port 2
Driving port 3
...
//case 2
program automatic test;
initial begin
for(int i=0;i<16;i++)
fork
int jj ; //variable create
jj = i; //variable initialization as a separate procedural assignment statement
send(jj);
join_none
end
task send(int j);
begin
$display("Driving port %0d",j);
#1;
end
endtask
end
endprogram
result :
simulation ends at time 0.
Driving port 16
Driving port 16
Driving port 16
Driving port 16
...
//case 3
program automatic test;
initial begin
for(int i=0;i<16;i++)
fork
begin //加上begin..end
int jj = i;
send(jj);
end
join_none
end
task send(int j);
begin //a single statement
$display("Driving port %0d",j);
#1;
end
endtask
end
endprogram
result :
simulation ends at time 0.
Driving port 16
Driving port 16
Driving port 16
Driving port 16
...
there will be 16 concurrent variables named index and only one named i. In case 1) & 2), the index variable gets created upon each entry into the fork/join_none block. That occurs before spawning any process within the fork/join_none. In case 1) the variable initialization also occurs before any process within the fork/join_none. The thing that you need to remember is that automatic variables get created upon entry and initialized before executing any procedural statement within the block they are located in.