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…)