I'm setting up a new UVM code, and want to make OOMR code in my uvm code, Do I need to avoid OOMR (Out Of Module Reference) code concept in UVM? If don't need it, What should I have to check before OOMR code and after?
tb.top.env.dut.a = 1;
a = tb.top.env.dut.b
If you see the link there some error message after run.
a=u_sub.b;
|
ncvlog: *E,ILLHIN (add.sv,6|12): illegal location for a hierarchical name (in a package).
To prevent this problem, I think I have to avoid like this code style. But I'm not sure what am I understanding this problem well.
Not sure but as I know some EDA tools support that issue. For example, cadence($xm_mirror), Mentor, VCS...
So I want to know Do I need to avoid these OOMR code style? or Should I have to use just EDA tool's helps. How to resolve this problem when I got similar error in huge complex uvm codes?
It is illegal to use Verilog Hierarchical References or OOMRs in a SystemVerilog package. This is because SystemVerilog packages are compiled first, in a different way to the rest of the SystemVerilog code.
Generally, you will be putting your classes in a package. Therefore, you would avoid using Verilog Hierarchical References or OOMRs in classes.
Obviously, you will want to connect the code in a class to the DUT ports (eg the drivers and monitors) and you may want to probe DUT internal signals, too. The solution to these is different for each case.
For connecting to DUT ports, most people would use a SystemVerilog interface . You instantiate the interface at the same level of hierarchy as the DUT and connect the interface members to the DUT somehow eg using Verilog Hierarchical References or OOMRs), eg:
interface TB_hook (input bit clk);
logic Stim, Resp;
...
endinterface
module harness;
bit clk;
TB_hook DUT_intf (.clk);
Sys_Top DUT (
.clk (clk),
.Stim (DUT_intf.Stim),
.Resp (DUT_intf.Resp),
...
Then in some class (a driver, monitor or agent) you can use a SystemVerilog virtual interface to connect to the interface instance. A virtual interface is a special kind of SystemVerilog variable that can store a Verilog Hierarchical Reference or OOMR to an interface instance or a modport. Because you have to assign that value at runtime, a virtual interface can be compiled in a package (but the code that assigns the value cannot be in a package), eg:
class driver;
virtual TB_hook V;
task drive (input bit data);
V.Stim <= data;
Then, in some Verilog module
(probably the top-level module), you would assign a value to the virtual interface variable. You could do this directly, eg:
module TB_top;
top_env env;
...
initial begin
...
env.agent.driver.V = harness.DUT_intf;
but most people would use the UVM config database:
module TB_top;
top_env env;
...
initial begin
...
uvm_config_db #(virtual TB_hook)::set(null, "*", "DUT_intf", harness.DUT_intf);
class driver;
virtual TB_hook V;
...
function void connect_phase(uvm_phase phase);
...
ok = uvm_config_db#(virtual TB_hook)::get(this, "", "DUT_intf", V);
You can enhance this technique using modports and/or clocking blocks.
For probing internal DUT signals, there are facilities provided by the UVM Register Layer. There are a set of functions/tasks for this:
uvm_hdl_check_path
– checks if HDL path existsuvm_hdl_deposit
– deposits a value into the RTLuvm_hdl_force
– forces a value into the RTLuvm_hdl_force_time
– forces a value for a specified durationuvm_hdl_release
– releases a forced value uvm_hdl_release_and_read
– releases a forced value and reads the new valueuvm_hdl_read
– reads an RTL value