How to force dut internal signals in UVM environment

In reply to Jun LI:

Just my two cents,
If you want to create an interface for internal signals there is a DVCon paper from Dave which shows how to integrate a UVM testbench with a bound interface. See this too.

When you use the force statement on a wire, that overrides all the drivers on the network until encountering another force or release statement.

For example

module test;  
    reg a, b, c, d;
    wire e;
    and and1 (e, a, b, c);

    initial begin
      $monitor("%d d=%b,e=%b", $stime, d, e);
      assign d = a & b & c;
      a = 1;
      b = 0;
      c = 1;
      #10;
      force d = (a | b | c);
      force e = (a | b | c);
      #10;
      release d;
      release e;
      #10 $finish;
    end
endmodule

In the example above and gate and1 is patched to work as or gate. If you simulate it, you’d get following results:

Results:
00 d=0,e=0
10 d=1,e=1
20 d=0,e=0

Without force statement, for t = 10, e should be equal to 0 (since 1 & 0 & 1 = 0). Using force statement overrides result of and1 and force e = 1. But as soon as release is applied to e, the value is change to 0 (the functionality of and gate is restored).

In the example above you can also see that force/release can be applied both to regs (d) and wires (e). This statements are used in testbenches, when you want to force determined value in reg or wire.

In case you want to force an interface using a variable, then that variable must not be transient. From Dave’s comment:
“A force statement many not contain any expressions made with automatic variables. That is because the lifetime of the effect of a force statement may go beyond the lifetime the the automatic variables. When you exit the task a, the automatic variable c disappears and there is no longer a valid expression for the force to use.
This is easy to fix on the RHS of the force by using an intermediate static variable.”
See verilog - Automatic variable may not be used in non-procedural constructs - Stack Overflow

Lastly, if you want to force /release an intern signal from an UVM class, then you will have to create a task in your interface to do the force/release, then call the task from your UVM class using virtual interfaces. If the DUT signal is unrelated to any existing interface, you may need to create a separate interface and use bind to instantiate the interface inside your DUT.
Notice that the SV force command CANNOT be used directly with virtual interfaces, therefore the need for the separated force tasks inside the interface.


interface blabla;

.....


  task force_reg_rn_1(logic [31:0] value);
         `ifdef VCS
             $hdl_xmr_force("secure_core_tb_top.u_secure_core_wrp.SR_REG_RN_1", "value", "0 ps", "freeze",  , 0);
         `else
             //QUESTA
             force secure_core_tb_top.u_secure_core_wrp.SR_REG_RN_1 = value;//direct force DUT intern signal
         `endif
    endtask
    task release_reg_rn_1();
         `ifdef VCS
             $hdl_xmr_release("secure_core_tb_top.u_secure_core_wrp.SR_REG_RN_1", 0);
         `else
             //QUESTA
             release secure_core_tb_top.u_secure_core_wrp.SR_REG_RN_1;//direct release DUT intern signal
         `endif
    endtask

endinterface