class A;
bit b = 1'b0;
bit c = 1'b0;
task t1;
$display("At time %0d - Start with task t1 (b=%b)",$time,b);
fork: fk0
begin
c = 1'b0;
#2;
c = 1'b1;
end
begin
#1;
if (b) #5;
disable fk0;
end
join
$display("At time %0d - Done with task t1 (b=%b,c=%b)",$time,b,c);
endtask // t1
endclass // A
module test_disable_fork;
initial begin
A c0,c1;
c0 = new;
c1 = new;
c1.b = 1'b1;
fork
c0.t1;
c1.t1;
join
$display("At time %0d - Done with both c0 and c1 t1 tasks",$time);
$finish;
end
endmodule // test_disable_fork
This outputs the following when run using Cadence irun:
At time 0 - Start with task t1 (b=0)
At time 0 - Start with task t1 (b=1)
At time 1 - Done with task t1 (b=1,c=0)
At time 1 - Done with task t1 (b=0,c=0)
At time 1 - Done with both c0 and c1 t1 tasks
Simulation complete via $finish(1) at time 1 NS + 0
.
Is this the expected behavior, or is this a bug in the simulator?
What is the suggested workaround to keep the fork names unique across objects?
I just discovered a workaround using the special built-in process class. Process objects declared within the t1 task are unique across objects of the A class, so killing a process in one object does not go and kill processes in other objects of class A.
I still would like to know if the original code is expected to behave this way or if it is a bug in the simulator.
Thanks, dwikle, I agree with you that this behavior is not expected and not very useful in my opinion, even if it is according to the SV LRM spec. My conclusion is NEVER DISABLE A BLOCK INSIDE A CLASS, instead use the process class for fine-grained process control inside classes. I’ve been getting away with violating this rule simply because, up until recently, the same tasks in different objects of the same class were not running concurrently.
Ed, that is a good rule to follow. Unfortunately there is a lot of stuff in the SystemVerilog LRM left in for backward compatibility with Verilog and it’s difficult to know what is only there for legacy code.