You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

虚拟函数继承未达预期:调用子类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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 21:45:31