How to pass a hierarchical path to an interface in the top as a parameter

Hi,

I am trying to generalize an existing interface to reuse its API. This interface have to call task in module using hierarchical path.

The FPGA vendors instantiates a BFM that has to be accessed through hierarchical path from the top, like this:

tb.zynq_sys.layer1.ps7.inst.task_name(0);

Those calls can’t be made from class code inside a package (because hierarchical paths), so I created an interface in the top that is a wrapper to those task calls:

interface cpu_if;
  task task_name(input[31:0] reset_ctrl);
      tb.zynq_sys.layer1.ps7.inst.task_name(reset_ctrl);
  endtask : task_name
endinterface

(Of course, there are multiple task in the interface)

With that interface instantiate in the top, I can now give an handle to the interface to the object code:

cpu_if zcpu();
t = top_string_factory[test_index].createTest(zcpu);

All the test code is reusable and everything is wonderful. Now I want to make the interface reusable. The only problem is the multiple hierarchical path present in the interface. I am trying to put that as a parameter. For example:

interface cpu_if(pointer_to_module bfm);
  task task_name(input[31:0] reset_ctrl);
      bfm.task_name(reset_ctrl);
  endtask : task_name
endinterface

cpu_if zcpu(tb.zynq_sys.layer1.ps7.inst);

t = top_string_factory[test_index].createTest(zcpu);

Of course, a pointer_to_module doesn’t exist. I am trying to use anything cleaner than an define followed by an include file. I looked at bind, but as far as I understand, bind would create an instance of the interface inside the BFM. Replacing all the instance referring to zcpu with the hierarchical path to the bound instance in the BFM would be dirtier than the initial problem.

Is there a clean way of doing this?

Thank you,
jf

In reply to jflarin:

Please see Updated Example Code from DVCon Paper: The Missing Link: The Testbench to DUT Connection | Verification Academy

In reply to dave_59:

Hi Dave,

Although it is not the parameter I was expecting, the link to the source code and your paper was exactly what I needed. Thank you for that.

I recognize the advantage of the abstract class, but I can’t use it in my current case because my classes want to receive a virtual interface (I’d rather not touch that code now).

Still the example showed me how binding can be used to solve my problem. For other people finding this thread, here is what fixed my problem. First I bind the interface inside the BFM:

 bind ps7_vip cpu_if bound_zcpu();

Then, I create a local handle to hold the ‘pointer’ to the bound interface in the dynamic code:

virtual cpu_if zcpu;

Then further down in the dynamic code, I tie my virtual interface variable to the bound interface:

zcpu = tb.zynq_sys.layer1.ps7.inst.bound_zcpu;

Then all my tasks are local and use upward naming, removing the hierarchy and only keeping
the inst to go up one level.

task task_name(input[31:0] reset_ctrl);
      inst.task_name(reset_ctrl);
  endtask : task_name

I now have some tools problems to fix, but so far it works.

Thank you again,

jf