Does fork join have order?

I know it is probably a dumb question but when I try running this code to understand fork join, I expected to see that any of the 4 processes could be kicked off first, which I thought what forking is supposed to do.

But, I see that the first process that gets the keys corresponds to the first display statement, irrespective of random seed number.
In other words, if I change the code to have display(2) just after the fork, $display will say it got 2 keys. If I change the line after fork, to display(3), $display will say it got 3 keys.

Is there any inherent ordering in this code that I am missing?

//-------------------------------------------------------------------------
//						www.verificationguide.com
//-------------------------------------------------------------------------
module semaphore_ex;
  semaphore sema; //declaring semaphore sema
  
  initial begin
    sema=new(4); //creating sema with '1' keys 
    fork
      display(1); //process-4
      display(3); //process-2
      display(2); //process-3
      display(2); //process-1
    join
  end
  
  //display method
  task automatic display(int key);
    sema.get(key); //getting 'key' number of keys from sema
    $display($time,"\tCurent Simulation Time, Got %0d keys",key);
    #30;
    sema.put(key); //putting 'key' number of keys to sema
  endtask
endmodule

In reply to UVM_learner6:
pe 1800’2017: 9.3.2 Parallel blocks
The fork-join parallel block construct enables the creation of concurrent processes from each of its parallel
statements. A parallel block shall have the following characteristics:
— Statements shall execute concurrently.

One or more statements can be specified; each statement shall execute as a concurrent process. The timing controls in a fork-join block do not have to be ordered sequentially in time.

A simulator may choose the order in the sequence in which it was written, but that is not a requirement, and one should not rely on that order. A tool may have chosen that approach for simplicity of implementation. If you want to circumvent this implied ordering, you can force a randomized delay. For example: Edit code - EDA Playground


module semaphore_ex;
  semaphore sema; //declaring semaphore sema
  
  initial begin
    sema=new(4); //creating sema with '1' keys 
    fork
      display(2, 1); //process-4
      display(2, 2); //process-2
      display(2, 3); //process-3
      display(2, 4); //process-1
    join
  end
  
  //display method
  task automatic display(int key, p);
    bit [0:2] delay; 
    realtime t; 
    if (!randomize(delay)) $display("rand error"); 
     //`uvm_fatal("RAND", "This is a randomize error")
    t= delay*1ns; $display("p= %d, t=%t", p, delay); 
    #t; 
    sema.get(key); //getting 'key' number of keys from sema
    $display("p=%d, time= %t, Got %0d keys", p, $realtime, key);
    #30;
    sema.put(key); //putting 'key' number of keys to sema
  endtask
endmodule 

KERNEL: p=           1, t=                   6
# KERNEL: p=           2, t=                   4
# KERNEL: p=           3, t=                   6
# KERNEL: p=           4, t=                   7
# KERNEL: p=          2, time=                    4, Got 2 keys
# KERNEL: p=          1, time=                    6, Got 2 keys
# KERNEL: p=          3, time=                   34, Got 2 keys
# KERNEL: p=          4, time=                   36, Got 2 keys

Ben Cohen
http://www.systemverilog.us/ ben@systemverilog.us
For training, consulting, services: contact Home - My cvcblr


  1. SVA Alternative for Complex Assertions
    Verification Horizons - March 2018 Issue | Verification Academy
  2. SVA: Package for dynamic and range delays and repeats | Verification Academy
  3. SVA in a UVM Class-based Environment
    SVA in a UVM Class-based Environment | Verification Horizons | Verification Academy