I put this example together years ago to check whether vendors had implemented all the fork / join / wait / disable capabilities, and all vendors did so years ago. In the example below, the odd behavior that I am observing is that at time 200, I see the join_none_msg, followed by the idle starting message, followed by the proc G, H, I starting messages. I have verified this behavior with two different simulators. They all display at time 200, but I would have expected the proc G, H, I messages to be printed first since they are positioned earlier in the code. What am I missing? The code and the output are both shown below.
`timescale 1ns/1ns
module forktest;
logic clk;
initial begin
#10 clk <= '1;
forever #5 clk = ~clk;
end
initial begin
idle(2);
fork
proc ("A", 3);
proc ("B", 5);
proc ("C", 2);
join
join_msg;
idle(3);
fork
proc ("D", 3);
proc ("E", 5);
proc ("F", 2);
join_any
join_any_msg;
idle(8);
fork
proc ("G", 3);
proc ("H", 5);
proc ("I", 2);
join_none
join_none_msg;
idle(3);
disable fork;
disable_fork_msg;
idle(9);
fork
proc ("J", 3);
proc ("K", 5);
proc ("L", 2);
join_any
join_any_msg;
idle(2);
wait fork;
wait_fork_msg;
idle(1);
$finish;
end
task automatic idle (input int n);
$display("\nIdle at time %0d for %0d clocks\n", $time, n);
repeat(n) @(posedge clk);
endtask
task automatic proc (input string s, input int n);
$display("Start running proc %s at time %0d for %0d clocks", s, $time, n);
repeat(n) @(posedge clk);
$display("--- End of proc %s at time %0d ---", s, $time);
endtask
function void join_msg;
$display("\"join\" at time %0d", $time);
endfunction
function void join_any_msg;
$display("\"join_any\" at time %0d", $time);
endfunction
function void join_none_msg;
$display("\"join_none\" at time %0d", $time);
endfunction
function void disable_fork_msg;
$display("\"disable fork\" at time %0d", $time);
endfunction
function void wait_fork_msg;
$display("\"wait fork\" at time %0d", $time);
endfunction
endmodule
// Idle at time 0 for 2 clocks
//
// Start running proc A at time 20 for 3 clocks
// Start running proc B at time 20 for 5 clocks
// Start running proc C at time 20 for 2 clocks
// — End of proc C at time 40 —
// — End of proc A at time 50 —
// — End of proc B at time 70 —
// “join” at time 70
//
// Idle at time 70 for 3 clocks
//
// Start running proc D at time 100 for 3 clocks
// Start running proc E at time 100 for 5 clocks
// Start running proc F at time 100 for 2 clocks
// — End of proc F at time 120 —
// “join_any” at time 120
//
// Idle at time 120 for 8 clocks
//
// — End of proc D at time 130 —
// — End of proc E at time 150 —
// “join_none” at time 200
//
// Idle at time 200 for 3 clocks
//
// Start running proc G at time 200 for 3 clocks
// Start running proc H at time 200 for 5 clocks
// Start running proc I at time 200 for 2 clocks
// — End of proc I at time 220 —
// — End of proc G at time 230 —
// “disable fork” at time 230
//
// Idle at time 230 for 9 clocks
//
// Start running proc J at time 320 for 3 clocks
// Start running proc K at time 320 for 5 clocks
// Start running proc L at time 320 for 2 clocks
// — End of proc L at time 340 —
// “join_any” at time 340
//
// Idle at time 340 for 2 clocks
//
// — End of proc J at time 350 —
// — End of proc K at time 370 —
// “wait fork” at time 370
//
// Idle at time 370 for 1 clocks
//
// ** Note: $finish : Time: 380 ns