In reply to NiLu:
You are correct. There needs to be a separate idx variable for each invocation of the fork/join_none. I overlooked this since it was not the main point of the original question. I have edited the example.
In reply to NiLu:
You are correct. There needs to be a separate idx variable for each invocation of the fork/join_none. I overlooked this since it was not the main point of the original question. I have edited the example.
Is it possible to do something similar, but accomplish join_any behavior instead of join_all? All examples that I have seen on this topic always use the “wait fork” statement.
I am interested in starting multiple threads in parallel and joining them when just one completes. In particular, I want to wait for just one of any events to occur. I have tried a few variations of the following example, but without success.
Any help would be greatly appreciated. Thanks!
JH
fork
begin
foreach(my_cbs[i]) begin // loop through an array of callbacks
fork
automatic int var_i = i;
begin
@(my_cbs[var_i].change_event); // wait for an event triggered within the callback
end
join_none
end
end
join_any
In reply to jhardy:
begin
event just_one_of any;
foreach(my_cbs[i]) // loop through an array of callbacks
fork
int var_i = i;
begin
@(my_cbs[var_i].change_event); // wait for an event triggered within the callback
-> just_one_of_any;
end
join_none
@just_one_of_any;
end
Thanks Dave! I appreciate the quick reply. Your suggestion solved my problem.
I assume that we still should declare the variable as automatic. Please correct correct me if I am wrong.
In reply to theketi:
i < 8 has to fail in order to end the loop. So i will be 8 after exiting the loop.
In reply to dave_59:
Hello Dave,
I am trying to run below code :
my_seq = new[2];
fork
begin : isolating_thread
for(int index=0;index<2;index++) begin : for_loop
automatic int idx=index;
automatic int local_qd=$urandom_range(1,4);
fork
`uvm_do_with(my_seq[idx],
{
qd == local_qd;
})
join_none;
end : for_loop
wait fork;
end : isolating_thread
join
I am getting below Error :
=======================================================
Solver failed when solving following set of constraints
integer qd = 0;
integer local_qd = 4;
constraint WITH_CONSTRAINT // (from this) (constraint_mode = ON) (<File_path>:233)
{
(qd == local_qd);
}
=======================================================
Can you please help me with this ?? Thanks a lot in advance.
In reply to birenkumar:
This likely has nothing to do with a fork statement. Maybe you did not declare qd as rand.
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
In reply to zz8318:
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.
In reply to dave_59:
With respect to the fork and join ALL inside for loop, I have a very basic question regarding the same.
for (i = 0; i<3;i++) begin
automatic int j = i;
fork
$display(j);
join
end
Will the output for the above code will be :
0
1
2
???
In reply to SanjanaDhiran:
A fork/join with one statement behaves just like a begin/end block as far as your example is concerned.
In reply to dave_59:
Hie Dave,
Thank you for responding. However, I am still a little confused. Will my output be :
0
1
2
??
In reply to dave_59:
Hi Dave,
I have a question here.
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;
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 reply to dave_59:
Hi Dave,
How to determine which thread is current thread ?
and which one is correct to meet the requirement I mentioned in my last post ?
In reply to zz8318:
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.
In reply to yourcheers:
These are valid results. Let me try to explain.
// 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