Difficulty: Medium · Puzzle 6 of 6 · Topic: Fork Join Puzzles
Which prints survive this nested-fork pattern, and why?
`timescale 1ns/1ns
module p6;
initial begin
fork
begin
fork
begin #2 $display("%0t A", $time); end
begin #4 $display("%0t B", $time); end
join_any
disable fork;
$display("%0t C", $time);
end
begin
#3 $display("%0t D", $time);
end
join
$display("%0t E", $time);
end
endmodule`disable fork` applies to child processes of the process that calls it (its innermost active fork context).
1) In inner fork, A prints at t=2; `join_any` unblocks immediately.
2) `disable fork` then kills inner sibling B before t=4.
3) C prints at t=2 after cleanup.
4) Outer sibling D is in a different fork context, so it still prints at t=3.
5) Outer join completes at t=3 and E prints at t=3.Answer: A@2, C@2, D@3, E@3; B does not print
Checked by running the code in Icarus Verilog 13 and Verilator 5; the printed output supports the answer above. The inner disable fork kills B but not D. (Icarus, 4-state) The inner disable fork kills B but not D. (Verilator, 2-state)
`disable fork` only affects the children of the process that calls it, so the inner call kills B but D, which belongs to the outer fork, still prints at t=3.
How would you explicitly terminate both outer branches from inside the first branch? Model answer: give the outer fork a label (`fork : outer`) and call `disable outer;` from the first branch; it terminates the whole labelled block, so D never prints and E follows immediately (note: Verilator 5.048 leaves the inner B thread running, Icarus kills it, so test on your simulator).
I would ask whose children each disable fork kills, because it only kills children of the process that calls it. The inner join any resumes when A prints at 2, and the disable fork kills inner sibling B, then C prints at 2. The outer sibling D belongs to another fork, so it still prints at 3, and E follows at 3. The trap is thinking the disable fork stops everything nearby. I would check which fork each thread belongs to, and use a named disable if I need to kill the outer branches.