Hello ,
I am unable to get the exact functionality of disable fork.
Example ;
task t1();
fork
begin : a1
#1;
$display("a1");
end
begin: a2
#2;
$display("a2");
end
join_none
fork
begin : a3
#5;
$display("a3");
end
begin : a4
#6;
$display("a4");
end
join_any
disable fork
fork
begin : a5
#5;
$display("a5");
end
begin : a6
#6;
$display("a6");
end
join_any
endtask
Now will this disable fork will disable a1 and a2 also??? Will there be any output in this case??? And, What will happen to a5 and a6???
Hi Anamika,
disable fork statement terminates all active child processes, grandchild processes etc. where it is called.
No, disable fork shall terminate only a3 process because when it is called only a3 process is active.
Both a5 and a6 process shall be continued because disable fork has been executed just before.
It is best to start from the root thread, which is started by an initial or always block.
module top;
initial begin : i1
fork : f1
#10 $display("f1")
join_none
t1();
end
endmodule
The disable fork statements kills the children of the currently running thread. (i.e the thread executing the disable fork statement).
In this example, the parent thread is enclosed by the scope i1. It starts a child thread f1, then calls task t1. Inside task t1, the first fork starts threads a1 and a2, then the second fork starts a3 and a3. Since the second fork has join_any, it waits for one of the threads to complete before executing the disable fork statement.
The disable fork will not execute until thread a3 completes at time 5, and only threads f1 and a4 are still active and will be killed. Had you used join_none instead of join_any, or used longer delays then the disable fork statement would have also killed threads a1, a2 and a3.
The threads a4 and a5 are forked after the disable fork, so it has no effect on those threads.
What if threads a1 and a2 had longer delays then a3 and join_any instead of join_none, does a1 and a2 also comes under list of active threads(along with f1 and a4) and will get killed?
Hi Dave,
In the example u mentioned above, thread f1 won’t get killed.
Here is what IEEE 1800-2009 std, clause “9.6.3 Disable fork statement”, pg 174 says:
“The disable fork statement terminates all descendants of the calling process as well as
================
the descendants of the process’s descendants.”
Here is my understanding:
Since calling process i.e. process which called “disable fork” is “t1”, all threads inside t1 and their descendants will get killed. Since thread f1 is not a descendant thread of t1 it should not get killed. I confirmed the same by simulating it w/ VCS too.
Calling a task or function does not create a new process; only a fork can do that. In this case, t1 is a task activation, not new process. So process f1 and a1-a6 are all descendents of the same parent process.
Since I work for Mentor, I can comment on Questa’s behavior, and as a member of the IEEE SystemVerilog 1800 committee, I can comment on my interpretation of the LRM, and whether it is correctly worded. In this case, Questa behavior matches my interpretation of the standard, and VCS does not.
On similar lines, can you explain what should be the ideal behavior for the below code (I was thinking disable fork should disable ff2, please clarify):
class a_bus_monitor;
bit my_event1;
int iter;
task my_monitor();
fork : ft1
forever begin:ff1
#5ns;
$display("Passed 5 ns now");
iter++;
if (iter == 20) begin
$display("Breaking because iter is 20");
break;
end
end
forever begin:ff2
@(my_event1);
$display("At time %0t found an event on my_event1 (= %0d)",$time,my_event1);
if (my_event1 == 0) begin
$display("Disabling fork now");
disable fork; // ???Should not this disable fork disable ff2???
end
end
join
endtask:my_monitor;
endclass
module top;
a_bus_monitor abm1;
initial begin: i1
abm1 = new();
fork:fm1
begin:fmf1
abm1.my_monitor();
end
begin:fmf2
#6ns;
abm1.my_event1 = 1;
#10ns;
abm1.my_event1 = 0;
#20ns;
abm1.my_event1 = 1;
#6ns;
abm1.my_event1 = 0;
end
join
$display("main fork has been joined");
end
endmodule
Here in the below code if i get timer_flag as ‘0’ even before the completion of thread named label, I am trying to disable that process. As per my analysis it should disable that particular iteration and again it has to wait for timer_flag to be 1 to continue, and it has to wait for time run_duration before making expired bit 1 from the last valid time_flag that it receives .But this logic is calculating run_duration from the first valid timer_flag.(Consider if re-setting timer_flag to 0 for two times at 0ns, 5ns and 10ns and run_duration value is 50ns,then the expired bit should get assert at 60ns but its happening at 50ns itself,which is not my requirement.) How does it happens even after disabling label thread?
Could you please provide some clarity on this.
Code::
fork
forever
begin :label //{
wait(timer_flag==1);
#(run_duration);
expired=1;
timer_flag=0;
end //}
forever
begin //{
@(timer_flag);
if(timer_flag==0)
begin
ovm_report_info(get_type_name,$psprintf("Disabling label thread at time %.6t", $realtime));
disable label;
end
end //}
join //}
You need to show how you reset the timer flag. If the timer_flag was set to 0 and back to 1 in zero delay, there is no guarantee that the second forever loop would see timer_flag==0 and disable the label
...
timer_flag = 0;
timer_flag <= 1; // this make sure it is 0 for one delta cycle.
...
Hi Sumit ,
please correct me if i am wrong but I believe this code will give output as :-
a1
a2
a3
a5
I tried with Vcs simulator , above is the output i got , I am not seeing any a6 there.
For the below example , as main task is calling the dev_state task which contains disable_fork .
Then as per LRM Std 1800-2012 , disable fork will kill all the remaining threads of main task also right .
So the output should be
5 THREAD 1
10 THREAD 3
10 After task call
Could you please let me know whether my understanding is correct
I wanted to know if a disable fork inside a task can kill threads launched by another task using fork…join_none. For example: In the following code, if task a2() is called 10 units after calling task a1(), will the threads inside a1() be killed?