Fork join inside a forever loop

I have the following scenario for an ALU SV testbench where I have a fork-join inside a forever:

task run();
    forever
      begin
        fork
          // f1
          begin 
            alu_agent_h.alu_driver_h.drive(); // this call the a driver task which is responsible to drive the values from generator to ALU DUT interface
          end

          // f2
          begin 
            alu_agent_h.alu_monitor_h.monitor_in; // used to monitor and store the DUT interface inputs.
          end

          // f3
          begin 
            alu_agent_h.alu_monitor_h.monitor_out; // used to monitor and store the DUT interface outputs as actual values. 
          end

          // f4
          begin 
            alu_ref_mdl_h.alu_expect(); // a reference model used to produce the expected value for ALU DUT
          end

          // f5
          begin 
            alu_scoreboard_h.compare(); // compare the expected with actual data in scoreboard class
          end

        join
      end
  endtask

This code can only work if I used a fork-join but when I try to replace the join with join_any or join_none the simulation fails. What could the be the reason why I can’t use join_any or join_none with this case?

In reply to emans:

When you replace the fork/join with a fork/jone_none, you get into a zero-delay forever loop with an infinite number of processes being spawned.

When you replace the fork/join with a fork/jone_any, you get into a zero-delay forever loop with an infinite number of processes being spawned if any of the forks is a function consuming zero time.

In reply to dave_59:

Can you please explain how fork join inside forever loop works.

Thanks,
Tejas

In reply to tejasakulu:

forever is a procedural statement that executes its accompanying procedural statement once, and when completes, it executes it again and again.

The accompanying statement must have some procedural blocking delay, otherwise you get into an infinite 0 delay loop and the simulation will hang.

That accompanying statement could be a single procedural statement, or a group of statements contained by a begin/end, or fork/join/join_any/join_none. Both begin/end and fork/join have the potential to be blocking statements if any of their statements have a blocking delay. The only difference between the latter two are begin/end execute their statements sequentially, whereas fork/join execute their statements in parallel.

Inside a forever loop in either of those two cases, if none of the contained statements are blocking, you get into an infinite 0 delay loop and the simulation will hang. A fork/join_none is always non-blocking. A fork/join_any is non-blocking if any one of its statements is non-blocking.