UVM: Forcing signals in UVM style

Apologies for a late post… Today I would like to mention about some of the useful HDL signal manipulation methods in UVM.

Have you ever wondered about how the backdoor accesses work in RAL?  We provide a string context path to our RAL based register class and we call some peek/poke API to hierarchically access the signal/register in DUT.

How can we do it in SystemVerilog? Providing a string based path and depositing/reading value based on hierarchical access. This seems to be very difficult using plain SystemVerilog. But this is a game played by something called as DPI/VPI.

UVM provides the backdoor access sub-routines for force/release or read/deposit some vale on any hierarchical path provided in the argument. These functions acts as an interface between SystemVerilog and C code to perform various operations. These functions can not only be used for backdoor accesses, but also for forcing some value in any RTL modules.

In a broad perspective, VPI enables the testbench to access the DUT via simulator accesses:

Untitled

SV and C interfacing

Following is a list of API’s that are provided by UVM to perform various things. We can directly call these functions from the testbench and provide proper string based path as an input argument. This will automatically invoke the DPI-C code in UVM BCL.

uvm_hdl_check_path Checks that the given HDL path exists.
uvm_hdl_deposit Sets the given HDL path to the specified value.
uvm_hdl_force Forces the value on the given path.
uvm_hdl_force_time Forces the value on the given path for the specified amount of force_time.
uvm_hdl_release_and_read Releases a value previously set with uvm_hdl_force.
uvm_hdl_release Releases a value previously set with uvm_hdl_force.
uvm_hdl_read() Gets the value at the given path.

A basic difference between the force and deposit is that a “forcepreserves the value on the signal until we explicitly call “release“. While, a value that we just “deposit” will be overwritten by any subsequent value updates/assignments.

Passing the string in these functions allows us to force different signals depending on runtime arguments. This was a bit complex when using plain SystemVerilog approach.

// Deposit some value via backdoor in any uvm environment collateral

$value$plusargs(“+FORCE_SIGNAL=%0s”,mysignal_hierarchy)

if(uvm_hdl_deposit({“top.my_tb_hierarchy”,mysignal_hierarchy},1)) begin
$display($time,”\tForced value 1!!”);
end else begin
$display($time,”\tForce failed!!”);
end

// Deposit some value via backdoor in any uvm environment collateral
uvm_hdl_read({“top.my_tb_hierarchy”,mysignal_hierarchy},val);
$display($time,”\tval=%0d”,val);

 

Basically since UVM is entirely based up on SystemVerilog, we also have similar approach of VPI in SV. SystemVerilog provides the  “vpi_handle_by_name” function to get handle of any signal in your testbench and then allows user to perform operations on that handle. Discussing about each and every VPI function in SystemVerilog is beyond the scope of this post, the IEEE 1800-2012 Chapter 37,38 describes it in detail.

Basically the DPI-C functions in UVM BCL invokes some of the low level SystemVerilog VPI functions to perform a given task.

One thing to note here is that we need to include the VPI compilation switch in our simulator to be able to use these functions. Moreover, the RTL signals should not be optimized/changed since the testbench is dependent on those signals. Also, the VPI routines are not very well supported by most of the simulators.

UVM provides a macro called “UVM_HDL_NO_DPI” to allow users to turn off the use of DPI/HDL code.

I have created a simple adder example where I am depositing and forcing the values to some RTL signal using uvm_hdl_deposit and uvm_hdl_force. We can see the forces getting applied in wavedump. The sample code is available at EDAPlayground.

Hope that this post has given you an interesting insight about usage of VPI functions. More information about VPI can be gained from UVM Reference doc, I Spy with my VPI paper, SNUG VCS VPI paper or VPI basics.

6 responses

  1. Excellent stuff Sharvil ,i do like reading all your posts

    Liked by 1 person

    1. Thanks!! 🙂

      Liked by 2 people

  2. Hi,
    Can you show how to get the below line driven by an interface in the test. Basically looking for the value 2, to be driven by interface signal.
    if (uvm_hdl_force(“top.add.m”,2)) begin

    Like

    1. The signal ‘m’ is internal to the DUT. Here we are forcing this signal (wire) via uvm_hdl_force. This isn’t driven by any external interface signal, it is just a dummy signal inside RTL for explanation purpose.

      If we want to drive it by frontdoor/interface signal, then we can use hierarchical access in top module. e.g. in top module, one can have “force add.m = intf.somesignal;” or something similar.

      Like

  3. Good article Sharvil 🙂 Keep writing such things. I would like you to clarify some doubts of mine here.

    1) As you said, One thing to note here is that we need to include the VPI compilation switch in our simulator to be able to use these functions. Can you please elaborate more on this like what sort of switch need to be given?

    2) I have once used this in my environment and I have faced following errors:

    Error-[VPI-PVNDBG] VPI put value on an object w/o debug
    At time 820000, in PLI routine called from
    Function vpi_put_value() for object ‘XXXXXXX.XXXXXX.PRESETn’ was not
    successful because the object does not have ‘force-net’ debug functionality
    enabled. Recompile the entire design (or the listed IPs) with the missing
    debug capability. Please recompile using the ‘-debug_access<+options>’
    switch and incremental options as required. Recommended options are
    ‘-debug_access’ for post-process debug, ‘-debug_access+class’ for testbench
    debug, and ‘-debug_access+all’ for all debug capabilities. Refer the VCS
    user guide for more granular options for debug control under the switch
    ‘-debug_access’ and refer to ‘-debug_region’ for region control.

    vpiSeverity - vpiError
    PLI Routine - vpi_put_value
    Reference Object - PRESETn
    Reference Scope - efuse_tb.efuse_inst
    Reference vpiType - vpiNet
    

    Are you referring to debug capabilities in my point#1?

    Thanks
    Alay

    Like

    1. Thanks Alay!

      For Point-1, I was referring to the VPI enablement switch. For VCS simulator, ‘+vpi’ switch is used to enable VPI capability.

      For the Point-2, I believe that there might be some code calling VPI force (vpi_put_value) in a C function which requires force capability. As far as I recall, we can use -debug_all or -debug_pp to enable them in VCS.

      Refer to Sutherland Paper for VCS VPI compile time options and this post for more information on the error.

      Like

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: