UVM model does not bind to RTL

Hi,

the DUT is instantiated into a verilog testbench: test - tb - dut
Another verilog module (probe) is used to instantiate the system verilog interfaces (meant to dig into the design) and run UVM.
Signals of interfaces are assigned by means of hierarchical paths (relative or absolute).
Those assignments are in the external module too.
In the same module, virtual interface handles are copied into config db through “set” calls.
Such module is bind to the RTL top level (the bind statement is external to all mudules)

test
+------------------------
|    tb +----------------
|       |   dut +--------
|       |       |  
|       |       +--------
|       +----------------
+------------------------

bind dut probe probe_i();

probe
+------------------------
|  myif myif_i();
|  assign myif_i.a=test.a; 
|  initial begin
|    uvm_config_db#(virtual myif)::set( ... );
|    run_test()
|  end
+------------------------

It works in vcs.

In vsim I’m getting

# ** Fatal: (vsim-12036) file_path_of_system_verilog_interface(34): Unresolved reference to 'dut' in /test.
#    Time: 0 fs  Iteration: 0  Region: /test File: file_path_of_system_verilog_interface
# FATAL ERROR while loading design
# Error loading design

Any clue?

In reply to gennaro:
Is ‘dut’ the name of the module, or the name of the instance? It should be the name of the module.

In reply to dave_59:
Could you please explain what test and what tb is?
Is test the toplevel module
Would great if you could show some more code from the toplevel module.

Thank you for the reply.

dut is the name of the module.
test is the name of the toplevel module.

The original code has different identifiers. The above example mirrors the hierarchy and the methodology used by the original code.
Original code compiles (with vsim) and elaborates but simulation is immediately interrupted with that error, which unfortunately does not say too much (to me). I did different attempts (use as example bind into the module).

It is also strange that if I “plug” the probe into another testbench, having a different hierarchy, I get a similar error message: top level name is different (because top level name is different) name of the interface is different (it is the first interface instantiated in the module); but the number (34) is the same (so apparently it is not indicating the line of the interface).

Something to be further considered is that interface instantiates other interfaces.

The idea is simply that interface is the vehicle to present signals to UVM probe and probe is bind to DUT which can be instantiated in any tb.

In reply to gennaro:

I do not understand what you are binding. bind is a SV construct to connect to DUT internal signals. But I do not see any signals you are connecting to.
It looks syntactically OK for me. This would explain why it compiles and elaborates.
Is line 34 (reported from the simulator) the line with the bind construct?
What happens if you are moving the myif instantiation to test?

Binding has been used as mean not to “touch” pre-existing tb and to probe the RTL.
I would say, if this method works, it could be generalised.
Line 34 is not the line with the bind construct.

Thank you for the suggestion. I’ll try to move the instantiation of i/f to test.

In reply to gennaro:
So what is on line 34? It may be difficult to solve your problem in this forum if you cannot share more code and the commands used to compile the code. I suggest you seek out help from your local vendor support.

In reply to gennaro:

If your bind module probe does not have any argument, you do not probe anything. And note bind allows only to observe signals.

I’ll follow the suggestion.

I’m not sure how to interpret

bind allows only to observe signals

.
I refer to chapter 23.11 of IEEE Std 1800™-2012 Standard for System Verilog.

In reply to gennaro:

The bind construct does not support the driving of signals of the component your are connecting to.

In reply to chr_sue:
Christoph, a bind module could make upward hierarchical references to the signals in the module it is bound to without having any ports, and can certainly use force statements to drive signals from the bind module.

But gennaro has not replied to any requests to show more detailed code, so it is difficult to help further.

In reply to dave_59:

Dave, whatabout a VHDL DUT?

In reply to chr_sue:
Not really relevant to this topic as VHDL has not been mentioned. Anyways, VHDL now has a force statement, but any inter-language specifics is going to be tool specific.

There’s the same failure also when interface instantiation and config db set methods are done into module test and “bind” is not used.


module dut();
  logic a0;
  logic a1;
endmodule

interface innerif();
  logic a;
endinterface

interface myif;
  innerif inner[2]();
  function virtual innerif get_inner_if(int i);
    case(i)
      0 : get_inner_if = myif.inner[0];
      1 : get_inner_if = myif.inner[1];
    endcase
  endfunction
endinterface

module test();
  dut dut_i();
  myif myif_i();
  assign myif_i.inner[0].a = tb.dut.a0; 
  assign myif_i.inner[1].a = tb.dut.a1; 
  initial begin
    uvm_config_db#(virtual myif)::set(uvm_root::get(),"*.probe","myif_vi",myif_i);
    run_test()
  end
endmodule

class probe extends uvm_env;
  virtual myif myif_vi;
  virtual innerif innerif_vi[2];
  function void build_phase (uvm_phase phase);
    uvm_config_db#(virtual myif)::get(this, "", "myif_vi",myif_vi);
    for(int i=0;i<2; i++) begin
      innerif_vi[i]=myif_vi.get_inner_if(i);
    end
  endfunction
endclass

Above code is not the original but has similar complexity.

In reply to gennaro:
After fixing all your typos and changing ‘tb.dut’ to ‘test.dut_i’, this works for me.

import uvm_pkg::*;
module dut();
  logic a0;
  logic a1;
endmodule
 
interface innerif();
  logic a;
endinterface
 
interface myif;
  innerif inner[2]();
  function virtual innerif get_inner_if(int i);
    case(i)
      0 : get_inner_if = myif.inner[0];
      1 : get_inner_if = myif.inner[1];
    endcase
  endfunction
endinterface
 
module test();
  dut dut_i();
  myif myif_i();
  assign myif_i.inner[0].a = test.dut_i.a0; 
  assign myif_i.inner[1].a = test.dut_i.a1; 
  initial begin
    uvm_config_db#(virtual myif)::set(uvm_root::get(),"*","myif_vi",myif_i);
     run_test("probe");
     
  end
endmodule
 
class probe extends uvm_env;
   typedef uvm_component_registry #(probe,"probe") type_id;

   function new(string name, uvm_component parent);
      super.new(name,parent);
   endfunction 
   
  virtual myif myif_vi;
  virtual innerif innerif_vi[2];
  function void build_phase (uvm_phase phase);
    uvm_config_db#(virtual myif)::get(this, "", "myif_vi",myif_vi);
    for(int i=0;i<2; i++) begin
      innerif_vi[i]=myif_vi.get_inner_if(i);
    end
  endfunction
endclass : probe

Same example works also binding the probe


import uvm_pkg::*;
`include "uvm_macros.svh"
module dut();
  logic a0;
  logic a1;
endmodule
 
interface innerif();
  logic a;
endinterface
 
interface myif;
  innerif inner[2]();
  function virtual innerif get_inner_if(int i);
    case(i)
      0 : get_inner_if = myif.inner[0];
      1 : get_inner_if = myif.inner[1];
    endcase
  endfunction
endinterface
 
module test();
  dut dut_i();
endmodule
 
class probe extends uvm_env;
`uvm_component_utils(probe)
  function new(string name, uvm_component parent);
    super.new(name,parent);
  endfunction 
 
  virtual myif myif_vi;
  virtual innerif innerif_vi[2];
  function void build_phase (uvm_phase phase);
    uvm_config_db#(virtual myif)::get(this, "", "myif_vi",myif_vi);
    for(int i=0;i<2; i++) begin
      innerif_vi[i]=myif_vi.get_inner_if(i);
    end
  endfunction
endclass : probe

module probe_top();
  myif myif_i();
  assign myif_i.inner[0].a = dut_i.a0; 
  assign myif_i.inner[1].a = dut_i.a1; 
  initial begin
    uvm_config_db#(virtual myif)::set(uvm_root::get(),"*","myif_vi",myif_i);
    run_test("probe");
  end
endmodule
bind dut probe_top probe_top_i();

This solves the subject of the thread. Thank you for the help.

Issue was wrong usage of switches -mfcu and -cuname (required to do bind)