If I have two for-loop, how to handle it ? Is below code correct ?
fork
begin : isolating_thread
for(int index=0;index<14;index++)begin : for_loop
fork
automatic int idx=index;
for(int j=0;j<14;j++)begin
automatic int jdx=j;
begin
`ovm_do_on(sequence_inst,p_sequencer.my_sqr[idx][jdx]);
end
join_none;
end : for_loop
wait fork;
end
end : isolating_thread
join
In reply to dave_59:
Hi Dave,
If I have two for-loop, how to handle it ? Is below code correct ?
fork
begin : isolating_thread
for(int index=0;index<14;index++)begin : for_loop
fork
automatic int idx=index;
for(int j=0;j<14;j++)begin
automatic int jdx=j;
begin
`ovm_do_on(sequence_inst,p_sequencer.my_sqr[idx][jdx]);
end
join_none;
end : for_loop
wait fork;
end
end : isolating_thread
join
That should work, not sure you need that second automatic variable assignment for j, but it shouldn’t hurt.
I just ran into this problem yesterday… great thread… I totally missed the part about the automatic variable for the fork.
Is there any different between below two snippet of code ? (The different code is pointed out with comment)
I have thread_A() which is an isolated thread, and thread_B(i) which is parameterized with forloop variable, and another thread_C() in my code. I want all thread_B(i) are spawned in parallel and start the thread_C() when all of them finished. and above process is regarded as a whole thread, and run with thread_A in parallel. One of them finished then disable all others.
fork
thread_A();
begin
fork // here is difference
for (int i = 0; i < 8; i++) begin
fork
automatic int j = i;
thread_B(j);
join_none
end
wait fork;
join // here is difference
thread_C();
end
join_any
disable fork;
fork
thread_A();
begin
for (int i = 0; i < 8; i++) begin
fork
automatic int j = i;
thread_B(j);
join_none
end
wait fork;
thread_C();
end
join_any
disable fork;
The wait fork waits for all child processes of the current thread to terminate. In your first example, any process created by thread_A are cousins, not children of the current thread. In your second example, any process created by thread_A are children of the current thread.
By current thread I mean from the perspective of the thread executing the wait fork statement. You should have enough information to make the correct decision.
module abc;
task thread_A();
#100;
endtask
task thread_B(int j);
#2;
endtask
task thread_C();
#30;
endtask
initial begin
fork
thread_A();
begin
fork // here is difference
for (int i = 0; i < 8; i++) begin
fork
automatic int j = i;
thread_B(j);
join_none
end
wait fork;
join // here is difference
thread_C();
end
join_any
$display($time);
disable fork;
end
initial begin
fork
thread_A();
begin
for (int i = 0; i < 8; i++) begin
fork
automatic int j = i;
thread_B(j);
join_none
end
wait fork;
thread_C();
end
join_any
$display($time);
disable fork;
end
endmodule
Dave, can you help me with understanding the above example.
the first initial block is printing #30, expecting it to be 32 (thread_B + thread_C).
the second initial block is printing #32, expecting it to be 102 (thread_A + thread_B + thread_C) bcz of the “wait fork” inside the begin-end.
// 1st initial block
initial begin
fork : fork_1
thread_A(); // Thread 1 of fork_1
begin // Thread 2 of fork_1
fork : fork_2
for (int i = 0; i < 8; i++) begin //Thread 1 of fork_2
fork : fork_3
automatic int j = i;
thread_B(j);
join_none : fork_3
end
wait fork; //Thread 2 of fork_2
join : fork_2
thread_C();
end
join_any : fork_1
$display($time);
disable fork;
end
//"wait fork;" is Thread 2 of fork_2. Thread 1 and Thread 2 are executing in parallel.
//None of the fork process were active during the execution of wait_fork. so it won't wait. so, Thread 2 finish at 0.
// Thread 1 will also finish in 0 time. Due to fork join_none (fork_3)
// fork_1
//thread_A(); -> #100
//begin _end -> #30
// join_any
so, $display prints #30.
---------------------------------------------------------------------------------------
//if you add begin....end fork 2 then you will see different
initial begin
fork : fork_1
thread_A(); // Thread 1 of fork_1
begin // Thread 2 of fork_1
fork : fork_2
begin /// ***Change*** //only Thread of fork_2
for (int i = 0; i < 8; i++) begin
fork : fork_3
automatic int j = i;
thread_B(j);
join_none : fork_3
end
wait fork;
end/// ***Change***
join : fork_2
thread_C();
end
join_any : fork_1
$display($time);
disable fork;
end
//2nd initial block
initial begin
fork : fork_1
thread_A(); //Thread 1 of fork_1
begin //Thread 2 of fork_1
for (int i = 0; i < 8; i++) begin
fork : fork_3
automatic int j = i;
thread_B(j);
join_none : fork_3
end
wait fork; // wait for fork_3 to finish
thread_C();
end
join_any : fork_1
$display($time);
disable fork;
end
// It have 2 Thread
// Thread 1 execution time is #100 which is thread_A() execution time
// Thread 2 execution time is #32 which is thread_B()+thread_C() execution time
//fork...join_any will wait for any one of the thread to finish. so, it display #32
In reply to zz8318:
The wait fork waits for all child processes of the current thread to terminate. In your first example, any process created by thread_A are cousins, not children of the current thread. In your second example, any process created by thread_A are children of the current thread.
in the second example, as per Dave’s explanation, thread_A is children of current thread, and shouldn’t “wait-fork” wait for thread_A ?
begin
fork
begin : isolating_thread
for(int index=0;index<14;index++)begin : for_loop
fork
automatic int idx=index;
begin
`ovm_do_on(sequence_inst,p_sequencer.my_sqr[idx]);
end
join_none;
end : for_loop
wait fork;
end : isolating_thread
join
end
I’m not sure if this was asked, but can there be multiple threads within the inner fork/join_none? If so, does this require multiple wait fork commands?
begin
fork
begin : isolating_thread
for(int index=0;index<4;index++)begin : for_loop
fork
automatic int idx=index;
begin
...
end
begin
...
end
join_none;
end : for_loop
wait fork;
end : isolating_thread
join
end
wait fork waits for ALL immediate children of the current thread to terminate. It doesn’t matter how the child threads are spawned; multiple statements in a single fork or multiple forks.
In reply to Robert.Lanier: wait fork waits for ALL immediate children of the current thread to terminate. It doesn’t matter how the child threads are spawned; multiple statements in a single fork or multiple forks.
If we want to use a for loop within a fork to run a sequence(s) multiple times consecutively, I wouldn’t want to use the wait fork command since I want to wait for first sequence to complete before starting the second. Is a disable fork needed in this case?