When all initial procedures within a program have reached their end, that program shall immediately terminate all descendent threads of initial procedures within that program.
I recently encountered a similar issue at work, so I came across this post from eight years ago. The difference is that with the same code as yours, vcs compiles and outputs the expected results, but when I put fork join_none in the function and call the function in initial, I get the same simulation results as yours, while in module it outputs normally. You know why?
program test;
task run;
#1;
$display("task thread..");
endtask
//task show;
function void show;
fork
run;
join_none
$display("show thread");
endfunction
//endtask
initial begin
show;
fork
$display("something");
join_none
$display("main");
//#2;
end
endprogram
out:
*…/simv up to date
Chronologic VCS simulator copyright 1991-2018
Contains Synopsys proprietary information.
Compiler version O-2018.09-SP2_Full64; Runtime version O-2018.09-SP2_Full64; Aug 21 22:05 2025
show thread
main
something
$finish at simulation time 0
*
Quite the expected - as @dave_59 explained earlier here - in your example the program end is reached before the simulator had a chance to execute your #1.
Good guidelines:
Avoid program block
Ensure you have a wait at the end of initial-block (inside program if you can’t stick to #1 above)