HDL access routines

UVM has the facility of doing backdoor reads from HDL paths via DPI/PLI interface.

Consider a simple design hierarchy shown below for illustration purposes. We also need a testbench to instantiate the design and start the test.

 module B; reg [3:0] cfg; endmodule module A; B b; endmodule // Testbench module module tb; A a(); initial run_test("base_test"); endmodule 

uvm_hdl_check_path

import "DPI-C" context function int uvm_hdl_check_path (string path);

This method returns 1 if the given HDL path exists, else it returns a 0.

 class base_test extends uvm_test; . virtual function void build_phase (uvm_phase phase); if (uvm_hdl_check_path ("tb.a.b.cfg")) `uvm_info ("TEST", "Path tb.a.b.cfg exists", UVM_MEDIUM) if (!uvm_hdl_check_path ("tb.a.def")) `uvm_info ("TEST", "Path tb.a.def does not exist", UVM_MEDIUM) endfunction endclass 

uvm_hdl_deposit

import "DPI-C" context function int uvm_hdl_deposit (string path, uvm_hdl_data_t value);

This method deposits the given value onto the HDL path and returns 1 if successful, else 0.

 class base_test extends uvm_test; . virtual task run_phase (uvm_phase phase); if (! uvm_hdl_deposit("tb.a.b.cfg", 4'h9)) `uvm_error ("TEST", "Deposit on tb.a.b.cfg failed", UVM_MEDIUM) endtask endclass 

uvm_hdl_force

import "DPI-C" context function int uvm_hdl_force (string path, uvm_hdl_data_t value);

This method forces the value on the given path and returns 1 if successful, else it returns 0. The difference between uvm_hdl_force and uvm_hdl_deposit is that the former has to be released at some point later in time for the original net to be able to drive the signal. For uvm_hdl_deposit , the value is simply placed onto the net and will persist until the original net drives some other value onto it.

 class base_test extends uvm_test; . virtual task run_phase (uvm_phase phase); if (! uvm_hdl_force("tb.a.b.cfg", 4'h9)) `uvm_error ("TEST", "Force on tb.a.b.cfg failed", UVM_MEDIUM) endtask endclass 

uvm_hdl_force_time

task uvm_hdl_force_time (string path, uvm_hdl_data_t value, time force_time = 0);

Forces the given value onto the HDL path for the specified amount of time. If force_time is 0, uvm_hdl_deposit will be called. Again, this method returns 1 if successful, else 0. The difference between this method and uvm_hdl_force is that the latter has to be released some time later, while this method automatically releases the force after the given time.

 class base_test extends uvm_test; . virtual task run_phase (uvm_phase phase); if (! uvm_hdl_force_time("tb.a.b.cfg", 4'h9, 30)) `uvm_error ("TEST", "Force on tb.a.b.cfg failed", UVM_MEDIUM) endtask endclass 

uvm_hdl_release_and_read

import "DPI-C" context function int uvm_hdl_release_and_read (string path, inout uvm_hdl_data_t value);

This releases the value previously set by uvm_hdl_force and returns 1 if it is successful, else 0. The value provided as an argument to this method is applied to the HDL after it is released.

 class base_test extends uvm_test; . virtual task run_phase (uvm_phase phase); if (! uvm_hdl_release_and_read("tb.a.b.cfg", 4'hE)) `uvm_error ("TEST", "Release on tb.a.b.cfg failed", UVM_MEDIUM) endtask endclass 

uvm_hdl_release

import "DPI-C" context function int uvm_hdl_release (string path);

This method will release the value previously forced on the given HDL path with uvm_hdl_force and returns 1 if successful, else 0.

 class base_test extends uvm_test; . virtual task run_phase (uvm_phase phase); if (! uvm_hdl_release("tb.a.b.cfg")) `uvm_error ("TEST", "Release on tb.a.b.cfg failed", UVM_MEDIUM) endtask endclass 

uvm_hdl_read

import "DPI-C" context function int uvm_hdl_read (string path, output uvm_hdl_data_t value);

Reads the current value on the given HDL path and returns 1 if successful, else 0.

 class base_test extends uvm_test; . virtual task run_phase (uvm_phase phase); int rdata; if (! uvm_hdl_read("tb.a.b.cfg", rdata)) `uvm_error ("TEST", "Read from tb.a.b.cfg failed", UVM_MEDIUM) endtask endclass