Upward references in bound interfaces

To avoid a somewhat ugly use of e.g. uvm_hdl_force that is currently in the codebase, I tried being “clever” and using a hierarchical upwards reference from a bound interface.

In the application, the design contains interfaces of some module, M. Let’s suppose it looks like this:

module M (input clk_i);
  logic my_state;
endmodule

I can define an interface like the following to be bound into the module. The idea is that M.my_state walks up the hierarchy to the first instance of M.

interface my_if (input clk_i);
  function flip();
    M.my_state = ~M.my_state;
  endfunction
endinterface

I can then bind in the interface with something like this:

bind M my_if u_my_if(.*);

And everything seems to work: I get an instance of the interface in each of the instances of the module and can interact with each happily! Yippee!

In the actual application, M is the name of some primitive block that is used in some, but not all, of the duts in my testbenches. When I tried the trick above with a dut/testbench that doesn’t happen to use M, the elaboration stage fails. With Xcelium, I get errors about the broken hierarchical up-reference. My suspicion is that this is caused by trying to make sense of an implicit instance of my_if at the top of the hierarchy (where the up-reference obviously won’t work).

It occurred to me to try a hack with parameters:

interface my_if #(bit bound = 0) (input clk_i);
  if (bound) begin
    function flip();
      M.my_state = ~M.my_state;
    endfunction
  end
endinterface

and then binding with

bind M my_if #(.bound(1)) u_my_if(.*);

My idea was that the conditional generate construct that wasn’t enabled wouldn’t be elaborated.

Unfortunately, I still get the same elaboration error (*E,CUVUNF): apparently, I’m not “turning elaboration off” as much as I’d hoped.

This leaves me with two questions:

  1. How could I implement something like this nicely, where an interface gets bound into every occurrence (zero or more) of some module and then interacts with that module’s internals?
  2. Why didn’t my hacks above work? :slight_smile: