Using a Non-UVM class instance inside the UVM Driver class

Hi everyone,

I am trying to do UVM verification for an AXI module. I have already a parametrized non-uvm class which contains all tasks and functions to drive signals. Someone else implemented it for a traditional testbench. I instantiate this class in my UVM driver class. And I need to pass an interface to the non-uvm class when I use “new” function.

First, I pass the interface from the top file to different classes and also to the driver class via uvm_config_db. In the driver class, in the build_phase I get the interface and assign it to the virtual one. After that the virtual interface is used inside the “new” function for the non-uvm class.

But when I run the code, UVM says, virtual interface resolution can not find a matching instance for virtual ifAXI(.AddrWidth(32), .DataWidth(64), .IDWidth(0)). Candidates are: top.sv ifAXI(32, 32, 0)

It takes the default parameters.

For example: my_class #(parameters here…) instance0;

build_phase _-> retrieve the interface
instance0 = new(virtual interface)

Any suggestions to this issue?

You’re not showing nearly enough code for us to help you. The fact that the class is non-UVM is most likely irrelevant. You need to trace all the parameter overrides to make sure all the actual interface instance parameters and the virtual interface variable declaration parameters match.

Thanks for your reply. I can not provide the whole code but I will try to make it clear.

Code

top.sv

// Code
parameter int unsigned AXI_AddrWidth  = 'd32,
parameter int unsigned AXI_DataWidth  = 'd32


ifAXI #(
.ADDR_WIDTH (AXI_AddrWidth),
.DATA_WIDTH (AXI_DataWidth),
.ID_WIDTH   (0)
) axilite_inst (
.clk    (clk),
.resetn (rst)
);
....


initial begin
 uvm_config_db#(virtual ifAXI#('d32,'d32,0))::set(null, "*",            "axilite_inst_0", axilite_inst);
end

test.sv

class test extends uvm_component;

`uvm_component_utils(test);


env e;
uvm_conf_env env_cfg;
uvm_sequence_mc_cfg uvm_sequence_mc_cfg_0;
virtual ifAXI #(
.ADDR_WIDTH (32),
.DATA_WIDTH (32),
.ID_WIDTH   (0)
) axilite_inst;


endclass: test

function void test::build_phase(uvm_phase phase);
super.build_phase(phase);
env_cfg =           uvm_conf_env::type_id::create("env_cfg",this);
e                       =        env::type_id::create("e",this);

uvm_sequence_mc_cfg_0 = uvm_sequence_mc_cfg::type_id::create("uvm_sequence_mc_cfg_0", this);

if(!uvm_config_db#(virtual ifAXI#('d32,'d32,0))::get(this, "", "axilite_inst_0", axilite_inst))
    `uvm_fatal("BASE_TEST", "Cannot get ifAXI from TOP")

env_cfg.axilite_inst = axilite_inst;
uvm_config_db#(uvm_conf_env)::set(this, "*", "env_cfg", env_cfg);

endfunction: build_phase

env.sv

// Build phase in the env class
function void env::build_phase(uvm_phase phase);
super.build_phase(phase);

uvm_conf_mc_cfg_0  =      uvm_conf_agent_mc_cfg::type_id::create("uvm_conf_mc_cfg_0", this);

uvm_agent_mc_cfg_0         =       uvm_agent_mc_cfg::type_id::create("uvm_agent_mc_cfg_0",this);

uvm_scoreboard_mc_cfg_0    =       uvm_scoreboard_mc_cfg::type_id::create("uvm_scoreboard_mc_cfg_0",this);

if (!uvm_config_db #(uvm_conf_env)::get(this, "", "env_cfg", env_cfg))
`uvm_fatal("NOCONF", "env_cfg not set in test")


uvm_conf_mc_cfg_0.axilite_inst = env_cfg.axilite_inst;

// Pass configuration objects to agents via uvm_config_db
uvm_config_db#(uvm_conf_agent_mc_cfg)::set(this, "*", "uvm_conf_mc_cfg_0", uvm_conf_mc_cfg_0);

endfunction: build_phase

uvm_conf_mc_cfg.sv

 virtual ifAXI #(
.ADDR_WIDTH (32),
.DATA_WIDTH (32),
.ID_WIDTH   (0)
) axilite_inst; ....

uvm_agent_mc_cfg.sv

 uvm_driver_mc_cfg_0      =        uvm_driver_mc_cfg#(.AXI_DataWidth('d32), .AXI_AddrWidth('d32))::type_id::create("uvm_driver_mc_cfg_0", this);

uvm_monitor_mc_cfg_0     =      uvm_monitor_mc_cfg::type_id::create("uvm_monitor_mc_cfg_0", this);


seqr = uvm_sequencer#(transaction)::type_id::create("seqr", this);

uvm_driver_mc_cfg.sv

 class uvm_driver_mc_cfg #(
    parameter int unsigned AXI_AddrWidth  = 'd32,
    parameter int unsigned AXI_DataWidth  = 'd32
) extends uvm_driver#(transaction);

`uvm_component_utils(uvm_driver_mc_cfg);


virtual ifAXI #(
    .ADDR_WIDTH (AXI_AddrWidth),
    .DATA_WIDTH (AXI_DataWidth),
    .ID_WIDTH   (0)
) axilite_inst;

uvm_conf_agent_mc_cfg uvm_conf_mc_cfg_0;
transaction tr;



my_class_axi # (
    .ADDR_WIDTH                     (AXI_AddrWidth),
    .DATA_WIDTH                     (AXI_DataWidth),
) my_class_axi_inst;



//  Constructor: new
function new(string name = "uvm_driver_mc_cfg", uvm_component parent);
    super.new(name, parent);
endfunction: new

/*---  UVM Build Phases            ---*/
/*------------------------------------*/
//  Function: build_phase
extern function void build_phase(uvm_phase phase);


endclass: uvm_driver_mc_cfg



function void uvm_driver_mc_cfg::build_phase(uvm_phase phase);

tr = transaction::type_id::create("tr");   

if(!uvm_config_db#(uvm_conf_agent_mc_cfg)::get(this,"","uvm_conf_mc_cfg_0",uvm_conf_mc_cfg_0))//uvm_test_top.env.agent.drv
  `uvm_error("DRV","Unable to access Conf object");


axilite_inst = uvm_conf_mc_cfg_0.axilite_inst;

my_class_axi_inst = new (axilite_inst);


endfunction: build_phase

my_class_axi

class my_class_axi #(
parameter int unsigned  ADDR_WIDTH      = 32,
parameter int unsigned  DATA_WIDTH      = 64,

);

virtual ifAXI #(
    .ADDR_WIDTH (ADDR_WIDTH),
    .DATA_WIDTH (DATA_WIDTH),
    .ID_WIDTH   (0)
) axi_bus;


function new (
    virtual ifAXI #(
        .ADDR_WIDTH (ADDR_WIDTH),
        .DATA_WIDTH (DATA_WIDTH),
        .ID_WIDTH   (0)
    ) axi_bus
);
    this.axi_bus = axi_bus;
 endfunction   
 endclass

Default parameter for the DATA_WIDTH is 64, it does not take the 32 that I passed from the driver class, instead it takes the default parameter.