Jump to content
Sign in to follow this  
cliffc

FATAL UVMREG register write operation

Recommended Posts

Hi, All -

 

I am hoping someone can spot my error in the following example.

 

I am missing a handle while running a test and getting a handle fatal message.

 

I am not 100% sure I am assigning the correct dutmap and the error happens when I try to do a reg-write from the tr_sequence. Pertinent code below. More code upon request.

 

Regards  - Cliff

 

 

From test1.sv:

  task run_phase(uvm_phase phase);

    tr_sequence seq = tr_sequence::type_id::create("seq");

    //----------------------------------------

    phase.raise_objection(this);

    //`uvm_do(seq)

    //seq.start(null);

    seq.start(e.vsqr.tb_sqr);

    phase.drop_objection(this);

  endtask

 

From tr_seq_base.sv

  dutblk           model;

 

  rand logic[15:0] data;

  uvm_status_e     status;

...

   

  task body;

    get_model();

  endtask

   

// Tried getting the reg_model handle two different ways - not sure either is working

  virtual function void get_model();

    uvm_object tmpobj;

    `uvm_info("TR_SEQ_BASE",{"get_full_name: ", get_full_name()},UVM_FULL)

    if(uvm_config_object::get(get_sequencer(),"","reg_model", tmpobj))

      if (!($cast(model, tmpobj))) `uvm_fatal("TR_SEQ_BASE", "BAD config cast operation")

   

    //`uvm_info("TR_SEQ_BASE",{"get_full_name: ", get_full_name(),".agnt.sqr"},UVM_FULL)

    //if(!(uvm_config_db#(dutblk)::get(null,{get_full_name(),".agnt.sqr"},"reg_model", model)))

      //`uvm_fatal("NO_REG_CONFIG", "Seq reg model was not set")

  endfunction

 

From tr_sequence.sv

  task body;

    super.body();

    `uvm_info("TRSEQ","going to randomize this.data",UVM_DEBUG)

 

     assert(this.randomize());

    `uvm_info("TRSEQ","going to reg-write data",UVM_DEBUG)

     model.gp_reg0.write(status, data, .parent(this));  // *** FAILS HERE ***

    `uvm_info("TRSEQ","done reg-write-ing data",UVM_DEBUG)

     assert(this.randomize());

     model.gp_reg1.reg1.write(status, data, .parent(this));

 

From env.sv

  tb_agent   agnt;

  vsequencer vsqr;

 

  dutblk                     model;   // Register model object

  reg2dut_adapter            reg2dut; // Bus adapter object

  uvm_reg_predictor#(trans1) predict; // predictor component

...

  function void build_phase(uvm_phase phase);

    super.build_phase(phase);

    agnt   =                    tb_agent::type_id::create("agnt", this);

    vsqr   =                  vsequencer::type_id::create("vsqr", this);

    

    model   =                     dutblk::type_id::create("model");

    reg2dut =            reg2dut_adapter::type_id::create("reg2dut");

    predict = uvm_reg_predictor#(trans1)::type_id::create("predict", this);

     

    model.build();

    model.lock_model();

// TRIED storing this handle two ways

    uvm_config_object::set(this,"*","reg_model", model);

    //uvm_config_db#(dutblk)::set(uvm_root::get(),"*","reg_model", model);

  endfunction

   

  function void connect_phase(uvm_phase phase);

    super.connect_phase(phase);

    `uvm_info("ENV",{"get_full_name.vsqr: ", get_full_name(), ".vsqr.tb_sqr"},UVM_DEBUG)

    `uvm_info("ENV",{"get_full_name.sqr : ", get_full_name(), ".agnt.sqr"},UVM_DEBUG)

    vsqr.tb_sqr = agnt.sqr;

    `uvm_info("ENV","copied agnt.sqr handle",UVM_DEBUG)

 

    model.dutmap.set_sequencer(agnt.sqr, predict);

    //predict.map     = model.default_map;

    predict.map     = model.dutmap;

    predict.adapter = reg2dut;

    // connect the predictor to the bus agent monitor analysis port

    agnt.aport.connect(predict.bus_in);

  endfunction

 

From dutblk class:

   class dutblk extends uvm_reg_block;

      `uvm_object_utils(dutblk)

 

      rand gp_reg0_reg gp_reg0; // General Purpose Reg0

      rand gp_reg1_reg gp_reg1; // General Purpose Reg1

 

      uvm_reg_map dutmap; // dutregs bus map

 

 

      // Function: new

      //

      function new(string name = "dutblk");

         super.new(name, UVM_NO_COVERAGE);

      endfunction

 

 

      // Function: build

      //

      virtual function void build();

         gp_reg0 = gp_reg0_reg::type_id::create("gp_reg0");

         gp_reg0.configure(this);

         gp_reg0.build();

 

         gp_reg1 = gp_reg1_reg::type_id::create("gp_reg1");

         gp_reg1.configure(this);

         gp_reg1.build();

 

         dutmap = create_map("dutmap", 'h0, 2, UVM_LITTLE_ENDIAN);

         default_map = dutmap;

 

         dutmap.add_reg(gp_reg0, 'h0, "RW");

         dutmap.add_reg(gp_reg1, 'h2, "RW");

 

         lock_model();

      endfunction

   endclass

 

FATAL error message from :

     model.gp_reg0.write(status, data, .parent(this));  // *** FAILS HERE ***

 

 

# UVM_INFO env.sv(42) @ 0: uvm_test_top.e [ENV] get_full_name.vsqr: uvm_test_top.e.vsqr.tb_sqr

# UVM_INFO env.sv(43) @ 0: uvm_test_top.e [ENV] get_full_name.sqr : uvm_test_top.e.agnt.sqr

# UVM_INFO env.sv(45) @ 0: uvm_test_top.e [ENV] copied agnt.sqr handle

# UVM_INFO verilog_src/questa_uvm_pkg-1.2/src/questa_uvm_pkg.sv(272) @ 0: reporter [Questa UVM] End Of Elaboration

# UVM_INFO verilog_src/uvm-1.1d/src/seq/uvm_sequencer_base.svh(1385) @ 0: uvm_test_top.e.vsqr [PHASESEQ] No default phase sequence for phase 'run'

# UVM_INFO verilog_src/uvm-1.1d/src/seq/uvm_sequencer_base.svh(1385) @ 0: uvm_test_top.e.agnt.sqr [PHASESEQ] No default phase sequence for phase 'run'

# UVM_INFO tb_driver.sv(40) @ 0: uvm_test_top.e.agnt.drv [iNIT] Initialize (time @0)

# UVM_INFO tb_driver.sv(29) @ 0: uvm_test_top.e.agnt.drv [DEBUG: Driver Run] ... getting next item ...

# UVM_INFO tr_seq_base.sv(30) @ 0: uvm_test_top.e.agnt.sqr@@seq [TR_SEQ_BASE] get_full_name: uvm_test_top.e.agnt.sqr.seq

# UVM_INFO tr_sequence.sv(21) @ 0: uvm_test_top.e.agnt.sqr@@seq [TRSEQ] going to randomize this.data

# UVM_INFO tr_sequence.sv(24) @ 0: uvm_test_top.e.agnt.sqr@@seq [TRSEQ] going to reg-write data

# ** Fatal: (SIGSEGV) Bad handle or reference.

#    Time: 0 ns  Iteration: 50  Process: /uvm_pkg::uvm_sequence_base::start/#FORK#294_b7048b8 File: /home/packages/questasim_10.3c/questasim/linux/../verilog_src/uvm-1.1d/src/reg/uvm_reg.svh

# Fatal error in Task uvm_pkg/uvm_reg_map::do_write at /home/packages/questasim_10.3c/questasim/linux/../verilog_src/uvm-1.1d/src/reg/uvm_reg_map.svh line 1734

 

Share this post


Link to post
Share on other sites

I find the message really strange, as there is an if there that explicitly guards against 'null' pointers:

if (adapter != null && adapter.parent_sequence != null) begin
  uvm_object o;
  uvm_sequence_base seq;
  o = adapter.parent_sequence.clone(); // this is line 1734
  //...

Have you tried stepping through the code to see what is null there?

 

@Uwe: I think this is how QuestaSim displays null pointer accesses in SV in its console, with SIGSEGV.

Share this post


Link to post
Share on other sites

@Uwe: I think this is how QuestaSim displays null pointer accesses in SV in its console, with SIGSEGV.

 

 

yes, at the first glance there should no nullptr error in that line given that this is an unmodified uvm11d (you never know). SIGSEGV is a very specific error typically only used by the OS itself. in any case i would think this is a tool issue 

 

/uwe

Share this post


Link to post
Share on other sites

Hi, All -

 

My thanks to those who responded and especially to my friends and colleagues, Tom Fitzpatrick of Mentor and Heath Chambers of HMC Design Verification for helping me to spot and correct the problems.

 

The biggest issue was that I passed the sequencer and predictor handles to the reg-model using the set_sequencer command. I should have passed the sequencer and adapter handles to the set_sequencer command. This caused the null-handle references (SIGSEGV - this was not a tool issue - this was my mistake):

    ERROR:   model.dutmap.set_sequencer(agnt.sqr, predict);

    CORRECT: model.dutmap.set_sequencer(agnt.sqr, reg2dut);

 

Two other useful modifications were to store the model handle created in the env class using the uvm_config_db as shown:

    NEW: uvm_config_db#(dutblk)::set(this,"agnt.sqr","reg_model", model);

Better than what I had:

    OLD: uvm_config_db#(dutblk)::set(this,"*","reg_model", model);

This stores the reg model handle in the uvm_config_db, accessible from the env.agnt.sqr.

 

I also modified how the tr_seq_base class extracts the reg model handle from the uvm_config_db using the command:

    if(!(uvm_config_db#(dutblk)::get(null,m_sequencer.get_full_name(),"reg_model", model)))
      `uvm_fatal("NO_REG_CONFIG", "Seq reg model was not set"

The reference to m_sequencer.get_full_name() returns the full name of the sequencer where the uvm_config_db has the stored model handle.

 

The example is now running. Thanks!

 

Regards - Cliff Cummings

Share this post


Link to post
Share on other sites

well,

 

>    ERROR:   model.dutmap.set_sequencer(agnt.sqr, predict);

>    CORRECT: model.dutmap.set_sequencer(agnt.sqr, reg2dut);

 

 

if im not mistaken the tool should have rejected this assignment since its not type compatible in the first place.

 

   extern virtual function void set_sequencer (uvm_sequencer_base sequencer, uvm_reg_adapter    adapter=null);

 

Two other useful modifications were to store the model handle created in the env class using the uvm_config_db as shown:

    NEW: uvm_config_db#(dutblk)::set(this,"agnt.sqr","reg_model", model);

Better than what I had:

    OLD: uvm_config_db#(dutblk)::set(this,"*","reg_model", model);

This stores the reg model handle in the uvm_config_db, accessible from the env.agnt.sqr.

 

 
both should have the same effect. when you distribute the same regmodel to different sequencers then the wildcard is usually better (simpler+faster). 
 
    if(!(uvm_config_db#(dutblk)::get(null,m_sequencer.get_full_name(),"reg_model", model)))
      `uvm_fatal("NO_REG_CONFIG", "Seq reg model was not set"

 

 

i usually prefer the ::get(get_sequencer(),"","reg_model", model)

because it avoid the string handling, is to some extend type safe and it doesnt use the m_* variable (which is an uvm internal). Also it might be better to further expand the check. 

 

    if(!(uvm_config_db#(dutblk)::get(get_sequencer(),"","reg_model", model))) begin

      if(model==null) `uvm_fatal("NO_REG_CONFIG","reg model set to NULL") 

    end else

      `uvm_fatal("NO_REG_CONFIG", "Seq reg model was not set"

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  

×