How to pass a regmodel from top_env to a sequence?

Hi,all:
I want to do some register model operating in sequence ,but I have initial this register model in my top_env,I use virtual sequence to do this job,but nc tells me ,that the pointer of regmodel is null, maybe the regmodel is used before it constructed. I don’t konw how to describe this problem , so, here is my code .

my_reg.sv

`ifndef MY_REG
`define MY_REG

import uvm_pkg::*;

class my_ram extends uvm_mem;
  function new(string name="n_ram");
    super.new(name,`UVM_REG_ADDR_WIDTH'h400,32,"RW",build_coverate(UVM_NO_COVERAGE));
  endfunction 
  virtual function void build();
  endfunction : build
  `uvm_object_utils(my_ram)
endfunction : my_ram

class my_reg_block extends uvm_reg_block;
  rand my_ram n_ram;
  function new(string name = "regmodel");
    super.new(name,build_coverage(UVM_NO_COVERAGE));
  endfunction : new
  virtual function void build();
    this.default_map=create_map("",0,4,UVM_LITTLE_ENDIAN);
    this.n_ram=my_ram::type_id::create("n_ram");
    this.n_ram.build();
    this.n_ram.configure(this,"n_ram.mem");
    this.default_map.add_mem(this.n_ram,`UVM_REG_ADDR_WIDTH'h0,"RW",0);
endclass : my_reg_block
`endif

reg_tb.sv

`ifndef REG_TB
`define REG_TB
 
`include "my_config.sv"
`include "reg_req_lib.sv"
`include "ral_apb_reg_block.sv"
 
class reg_tb extends uvm_env;
    `uvm_component_utils(reg_tb)
    apb_env  apb0;
    my_config  cfg;
    my_reg_block regmodel;
    reg_to_apb_adapter  reg_sqr_adapter;
    reg_to_apb_adapter  mon_reg_adapter;
    uvm_reg_predictor#(apb_transfer) reg_predictor;
 
    function new(string name,uvm_component parent);
        super.new(name,parent);
    endfunction:new
    virtual function void build_phase(uvm_phase phase);
        super.build_phase(phase);
        cfg=my_config::type_id::create("cfg");
        apb0=apb_env::type_id::create("apb0",this);
        uvm_config_object::set(this,"apb0*","cfg",cfg);
        uvm_config_object::set(this,"slave[0]*","cfg",cfg.slave_configs[0]);
 
        regmodel=my_reg_block::type_id::create("regmodel",,get_full_name());
        regmodel.configure(null,"top.u_dut.apb_slave");
        regmodel.build();
        regmodel.lock_model();
        regmodel.reset();
        reg_sqr_adapter=reg_to_apb_adapter::type_id::create("reg_sqr_adapter",,get_full_name());
        mon_reg_adapter=reg_to_apb_adapter::type_id::create("mon_reg_adapter",,get_full_name());
        reg_predictor=new("reg_predictor",this);
    endfunction : build_phase
 
    virtual function void connect_phase(uvm_phase phase);
        regmodel.default_map.set_sequencer(apb0.master.sequencer,reg_sqr_adapter);
        regmodel.default_map.set_auto_predict(1);
        reg_predictor.map=apb_slave.default_map;
        reg_predictor.adapter=mon_reg_adapter;
        apb0.master.monitor.item_collected_port.connect(reg_predictor.bus_in);
    endfunction:connect_phase
endclass : reg_tb
`endif

vsequencer.sv

class vsequencer extends uvm_sequencer;
   `uvm_component_utils(vsequencer)
     apb_master_sequencer   apb_seq;
     my_reg_block   regmodel;
     function new(string name,uvm_component parent);
         super.new(name,parent);
     endfunction
endclass:vsequencer

reg_seq_lib.sv

`ifndef REG_SEQ_LIB
`define REG_SEQ_LIB

`include "vsequencer.sv"
class my_reg_seq extends uvm_reg_sequence;
    my_reg_block regmodel;
    `uvm_object_utils(my_reg_seq)
    function new(string name ="my_reg_seq");
        super.new(name);
    endfunction : new
    rand uvm_reg_addr_t addr;
    rand uvm_reg_data_t data;
    virtual task body();
        uvm_status_e status;
        if(starting_phase != null)
            starting_phase.raise_objection(this,{"Running sequence '"get_full_name(),"'"});
        addr=32'h0;
        data=32'h1;
        regmodel=my_reg_block::type_id::create("regmodel");
        repeat(10) begin
            regmodel.n_ram.write(status,addr,data,.parent(this));
            addr++;
            data += 32'h10;
        end
        if(starting_phase != null)
            starting_phase.drop_objection(this,{"Completed sequence '",get_full_name(),"'"});
    endtask : body
endclass : my_reg_seq

class  vsequence  extends uvm_sequence;
   `uvm_object_utils(vsequence)
   `uvm_declare_p_sequencer(vsequencer)
    my_reg_seq   reg_seq;
    function  new(string name="vsequence");
        super.new(name);
    endfunction : new
    virtual   task  body();
        reg_seq=my_reg_seq::type_id::create("reg_seq");
        reg_seq.regmodel=p_sequencer.regmodel;
        reg_seq.start(null);
    endtask : body
endclass : vsequence
           
`endif

reg_test_lib.sv

`ifndef REG_TEST_LIB
`define REG_TEST_LIB

`include "reg_tb.sv"
`include "vsequencer.sv"

class reg_test extends uvm_test;
  `uvm_component_utils(reg_test)
  reg_tb reg_tb0;
  vsequencer vsqr;
  function new(string name ,uvm_component parent);
    super.new(name,parent);
  endfunction : new
  virtual function void build_phase(uvm_phase phase);
    super.build_phase(phase);
    reg_tb0=reg_tb::type_id::create("reg_tb0",this);
    uvm_config_db#(uvm_object_wrapper)::set(this,"vsqr.main_phase","default_sequence",vsequence::type_id::get());
  endfunction : build_phase
  virtual function void connect_phase(uvm_phase phase);
    vsqr.regmodel=reg_tb0.regmodel;
  endfunction : connect_phase
endclass :reg_test
`endif

What’s wrong with my code ,and how i modify it?

Just curious, where are you instantiating vsequencer handlr vsqr? I don’t see a create method being called for this anywhere.
This might be root cause for your problem. As handle is not created for this class accessing this item will provide null as output.

–Sireesh K

In reply to skumar:

Thanks a lot!
oh,That is the problem lies.thank you again.

Hi,

In above example, my reg_sequence is like below :

class base_reg_seq extends uvm_reg_sequence;

  `uvm_object_utils(base_reg_seq)

  my_reg_block                regmodel;
  uvm_status_e                status;
  uvm_reg_data_t              read_value;
  uvm_reg                     regs[$];

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

  function int get_max_ral_addr();// Calculate the max address of the register space
    regmodel.get_registers(regs, UVM_HIER);
    $display("\n regmodel size : %0d", regs.size()); // Here I am getting size as 0.
    return regs[regs.size() - 1].get_address(); // So, here I am getting Null Pointer Error
  endfunction : get_max_ral_addr
 
  task pre_body();
    if(starting_phase !=null)
      starting_phase.raise_objection(this,get_type_name());
  endtask

  task post_body();
      if(starting_phase != null)
        starting_phase.drop_objection(this,get_type_name());
  endtask
 
endclass
class reg_rsvd_xces_seq extends base_reg_seq;
  `uvm_object_utils(reg_rsvd_xces_seq)

  ips_transaction ips_trans;
  function new(string name="reg_rsvd_xces_seq");
    super.new(name);
  endfunction
  
  virtual task body();
    regmodel        = my_reg_block ::type_id::create("regmodel");
    regmodel.reset();
 
    `uvm_info(get_type_name(), $sformatf(" Checking xfr error on register access based on valid address space "), UVM_NONE)
    for(int addr = 0;  addr <= get_max_ral_addr()+4; addr = addr + 4) begin // Here : Null Pointer Error comes

      //Read Access
      //Write Access
    end
  endtask
endclass

What I am missing here ?? Please suggest me how to get rid of the Error…

In reply to birenkumar:

I have got the solution here.

I do not need to create the object for regmodel again. It’s already been connected from the env.

regmodel = my_reg_block ::type_id::create(“regmodel”);
regmodel.reset();

After removing above 2 lines from the body() of reg_rsvd_xces_seq, I am able to get rid of Null Pointer Issue.

In reply to oscillator:

Hi,

I think you need not require to create object of the regmodel inside your ‘my_reg_seq’ class’s body() method. Anyways you are connecting the regmodel from the env. So, you can directly use it in your seuqence’s body() method.

In my example I have checked it.

In reply to birenkumar:

Never create your Register mo0del more than once! Create your Register model in an agent, include it into a corresponding configuration object and pass this object to your config_db. Then you can retrieve it from everywhere including transient objects like sequences.

In reply to chr_sue:

HI chr_sue

I have a mem model generated which has multiple reg_blocks . Should I instantiate all those blocks in the env and build them or can you suggest a way to use all these reg blocks in top_env

In reply to verific_engi:

A reg_block is not a component in your testbench. It is considered like an uvm_object. As I said in a former post, you can create this reg_model in an config object and pass it to any place where you need it… If you need only a sub-part you can handle this in the same way.