I would like to access a DUT signal from within one of my UVM test cases.
But when I try to do so, I get the Cadence ncvlog error E*ILLHIN: illegal location for a hierarchical name (in a package).
This is the organization of the files for compilation.
module top;
import PRJ_pkg::*;
// Interface declarations
DUT u_dut (
...
);
// uvm_config_db # ( ) :: set statements for interface handle transfer to the agents
endmodule : top
PROBLEM:
I can do hierarchical reference ( like “top.u_dut.sig” ) from the body task of “sample_reg_seq.sv” which is a sequence derived from uvm_reg_sequence.
BUT I can’t do the same from the main_phase task of “PRJ_TEST1.sv”; I get the above E*ILLHIN compilation error,
I couldn’t figure out what I can add to PRJ_TEST1.sv to make that hierarchical ref work.
First of all, you should be using run_phase() and not main_phase().
Second of all, why would you possibly want to hard-code a hierarchical path to the DUT in your UVM? You are completely sacrificing the ability to reuse anything when you do that. Instead, you should create an interface that includes the signal(s) you want to access (the interface could include the hierarchical reference), and then you could pass that interface as a virtual interface via the config_db to your test/env and access it that way.
Thanks! The technique to create a probing interface worked. But I am curious why the hierarchical reference worked in a uvm_reg_sequence based class but not a uvm_test based class.
Also, why shouldn’t main_phase be used? I am curious. What are the best scenarios for using run_phase and main_phase? Thanks.
Sometimes, in cases you are sure that reuse is irrelevant, one can use the $root.
For example:
if ($root.top.u_dut.sig)
`uvm_error (“test”, "signal is active)
Though, I recommend not to use this method, and to stick to interface passing through config_db.
The virtual interface technique works fine when there is a need to monitor signals. But, if there is a need to drive signals buried deep into DUT, how can that be achieved using virtual interface?
My exact use case is, i am trying to do $readmemh on memory cells (behavioral memory model) which are instantiated in DUT.
It would be a big advantage if we could sample internal RTL signals in the DUT especially from functional coverage perspective. Unfortunately UVM doesn’t seem have build-in support for directly accessing RTL signals, not like Specman does (in Specman, an RTL signal can be accessed using RTL path). There are situations we want to sample RTL signals on an RTL event or want to collect the cross coverage of the RTL signal values with a coverpoint.
Also you can see a small article on how to access the DUT memory from anywhere in TB.
As @dave_59 suggested me, that we can also use the Interface class(better way actually) instead of abstract class. But this article give you a idea how things work.
Thanks Dave and Vinay/Jain for the paper/article. It is good to know there are working workaround. I believe we can use module as well instead of interface to bind to RTL and to embed the probe class for sampling internal RTL signals.
Question regarding Dave_59’s article. I’m trying to use something like this in a bigger UVM design. But I can’t see how the probe class can be used more than once. The uvm_object is registered with an ID of "probe_"PATH where PATH is a string to delimit different instances. But I can’t see how PATH gets set i.e. The $cast will fail because PATH isn’t set.
Hi,
I am also facing a similar limitation wrt hierarchical path.
i want to run a particular sequence till i get 100% coverage for a cross product.
I thought of using the inbuilt function $get_coverage of covergroup in the sequence to decide when to stop the simulation.
But i cannot give the hierarchical path in the sequence. it gives me “illegal location for a hierarchical name” error.
Going through different forums, i came to know that interface is the only component which can have hierarchical path in it.
I would like to know if there is anyway other than using an interface to achieve this.
Where do you have your covergroups implemented? In the sequence?
My practical experience shows this is not a good place having functional coverage there.
Because a sequence is a transient object which will be generated at a certain time and disappears after completion. You should implement your covergroups and crosses in a UVM component. Thsi is stable at least for a certain test and belongs to the verification environment. From there you can call $get_coverage easily.
Hi chr_sue,
I have the cover group as a separate component in the environment. it gets the transactions from the uvm_monitor.My apologies for not mentioning this in the question.
i am trying to access uvm_test_top.envh.cgh from sequence.
the sequence does not have a fixed place in your UVM environment. There is no hierarchical path to the UVM environment. You should call $get_coverage from your env and stop the execution when the coverage goal is reached.
Hi Dave
I wanted to access a variable in a uvm_component from uvm_sequence and this is how i accomplished it.
below is the background of my problem.
I have a cover_group as a separate component in the environment. it gets the transactions from the uvm_monitor. Then i want to run the sequence till i get a particular coverage value say >90%.
I derived a class coverage_obj from uvm_object and have a static variable coverage_value in it.
In cover_group, i created a coverage_obj and the static variable coverage_value will be updated each time covergroup.sample() is called using get_coverage function.
Then the sequence also have coverage_obj instantiated.
Then in the sequence i check for the coverage_value.since its a static variable,both uvm_component and uvm_sequence sees the same variable.
This way i was able to access the variable in a uvm_component from uvm_sequence.