I have made an environment for I2C verification but it is giving me an error in agent’s connect phase when connecting sequencer to driver in my simulation. When I compile everything, it is all OK. In addition to it I must mention here that I have not made a Monitor as yet because i just wanted to check the pins activity that is happening. I will made monitor but as yet I have all the verification components except monitor and scoreboard. Please find the agent’s code below and see what is wrong with this code. Also I am mentioning error below.
class i2c_master_agent extends uvm_agent;
virtual i2c_if vif;
i2c_master_configuration m_cfg;
i2c_sequencer i2c_sqr;
i2c_master_driver i2c_drvr;
`uvm_component_utils_begin(i2c_master_agent)
`uvm_field_object(m_cfg,UVM_ALL_ON)
`uvm_field_object(i2c_drvr,UVM_ALL_ON)
`uvm_field_object(i2c_sqr,UVM_ALL_ON)
`uvm_component_utils_end
extern function new(string name ="i2c_master_agent", uvm_component parent);
extern function void build_phase(uvm_phase phase);
extern function void connect_phase(uvm_phase phase);
endclass:i2c_master_agent
function i2c_master_agent:: new(string name ="i2c_master_agent", uvm_component parent);
super.new(name, parent);
endfunction: new
function void i2c_master_agent:: build_phase(uvm_phase phase);
super.build_phase(phase);
begin
//i2c_master_configuration m_cfg=new;
m_cfg = i2c_master_configuration::type_id::create("m_cfg",this); //Constructing configuration using factory method
uvm_config_db#(i2c_master_configuration)::set(null, {get_full_name(), ".i2c_sqr"}, "m_cfg", m_cfg); //putting cfg object in config db so sequences can use it
if(m_cfg.is_active) begin
`uvm_info("UVM_MASTER_CONFIG_AGENT_BLOCK","i2c_master_agent has Configuration!!", UVM_NONE)
i2c_sqr = i2c_sequencer ::type_id::create("i2c_sqr", this);
i2c_drvr = i2c_master_driver ::type_id::create("i2c_drvr", this);
i2c_drvr.vif=vif; //passing virtual interface into driver
i2c_drvr.m_cfg=m_cfg; //passing config into driver
end
end
endfunction: build_phase
function void i2c_master_agent:: connect_phase(uvm_phase phase);
super.connect_phase(phase);
begin
`uvm_info("UVM_MASTER_CONNECT_PHASE","I M HERE!!", UVM_NONE)
i2c_drvr.seq_item_port.connect(i2c_sqr.seq_item_export);
end
endfunction: connect_phase
Error is below in simulation
Fatal error in Function i2c_pkg/i2c_master_agent::connect_phase at i2c_master_agent.sv line 47
There should be some more information regarding the fatal error. Is it due to a null object or something else? Please post the entire message regarding the fatal error.
Also, which line is line 47? It is hard to figure that out from the code you posted.
An initial guess is that maybe the configuration object defines is_active as FALSE, which results in the sequencer and driver not being built, resulting in null objects. But that is only a guess without seeing more information.
Dear cgales,
thanks for your kind reply. First thing is Line 47 is the line below in code posted above.
i2c_drvr.seq_item_port.connect(i2c_sqr.seq_item_export);
Secondly you are perfectly right! I also figured this out that my configuration object is NULL. But the problem is that even though i am making my configuration object as like uvm_active_passive_enum is_active;
Then I registered it with uvm_field_enum
and then i have put a constraint like this:
constraint i2c_master_configuration::is_active_agent_c{soft is_active==UVM_ACTIVE;}
When you have a constraint, it will only be used when you call randomize() for that class. Since you don’t randomize() your configuration object, is_active will be assigned the default value, which isn’t defined (i.e. it will be 0).
You can either assign a default value to is_active:
uvm_active_passive_enum is_active = UVM_ACTIVE;
Or you can call randomize().
Additionally, you should remove all `uvm_field_* macros. There are many threads which discuss why these shouldn’t be used.
In reply to cgales:
Thanks cgales for informing about `uvm_field_* macros!!
In addition to it, I wanted to tell you that i missed in last post writing rand!
inside i2c_master_configuration i have declared it as
rand uvm_active_passive_enum is_active;
and after that a constraint
extern constraint is_active_agent_c;
constraint i2c_master_configuration::is_active_agent_c{ is_active==UVM_ACTIVE;}
Is it that rand you really meant?
No. After you create the configuration object, you need to call randomize():
m_cfg = i2c_master_configuration::type_id::create("m_cfg",this); //Constructing configuration using factory method
if (!m_cfg.randomize()) `uvm_fatal("RNDERR", "Unable to randomize() configuration object");
uvm_config_db#(i2c_master_configuration)::set(null, {get_full_name(), ".i2c_sqr"}, "m_cfg", m_cfg); //putting cfg object in config db so sequences can use it
and then i am getting it as well in my test class and it says it has virtual interface !!
May be this error is due to this virtual interface? Any idea?
It is recommended that you use the following UVM guidance:
Make the virtual interface handle part of your agent’s configuration object.
Mage the agent’s configuration object part of your environment configuration object.
Set the virtual interface handle to the config_db at the top level of your testbench (as you are doing).
Create the environment configuration during the test build phase and set it in the config_db during the build phase, creating the agent configuration as well.
Assign the agent’s virtual interface handle from the config_db to the agent’s configuration object.
Create the environment.
Get the environment configuration from the config_db. Set the agent’s configuration object to the config_db.
Create the agent.
Get the agent’s configuration from the oonfig_db. Get the virtual interface handle and other configuration parameters from the configuration object.
Thanks cgales!!
Steps worked really! and now configuration object is active also interface is set!. I tried to display them using uvm_info* macro and it is working!!
But the thing is that now it is not taking the values that i have put as a constraint in configuration object. e.g I have put a constraint to frequency mode and say that it must be in a standard mode. But it is not taking that. Even though configuration object is Active.
You should make sure that you have implemented all of the required methods (See link on Methods) in your configuration object.
After creating and randomizing your configuration object, you can easily print out your configuration to see what is set and then make sure that you are using the values appropriately.