In reply to dave_59:
Dave,
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?
In reply to dave_59:
Dave,
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?
In reply to dave_59:
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.
Thanks,
Ashish
In reply to AshishP:
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.
In reply to dave_59:
Hi Dave,
Then is it a bug in VCS since it behaves the way it’s mentioned in comment #6 which doesn’t match w/ what you mentioned in comment #7?
Thanks,
Ashish
In reply to AshishP:
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.
In reply to AshishP:
Hi Dave,
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
Questasim 10.3b gives below output:
In reply to Sailaja:
No.
The disable fork statements kills the children of the currently running thread. (i.e the thread executing the disable fork statement).
Your ff2 thread is a single forever statement. You can use the break statement instead to get out of the forever loop.
In reply to Sailaja:
Hi Dave,
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 //}
Thanks
In reply to sandy1664:
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.
...
In reply to dave_59:
Everytime i reset the timer , the timer_flag becomes 0 and after we start the timer again by making timer_falg to 1 after 1ps delay.
In reply to Sumit Jain:
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.
Thanks
Arpit
In reply to dave_59:
Hi Dave,
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
module test;
initial begin
main();
end
task main();
fork
#5 $display($time,,"THREAD 1");
#25 $display($time,,"THREAD 2");
join_any
dev_state();
$display($time,,"After task call");
#100 $finish;
endtask
task dev_state();
fork
#5 $display($time,,"THREAD 3");
#10 $display($time,,"THREAD 4");
join_any
disable fork;
endtask
endmodule
In reply to kvssrohit:
Correct, sort of. It will kill all remaining child threads of the initial block. A task call is not a thread.
Please use code tags to make your code easier to read. I have added them for you.
Hi Dave,
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?
class alpha;
task a1();
fork
#(20) $display("run1");
#(30) $display("run2");
join_none
endtask: a1
task a2();
disable fork;
endtask: a2
endclass: alpha
module top;
alpha abc;
initial begin
abc = new();
abc.a1();
#(10) abc.a2();
end
endmodule
In reply to desaivs1994:
As I said above, Calling a task or function does not create a new thread; only a fork can do that. So whether a disable is “inside” a task has no relevance - it’s the thread that matters.
Hi Dave,
Can you please explain the below code.
module top_fork();
task task1();
forever begin
#5;
$display("in task1");
end
endtask
task task2();
forever begin
#6;
$display("in task2");
end
endtask
task task3();
fork : task3_0
forever begin
#7;
// disable fork task3_0 ;
$display("disable fork before");
// disable task3_0 ;
disable fork ;
$display("disable fork after");
$display("in task3");
end
join
endtask
task task4();
forever begin
#8;
$display("in task4");
end
endtask
initial begin
fork : name
task1();
task2();
task3();
task4();
join
end
initial begin
#60;
$finish;
end
endmodule
As per my understanding after disabling the fork in task3 it should not print the messages from task3. But it is not the scenario what i was getting in simulation.
Thanks & Regards,
Shriramvaraprasad B.
In reply to SHRI12326:
I’ll repeat this for the third time here.
The disable fork statements kills the children of the currently running thread. (i.e the thread executing the disable fork statement).
The thread where you execute the disable fork has no children. The fork/join you put inside task3 creates a child thread, but the disable is executed from the child. You can use a break statement to get out of your forever loop instead of the disable. Then there is no need for the fork inside task3.