Hello ,
I am trying to retrieve information from my top testbench which is a parameter of my DUT, using set in the testbench and get in my agent_configuration file.
so in my testbench I wrote this:
uvm_config_db#(int)::set(null,“*”,“RD_LATENCY”,RD_LATENCY);
and in my agent_configuration file which contains agent_configuration class that extends from uvm_object ,I wrote the following:
if (!uvm_config_db #(int)::get(this,“”, “RD_LATENCY”,RD_LATENCY))begin
`uvm_fatal(get_type_name(), $sformatf(“READ LATENCY %d not found in uvm_config_db”, RD_LATENCY))
end
I am getting the following error when I run my code:
xmvlog: *E,TYCMPAT (/src/env/mem_uvm_agent_configuration.sv,46|34): formal and actual do not have assignment compatible data types (expecting datatype compatible with ‘class uvm_pkg::uvm_component’ but found ‘class mem_uvm_env_pkg::mem_uvm_agent_configuration’ instead).
so basically the error is related to the cntxt type when I do the “get” which is a uvm_object and not uvm_component
is there any solution to this ?
In reply to verif_25:
The first argument of uvm_config_db is a uvm_component handle, or null.
Your agent configuration is probably derived from uvm_object, so the handle “this” is the wrong type. Either pass in a component handle, such as the agent’s
``` verilog
uvm_config_db #(int)::get(agt, "", "RD_LATENCY",RD_LATENCY)
Or make the call inside a component such as the agent, and pass "this".
If you derived the config object from uvm_component, as I tried yesterday, it leads to ordering problems. The test creates the configuration before components are created, but the agent config would have to be a child of the agent. Don't do it.
In reply to chrisspear:
thanks for your prompt reply.
Indeed my agent configuration is derived from uvm_object.
so what do you suggest is that I make the call inside my agent while the “RD_LATENCY” is being declared in my agent config file ?
right ?
In reply to verif_25:
Your type is wrong in the config_db command. As you said “RD_LATENCY” is defined and speciifed in a configuration object.
You should use this configuration object type instead of int.
In reply to chr_sue:
I think RD_LATENCY is an int in his agent config class. The problem is that he is calling uvm_config_db::get(this,) from inside the agent config class, derived from uvm_object, and that first handle has to be a class handle, derived from uvm_component.
As I said in my first reply, the correct place for this get() call is probably in the agent class. It depends on who created the configuration object, usually the test class.
The call in the agent class looks like:
class my_agent extends uvm_agent;
virtual function void build_phase(...);
if (! uvm_config_db #(int)::get(this, "", "RD_LATENCY", agt_cfg.RD_LATENCY))
`uvm_fatal("NSFW", "No RD_LATENCY")
Long term, why do you want to pass RD_LATENCY “globally” so it is seen by all components? Who sets it? Does every component really need to see it? What happens if you have multiple subsystems, each with their own RD_LATENCY value?
In reply to chrisspear:
Thank you again chris , what you wrote is exactly the case, indeed RD_LATENCY is an integer and I implemented the solution you suggested and it is working fine.
about your last question , RD_LATENCY is a parameter in my DUT , so it is set in my top testbench using config_db , and I passed it globally in case I need it somewhere else.
but I don’t have any other subsystems that have their own RD_LATENCY.
do you think I should limit the accessibility of the database entry?
In reply to verif_25:
Depends on how your TB builds config objects and shares them. 10 different people have 12 different styles. If your test class creates all the config objects including this agent one, set it directly. My opinion of the uvm_config_db is to use it as little as possible.
In reply to verif_25:
I read an interesting article from Cliff Cummings.
http://www.sunburst-design.com/papers/CummingsDVCon2023_uvm_resource_db_API.pdf. He advocates for the use of uvm_resource_db for this purpose and I see his point. You can easily access the DB from an uvm_object. In your case though an OOP-style passing might be all you need.
Grab a pointer to your cfg and assign your variable.
agt_cfg.RD_LATENCY = RD_LATENCY;
Good luck
In reply to gkaragatchliev:
There are literally dozens of different ways to pass information around a testbench. The uvm_config_db is built on the uvm_resource_db. My good friend Cliff did an excellent job researching the difference between these two styles over his 33-page paper. I see them as two sides of the same coin. For example, these two calls pass a virtual interface from the top module to a test class.
// top module
uvm_config_db#(virtual dut_if)::set(null, "uvm_test_top", "vif", ifc);
// test class
uvm_config_db#(virtual dut_if)::get(this, "", "vif", vif);
maps to the calls:
// test module
uvm_resource_db#(virtual dut_if)::set("uvm_test_top", "vif", ifc);
// test class
uvm_resource_db#(virtual dut_if)::read_by_name(get_full_name(), "vif", vif, this);
To me, these look equivalent. If I had to pick between them, I would choose the more reusable code. Most UVM users are more familiar with uvm_config_db, so I would stick with it.
Cliff promotes get_full_name() over the handle ‘this’. It is easy to use these with both DBs. His latest version of the paper includes my comments and his responses. Read them both and make your own decision.
Either way, whenever possible, pass handles to config objects whenever possible and avoid individual values. Once you have the code for the config objects, you can easily add new variables, without having to read my posts or Cliff’s award winning papers.