Hi,
If I have two forever blocks in fork block.How does it behaves.
Example::
fork
begin
forever
begin
//logic
end
end
begin
forever
begin
//logic
end
end
join
Please someone clarify me abt this.
Thanks.
Hi,
If I have two forever blocks in fork block.How does it behaves.
Example::
fork
begin
forever
begin
//logic
end
end
begin
forever
begin
//logic
end
end
join
Please someone clarify me abt this.
Thanks.
Hi Sandy1664,
Please use code tags when posting code in the future.
A fork/join splits the current thread into multiple parallel child threads, one for each statement in the block. The parent thread suspends until all child threads complete or terminate. Your fork/join block contains two statements, so there will be two child threads spawned. Each statement happens to be a begin/end block, which will int turn execute each statement inside it sequentially. Your begin/end blocks contains one statement - a forever loop, which repeatedly executes its statement (another begin/end block) over and over indefinitely.
So your fork/join block will suspend the parent thread indefinitely until both forever loops are terminated either by a break or some other process terminating statement.
In reply to dave_59:
Hi Dave,
Thanks for the explanation.Have a look at the code
fork
forever
begin:label_1
wait(flag1==1);
$display(“flag1 asserted”);
#(duration);
flag2 = 1;
end
forever
begin
@(flag1);
if(flag1==0)
disable label_1;
end
join
multiple processes of label_1 will get created at same time or create one after the other after flag2 becomes 1.
Best Regards,
Sandy.
In reply to roopanandakumaran:
https://verificationacademy.com/forums/ovm/please-format-your-code-code-and/code-tags
In reply to dave_59:
Hi Dave,
Thanks for the explanation.Have a look at the code
fork
forever
begin:label_1
wait(flag1==1);
$display("flag1 asserted");
#(duration);
flag2 = 1;
end
forever
begin
@(flag1);
if(flag1==0)
disable label_1;
end
join
multiple processes of label_1 will get created at same time or create one after the other after flag2 becomes 1.
Best Regards,
Sandy.
October 28, 2014 at 9:33 am
sandy1664
sandy1664
In reply to sandy1664:
There are two processes created by the fork/join block - the two forever statements. label_1 is a statement label that is a part of the forever statement; label_1 is not a separate process. The disable statement just terminates the statement with the label_1. Terminating a statement means it jumps to the end of the statement. And since this statement is inside a forever statement, it repeats the statement forever.
You can wrap the two forever statements in begin/end blocks without changing the functionality.
fork
begin : process_1
forever
begin:label_1
wait(flag1==1);
$display("flag1 asserted");
#(duration);
flag2 = 1;
end
end : process_1
begin : process_2
forever
begin
@(flag1);
if(flag1==0)
disable label_1;
end
end : process_2
join
But now the statement label process_1 encompasses an entire process, so disabling that statement will terminate the process.
P.S. You need to be careful using the disable label; statement. Statement labels are static identifiers and if the label is inside a task and there are multiple invocations of the task, disabling the label will disable all invocations of that label inside all tasks. SystemVerilog provides a variety of other mechanisms to terminate process that are more specific to the current process. (disable fork, process::kill)
In reply to dave_59:
Hi Dave,
I am also using the same code type above . I am facing a problem in my problem flag1 == 1 coming two times but print is coming only once. I need display whenever the signal flag1 ==1 .
Regards,
Jyothsna.
In reply to Jyothsna:
Can’t help you without knowing the timing of ‘flag1’ and the value of ‘duration’. Also, a better way of modeling what they wanted is
forever begin
fork
begin
wait(flag1==1);
$display("flag1 asserted");
#(duration);
flag2 = 1;
end
@negedge flag1;
join_any
disable fork;
end
In reply to dave_59:
With the above syntax i tried it could stucked at run_phase itself. so i tried with the below syntax.
task run_phase
begin
fork
begin
test1();
end
begin
test2();
end
join
end
endtask : run_phase
task test1();
begin
forever @(posedge clk);
begin
fork
begin
@(posedge intf.c1);
uvm_info("p1",uvm_low)
end
begin
@(posedge intf.c2);
uvm_info("p2",uvm_low)
end
join_none
end
end
endtask
task test2();
begin
forever @(posedge clk1);
begin
fork
begin
@(posedge intf.c6);
uvm_info("p6",uvm_low)
end
begin
@(posedge intf.c7);
uvm_info("p7",uvm_low)
end
join_none
end
end
endtask
I need to check c1,c2,c6,c7 until case to be done so i kept fork in raise, drop objections.
The clk,clk1 are of high speed. When the c1,c2,c6,c7 are hit first time at the same time stamp p1,p2,p6,p7 prints are coming continuously.
In reply to Jyothsna:
It would help readability to remove all of the unnecessary begin/end keywords. Also, I assume the semicolons after the @(posedge clk) are typos. Otherwise your code would hang and there would be no output. Here is your code with that corrected:
task run_phase;
fork
test1();
test2();
join
endtask : run_phase
task test1();
forever @(posedge clk)
fork
begin
@(posedge intf.c1);
`uvm_info("p1",uvm_low)
end
begin
@(posedge intf.c2);
`uvm_info("p2",uvm_low)
end
join_none
endtask
task test2();
forever @(posedge clk1)
fork
begin
@(posedge intf.c6);
`uvm_info("p6",uvm_low)
end
begin
@(posedge intf.c7);
`uvm_info("p7",uvm_low)
end
join_none
endtask
Now it is easy to see that for each iteration of the forever loop, you are creating a set 4 processes associated with p1, p2, p6 and p7. And every posedge clk you are creating another 4 processes, but the previous process are still active since you used join_none. So by the time you get your c1,c2, c6, or c7 event, there are many processes waiting for that event.
I don’t know what you are trying to achieve, so it is difficult to recommend an alternative.
In reply to dave_59:
Hi Dave,
I have a similar question here. My requirement is like below. We have 4 DMA engines and each of them are separately. They need to do something forever in my test. Here is my code but I am not sure if it’s correct.
task my_thread();
fork
begin
for (int i = 0; i < 4; i++) begin
automatic int ii = i;
fork
forever begin
cycle = $urandom_range(10,1000);
wait_cycle(cycle);
do something here...
end
join_none
end
wait fork;
end
join
endtask : my_thread
[\systemverilog]
and I wonder how can I disable the whole thread if we reach to the end of simulation.
In reply to dave_59:
In reply to sandy1664:
There are two processes created by the fork/join block - the two forever statements. label_1 is a statement label that is a part of the forever statement; label_1 is not a separate process. The disable statement just terminates the statement with the label_1. Terminating a statement means it jumps to the end of the statement. And since this statement is inside a forever statement, it repeats the statement forever.
You can wrap the two forever statements in begin/end blocks without changing the functionality.
fork
begin : process_1
forever
begin:label_1
wait(flag1==1);
$display("flag1 asserted");
#(duration);
flag2 = 1;
end
end : process_1
begin : process_2
forever
begin
@(flag1);
if(flag1==0)
disable label_1;
end
end : process_2
join
But now the statement label process_1 encompasses an entire process, so disabling that statement will terminate the process.
P.S. You need to be careful using the disable label; statement. Statement labels are static identifiers and if the label is inside a task and there are multiple invocations of the task, disabling the label will disable all invocations of that label inside all tasks. SystemVerilog provides a variety of other mechanisms to terminate process that are more specific to the current process. (disable fork, process::kill)
Dave, Thanks for the explanation.
A following up question regarding disable fork vs disable label of fork for all descendants. Will “disable label of fork” disable all descendants processes?
For example;
task threads();
fork : PROC_1
#10;
join : PROC_1
endtask
initial begin
fork : PROC_2
threads();
#5;
join_any
// disable fork; will disable PROC_1.
disable PROC_2 Will the PROC_1 get disabled ? It seems the result is not
same from 3 different simulator.