Config_db specialization for virtual interface using modport


LRM  Syntax 25-5  quotes :
data_type ::= 
 virtual [ interface ] interface_identifier [ parameter_value_assignment ] [ . modport_identifier ]

So essentially keyword “interface” and .modport_name are optional.

This would mean within a driver component these 3 would be equivalent


     virtual  interface  intf.master_cb  vif ;  //  (a)
     virtual  intf.master_cb             vif ;  //  (b)
     virtual  interface  intf            vif   //  (c)
    

For any one of the above 3 handle declaration I wanted to know the legal ways to set and get the interface .

(1) What would be the correct way to set the virtual interface for above driver component ?


       //  Within  top_tb ::

        intf  intf_instance ( clk , rst ) ;
      
      initial  //  Keyword  "interface"  used  as  specialization  along  with  interface_type.modport 
        uvm_config_db #( virtual interface intf.master_cb ) :: set ( null , "uvm_test_top.env_h.agent_h.drvr_h" , "vif_intf" , intf_instance ) ;
       
      initial  //  Specialization  is  interface_type.modport 
        uvm_config_db #( virtual intf.master_cb ) :: set ( null , "uvm_test_top.env_h.agent_h.drvr_h" , "vif_intf" , intf_instance ) ;

      initial  //  Specialization  is  only  interface_type
        uvm_config_db #( virtual intf ) :: set ( null , "uvm_test_top.env_h.agent_h.drvr_h" , "vif_intf" , intf_instance ) ;
     

Are all 3 cases for uvm_config_db set equivalent ?
Can anyone of these 3 set be used for all 3 cases of handle declaration [ (a) , (b) and (c) ] interchangeably ?

(2) What would be the correct way to get the virtual interface for the driver component ?


       //  Within  driver  component's  build_phase() ::
       
       
       //  (i)   Keyword  "interface"  used  as  specialization  along  with  interface_type.modport 
        uvm_config_db #( virtual interface intf.master_cb ) :: get ( this , "" , "vif_intf" ,  vif ) ;
       
       //  (ii)  Specialization  is  interface_type.modport 
        uvm_config_db #( virtual intf.master_cb ) :: get ( this , "" , "vif_intf" , vif ) ;

       //  (iii)  Specialization  is  only  interface_type
        uvm_config_db #( virtual intf ) :: get (  this , "" , "vif_intf" , vif ) ;
     
 **Are  all  3  cases  for  uvm_config_db  get  equivalent ?
    Can  anyone of these 3 get be used for all 3 cases (a) , (b) and (c) interchangeably ?**

In reply to MICRO_91:

First of all, I recommend avoiding modports in testbench code; simulation tools ignore the directions that they are supposed to enforce.

Just because the BNF syntax shows something is optional does not necessarily mean it has no effect on the meaning.

The [interface] keyword is optional just there for visual clarity.

However, the LRM says this about modports in a virtual interface declaration.

A virtual interface declaration may select a modport of an interface in which case the modport is also part of its type. An interface instance or virtual interface with no modport selected may be assigned to a virtual interface with a modport selected.

That implies you cannot make assignments from something with a modport to without a modport, or from one modport selected to another modport selected.

Hi Dave ,

I have a clocking block as part of the modport to enforce the direction is followed by respective components.

If I were to declare virtual interface handle as :

virtual  interface  intf.Driver  vif ; //  Clocking  block  driver_cb  is  part of  the  modport  Driver

      //  Fetching  virtual  interface  :
if( ! uvm_config_db #( virtual interface  intf ) :: get( this , "" , "vif_intf"  ,  vif ) )
      `uvm_fatal( .. )
 

I observe elaboration error :

formal and actual do not have assignment compatible data types (expecting datatype compatible with ‘virtual interface intf.Driver’ but found ‘virtual interface intf’ instead)

As ’ vif ’ has modport in the declaration i.e intf.Driver whereas I am trying to assign non-modport type intf , this results in elaboration error .

The solution would to be use virtual interface intf.Driver as the specialization.

 i.e  uvm_config_db #( virtual interface  intf.Driver ) 

This also means the modport needs to be part of specialization when setting the virtual interface in top_tb else fatal message .


NOTE : uvm_config_db #( virtual interface  intf ) is a different specialization than uvm_config_db #( virtual interface  intf.Driver )

An interface instance or virtual interface with no modport selected may be assigned to a virtual interface with a modport selected.

Using the above quote an alternate solution would be :


 //  top_tb  would  simply  need  to  do  a  single  set  with  no  modport  specialization :

 uvm_config_db #( virtual interface intf ) :: set ( null , "uvm_test_top.env_h.agent_h*" , "vintf" , intf_instance );

 //  Then  within  Driver  and  Monitor  Components  with  virtual  interface  handles  using  a  modport :
 
    function  void  build_phase( uvm_phase  phase);
     virtual interface  intf  vintf ;

   if( ! uvm_cofig_db #( ( virtual interface intf ) :: get ( this , "" , "vintf" , vintf ) )
       `uvm_fatal( .. ) 
     
     //  LHS  is  declared  as  :  virtual  interface  intf.Driver  vintf_driver ;
      vintf_driver =  vintf ;  //  Assigning  virutal  interface with no modport to virtual interface with a modport 
      ....................

Hello there, I’m a beginner to UVM and I’m facing an issue with the verification of an encrypted design that needs an interface modport to function correctly (at least I think so). Anyways when I’m trying to pass the interface instance to the TB, I’m faced with an issue in my Monitor classes, here’s my code:
part of the interface file:

interface inf (
input logic clk
);

import FIFO_pkg::*;

inputs_monitor inputs_monitor_h;
outputs_monitor outputs_monitor_h;


. …
modport TEST (input wr_ack, overflow, underflow, almostempty, empty, almostfull, full, half_full, data_out, output clk, rst_n, data_in, wr_en, rd_en); //the test modport

part of the monitor file that the sim error is in:

function void connect_phase(uvm_phase phase);
super.connect_phase(phase);
my_vif.inputs_monitor_h = this; //error
$display(“my_monitor connect phase”);
endfunction

my top.sv:

initial begin
uvm_config_db#(virtual interface inf.TEST)::set(null,“uvm_test_top”, “my_vif”, f_if);
run_test();
end

The error: # ** Error (suppressible): (vsim-8209) Virtual interface elem. ‘inputs_monitor_h’ not found in modport ‘TEST’.

I understand the issue, can’t get around to solving it though
Two questions come to mind,

  1. Can I ignore using modports for my tb if its implemented too for my DUT? I tried and faced a problem where the TB does not understand what I’m pointing at inside the interface i.e.(@(posedge my_vif.clk)) always blocking
  2. If using modports is unavoidable for my tb, How can I fix this? can I add a method to a portlist?

I fixed the error by making another instance of the same interface without using the modport then setting and getting it in the monitor class and then using it instead of the modport one, still wondering about Q)2.)

uvm_config_db#(virtual interface inf)::set(null,“uvm_test_top.env_h.agent_h.inputs_monitor_h”, “my_vif1”, inf1);

As I mentioned above, I do not recommend using modports for your test bench. There is a little value. it’s not clear what the problem was when you removed them. and yes, you can add functions and tasks to a modport, but it seems unnecessary in your case. what function would you add?

1 Like

Hello Dave, thanks for the reply!

I’m very convinced that they’re 99% of the time obsolete, I just don’t know a workaround yet because my DUT in this case is Encrypted and I need to use the modports to deliver the portlist to the DUT.

module FIFO(inf.DUT f_if);
parameter FIFO_WIDTH = 16;
parameter FIFO_DEPTH = 8;
`pragma protect begin_protected
                                                                           ...................
`pragma protect end_protected

However in my tb, if I do not use the modport/specify it when making an instance to the interface and just use a direct Interface instance(without specifying the modport), my TB does not move if I add something like @(negedge my_vif.clk); It blocks until end of simulation.

top.sv:
	inf f_if(clk);
	FIFO DUT(f_if);
	bind FIFO FIFO_sva sva(f_if);
	initial begin
		uvm_config_db#(virtual inf)::set(null,"uvm_test_top", "my_vif", f_if);

also even if I use:

top.sv:
	inf f_if(clk);
	FIFO DUT(f_if);
	bind FIFO FIFO_sva sva(f_if);
	initial begin
		uvm_config_db#(virtual inf.TEST)::set(null,"uvm_test_top", "my_vif", f_if.TEST);

or even if I use:

top.sv:
	inf f_if(clk);
	FIFO DUT(f_if);
	bind FIFO FIFO_sva sva(f_if);
        inf atlas();
	initial begin
		uvm_config_db#(virtual inf.TEST)::set(null,"uvm_test_top", "my_vif", atlas.TEST);

I’m still faced with the blocking issue, it happens here for example:

	task run_phase(uvm_phase phase);
		super.run_phase(phase);
      @(negedge my_vif.clk);
		$display("coverage run_phase");

Questasim output:

# env run phase
# my_predictor run phase
# UVM_INFO components/comparator.svh(46) @ 0: uvm_test_top.env_h.scoreboard_h.comparator_h [COMPARATOR] RUN PHASE
# my_agent run phase

while if I remove the (@(negedge my_vif.clk))

	task run_phase(uvm_phase phase);
		super.run_phase(phase);
		$display("coverage run_phase");

Questasim output:

# env run phase
# my_predictor run phase
# UVM_INFO components/comparator.svh(46) @ 0: uvm_test_top.env_h.scoreboard_h.comparator_h [COMPARATOR] RUN PHASE
# coverage run_phase
# my_agent run phase

I have set up the set and get methods correctly AFAIK, No fatal errors show up when getting it from the db. The following is how I do it if I’m setting x.TEST in config_db

virtual inf.TEST my_vif;
                                            ...................................

 if(!uvm_config_db#(virtual inf.TEST)::get(this,"","my_vif",my_vif)) begin
			`uvm_fatal(get_full_name(),"Error");
		end

The method or type in this case would be the ones I’m trying to call from inside my Interface module to communicate with my monitor classes, but I just made another vif as a workaround, that doesn’t use the modport, and it works (at least in this scope) (won’t work if I try smth like @(negedge my_vif.clk); for example as i explained above)