UVM Agent connect phase error connecting driver to sequencer

Hello everyone,

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

In reply to khnabeel:

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.

In reply to cgales:

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;}

But it is not making it active anyway!!

Any idea? what is wrong?

In reply to khnabeel:

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?

Waiting for your reply.

In reply to khnabeel:

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

In reply to cgales:

Thanks cgales. You have been very kind
I tried it.
But still it didn’t help me out!! :(

Any other possibility? Or suggestions?

In reply to khnabeel:

Did you set the default value as I suggested previously?

In reply to cgales:

inside the i2c_master_configuration object? YES!!
like this NOW
rand uvm_active_passive_enum is_active=UVM_ACTIVE;

also by putting constraint!

Now another twist is that when in i2c_master_agent i have checked that either virtual interface is set or not? It says Virtual interface not set.

Even though i have set it in my i2c_top as

uvm_config_db#(virtual i2c_if)::set(null,“*”, “i2c_if”, vif);

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?

In reply to khnabeel:

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.

In reply to cgales:

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.

Any idea? Any suggestions?

In reply to khnabeel:

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.