Access API in a module from a UVM driver

What’s the best way to access API (tasks and functions) in a 3rd party model (e.g. processor model) buried in RTL? I’m getting an error in DVT when I try to do this in my driver:

top.dut.cpu.read_data(0);

Of course, my driver is inside of a package so I’m not supposed to be able to do this even though RivieraPRO allows it. What’s the best way to handle this? Somehow with an interface?

Thanks!

In reply to Wes:

Read the entire thread:
https://verificationacademy.com/forums/ovm/ovm-wrapper-verilog-bfms

In reply to dave_59:
I read through the link that you pointed out and carefully read “The Missing Link: The Testbench to DUT Connection”, but I’m still having trouble. The following code below works but I need to have an interface for each dut in the testbench, so the hierarchy in “dut_intf” will need to be different. I’m thinking about how I can use “bind” to make this work but I still don’t think I’ll have access to the tasks in “mydesign_top”. How can I make this work without repeating the implementation of “abs_intf” for each internal module? In the real design, there are a lot of tasks that I will need access to and they are deep in the dut hierarchy.

package abs_pkg;
    virtual class abs_intf;
        bit y0, y1;
        pure virtual task write (input bit i0, i1);
        pure virtual task read;
    endclass
endpackage

interface dut_intf;
    import abs_pkg::*;

    class probe_concrete extends abs_intf;
        task write (input bit i0, i1);
            tb_top.dut0.write(i0, i1);
        endtask
        task read;
            tb_top.dut0.read(y0, y1);
        endtask
    endclass

    probe_concrete p = new;
endinterface

package uvmlike_pkg;
    import abs_pkg::*;
    class driver;
        abs_intf vintf;
        task run;
        endtask
    endclass
endpackage

////////////////////////////////////////////////////////////////////////
module mysub( input bit i, output reg x);
    initial x=0;
    always @(i) x = i;
endmodule

module mydesign_top;
    bit  it0, it1;
    wire x0, x1;

    mysub m0 (.i(it0), .x(x0));
    mysub m1 (.i(it1), .x(x1));

    task write (input bit i0, i1);
        #1;
        it0 = i0;
        it1 = i1;
        #1;
    endtask
    task read (output bit out0, out1);
        #1;
        out0 = x0;
        out1 = x1;
    endtask
endmodule

////////////////////////////////////////////////////////////////////////
module tb_top;
    import uvmlike_pkg::*;
    bit out0, out1;

    mydesign_top dut0 ();
    mydesign_top dut1 ();

    dut_intf intf();

    driver d;

    initial begin
        d       = new;
        d.vintf = intf.p;

        dut0.read(out0, out1);
        $display("  out  : %b %b", out0, out1);
    end
endmodule

“bind” worked for me in this situation.

Thanks for the link Dave.