UVM configuration NULL pointer dereference Problem

Hi,

I’m trying to understand uvm_config_db() behavior, so I added it into my simple UVM example which has been in No Problem for simulation.
But I got NULL pointer dereference. error after run simulation with uvm_config_db().

I just added one apb_master_config class.

class apb_master_config extends uvm_object;
    `uvm_object_utils(apb_master_config)

    virtual apb_interface apb_if;

    function new (string name = "");
        super.new(name);
    endfunction

    uvm_active_passive_enum active = UVM_ACTIVE;

endclass

and I added into my test class as the below

class apb_basic_test extends uvm_test;
    
  `uvm_component_utils_begin(apb_basic_test)
  `uvm_component_utils_end 

  apb_master_config m_cfg;
  apb_master_environment apb_environment;//evironment handle 
  apb_sequence seq;//sequence handle
  
  function new(string name="apb_basic_test", uvm_component parent);
    super.new(name,parent);
    `uvm_info(get_type_name(),"the objection test object has been built",UVM_LOW);
  endfunction
  
  virtual function void build_phase(uvm_phase phase);
    super.build_phase(phase);
    uvm_config_db #(apb_master_config)::set(null, "*",  "apb_master_config", m_cfg);
    apb_environment = apb_master_environment::type_id::create("apb_environment",this);
    seq = apb_sequence::type_id::create("seq", this);
   endfunction
  
  virtual function void connect_phase(uvm_phase phase);
   `uvm_info(get_type_name(),"the connect phase of the basic_test completed", UVM_LOW)
  endfunction

  virtual task run_phase(uvm_phase phase);                                                          
    super.run_phase(phase);
    phase.raise_objection(this);//raise objection                                                   
    seq.start(apb_environment.apb_agent.sequencer);                                                 
    phase.drop_objection(this);//drop objection                                                     
  endtask


This is Agent


class apb_master_agent extends uvm_agent;

  apb_master_config m_cfg;

  apb_sequencer sequencer;
  apb_master_driver driver;
  apb_monitor monitor;
 
  `uvm_component_utils(apb_master_agent)
  
  function new(string name="apb_master_agent", uvm_component parent);
    super.new(name,parent);
  endfunction
  
  virtual function void build_phase(uvm_phase phase);
    super.build_phase(phase);
    
    if(!uvm_config_db #(apb_master_config)::get(null, "*", "apb_master_config", m_cfg))
        `uvm_fatal("FATAL MSG", "Configuration object is not set properly")

        `uvm_info(get_type_name(), $psprintf("agent is: %s", m_cfg.active),UVM_LOW) //<== Here m_cfg make NULL pointer dereference 
        `uvm_info(get_type_name(), $psprintf("vif: %p", m_cfg.apb_if), UVM_LOW)     //<== Here m_cfg make NULL pointer dereference                

    
    /// Monitor will Always Be Available ///
    monitor=apb_monitor::type_id::create("monitor",this);
    if(monitor==null)
      `uvm_fatal(get_type_name(),"the monitor has not beed built");                                 

    /// Driver & Sequencer will be Implemented only in ACTIVE mode
    if(m_cfg.active == UVM_ACTIVE) begin  //<== Here m_cfg make NULL pointer dereference 
        driver=apb_master_driver::type_id::create("driver",this);                                   
        sequencer=apb_sequencer::type_id::create("sequencer", this);
        
        if(sequencer==null)
          `uvm_fatal(get_type_name(),"the sequecer has not been built");
        if(driver==null)
          `uvm_fatal(get_type_name(),"the driver has not been built");

        `uvm_info(get_type_name(), "UVM is PASSIVE", UVM_LOW);
   
  endfunction

If I use m_cfg like `uvm_info(get_type_name(), $psprintf(“agent is: %s”, m_cfg.active),UVM_LOW) then I got Null point Error at the starting simulation.
I think uvm_config_db setting no problem, But still I get the Null point Error about m_cfg.
Would you please help me to understand why does it make NULL point error at the starting simulation?
If I commented all about m_cfg, then there is no problem. simulation is done as well.

In reply to UVM_LOVE:

Where do you create the apb_master_config m_cfg? It should be created before you post it in the uvm_config_db in the build_phase of your apb_basic_test

In reply to sylvainb:

In reply to UVM_LOVE:
Where do you create the apb_master_config m_cfg? It should be created before you post it in the uvm_config_db in the build_phase of your apb_basic_test

Thank you I found it.

In reply to UVM_LOVE:

Your call to get() in your agent is also incorrect. You want:


if(!uvm_config_db #(apb_master_config)::get(this, "", "apb_master_config", m_cfg))
  `uvm_fatal("FATAL MSG", "Configuration object is not set properly")

In reply to cgales:

In reply to UVM_LOVE:
Your call to get() in your agent is also incorrect. You want:


if(!uvm_config_db #(apb_master_config)::get(this, "", "apb_master_config", m_cfg))
`uvm_fatal("FATAL MSG", "Configuration object is not set properly")

Thank you cgales, I missed it. Thanks again.

In reply to sylvainb:

In reply to UVM_LOVE:
Where do you create the apb_master_config m_cfg? It should be created before you post it in the uvm_config_db in the build_phase of your apb_basic_test

I can get m_cfg properties after created apb_master_config as your recommend.
But Virtual interface is not still NULL, But other properties are good in configuration.

I added the creation apb_master_config in test class as your recommands, as the below,

class apb_basic_test extends uvm_test;
  int packets;
  
  `uvm_component_utils_begin(apb_basic_test)
  `uvm_field_int(packets,UVM_ALL_ON)
  `uvm_component_utils_end

  apb_master_config m_cfg;
  apb_master_environment apb_environment;//evironment handle 
  apb_sequence seq;//sequence handle

  
  function new(string name="apb_basic_test", uvm_component parent);
    super.new(name,parent);
    `uvm_info(get_type_name(),"the objection test object has been built",UVM_LOW);
  endfunction
 
  virtual function void build_phase(uvm_phase phase);
    uvm_config_int::set(this, "*", "recording_detail", 1);
    super.build_phase(phase);
    m_cfg=apb_master_config::type_id::create("m_cfg",this);

    uvm_config_db #(apb_master_config)::set(this, "*",  "apb_master_config", m_cfg);
    if(!uvm_config_db#(int)::get(this,"","number_of_packets",packets))
      `uvm_info(get_type_name(),"the geting of packets variable failed",UVM_LOW)
      
    apb_environment = apb_master_environment::type_id::create("apb_environment",this);
    seq = apb_sequence::type_id::create("seq", this);
    
   endfunction
  
  virtual function void connect_phase(uvm_phase phase);

    seq.packets = packets;
   `uvm_info(get_type_name(),"the connect phase of the basic_test completed", UVM_LOW)
  endfunction
  

    

And Here’s Agent.

class apb_master_agent extends uvm_agent;

  apb_master_config m_cfg;

  apb_sequencer sequencer;
  apb_master_driver driver;
  apb_monitor monitor;
  apb_master_coverage coverage;

  
  `uvm_component_utils(apb_master_agent)
  
  function new(string name="apb_master_agent", uvm_component parent);
    super.new(name,parent);
  endfunction
  
  virtual function void build_phase(uvm_phase phase);
    super.build_phase(phase);
    
    if(!uvm_config_db #(apb_master_config)::get(this, "*", "apb_master_config", m_cfg))
        `uvm_fatal("FATAL MSG", "Configuration object is not set properly")

        `uvm_info(get_type_name(), $psprintf("agent is: %p", m_cfg.active),UVM_LOW)
        `uvm_info(get_type_name(), $psprintf("vif: %p", m_cfg.apb_if), UVM_LOW)

    
    /// Monitor will Always Be Available ///
    monitor=apb_monitor::type_id::create("monitor",this);
    if(monitor==null)
      `uvm_fatal(get_type_name(),"the monitor has not beed built");

    /// Driver & Sequencer will be Implemented only in ACTIVE mode
    if(m_cfg.active == UVM_ACTIVE) begin
        driver=apb_master_driver::type_id::create("driver",this);
        sequencer=apb_sequencer::type_id::create("sequencer", this);
        
        if(sequencer==null)
          `uvm_fatal(get_type_name(),"the sequecer has not been built");
        if(driver==null)
          `uvm_fatal(get_type_name(),"the driver has not been built");
    end
    else
        `uvm_info(get_type_name(), "UVM is PASSIVE", UVM_LOW);

        `uvm_info(get_type_name(), $psprintf("Coverage is: %p", m_cfg.has_functional_coverage),UVM_LOW)
    if(m_cfg.has_functional_coverage) begin
        coverage = apb_master_coverage::type_id::create("coverage", this);
    end 

and the problem class is the monitor especially m_cfg.apb_if has NULL error.

class apb_monitor extends uvm_monitor;

    `uvm_component_utils(apb_monitor)

    virtual apb_interface vapb_intf;
    apb_sequence_item apb_rx;
    apb_master_config m_cfg;

function new(string name="apb_monitor", uvm_component parent = null);
    super.new(name, parent);
endfunction

uvm_analysis_port #(apb_sequence_item) my_mon_port;

virtual function void build_phase(uvm_phase phase);
    super.build_phase(phase);
    my_mon_port = new ("my_mon_port", this);

endfunction

virtual function void connect_phase(uvm_phase phase);
    super.connect_phase(phase);
    if(!uvm_config_db #(apb_master_config)::get(this, "*", "apb_master_config", m_cfg))
        `uvm_fatal("FATAL MSG", "Configuration object is not set properly")
    
    vapb_intf = m_cfg.apb_if;
        `uvm_info(get_type_name(), $psprintf("!!!!!!t is: %p", m_cfg.apb_if),UVM_LOW)

endfunction

virtual task run_phase(uvm_phase phase);
    apb_rx = apb_sequence_item::type_id::create("apb_sequence_item");
    forever begin
        @(posedge vapb_intf.pclk)

       
        //USE "if statement" for synchonize between driver and Monitor write() functions in scoreboard.
         if (vapb_intf.penable) begin //USE "if statmenet" for synchonize between driver and Monitor write() functions in scoreboard.

            vapb_intf.collect_data(apb_rx.address, apb_rx.data, apb_rx.acc);

When I check apb_if then I got the NULL.

vapb_intf = m_cfg.apb_if;
        `uvm_info(get_type_name(), $psprintf("!!!!!!t is: %p", m_cfg.apb_if),UVM_LOW)

But When I check the active variavle then I got the UVM_ACTIVE well.


        `uvm_info(get_type_name(), $psprintf("!!!!!!t is: %p", m_cfg.active),UVM_LOW)

and this is my configuration class.

class apb_master_config extends uvm_object;
    `uvm_object_utils(apb_master_config)

    virtual apb_interface apb_if;

    function new (string name = "");
        super.new(name);
    endfunction

    uvm_active_passive_enum active = UVM_ACTIVE;

    logic [1:0] id = 1;
    bit has_functional_coverage = 1;
    bit has_scoreboard = 0;
    logic [31:0] start_adress[15:0];
    logic [31:0] r_data[15:0];
    int no_select_line = 1;

endclass

How to pass the virtual interface by using configuration into other class?

In reply to UVM_LOVE:

You have to pass the interface using the uvm_config_db (using set) directly from your test bench, where you instantiate the DUT and connect it to a real instance of an apb_interface (not virtual!).
Then in the build_phase of your apb_basic_test after you create the m_cfg you can assign m_cfg.apb_if using the get method of the uvm_config_db

In reply to sylvainb:

In reply to UVM_LOVE:
You have to pass the interface using the uvm_config_db (using set) directly from your test bench, where you instantiate the DUT and connect it to a real instance of an apb_interface (not virtual!).
Then in the build_phase of your apb_basic_test after you create the m_cfg you can assign m_cfg.apb_if using the get method of the uvm_config_db

Basically, My testbench.sv looks like as the below


`include "uvm_macros.svh"
 import uvm_pkg::*;

`include "apb_master_agent.sv"
`include "apb_scoreboard.sv"
`include "apb_master_environment.sv"
...
`include "apb_basic_test.sv"

module top;
  int i;
  apb_interface apb_intf();

  assign apb_intf.pready=apb_intf.pselect&apb_intf.penable;
  
  always
    #5 apb_intf.pclk=!apb_intf.pclk;
   
  
  DUT u_DUT(

    .a(apb_intf.paddress), //[9:0]
    .b(apb_intf.pwdata),   //[31:0]
    //output    
    .c(apb_intf.preaddata) //[31:0]
  );


  initial
    begin
    apb_intf.presetn=1'b1;
  end

  initial
    begin
     i=3;
      uvm_config_db#(virtual apb_interface)::set(null,"*","apb_master_intf",apb_intf);
      run_test("apb_basic_test");
    end
endmodule

As your answer, I declared uvm_config_db#(virtual apb_interface)::set(null,“*”,“apb_master_intf”,apb_intf);

then in the build_phase of apb_basic_test.sv

I declared as the below.

virtual function void build_phase(uvm_phase phase);
 super.build_phase(phase);
 m_cfg=apb_master_config::type_id::create("m_cfg",this);
 uvm_config_db #(apb_master_config)::set(this, "*",  "apb_master_config", m_cfg);

But still I got NULL point ERROR

In apb_monitor.sv

class apb_monitor extends uvm_monitor;

    `uvm_component_utils(apb_monitor)

    virtual apb_interface vapb_intf;
    apb_sequence_item apb_rx;
    apb_master_config m_cfg;

function new(string name="apb_monitor", uvm_component parent = null);
    super.new(name, parent);
endfunction

uvm_analysis_port #(apb_sequence_item) my_mon_port;

virtual function void build_phase(uvm_phase phase);
    super.build_phase(phase);
    my_mon_port = new ("my_mon_port", this);
/*
   if (! uvm_config_db #(virtual apb_interface) :: get (this, "", "apb_master_intf", vapb_intf)) begin
      `uvm_fatal (get_type_name (), "Monitor Didn't get handle to virtual interface virtualapb_intf")
    end
*/

endfunction 

virtual function void connect_phase(uvm_phase phase);
    super.connect_phase(phase);
    if(!uvm_config_db #(apb_master_config)::get(this, "*", "apb_master_config", m_cfg))
        `uvm_fatal("FATAL MSG", "Configuration object is not set properly")
    
    vapb_intf = m_cfg.apb_if;
        `uvm_info(get_type_name(), $psprintf("!!!!!!t is: %p", m_cfg.apb_if),UVM_LOW)

endfunction

In reply to UVM_LOVE:

You should write in the build_phase of your test:
m_cfg=apb_master_config::type_id::create(“m_cfg”,this);
uvm_config_db #(apb_master_config)::get(this, “”, “apb_master_intf”, m_cfg.apb_if);

In reply to sylvainb:

In reply to UVM_LOVE:
You should write in the build_phase of your test:
m_cfg=apb_master_config::type_id::create(“m_cfg”,this);
uvm_config_db #(apb_master_config)::get(this, “”, “apb_master_intf”, m_cfg.apb_if);

After fixing the code as the below
testbench.sv

...
 import uvm_pkg::*;

`include "apb_interface.sv"
...
`include "apb_basic_test.sv"

module top;

  apb_interface apb_intf();

  DUT u_DUT(

    .a(apb_intf.paddress), //[9:0]
    .b(apb_intf.pwdata),   //[31:0]
  .c(apb_intf.preaddata) //[31:0]
  );


  initial
    begin
      uvm_config_db#(virtual apb_interface)::set(null,"*","apb_master_intf",apb_intf);
      run_test("apb_basic_test");
    end
endmodule

and apb_basic_test.sv


class apb_basic_test extends uvm_test;
  ...
  `uvm_component_utils_begin(apb_basic_test)
  `uvm_component_utils_end

  apb_master_config m_cfg;
  apb_master_environment apb_environment;//evironment handle 
  
  function new(string name="apb_basic_test", uvm_component parent);
    super.new(name,parent);
    `uvm_info(get_type_name(),"the objection test object has been built",UVM_LOW);
  endfunction
  
  virtual function void build_phase(uvm_phase phase);
    super.build_phase(phase);
    m_cfg=apb_master_config::type_id::create("m_cfg",this);
    uvm_config_db #(apb_master_config)::set(this, "*",  "apb_master_config", m_cfg);
    uvm_config_db #(virtual interface apb_interface)::get(this, "", "apb_master_intf", m_cfg.apb_if);

    apb_environment = apb_master_environment::type_id::create("apb_environment",this);
    seq = apb_sequence::type_id::create("seq", this);
    
   endfunction

and this is apb_master_env.sv


class apb_master_environment extends uvm_env;
  
  `uvm_component_utils(apb_master_environment)
  
  apb_master_config m_cfg;
  apb_master_agent apb_agent;
  apb_scoreboard apb_sb;
  
  function new(string name="apb_master_environment",uvm_component parent);
    super.new(name,parent);
  endfunction
  
  virtual function void build_phase(uvm_phase phase);
    super.build_phase(phase);

    if(!uvm_config_db #(apb_master_config)::get(this, "*", "apb_master_config", m_cfg))
        `uvm_fatal("FATAL MSG", "Configuration object is not set properly")

    apb_agent=apb_master_agent::type_id::create("apb_agent",this);
    if(apb_agent==null)
      `uvm_fatal(get_type_name(),"the apb agent has not been built");

    apb_sb = apb_scoreboard::type_id::create("apb_sb", this);
    if(apb_sb==null)
        `uvm_fatal(get_type_name(), "the apb_sb has not been created");

    apb_agent.m_cfg = m_cfg;
    
   endfunction

and apb_master_agent.sv


class apb_master_agent extends uvm_agent;

  apb_master_config m_cfg;

  apb_sequencer sequencer;
  apb_master_driver driver;
  apb_monitor monitor;
  apb_master_coverage coverage;


  `uvm_component_utils(apb_master_agent)

  function new(string name="apb_master_agent", uvm_component parent);
    super.new(name,parent);
  endfunction

  virtual function void build_phase(uvm_phase phase);
    super.build_phase(phase);

    if(!uvm_config_db #(apb_master_config)::get(this, "*", "apb_master_config", m_cfg))
        `uvm_fatal("FATAL MSG", "Configuration object is not set properly")
      
        `uvm_info(get_type_name(), $psprintf("agent is: %p", m_cfg.active),UVM_LOW)
        `uvm_info(get_type_name(), $psprintf("vif: %p", m_cfg.apb_if), UVM_LOW)
    
        
    /// Monitor will Always Be Available ///
    monitor=apb_monitor::type_id::create("monitor",this);
    if(monitor==null)
      `uvm_fatal(get_type_name(),"the monitor has not beed built");
        
    /// Driver & Sequencer will be Implemented only in ACTIVE mode
    if(m_cfg.active == UVM_ACTIVE) begin
        driver=apb_master_driver::type_id::create("driver",this);
        sequencer=apb_sequencer::type_id::create("sequencer", this);
  
        if(sequencer==null)
          `uvm_fatal(get_type_name(),"the sequecer has not been built");
        if(driver==null)
          `uvm_fatal(get_type_name(),"the driver has not been built");


and this is the apb_master_agent.sv

``` verilog

class apb_master_agent extends uvm_agent;

  apb_master_config m_cfg;

  apb_sequencer sequencer;
  apb_master_driver driver;
  apb_monitor monitor;
  apb_master_coverage coverage;


  `uvm_component_utils(apb_master_agent)

  function new(string name="apb_master_agent", uvm_component parent);
    super.new(name,parent);
  endfunction

  virtual function void build_phase(uvm_phase phase);
    super.build_phase(phase);

    if(!uvm_config_db #(apb_master_config)::get(this, "*", "apb_master_config", m_cfg))
        `uvm_fatal("FATAL MSG", "Configuration object is not set properly")
      
        `uvm_info(get_type_name(), $psprintf("agent is: %p", m_cfg.active),UVM_LOW)
        `uvm_info(get_type_name(), $psprintf("vif: %p", m_cfg.apb_if), UVM_LOW)
    
        
    /// Monitor will Always Be Available ///
    monitor=apb_monitor::type_id::create("monitor",this);
    if(monitor==null)
      `uvm_fatal(get_type_name(),"the monitor has not beed built");
        
    /// Driver & Sequencer will be Implemented only in ACTIVE mode
    if(m_cfg.active == UVM_ACTIVE) begin
        driver=apb_master_driver::type_id::create("driver",this);
        sequencer=apb_sequencer::type_id::create("sequencer", this);
  
        if(sequencer==null)
          `uvm_fatal(get_type_name(),"the sequecer has not been built");
        if(driver==null)
          `uvm_fatal(get_type_name(),"the driver has not been built");

and this is the apb_master_monitor.sv

class apb_monitor extends uvm_monitor;

    `uvm_component_utils(apb_monitor)

    virtual apb_interface vapb_intf;
    apb_sequence_item apb_rx;
    apb_master_config m_cfg;

function new(string name="apb_monitor", uvm_component parent = null);
    super.new(name, parent);
endfunction

uvm_analysis_port #(apb_sequence_item) my_mon_port;

virtual function void build_phase(uvm_phase phase);
    super.build_phase(phase);
    my_mon_port = new ("my_mon_port", this);
/*
   if (! uvm_config_db #(virtual apb_interface) :: get (this, "*", "apb_master_intf", vapb_intf)) begin
      `uvm_fatal (get_type_name (), "Monitor Didn't get handle to virtual interface virtualapb_intf")
    end
*/

endfunction

virtual function void connect_phase(uvm_phase phase);
    super.connect_phase(phase);
    if(!uvm_config_db #(apb_master_config)::get(this, "", "apb_master_config", m_cfg))
        `uvm_fatal("FATAL MSG", "Configuration object is not set properly")
    
    vapb_intf = m_cfg.apb_if;
        `uvm_info(get_type_name(), $psprintf("!!!!!!t is: %p", m_cfg.apb_if),UVM_LOW)

endfunction

virtual task run_phase(uvm_phase phase);
    apb_rx = apb_sequence_item::type_id::create("apb_sequence_item");
    forever begin
        @(posedge vapb_intf.pclk)

After change it as the below

 virtual function void build_phase(uvm_phase phase);
    uvm_config_int::set(this, "*", "recording_detail", 1);
    super.build_phase(phase);
    m_cfg=apb_master_config::type_id::create("m_cfg",this);
    uvm_config_db #(apb_master_config)::set(this, "*",  "apb_master_config", m_cfg);

//  uvm_config_db #(apb_master_config)::get(this, "", "apb_master_intf", m_cfg.apb_if);
    uvm_config_db #(virtual interface apb_interface)::get(this, "", "apb_master_intf", m_cfg.apb_if);

Simulation is done well . but I am still in doubt what I am correctly implemented as your recommand or not.

In reply to UVM_LOVE:

For removing the doubt about what you are doing with the config, I would recommend you to use the uvm_config_db debugger that comes with your simulator GUI. It allows you to see and trace where the set and get are done for each item.
You can also use the option :“+UVM_CONFIG_DB_TRACE” in the command line

In reply to sylvainb:

In reply to UVM_LOVE:
For removing the doubt about what you are doing with the config, I would recommend you to use the uvm_config_db debugger that comes with your simulator GUI. It allows you to see and trace where the set and get are done for each item.
You can also use the option :“+UVM_CONFIG_DB_TRACE” in the command line

Thank you!! again sylvainb