Reputation: 84
I have a parent class and a lot of child classes. And I want to instantiate all the child classes and cast them into a parent object array/queue so I can do something useful things using the parent array/queue.
The code is below:
class parent;
endclass
class child1 extends parent;
endclass
class child2 extends parent;
endclass
program top;
child1 c1;
child2 c2;
parent p, p_arr[$];
initial
begin
c1 = new;
assert ($cast(p,c1)) else $fatal;
p_arr.push_back(p);
c2 = new;
assert ($cast(p,c2)) else $fatal;
p_arr.push_back(p);
// Doing useful things with p_arr
// .......
end
endprogram
I wonder if there is a way make this more tidy. So I change my code into this:
begin
assert ($cast(p,child1::new())) else $fatal; <---- QuestaSim compiler complained about "child1::new"
p_arr.push_back(p);
assert ($cast(p,child2.new())) else $fatal; <---- QuestaSim compiler complained about "child2.new"
p_arr.push_back(p);
end
But the compiler complains about directly using static constructor "child1::new()" or "child1.new()". Does SystemVerilog support such a feature? (If it is a simulator incapability, can you state what simulator support it?) If not, is there is tidy way to do it? For example using macro?
The problem with macro is that I have to use two macros to do it. One macro declares the instance at the top of the function/program first:
child1 c1;
And then another macro initializes the instance and put itinto array in the body of the function/program:
c1 = new;
assert ($cast(p,c1)) else $fatal;
p_arr.push_back(p);
Is there a way to use one macro to do this instead of two macro?
---------------------EDIT------------------------
Thank @Tudor and @dave_59 for the answer, the example worked for p = child1::new(). I realized my parent class is a parameterized class. And syntax work for them as well.
p = child1_class #(.WIDTH(WIDTH))::new();
p_arr.push_back(p);
p = child2_class #(.WIDTH(WIDTH))::new();
p_arr.push_back(p);
Unfortunately for a new constructor, I have to explicitly specified what object the new is assigned to. And the following syntax does not work.
p_arr.push_back(child1::new());
Upvotes: 2
Views: 326
Reputation: 42623
The SystemVerilog BNF requires that new() appear on the RHS of an assignment. But there's no need to use $cast when making an assignment from an extended class to a base class variable. So you can do:
module top;
parent p, p_arr[$];
initial
begin
p = child1::new();
p_arr.push_back(p);
p = child2::new();
p_arr.push_back(p);
// Doing useful things with p_arr
// .......
end
endmodule
You can also do things like
p_arr = '{3{null}};
p_arr[0] = child1::new();
p_arr[1] = child2::new();
p_arr[2] = child1::new();
Upvotes: 2
Reputation: 7573
The syntax described in the LRM for scoped constructor calls is:
child1::new();
If you're lucky, your simulator supports it.
What you don't need in your code, though, are the $cast(...)
statements. Since you're down-casting (going from sub-class to parent class), the following would also be legal:
p = child1::new();
If you're even luckier, you can even shorten it to:
p_arr.push_back(child1::new());
but again, this depends on what your simulator supports.
Upvotes: 2