如何克服 System Verilog 中的函数重载

How to overcome function overloading in System Verilog

program automatic test;  
class A;  
    task get();  
        $display("A");  
    endtask  
endclass  
  
class B extends A;  
      
    task get(int a,int b);  
        $display("%d %d",a,b);  
    endtask  
endclass  
  
initial  
begin  
    B b = new();  
    b.get();  // Throws Error Because of Hiding
end  
  
endprogram: test 

在 C++ 中,我们可以通过使用 using A::get 来克服这个问题,但在 SV 中如何避免函数隐藏并访问父 class 函数 get()?

由于 Verilog 中的弱类型系统,函数重载很难在 SystemVerilog 中实现。如果您有一个具有 32 位输入的函数并用一个具有 16 位输入的函数重载它,但调用该函数时具有 8 位值,会发生什么情况。你选了哪一个?

但这里确实存在两个截然不同的问题。 C++ 中的函数重载不一定涉及继承——您可以在同一个 class 中声明两个 get 函数。如果您的函数具有不同的原型并且调用者需要知道哪些是可用的,您不妨为它们指定唯一的名称。

module automatic test;  
class A;  
    task get();  
        $display("A");  
    endtask  
endclass  
  
class B extends A;      
    task get2(int a,int b);  
        $display("%d %d",a,b);  
    endtask  
endclass  
  
initial  
begin  
    B b=new();  
    b.get();
    b.get2(1,2);
end  
endmodule: test

您还可以利用 SystemVerilog 的默认参数功能为您的参数分配 不可用

module automatic test;  
class A;  
    task get();  
        $display("A");  
    endtask  
endclass  
  
class B extends A;      
    task get(int a=-1,int b=-1);
        if (a<0) super.get();
        else $display("%d %d",a,b);  
    endtask  
endclass  
  
initial  
begin  
    B b=new();  
    b.get(); // indirectly calls A::get()
end  
endmodule: test

解决有关访问基 class 的非虚拟成员的其他问题,您需要将句柄向上转换为 A class 变量。

initial  
begin  
    B b=new();
    A a;
    a = b; 
    a.get();
end  

您不能使用扩展的 class 对象直接访问基础 class get 方法。但是您可以在扩展 class get 方法中访问它,如下所示。还解决了几个问题。

program automatic test;  
class A;  
    virtual task get();  
        $display("A");  
    endtask  
endclass  
  
class B extends A;  
      
    task get();  // Removed the arguments as during this method call in initial block, you were not passing anything. If you need arguments then pass some value during task call
      super.get(); // Using super you can access the base class get method
      A::get();  // Or you can also access it using class name and scope operator. This way is helpful when there is a deep down hierarchy 
      $display("B");  
    endtask  
endclass  
  
initial  
begin  
    B b=new(); // You didn't create the object
    b.get();
end  
  
endprogram: test