fork
begin
fork
begin
#3000;
$display("timeout");
end
begin
sem.get(1);
end
join_any
disable fork;
end
join
Why wrap it in another fork-join pair? This is due to how disable fork works. disable fork disables ALL forks at its level and below. If the above code is inside of a task which is part of a module, then calling disable fork without it being wrapped will disable all forks running in the module. I KNOW! It's ludicrous! Yes, but this is how it works.
What about named forks? Also problematic. This is because when you use a named fork and then call disable
Any other options? I don't know. This seems to be the only way to do the job in SystemVerilog. Perhaps avoiding semaphores and doing everything with wait statements or events, but for now I prefer to use semaphores as they are an item I can 'new', and therefore they allow for much more flexibilty.
Thanks a lot. This writeup was really helpful.
ReplyDeleteI spent last two days debugging what's going wrong. And finally it turns out that the disable fork disables ALL forks at its level and below.
It needs to be wrapped in another fork-join.
Thanks again.
Thanks a ton for this info. Its a SV Gotcha!!!
ReplyDeleteA better alternative is to use the process::kill() method.
ReplyDeleteprogram a();
ReplyDeleteinitial
begin
fork
thread_1();
thread_2();
join_none
#20;
$display("Out Of Fork");
end
task thread_1();
$display("thread_1");
fork
begin
$display("thread_1.1");
end
begin
$display("thread_1.2");
end
join_any
disable fork;
$display("thread_3");
fork
begin
$display("thread_3.1");
end
begin
$display("thread_3.2");
end
join_any
disable fork;
endtask
task thread_2();
$display("thread_2");
fork
begin
$display("thread_2.1");
#5;
$display("thread_2.1.1");
end
begin
$display("thread_2.2");
#5;
$display("thread_2.2.1");
end
join_any
$display("thread_4");
fork
begin
$display("thread_4.1");
#5;
$display("thread_4.1.1");
end
begin
$display("thread_4.2");
#5;
$display("thread_4.2.1");
end
join_any
endtask
endprogram
I tried this code to check , i didn't get that disable fork disabled other fork , other that its fork..
thread_1
ReplyDeletethread_2
thread_1.1
thread_3
thread_2.1
thread_2.2
thread_3.1
thread_2.1.1
thread_4
thread_2.2.1
thread_4.1
thread_4.2
thread_4.1.1
thread_4.2.1
Out Of Fork
$finish at simulation time 20
Hi,
ReplyDeleteI know this is old thread, but I want to answer the above question so new learners can have some help.
tasks, and functions have implicit begin/end statements. Hence its usage is optional in task/function as compared to Verilog.
Now consider the thread_1.
you are spawning two threads thread_1.1 and thread_1.2 using fork..join_any and then disabling fork. entire this code is inside of task i.e., inside the implicit begin/end block of task. when disable fork is called, all threads spawned in that block are killed. Here t_1.2 got killed.