How to get uvm_config_db to accept a virtual interface that contains an interface in the port?

I am trying to “set” an interface instance in the uvm_config_db, but get an error because my interface uses an interface in its port. This practice is used when separating HDL/HVL in uvm monitors/drivers for acceleration. I think this could also be used generically when ever one interface uses another interface. This seems referenced in several places on the web and in Mentor discussions, but i cant get it to work. I have created a over simplified test case below. How can i create an interface that uses another interface and pass that to the config_db?

thanks

The elab error i get:
**
uvm_config_db#(virtual bfm_if)::set( null, “”, “BFM_IF”, BFM );
|
ncelab: *E,CUVIIP (./xx_bfm.sv,66|32): This virtual interface declaration is illegal, because interface ‘bfm_if’ has interface port ‘ABC’.


irun: *E,ELBERR: Error during elaboration (status 1), exiting.
**

Below is a simplified example:


...
  1 `include "uvm_macros.svh"
  2 import uvm_pkg::*;
  3 
  4 interface abc_if( input bit clk, rstn );
  5   logic a,b,c;
  6 
  7   modport MON (
  8     input clk, rstn,
  9     input a,
 10     input b,
 11     input c
 12   );
 13 
 14 endinterface
 15 
 16 interface bfm_if( abc_if ABC );  // NOTE: interface in the port list!
 17 
 18 
 19   task run();
 20     @( ABC.clk );
 21     forever begin
 22       @(posedge ABC.clk );
 23       $display("%m: time %0t", $realtime() );
 24     end
 25   endtask
 26 endinterface
 27 
 28 class test1 extends uvm_test;
 29 
 30     virtual interface abc_if    BFM;
 31 
 32     `uvm_component_utils( test1 )
 33 
 34     function new( string name="test1", uvm_component parent=null );
 35         super.new( name, parent );
 36     endfunction
 37 
 38     task run_phase( uvm_phase phase );
 39         phase.raise_objection(this);
 40         `uvm_info( get_full_name(), "Test Start...", UVM_NONE )
 41         #1000ns;
 42         `uvm_info( get_full_name(), "Test End...", UVM_NONE )
 43         phase.drop_objection(this);
 44     endtask
 45 endclass
 46 
 47 
 48 module top;
 49   import uvm_pkg::*;
 50   `include "uvm_macros.svh"
 51 
 52   reg clk, rstn;
 53 
 54   always clk = #10 ~clk;
 55   initial begin
 56     clk=0; rstn=0;
 57     #(100);
 58     rstn = 1;
 59   end
 60 
 61   abc_if ABC( clk, rstn );
 62   bfm_if BFM( ABC.MON );
 63 
 64   initial begin
 65     uvm_config_db#(virtual abc_if)::set( null, "", "ABC_IF", ABC );
 66     uvm_config_db#(virtual bfm_if)::set( null, "", "BFM_IF", BFM );  // <-- this FAILS
 67 
 68 
 69     run_test();     // expand UVM test and start phasing...
 70   end
 71 endmodule


I can overcome the problem by creating the abc_if instance INSIDE the bfm_if, but i dont want to do that because i’ll be binding my abc_if. If i DO do it, then my uvm_config_db’s become as shown below. However, my question is HOW i can get it to work without doing this?

 
 16 interface bfm_if( input bit clk, rstn );  // the fix. Dont pass interface
 17   abc_if ABC( clk,rstn);  // the fix. Instance interface inside

 ...
 26 endinterface
...
 48 module top;
 ...
 61 //abc_if ABC( clk, rstn );      // comment this out if using the fix
 62   bfm_if BFM( clk, rstn );      // the fix
 63 
 64   initial begin
 65   //uvm_config_db#(virtual abc_if)::set( null, "", "ABC_IF", ABC );
 66     uvm_config_db#(virtual abc_if)::set( null, "", "ABC_IF", BFM.ABC );   // the fix; note hierarchy into BFM
 67     uvm_config_db#(virtual bfm_if)::set( null, "", "BFM_IF", BFM );

Another way to avoid the issue would be for me to just replace all occurrences of abc_if with the bfm_if (i would need to duplicate the logic signals). But i dont want to do that either. In this simple case it looks trivial, but in a real case it is not (plus, i dont like the maintenance of dup code…)

https://verificationacademy.com/cookbook/emulation/example

According to this, it is LRM non compliant to pass an interface in port list of another interface though it shouldnt be the case.