虚拟函数继承未达预期:调用子类print_f为何输出"tr"而非"ch_trans"
SystemVerilog虚拟方法默认参数值问题分析
我编写了下述SystemVerilog代码学习虚拟方法的便捷性,定义了包含虚拟函数的基类trans及其子类ch_trans,子类重写了print_f函数。将子类实例ct1赋值给基类引用t1后,调用t1.print_f(7)时,输出的name为"tr"而非预期的"ch_trans"。经VCS调试确认调用的是子类print_f函数,但结果不符预期,特此咨询原因。
module virtual_method; // this example is referred to the lab1 class inheritance // the purpose is to learn the convenience of the virtual method class trans; bit[31:0] data; int pkt_id; int data_nidles; int pkt_nidles; bit rsp; string name; virtual function trans clone(trans t = null); if (t == null) t = new(); t.data = data; t.pkt_id = pkt_id; t.data_nidles = data_nidles; t.pkt_nidles= pkt_nidles; t.rsp = rsp; return t; endfunction virtual function print_f(int i, name = "tr"); $display("this is trans class i = %d,name = %s",i,name); endfunction endclass class ch_trans extends trans; int ch_id; string name; virtual function trans clone(trans t = null); ch_trans ct; if (t == null) ct = new(); else void'($cast(ct,t)); ct.ch_id = ch_id; return ct; endfunction virtual function print_f(int i, name = "ch_trans"); $display("this is ch_trans class i = %d name =%s ",i,name); endfunction endclass initial begin trans t1,t2; ch_trans ct1,ct2; ct1 = new(); ct1.pkt_id = 2; ct1.ch_id = 3; $display("ct1 = %p",ct1); t1 = ct1; t1.print_f(7); end endmodule
问题原因
这是因为SystemVerilog中,虚拟函数的默认参数值是在编译阶段根据调用时的静态类型确定的,而非运行时的动态类型:
- 调用
t1.print_f(7)时,t1的静态类型是基类trans,编译器会直接使用基类print_f函数中name参数的默认值"tr",并将该值传递给子类的print_f函数。 - 子类
print_f定义的默认值"ch_trans"仅在直接通过子类类型的引用(如ct1.print_f(7))调用时才会生效。
解决方法
可以通过以下两种方式实现预期效果:
- 显式传递参数:调用时手动指定
name参数,例如t1.print_f(7, "ch_trans")。 - 使用类成员变量替代默认参数:在基类和子类的构造函数中分别初始化
name成员变量,修改print_f函数使用类成员而非参数:class trans; // ... 其他成员 ... string name; function new(); name = "tr"; endfunction virtual function print_f(int i); $display("this is trans class i = %d,name = %s",i,this.name); endfunction endclass class ch_trans extends trans; // ... 其他成员 ... function new(); name = "ch_trans"; endfunction virtual function print_f(int i); $display("this is ch_trans class i = %d name =%s ",i,this.name); endfunction endclass
内容的提问来源于stack exchange,提问作者richard
相关产品推荐
相关产品推荐

