How to get a p_sequencer from a sequence start?

Hi.

I came to know that start_item() is a method of an already running sequence - the sequencer was set when you started it. start_item/finish_item is used to send transactions to a driver, and thus must be connected to a sequencer. and start() is a method of a sequence object you just created, and in turn calls its body() method.

To understand the behavior of start_item() I commented out the task body() and implement as the below ,

class core_A_seq extends uvm_sequence #(seq_item);
  seq_item req;
  `uvm_object_utils(core_A_seq)
  
  function new (string name = "core_A_seq");
    super.new(name);
  endfunction
  
  task body();
    `uvm_info(get_type_name(), "core_A_seq: Inside Body", UVM_LOW);
    req = seq_item::type_id::create("req");
    req.core = CORE_A;
    wait_for_grant();
    assert(req.randomize());
    send_request(req);
    wait_for_item_done();
  endtask
endclass


class core_B_seq extends uvm_sequence #(seq_item);
  seq_item req;
  `uvm_object_utils(core_B_seq)
  
  function new (string name = "core_B_seq");
    super.new(name);
  endfunction
  
  task body();
    `uvm_info(get_type_name(), "core_B_seq: Inside Body", UVM_LOW);
    req = seq_item::type_id::create("req");
    req.core = CORE_B;
    wait_for_grant();
    assert(req.randomize());
    send_request(req);
    wait_for_item_done();
  endtask
endclass

// create a virtual sequence which holds core_A_seq and core_B_seq

class virtual_seq extends uvm_sequence #(seq_item);
  core_A_seq Aseq;
  core_B_seq Bseq;  
  
  core_A_sequencer seqr_A;
  core_B_sequencer seqr_B;
  `uvm_object_utils(virtual_seq)
  `uvm_declare_p_sequencer(virtual_sequencer)
  
  function new (string name = "virtual_seq");
    super.new(name);
  endfunction
  /*
  task body();
    `uvm_info(get_type_name(), "virtual_seq: Inside Body", UVM_LOW);
    Aseq = core_A_seq::type_id::create("Aseq");
    Bseq = core_B_seq::type_id::create("Bseq");
    
    Aseq.start(p_sequencer.seqr_A);
    Bseq.start(p_sequencer.seqr_B);
  endtask
  */
  task my_task();
    `uvm_info(get_type_name(), "virtual_seq: Inside Body", UVM_LOW);
    Aseq = core_A_seq::type_id::create("Aseq");
    Bseq = core_B_seq::type_id::create("Bseq");
    
    Aseq.start(p_sequencer.seqr_A);
    Bseq.start(p_sequencer.seqr_B);
  endtask
endclass


When I execute the sequence with start_item() I get the error

UVM_INFO @ 0: reporter [RNTST] Running test base_test…
UVM_INFO sequence.sv(65) @ 0: reporter@@v_seq [virtual_seq] virtual_seq: Inside Body
xmsim: *E,TRNULLID: NULL pointer dereference.
File: ./sequence.sv, line = 69, pos = 25
Scope: worklib.$unit_0x4ccdf83b::virtual_seq@4292_23.my_task
Time: 0 FS + 44

But I can’t understand why I can’t get the p_sequencer ?

In reply to UVM_LOVE:

You should never use p_sequencer as it ties you to a specific sequencer. Instead, you should assign the sequencers from your test so that the sequences run where required:


class virtual_seq extends uvm_sequence #(seq_item);
  core_A_seq Aseq;
  core_B_seq Bseq;  
 
  core_A_sequencer seqr_A;
  core_B_sequencer seqr_B;
  `uvm_object_utils(virtual_seq)
 
  function new (string name = "virtual_seq");
    super.new(name);
  endfunction

  task body();
    `uvm_info(get_type_name(), "virtual_seq: Inside Body", UVM_LOW);
    if (seqr_A == null || seqr_B == null)
      `uvm_fatal(get_full_name(), "Sequencers not set correctly");
    Aseq = core_A_seq::type_id::create("Aseq");
    Bseq = core_B_seq::type_id::create("Bseq");
 
    Aseq.start(seqr_A);
    Bseq.start(seqr_B);
  endtask
endclass

class my_test;
  // constructor/ factory registration
  env my_env;

  task run_phase(uvm_phase phase);
    virtual_seq my_seq = virtual_seq::type_id::create("my_seq");

    // raise objection....
    my_seq.seqr_A = my_env.agent_a.seqr;
    my_seq.seqr_B = my_env.agent_b.seqr;
    my_seq.start(null);

    // lower objection....
  endtask
endclass