Fork within loop with join ALL

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 SanjanaDhiran:

Are you able to try it your self? There is always www.edaplayground.com

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
 


https://www.linkedin.com/in/patel-rahulkumar/

In reply to dave_59:

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 ?

In reply to dave_59:

In reply to jhardy:

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

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.

In reply to dave_59:

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?

In reply to Robert.Lanier:

If you are calling a sequence multiple times consecutively I don’t know why you would be using a fork statement.

In reply to dave_59:

In reply to Robert.Lanier:
If you are calling a sequence multiple times consecutively I don’t know why you would be using a fork statement.

I have a need to run two parallel threads, and to restart the threads N number of times.

In reply to Robert.Lanier:

Then a simple fork/join in a loop should work.

 for(int index=0;index<N;index++)
      fork
        begin
            ...
        end
        begin
            ...
        end
      join

In reply to dave_59:

Yes sir, this works fine. Thank you.