Uvm agent/driver/monitor with cfg question

Here is my_agent code:



class my_agent extends uvm_agent;

  my_sqr sqr;
  my_drv drv;
  my_mon mon;
  uvm_analysis_port #(my_mon) ap;

  my_cfg cfg;

  function void build_phase(uvm_phase phase);
    super.build_phase(phase);
    cfg = my_cfg::type_id::create("cfg", this);
    uvm_config_db#(my_cfg)::get(this, "", "cfg", cfg);

    if (cfg.has_drv) begin
        sqr = my_sqr::type_id::create("sqr", this);
        drv = my_drv::type_id::create("drv", this);
    end

    if (cfg.has_mon) begin
        mon = my_mon::type_id::create("mon", this);
    end
  endfunction

  function void connect_phase(uvm_phase phase);
    super.connect_phase(phase);
    if (cfg.has_drv) begin
        drv.seq_item_port.connect(sqr.seq_item_export);
    end

    if (cfg.has_mon) begin
        this.ap = mon.ap;            <= Here is what I suspect...
    end
  endfunction

endclass


Here is my cfg code :


class my_cfg extends uvm_object;

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

    `uvm_object_utils(my_cfg)

    bit has_drv, has_mon;
endclass

Here is my monitor code :


class my_monitor extends uvm_monitor;

    `uvm_component_utils(my_monitor)

    uvm_analysis_port #(ITEM_TYPE) ap;

    function new(string name, uvm_component parent);
        super.new(name, parent);
    endfunction : new

    function void build_phase(uvm_phase phase);
        super.build_phase(phase);
        ap = new("ap", this);
    endfunction : build_phase
...
...
endclass

When I set has_mon be 1 in my_env file for all the agent/driver/monitor/…(which is derived from my_agent/my_driver/my_monitor/…), they are successfully to pass the compilation.
But if I set has_mon be 0 in a certain monitor, it will fail at compile error as below.

Could not find member ‘ap’

Shall I know why it happened ?

In reply to zz8318:

In your agent I do not see where you are constructing the analysis port ap.

In reply to chr_sue:

In my_agent, I declared the ap as below


  uvm_analysis_port #(my_mon) ap;

and if has_mon=1, I will use it like below.


 
    if (cfg.has_mon) begin
        this.ap = mon.ap;            <= Here is what I suspect...
    end

I guess each child agent (based on this my_agent) will check the associated monitor ap whatever has_mon is 1 or 0…

In reply to zz8318:

This is how you want to connect your analysis ports. But the construction is missing.
It is like this in the build_phase:

ap = new("ap", this);

After calling new the ap is existing.

In reply to chr_sue:

I am not sure if this “new” statement is required in build_phase. (because others are passed if has_mon = 1. The only failure is occurred when I set has_mon be 0 for a certain child agent)

In reply to zz8318:

I do not believe this. Because in the code you are providing the ap is never contructed.
You have only a reference and this is ‘null’. After calling the constructor the object exists.

In reply to chr_sue:

Actually I already tried it but not effected.
Anyway thank you for your suggestion and I will investigate it more…

In reply to zz8318:

Where are you setting the configuration object and passing it to the config_db.
Did you check the content of the cfg object after retrieving it from the config_db?

In reply to chr_sue:

I set the cfg in my_env file as shown below.


  my_agent m_agt;
  my_cfg m_cfg;
...
  m_agt  = my_agent::type_id::create("m_agt", this);
  m_cfg  = my_cfg::type_id::create("m_cfg", this);
  m_cfg.has_drv = 1;
  m_cfg.has_mon = 0;
   uvm_config_db#(my_cfg)::set(this, "m_agt", "cfg", m_cfg);
...


and in the agent file, we get this cfg.


...
    cfg = my_cfg::type_id::create("cfg", this);

    uvm_config_db#(my_cfg)::get(this, "", "cfg", cfg);

    if (cfg.has_drv) begin
        sqr = my_sqr::type_id::create("sqr", this);
        drv = my_drv::type_id::create("drv", this);
    end
    if (cfg.has_mon) begin
        mon = my_mon::type_id::create("mon", this);
        ap  = new("ap", this);
    end


In reply to zz8318:

Looks good, but checking the get was successful like this:

if (!uvm_config_db#(my_cfg)::get(this, "", "cfg", cfg);)
  `uvm_error(get_type_name(), "get was not successful")

made the get safe.