Hi,
As we know the task inside the class is automatic. But my query is, is it automatic only in the case if it is called by different object handles of same class. For instance:
Class A;
task A_T(int p);
int b;
b = p;
endtask
endclass
module check_task;
A a_1;
A a_2;
initial begin
a_1 = new();
a_2 = new();
a_1.A_T(5);
a_2.A_T(6);
end
endmodule
module check_task_2;
A a_3;
initial begin
fork
a_3.A_T(7);
a_3.A_T(10);
join
end
endmodule
So, in the case of module check_task there will be 2 objects(pointed by a_1 and a_2 respectively) and their tasks are also different thus automatic. But in the case of check_task_2, there is only 1 object(pointed by a_3), so in this case the task A_T is not truly automatic and calling to this task at the same time can cause race conditions.
So my final question is, task in class are automatic only if different objects of the same class exist, and if only one object is available that task will act as static?
Thanks,
Mukul
In reply to mukul1996:
You are confusing the lifetime of a task with the static class qualifier.A task declared as a class method always has an automatic lifetime. The static class qualifier on a class method has nothing to do with its lifetime. It does make a difference on class variables. It determines if the class member is associated with the class type, or an instance of a class object. It is unfortunate that the same keyword gets used for slightly different meanings.
Your module check_task_2 does not create any class objects. There is no race condition because each call to A_T. has a separate instance of the automatic variable p. If instead you had defined the class as
class A;
static int b;
task A_T(int p);
b = p;
endtask
endclass
Now there is only once instance of the static variable b. It gets instanciated as part of the class type and does not depend on class A ever being constructed.
In reply to dave_59:
Sorry, I forgot to construct the a_3 in module check_task_2, Here I have rewritten a code:
class A;
task A_T(int p);
int b;
b = p;
#1;
$display("The value of b is %0d", b);
endtask
endclass
module check_task_2;
A a_3;
initial begin
a_3 = new();
fork
a_3.A_T(7);
a_3.A_T(10);
join
end
endmodule
Here, I am getting the output as suggested by you:
Compiler version S-2021.09; Runtime version S-2021.09; Nov 5 03:14 2022
The value of b is 7
The value of b is 10
V C S S i m u l a t i o n R e p o r t
Time: 1 ns
So the final conclusion is, everytime a task is called through an object handle, it will create a new memory for the task?
In reply to mukul1996:
Yup. The class is dynamic; methods will be automatic by default. If you declared it inside a module, it would have been static and we would have had to make them automatic.
In reply to mukul1996:
Every time you call a task with an automatic lifetime, new memory gets allocated for its arguments.
All tasks declared within classes have an automatic lifetime.
A task declared with a static class qualifier still has an automatic lifetime.
Hi Dave,
Could you please help me understand how pass by reference will work if task inside the class is automatic and allocates new memory each time task is called?
Thank you,
Frank
Consider a pass-by-preference argument as a reference to the actual argument. Whenever a call to the automatic task is made, space is allocated for another reference. Concurrent tasks with automatic lifetimes have independent space for their arguments, regardless of whether they are references or not.