Uvm monitor Access interface created by generate statement - Illegal operand for constant expression

I am running into a “Illegal operand for constant expression” when access an array of interface that was created by generate statement in testbench
Here is my code -
On the verilog side, I have

interface sub_interface;
endinterface

interface main_interface
  genvar i;
    generate
     for (i =0;i< SUB_NUM;i++) begin :sub_vif
        sub_interface sub_vif_h ();
     end
    endgenerate 
endinterface

I then instantiate the main_interface and pass it to the UVM monitor by config_db set/get pair.

On the UVM side in the monitor, I was able to retrieve the main_interface object. However, I am not able to access the sub_interface objects by an index id. For example

class my_monitor extends uvm_collector;
  virtual main_interface my_main_vif_h;
  virtual  sub_interface my_sub_vif_h;
  
  function foo(int index);
     my_sub_vif_h = my_main_vif_h.sub_vif[index].sub_vif_h;
  endfunction
endclass

I got “Illegal operand for constant expression” error on the foo() during compile time. I can however do this
my_sub_vif_h = my_main_vif_h.sub_vif[0].sub_vif_h;
So it means my hierarchical path is correct.

So why is the compile error in the foo()? What is a solution to get the sub_interface instance by index?

Thanks in advance

In reply to Michaelotus:

You cannot select an array of instances or a generated loop of instances with a variable. Arrays of scopes are not the same as arrays of variables.

You can create an array of virtual interface variables

interface main_interface;
     virtual sub_interface sub_vif_h[SUB_NUM];
     for (genvar i =0;i< SUB_NUM;i++) begin :sub_vif
        sub_interface sub ();
        initial sub_vif_h[i] = sub;
     end
endinterface

“index” has to be a compile time constant for this to work
my_sub_vif_h = my_main_vif_h.sub_vif[index].sub_vif_h;

If you can make index a genvar variable it would work as
genvars are resolved at compile time.

Or as Dave proposed create an array of virtual interface
handles and now you can make index a variable that can be
assigned at runtime.

Hope this helps.

Logie Ramachandran
Verikwest Systems Inc.

In reply to dave_59:

In reply to Michaelotus:
You cannot select an array of instances or a generated loop of instances with a variable. Arrays of scopes are not the same as arrays of variables.
You can create an array of virtual interface variables

interface main_interface;
virtual sub_interface sub_vif_h[SUB_NUM];
for (genvar i =0;i< SUB_NUM;i++) begin :sub_vif
sub_interface sub ();
initial sub_vif_h[i] = sub;
end
endinterface

Thank you Dave. I gave the suggestion a try. I got this error

Virtual interface declaration is not allowed here [SystemVerilog]
at the virtual declaration line. I am using xcelium. Is this a limit of Cadence or LRM?

In reply to Michaelotus:

In reply to dave_59:
Thank you Dave. I gave the suggestion a try. I got this error
Virtual interface declaration is not allowed here [SystemVerilog]
at the virtual declaration line. I am using xcelium. Is this a limit of Cadence or LRM?

OK. I figured out.

  1. The module interface is static in nature. It does not allow the virtual dynamic concept.
  2. However, interface can have structured data member which that has virtual dynamic concept.

So the solution is to create a struct contains virtual interface handles and cheats the interface.

Bellow code will work

interface main_interface;
     sub_if_wrap my_sub_if_wrap; 
     for (genvar i =0;i< SUB_NUM;i++) begin :sub_vif
        sub_interface sub ();
        initial my_sub_if_wrap.sub_vif_h[i] = sub;
     end
endinterface

[/quote]
Above creates sub interface instances and store their handles in the virtual interface array in the warp structure

On the class side, i.e. in package

typedef struct {
     virtual sub_interface sub_vif_h[SUB_NUM];
} sub_if_wrap

[/quote]

This typedef MUST be defined in the package, otherwise will get an elaboration error “Disallowed virtual interface hierarchical reference object type” in the function foo()

Then in the monitor code, retrieve the sub interface

class my_monitor extends uvm_collector;
  virtual main_interface my_main_vif_h;
  virtual  sub_interface my_sub_vif_h;
 
  function foo(int index);
     my_sub_vif_h = my_main_vif_h.my_sub_if_wrap.sub_vif_h[i];
  endfunction
endclass

[/quote]

Thanks Dave & Logie that provided the key hint.