Fork join - wait fork question

  initial begin
    $dumpfile("dump.vcd");
    $dumpvars(0, top);
      

    fork
      begin : isolating_thread
        for(int index=0;index<4;index++)begin : outer_for_loop
          fork
            automatic int idx=index;            
              `uvm_info(" testing ",$sformatf("  idx:%0d ",idx), UVM_LOW)         
              #1000 `uvm_info(" testing ",$sformatf("  idx:%0d  ",idx  ), UVM_LOW)  <-------   test ends before this msg gets printed
              #10 `uvm_info("  testing ",$sformatf("  idx:%0d  ",idx ), UVM_LOW)                                     
          join_none
        end : outer_for_loop  
        `uvm_info("  testing before wait fork"," before ", UVM_LOW)
        wait fork;
          `uvm_info("  testing after wait fork"," after ", UVM_LOW)
       end : isolating_thread
     join                 	  
    
  end

I thought wait fork will wait for all the grand children threads. Thank you for any help in advance.

In reply to S2011:

I thought wait fork will wait for all the grand children threads. Thank you for any help in advance.

Where did you get that thought? Certainly not from reading the LRM

The wait fork statement blocks process execution flow until all immediate child subprocesses (processes created by the current process, excluding their descendants) have completed their execution.

In reply to dave_59:

Then what can I do to keep the test alive till below statement gets printed? #1000 is a arbitrary number I am using to replicate some random delays in my real test.

#1000 `uvm_info(" testing “,$sformatf(” idx:%0d ",idx ), UVM_LOW)

In reply to S2011:
The output I get is:

# UVM_INFO testbench.sv(22) @ 0: reporter [  testing before wait fork]  before 
# UVM_INFO testbench.sv(17) @ 0: reporter [ testing ]   idx:3 
# UVM_INFO testbench.sv(17) @ 0: reporter [ testing ]   idx:2 
# UVM_INFO testbench.sv(17) @ 0: reporter [ testing ]   idx:1 
# UVM_INFO testbench.sv(17) @ 0: reporter [ testing ]   idx:0 
# UVM_INFO testbench.sv(19) @ 10: reporter [  testing ]   idx:3  
# UVM_INFO testbench.sv(19) @ 10: reporter [  testing ]   idx:2  
# UVM_INFO testbench.sv(19) @ 10: reporter [  testing ]   idx:1  
# UVM_INFO testbench.sv(19) @ 10: reporter [  testing ]   idx:0  
# UVM_INFO testbench.sv(18) @ 1000: reporter [ testing ]   idx:3  
# UVM_INFO testbench.sv(18) @ 1000: reporter [ testing ]   idx:2  
# UVM_INFO testbench.sv(18) @ 1000: reporter [ testing ]   idx:1  
# UVM_INFO testbench.sv(18) @ 1000: reporter [ testing ]   idx:0  
# UVM_INFO testbench.sv(24) @ 1000: reporter [  testing after wait fork]  after 
# exit

So what is your problem

In reply to dave_59:

Here is my code, I am not seeing `uvm_info msg with no delay and with #1000 delay, not sure why?

task run_phase(uvm_phase phase);
      // We raise objection to keep the test from completing
      phase.raise_objection(this);
      #10;
      `uvm_warning("", "Hello World!")
      fork
      begin : isolating_thread
       for(int index=0;index<4;index++)begin : outer_for_loop
          fork
            automatic int idx=index;   
           	  for(int j=0;j<3;j++)begin : inner_for_loop                   
               fork
               automatic int jdx=j;
                 begin
                   `uvm_info(" testing ",$sformatf("  idx:%0d jdx:%0d",idx, jdx), UVM_LOW)          
                    #1000 `uvm_info("  testing ",$sformatf("  idx:%0d jdx:%0d ",idx, jdx  ), UVM_LOW)  
                    #10 `uvm_info(" testing ",$sformatf("  idx:%0d  jdx:%0d",idx, jdx ), UVM_LOW)  
                 end
               join_none
              end : inner_for_loop     
            `uvm_info(" testing before wait fork inner loop"," before ", UVM_LOW)
        	wait fork;
              `uvm_info(" testing after wait fork inner loop"," after ", UVM_LOW)              
          join_none
        end : outer_for_loop  
            `uvm_info("  testing before wait fork outer loop "," before ", UVM_LOW)
        wait fork;
          `uvm_info("  testing after wait fork outer loop "," after ", UVM_LOW)
       end : isolating_thread
     join                 	  
      
      // We drop objection to allow the test to complete
      phase.drop_objection(this);
    endtask

UVM_INFO verilog_src/questa_uvm_pkg-1.2/src/questa_uvm_pkg.sv(277) @ 0: reporter [Questa UVM] QUESTA_UVM-1.2.3

UVM_INFO verilog_src/questa_uvm_pkg-1.2/src/questa_uvm_pkg.sv(278) @ 0: reporter [Questa UVM] questa_uvm::init(+struct)

UVM_INFO @ 0: reporter [RNTST] Running test my_test…

UVM_WARNING my_testbench_pkg.svh(76) @ 10: uvm_test_top Hello World!

UVM_INFO my_testbench_pkg.svh(97) @ 10: uvm_test_top [ testing before wait fork outer loop ] before

UVM_INFO my_testbench_pkg.svh(86) @ 10: uvm_test_top [ testing ] idx:3 jdx:2

UVM_INFO my_testbench_pkg.svh(86) @ 10: uvm_test_top [ testing ] idx:3 jdx:1

UVM_INFO my_testbench_pkg.svh(86) @ 10: uvm_test_top [ testing ] idx:3 jdx:0

UVM_INFO my_testbench_pkg.svh(92) @ 10: uvm_test_top [ testing before wait fork inner loop] before

UVM_INFO my_testbench_pkg.svh(94) @ 10: uvm_test_top [ testing after wait fork inner loop] after

UVM_INFO my_testbench_pkg.svh(86) @ 10: uvm_test_top [ testing ] idx:2 jdx:2

UVM_INFO my_testbench_pkg.svh(86) @ 10: uvm_test_top [ testing ] idx:2 jdx:1

UVM_INFO my_testbench_pkg.svh(86) @ 10: uvm_test_top [ testing ] idx:2 jdx:0

UVM_INFO my_testbench_pkg.svh(92) @ 10: uvm_test_top [ testing before wait fork inner loop] before

UVM_INFO my_testbench_pkg.svh(94) @ 10: uvm_test_top [ testing after wait fork inner loop] after

UVM_INFO my_testbench_pkg.svh(86) @ 10: uvm_test_top [ testing ] idx:1 jdx:2

UVM_INFO my_testbench_pkg.svh(86) @ 10: uvm_test_top [ testing ] idx:1 jdx:1

UVM_INFO my_testbench_pkg.svh(86) @ 10: uvm_test_top [ testing ] idx:1 jdx:0

UVM_INFO my_testbench_pkg.svh(92) @ 10: uvm_test_top [ testing before wait fork inner loop] before

UVM_INFO my_testbench_pkg.svh(94) @ 10: uvm_test_top [ testing after wait fork inner loop] after

UVM_INFO my_testbench_pkg.svh(86) @ 10: uvm_test_top [ testing ] idx:0 jdx:2

UVM_INFO my_testbench_pkg.svh(86) @ 10: uvm_test_top [ testing ] idx:0 jdx:1

UVM_INFO my_testbench_pkg.svh(86) @ 10: uvm_test_top [ testing ] idx:0 jdx:0

UVM_INFO my_testbench_pkg.svh(92) @ 10: uvm_test_top [ testing before wait fork inner loop] before

UVM_INFO my_testbench_pkg.svh(94) @ 10: uvm_test_top [ testing after wait fork inner loop] after

UVM_INFO my_testbench_pkg.svh(99) @ 10: uvm_test_top [ testing after wait fork outer loop ] after

UVM_INFO design.sv(20) @ 15: reporter [DUT] Received cmd=0, addr=0xc6, data=0x08

UVM_INFO design.sv(20) @ 25: reporter [DUT] Received cmd=0, addr=0x1f, data=0xb4

UVM_INFO design.sv(20) @ 35: reporter [DUT] Received cmd=0, addr=0x95, data=0x53

UVM_INFO design.sv(20) @ 45: reporter [DUT] Received cmd=0, addr=0x18, data=0x36

UVM_INFO design.sv(20) @ 55: reporter [DUT] Received cmd=0, addr=0x93, data=0x3f

UVM_INFO design.sv(20) @ 65: reporter [DUT] Received cmd=0, addr=0x2a, data=0xf5

UVM_INFO design.sv(20) @ 75: reporter [DUT] Received cmd=0, addr=0x7d, data=0xe6

UVM_INFO design.sv(20) @ 85: reporter [DUT] Received cmd=1, addr=0x8b, data=0x77

UVM_INFO verilog_src/uvm-1.2/src/base/uvm_objection.svh(1270) @ 85: reporter [TEST_DONE] ‘run’ phase is ready to proceed to the ‘extract’ phase

UVM_INFO verilog_src/uvm-1.2/src/base/uvm_report_server.svh(847) @ 85: reporter [UVM/REPORT/SERVER]

In reply to S2011:

Please use code tags making your code easier to read. I have added them for you.

That’s much more information than in your original example. Dropping objections is what’s causing your test to end.

There are number of ways of getting your code to do what you are looking for. For example, the middle fork/join_none in your code is unnecessary. Getting rid of it will make the wait fork work properly since all the forked threads are now immediate children. You can also have each thread raise and drop an objection to keep the phase going.

In reply to dave_59:
Thank you! removing the inner fork fixed the issue.


 task run_phase(uvm_phase phase);
      // We raise objection to keep the test from completing
      phase.raise_objection(this);
      #10;
      `uvm_warning("", "Hello World!")
      fork
      begin : isolating_thread
       for(int index=0;index<4;index++)begin : outer_for_loop
          fork
            automatic int idx=index;   
           	  for(int j=0;j<3;j++)begin : inner_for_loop                   
               
                   `uvm_info(" testing ",$sformatf("  idx:%0d jdx:%0d",idx, j), UVM_LOW)          
                    #1000 `uvm_info("  testing ",$sformatf("  idx:%0d jdx:%0d ",idx, j ), UVM_LOW)  
                    #10 `uvm_info(" testing ",$sformatf("  idx:%0d  jdx:%0d",idx, j ), UVM_LOW)  
              end
          join_none  
        end : outer_for_loop  
            `uvm_info("  testing before wait fork outer loop "," before ", UVM_LOW)
        wait fork;
          `uvm_info("  testing after wait fork outer loop "," after ", UVM_LOW)
       end : isolating_thread
     join                 	  
      
      // We drop objection to allow the test to complete
      phase.drop_objection(this);
    endtask