How to access a DUT signal from a UVM test case class?

Hi,

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.

PRJ_pkg.sv:


`include "uvm_macros.svh"
package PRJ_pkg;
   import uvm_pkg::*;
   import agt1_pkg::*;
   import agt2_pkg::*;
   import reg_model_pkg::*;
   import reg_seq_pkg::*;  // Contains sequences derived from uvm_reg_sequence class

   `include "PRJ_env.sv"
   `include "PRJ_base_test.sv"
   `include "PRJ_TEST1.sv" // class PRJ_TEST1 extends PRJ_base_test;
endpackage

reg_seq_pkg.sv:


`include "uvm_macros.svh"
package reg_seq_pkg;
   import uvm_pkg::*;
   `include "sample_reg_seq.sv"
endpackage   

top.sv:


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.

Good luck,
-Tom

In reply to tfitz:

Hi Tom,

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.

Beeri

1 Like

In reply to kaushalmodi:

Hi,

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.

In reply to Beeri:

Hi Beeri ,

Are you got the solution for Your Query?

please suggest me how can we access the top module signals in uvm test class .

Thanks
kbkdec15

In reply to kbkdec15:

The solution is already there. Please see above Tom’s solution.

In reply to tomrohit:

Hi Tom,

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.

Thanks,
James

In reply to jamesq2001:

See my DVCon paper The Missing Link: The Testbench to DUT Connection

In reply to dave_59:

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.

In reply to Vinay Jain:

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.

In reply to jamesq2001:

Hi,

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.

Newbie at UVM btw…

MikeS

In reply to MikeSoco:

OK. %m - gives the path. Ignore!

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.

Thanks,
Maya

In reply to Maya Sasidharan:

See my link above

In reply to Maya Sasidharan:

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.

In reply to chr_sue:

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.

Thanks,
Maya

In reply to Maya Sasidharan:
Hi Maya,

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.

In reply to Maya Sasidharan:

Sounds good to me. Good luck for your further work.

In reply to dave_59:

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.

Thanks,
Maya