P_sequencer is a null object access

I hit below error in my uvm testbench. and I have no idea how to fix it.

Error-[NOA] Null object access
The object at dereference depth 1 is being used before it was constructed/allocated.
Please make sure that the object is allocated before using it.

Here is some related code pasted below.

  1. base_sqr.sv
    class base_sqr extends uvm_sequencer;

    endclass

  2. my_sqr.sv
    class my_sqr extends base_sqr;

    task send_base();

    endtask
    endclass

  3. my_seq.sv
    typedef class my_sqr;
    classs my_seq extends uvm_sequence #(my_trans);

    `uvm_declare_p_sequencer(my_sqr)
    task send();
    my_trans m_trans = new;

    p_sequencer.send_base(m_trans);
    endtask

    endclass

appreciate for any help !

In reply to zz8318:

Several suggestions:

  1. You should never need to create your own sequencers. Instead, you should use a typedef to define them:

typedef uvm_sequencer#(my_seq_item) my_sequencer;

  1. If you think you need to define your own sequencer, you don’t. If you are creating a virtual sequencer by adding sequencer handles, add the sequencer handles to the virtual sequence instead.

  2. Never use `uvm_declare_p_sequencer(). This will tie a sequence to a specific sequencer and significantly reduce the reusability of the sequence.

  3. If you need to reference the sequencer that a sequence is running on, use m_sequencer.

In reply to cgales:

Thanks for your suggestion… I have to use p_sequencer in our project due to the legacy reason and I will think about it how to fix it …

In reply to zz8318:

It’s hard to use something if it is generating errors. There is never a need to use p_sequencer, and I consider the ‘legacy’ excuse to be very poor.

However, after getting off my soap box, you should never see a null p_sequencer handle if everything occurs in the correct phases. All of the build_phase() should be complete prior to any run_phase() execution. I’m assuming that you are calling send() in the run_phase()?

You should also make sure to use:


m_trans = my_trans::type_id::create("m_trans");

instead of calling new(). This will ensure that p_sequencer is assigned correctly.

In reply to cgales:

Yes, I called send() in the run_phase… is that ok ?

In reply to zz8318:

Yes, you should only use it in the run_phase().

Make sure you use the create() instead of new().

In reply to zz8318:

I looked through the code and figured out your issue.

A sequence is designed to have a body() task, which executes when start() is called. As part of the start() task, the p_sequencer handle is assigned correctly.

Since you are inexplicably not using body() and are instead creating your own send() task, this underlying process is bypassed. Part of the start() call includes the sequencer that the sequence will be running on. You will need to somehow pass the sequencer handle to your send() task. You will also need to assign the sequencer handle to m_sequencer and call m_set_p_sequencer().

Or you could use the body() task per the UVM guidelines.