Difficulty: Medium · Puzzle 2 of 6 · Topic: Fork Join Puzzles
Predict every line printed by the two loops and explain why they differ. The LRM does not define the order of lines printed in the same time step, so give the values.
`timescale 1ns/1ns
module p2;
int i;
initial begin
// Loop A
for (i = 0; i < 3; i++) begin
fork
#1 $display("A i=%0d", i);
join_none
end
#2;
// Loop B
for (i = 0; i < 3; i++) begin
automatic int k = i;
fork
#1 $display("B k=%0d", k);
join_none
end
#2;
end
endmoduleCount the storage locations the children can see: one variable for the whole loop, or one variable per iteration. Then ask what that variable holds one time unit later.
1) In loop A every child reads the single module-level variable `i`. The parent finishes the loop at the same time step with `i == 3` and children only run at t=1, so all three print `A i=3`.
2) In loop B, `k` is declared automatic inside the loop body, so every iteration allocates a new `k` initialised from the current `i` before the child forks (LRM 6.21 variable lifetime, 9.3.2 fork/join_none example). The three children print their own copies: 0, 1 and 2.
3) The rule: static storage is shared by everything that names it, automatic storage is created per entry into the block.Answer: Loop A: `A i=3` three times. Loop B: `B k=0`, `B k=1`, `B k=2` (one each, order within the time step not defined)
Checked by running the code in Verilator 5; the printed output supports the answer above. The three A lines all show 3 (shared static i) while the B lines show per-iteration copies. Order of the B lines within one time step is not defined by the LRM, so each value is checked on its own. Order of the B lines within one time step is not defined by the LRM, so each value is checked on its own. Order of the B lines within one time step is not defined by the LRM, so each value is checked on its own.
Loop A prints 3 three times because the children share one static variable that the finished loop left at 3; and the order of the three lines in loop B is not guaranteed by the language even if tools print 0, 1, 2.
What if loop A is written `for (int j = 0; j < 3; j++) fork #1 $display(j); join_none`: is it 0,1,2 or 3,3,3? Model answer: do not rely on it, tools differ (Icarus prints 3 3 3, Verilator 5.048 prints 0 1 2), so always copy the index into an `automatic` variable inside the loop body, as loop B does.
I would ask which variable each child reads, because that is what decides the output. In the first loop the children share one static variable that the loop leaves at 3, so I get three lines saying 3. In the second loop each iteration has its own automatic copy, so I get 0, 1 and 2. The trap is that the order of those three lines in the second loop is not defined by the language, even if a tool prints them in order, and the first style can even differ between tools. I would check that every forked child copies the loop index into an automatic variable.