2016-05-20 46 views
2

我有一个父类和很多子类。我想实例化所有子类,并将它们转换为父对象数组/队列,以便我可以使用父数组/队列做一些有用的事情。如何模仿SystemVerilog中的静态构造函数?

的代码如下:

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 

我不知道是否有一种方法使这更整洁。 所以,我改变我的代码到这个:

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  

但是,编译器会抱怨使用直接静态构造函数“child1 ::新()”或​​“child1.new()”。 SystemVerilog是否支持这种功能? (如果它是一个模拟器无法使用,你能说明它支持什么模拟器吗?)如果没有,是否有整洁的方法来做到这一点?例如使用宏?

宏的问题是我必须使用两个宏来完成它。 一个宏声明的实例中的功能/程序的顶部第一:

child1 c1; 

然后另一个宏初始化实例,并把itinto阵列中的功能/程序的主体:

c1 = new; 
assert ($cast(p,c1)) else $fatal; 
p_arr.push_back(p); 

有没有办法使用一个宏而不是两个宏来做到这一点?

---------------------编辑------------------------

感谢@Tudor和@ dave_59作为答案,该示例适用于p = child1 :: new()。我意识到我的父类是一个参数化类。语法也适用于他们。

p = child1_class #(.WIDTH(WIDTH))::new(); 
p_arr.push_back(p); 
p = child2_class #(.WIDTH(WIDTH))::new(); 
p_arr.push_back(p); 

不幸的是,对于新的构造函数,我不得不明确指定新的对象。以下语法不起作用。

p_arr.push_back(child1::new()); 

回答

2

在LRM的范围的构造函数调用中描述的语法是:

child1::new(); 

如果你幸运的话,你的模拟器支持它。

但是,代码中不需要的是$cast(...)语句。既然你下铸造(从子类将父类),以下也将是合法的:

p = child1::new(); 

如果你更幸运,你甚至可以缩短到:

p_arr.push_back(child1::new()); 

但是,这又取决于你的模拟器支持什么。

+0

什么模拟器支持呢?我在QuestaSim上运行它,它也抱怨child1 :: new()。 VCS或Icarus是否支持它? – TyL

+0

在此处查看我的答案https://verificationacademy.com/forums/systemverilog/how-mimic-static-constructor-systemverilog#reply-54421 –

2

SystemVerilog BNF要求new()出现在任务的RHS上。但是当从扩展类到基类变量进行赋值时,不需要使用$ cast。所以,你可以这样做:

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 

你也可以做这样的事情

 p_arr = '{3{null}}; 
    p_arr[0] = child1::new(); 
    p_arr[1] = child2::new(); 
    p_arr[2] = child1::new(); 
+0

谢谢!它为我工作。 – TyL