Hi ,
could you provide the clarifications on the below
how to kill the all threads forked off in the belwo fork join_none . I tried with disable fork_name , but it gave compilation error
for (int j=0; j<3; j++) begin
fork :fork_name
automatic int k = j; // Make copy of index
taskname(k); // Print copy
join_none
end
It would help to show the code you tried to use to kill all the threads because it matters where you are trying to kill the threads from in relation to the forked threads.
Most likely you can use the disable fork construct which kills all the child threads of the current thread.
begin
for (int j=0; j<3; j++) begin
fork :fork_name
automatic int k = j; // Make copy of index
task_name(k); // Print copy
join_none
...
disable fork;
end
You have to be careful using this construct because the disable fork construct kills ALL threads that are children of the current thread, not just the threads created by the previous fork statement.
In reply to dave_59:
Hi Dave Thanks for the inputs.
could you provide the clarifications for the following .
I am working on a test where reset needs to be applied second time . then I am facing one issue. issue is mentioned below.
fork
fork
task1
join_none
for loop begin
fork
task2
join_none
for loop end
fork
task3
join_none
begin
@reset event
disable fork //place 1
end
join
@reset event
disable fork //place 2
all the tasks are the tasks that run until the end of simulation. I need to kill them when reset is applied. I tried with disable fork at both places (place 1 and place 2) by waiting until reset occurs . but the tasks are not getting killed. Then I tried with disable fork_name . Then it worked. due to that I tried to kill the fork join_none block in the for loop with disable fork_name. all the code is in main phase of vmm xactor. i guess the xactor is not killing the threads when cleanup task is called.
Could you suggest better Idea.
In reply to srbeeram:
It would really help to show the actual code you tried to use. In your original post, you said the disable fork_name gave you a compilation error, then you said “it worked” in your followup post without showing what you actually did.
The disable forks you show will not work because: In place 1, there are no child threads of the begin/end block thread inside the fork/join. In place 2, each statement block within the fork/join block creates a child thread and the fork/join_none block becomes a child of that thread, but the disable fork statement is outside the fork/join block and all the child threads that it created are done. disable fork only kills the direct children threads, not the grandchildren.
What you probably want is
fork : fork_block
begin: begin_block
fork
task1;
join_none
for (;;) begin : for_loop
fork
task2;
join_none
end : for_loop
fork
task3;
join_none
@reset_event disable fork;
end : begin_block
join : join_block
You will have to explain further about what you meant about reset needing to be applied second time, or is the reset_event here the second time already?
In reply to srbeeram:
Hi Dave,
in the following code also , still tasks are grand children as they are inside the fork blocks which are children of begin end thread. then is disable fork expected to kill the grandchildren threads (tasks) also. in this case why it is expected. could you please provide the clarifications.
fork : fork_block
begin: begin_block
fork
task1;
join_none
for (;;) begin : for_loop
fork
task2;
join_none
end : for_loop
fork
task3;
join_none
@reset_event disable fork;
end : begin_block
join : join_block
In reply to srbeeram:
Calling a task does not create a child thread, but each statement of a fork/join* block creates a child thread. And that statement could be another fork, a begin/end block, calling a task, or a simple assignment. A begin/end block inside a fork is treated as one thread, regardless of how many statements are inside it. Note that
fork
task1;
join_none
is the same as
fork
begin : forked_thread
task1; // could have more statements - all in the same thread
end : forked_thread
join_none
So your earlier example
fork
fork
task1
join_none
for loop begin
fork
task2
join_none
for loop end
fork
task3
join_none
begin
@reset event
disable fork //place 1
end
join
is interpreted as
fork : fork_block
begin: thread1
fork
begin : child11
task1;
end child1
join_none end : thread1
begin : thread2
for begin : foo_loop
fork
begin : child 2N
task2
end : child2N
join_none
end : for_loop
end : thread2
begin : thread3
fork
begin : child3
task3;
end : child3
join_none
end : thread3
begin : thread4
@reset event
disable fork //place 1
end : thread4
join : fork_block
In reply to dave_59:
Hi Dave,
I have one question in similar topic
fork : fork_block
begin: begin_block
fork ---(fork1)
task1;
join_none
for (;;) begin : for_loop
fork----(for_loop fork)
task2;
join_none
end : for_loop
fork---------(third fork)
task3;
join_none
@reset_event disable fork;
end : begin_block
join : join_block
In the above code i assume all the 3 forks i.e (first_fork, for_loop fork and Third fork ) runs sequentially but if design requires to run them in parallel how we can modify the code .
Also is there any way we can kill the grand children threads because you mentioned in earlier post disable fork kills only child threads not grand child threads so if suppose task1 in above example has following code.
task 1();
#Huge_delay operations
endtask
How can we end up such a task when reset is applied .
Thanks
In reply to raku:
The child threads created by the 3 fork/join_none run in parallel regardless of the forks running sequentially or in parallel. A fork/join_none is a 0-time consuming construct and none of the child threads start until the parent thread reaches its end or a blocking statement. Putting the begin_block inside the fork/join serves two purposes: 1) it keeps the disable fork in the parent thread to be able to disable the children. 2) It prevents unwanted disabling of potentially earlier fork/join_none’s that were spawned by the same parent thread.
If you want other ways of disabling threads, see section 9.7 Fine-grain process control of the 1800-2012 LRM. Note that if you are using UVM sequences, it has methods for killing sequences as well.
In reply to dave_59:
Hi Dave , sorry for the confusion. It worked means killing the grand children happened with disable fork_name on one fork join_none block that is not the fork join_none block inside the for loop. so I tried to kill the fork block inside the for loop the same way and it gave compilation error. You are right. and applying the reset second time means I need to apply the reset on rtl when traffic flows . and the traffic flow starts after initial reset. here is the code.
fork begin
fork
Rate();
join_none
fork
Cycle();
join_none
if(!empty)
begin
for (int i_s=Min; i_s<=Max; i_s++) begin
fork
automatic int local_i_s = i_s;
begin
task0(local_i_s);
end
join_none
end
fork: fork_drivePkt
task1;
task2;
join_none :fork_drivePkt
// I tried by placing the code @reset_event disable fork here (reset_event is endThreads in the code) but it didn't work. I will give a trail again.
begin
@endThreads;
disable fork_drivePkt;
end
end
end
join
I want to kill all the tasks inside not empty block . all the code is in main task of vmm
In reply to dave_59:
Hi dave,
I tried with the below code
ork : fork_block
begin: begin_block
fork
task1;
join_none
for (;;) begin : for_loop
fork
task2;
join_none
end : for_loop
fork
task3;
join_none
@reset_event disable fork;
end : begin_block
join : join_block
somehow the simulation is hanged.
I can see issue is driver getting not stopped
here is the difference between passing and failing logs. failing log is not giving those messages and passing log is giving the messages and continuing further. I guess failing log is waiting for them to get stopped. I am not sure how the disable fork_drivepkt is avoiding the issue. Could you please clarify what is the difference between disable fork and disable fork_name. what could be the possible reason for the simulation to work with disable fork_name
messages in passing log are as follows.
Driver(0) Stop requested
Driver(0) 0 out of 1 threads have now stopped
1 out of 1 threads have now stopped
Driver(0) Stopped
the reset_event is triggered during the stop_xactor call of this driver.I wanted to stop the all xactors but the tasks are not getting stopped.I needed to disable them manually with simple solution.it seems reset xactor will kill them all without disabling them manually.
In reply to srbeeram:
srbeeram,
I’m sorry, I don’t have anymore time to help you unless you can provide me with complete small examples of code so people can understand what you are trying to do.