In reply to dave_59:
Hi Dave,
Thanks a lot for the explanation!
That works indeed perfectly.
Dave :
I would like to know the purpose of using “wait fork” here ?
do you think fork/join actually already take care of wait fork? or it has to do something about child seqs of sequence_inst in Andreas38’s example?
thanks in adv
In reply to aming:
The wait fork suspends the parent sequence (or test) until all the child sequences (processes) have completed. There reason you can’t just use fork/join is because of the outer for_loop used to spawn each sequence (process) with a fork statement. If you used a fork/join, then each iteration of the loop would be blocked until the sequence completed, and the fork/join is not really doing anything different than a begin/end.
Thanks Dave. I am afraid i still dont fully understand the usage of wait fork here. :(
I copied your code below, I understand that using fork/join_none inside of for-loop, and using fork/join(first line and last line of your code) to wait all threads created by for-loop to be completed, but i dont understand why there is still a wait fork statement befor join, does the fork/join ( first line and last line of your code ) already wait for all threads to be completed?
thank you
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
In reply to aming:
A fork/join blocks until all direct child threads to complete. A fork/join block does not wait for its grandchildren threads to complete unless a child thread is blocked waiting for a grandchild thread.
In the example above there is only one child thread of the outerfork/join, the isolating_thread begin/end block. Without the wait fork statement, the isolating_thread would not block waiting for the grandchildren threads spawned by the fork/join_none inside the for loop.
Now the reason for the outer fork/join block is a bit trickier to explain, since we are only showing a fragment of code.
The wait fork statement blocks until all child threads of the current parent thread complete. We do not know if there were any other fork/join_none statements that came before this code snippet that we do not want to wait for, The isolating thread creates thread layer that guarantees that we only block waiting for the child threads of the isolating_thread.
In these examples, the automatic variable is declared before the fork. In most other examples I have seen it inside the Fork. Are both equivalent? Before forking feels as if the variable isn’t really belonging to the forked thread?
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
??