System verilog 在没有定义的情况下分层调用任务

System verilog 在没有定义的情况下分层调用任务,system-verilog,uvm,System Verilog,Uvm,我有一个供应商提供的BFM模块在我的层次结构中被实例化;让我们调用路径top.dut.u1.u2.bfm1。BFM的API对于我们的需求来说有点陈旧和混乱。我想编写一个“对象”(类?接口?其他什么?),它将为任务提供一个更简单的调用接口,并可以调用它已“链接”的特定BFM的任务。我搞不懂的是这种“联系” 我有一个定义为模块的简单版本,它使用`定义'来指定BFM的路径,大致如下: `define BFM top.dut.u1.u2.bfm1 module bfm_wrapper; ...

我有一个供应商提供的BFM模块在我的层次结构中被实例化;让我们调用路径
top.dut.u1.u2.bfm1
。BFM的API对于我们的需求来说有点陈旧和混乱。我想编写一个“对象”(类?接口?其他什么?),它将为任务提供一个更简单的调用接口,并可以调用它已“链接”的特定BFM的任务。我搞不懂的是这种“联系”

我有一个定义为模块的简单版本,它使用`定义'来指定BFM的路径,大致如下:

`define BFM top.dut.u1.u2.bfm1
module bfm_wrapper;
  ...
  task read_burst(...);
    ...
    `BFM.read_burst(...);
  endtask;
  ...
endmodule
显然,这不是很容易重用的。我如何用更可移植或抽象到下一个更高级别的东西来取代“BFM”

我是SystemVerilog的新手,我甚至还没有使用UVM,但如果有什么可以帮助我的话,我会尝试一下。感谢您的帮助

[更新]我没有提到的几个限制:

  • 我不能更改或更换供应商提供的BFM。我甚至不希望包装它(例如,在包装器中实例化它)。
  • 出于我不想在这里讨论的原因,BFM需要在DUT内部实例化。改变这一点需要付出比我现在投入更多的努力。
    与抽象接口绑定在一起将帮助您建立到BFM的连接。看看我的两份DVCon文件

    [更新]

    package bfm_pkg;
    interface class bfm_api;
       pure virtual task read_burst(...);
    endclass
    endpackage
    
    module bfm_wrapper;
     import bfm_pkg::*;
      ...
      class wrapper extends bfm_api;
      task read_burst(...);
        `BFM.read_burst(...);
      endtask;
      endclass
      wrapper h = new();
    endmodule
    
    然后从你的课程中,你可以写

    import bfm_pkg;:*;
    class someclass
      bfm_api h;
      task foo;
       ...
       h.read_burst(...);
      endtask
    endclass
    
    现在,您只需要在bfm_包装器中将h的句柄设置为h inside对象foo。如果您使用的是UVM,那么UVM_config_db在这里会有所帮助,否则您需要创建自己的机制来复制句柄h。

    最终答案(最初由@toolic和@Greg建议,后来由@dave_59建议)是使用
    bind
    动态地将包装器放置在“向上名称引用”的供应商BFM所在的位置(特别是,将包装器放在供应商BFM中)。因此,我上面的代码类似于:

    `define BFM top.dut.u1.u2.bfm1
    module top;
      ...
      // Instantiate my wrapper code inside of the vendor's BFM
      bind `BFM bfm_wrapper my_bfm();
    
      // BFM commands go here
      initial begin
        wait (`BFM.reset === 0) @(posedge `BFM.clk);
        `BFM.my_bfm.my_read_burst(...);
        ...
      end
    endmodule
    
    module bfm_wrapper;
      ...
      task my_read_burst(...);
        ...
        read_burst(...);
      endtask;
      ...
    endmodule
    
    如果有任何拼写错误,我深表歉意。我的代码并不是这样的


    请注意,我没有完全摆脱
    定义
    。这可能需要@dave_59论文中更优雅的技术。但我至少把它从代码的可重用部分移走了,现在已经足够好了。

    我不确定在这种情况下如何使用
    绑定
    。你是说绑定
     bfm_包装器
    进入bfm实例化的范围?如果是这样,我应该在上述(伪)代码中用什么来代替
    `bfm
    ?您的包装器可以
    绑定到
    u2
    的模块或路径。在包装器中,有自己的使用“向上名称引用”的读突发任务§23.8.包装器本身可以包含将辅助代码链接到类、虚拟接口、uvm_config_db等的代码。如果我
    将它绑定到
    u2
    ,我仍然不确定如何引用BFM。为了使包装器可重用,我不能假设它被称为
    bfm1
    。事实上,我不想假设只有y一个BFM(例如,如果
    u2
    包含两个独立的总线)。或者你的意思是“绑定到
    bfm1
    ”?我会仔细阅读引用,看看这是否有效。谢谢。我仍在阅读论文,但有一个问题(现在反映在我原来的帖子中):这可以在不更改或重新定位原始BFM的情况下完成吗?如果是这样,我仍然不知道如何从代码的可重用部分引用BFM。如果我过于密集,很抱歉,但是您上面的代码仍然有
    `BFM
    。这是我试图摆脱的部分。如果将
    BFM更改为表示
    bfm1,然后您
    将bfm\u包装绑定到该模块中。假设该模块是
    vendor\u bfm
    。对
    vendor\u bfm.read\u burst()
    的调用现在是向上引用。