Common Reg model access for uvm env and virtual seq library

Hi,

I am having some issue on reg model access, here is the problem description.

I have a uvm env which is integrated with axi vip to drive the transactions and also sequences interacting with reg model.
There is another virtual sequence library outside of the env which is also using same reg model for axi read/write.

I have instantiated reg model in env.svh and config_db is used to set with uvm_reg_block type.
Here is the snippet:

class toy_env extends uvm_env;
`uvm_component_utils(toy_env)

extern function new(string name = “toy_env”, uvm_component parent = null);

toy_AXIL4_cfg_s_mmap_block_type ral_model; ///< Register model

endclass

function void toy_env::build_phase(uvm_phase phase)
db_name = drive_me;
uvm_config_db #(uvm_reg_block)::set(null, “toy_tc_top”, db_name, ral_model);
endfunction

And in connect phase ral predictor is connected using set_sequencer.

in toy_env file there is instantiation of virtual sequencer having virtual sequence handle is created, which is outside of the toy_env.
This virtual sequence is using same reg model which is trying to get from the config_db with same type as uvm_reg_block
uvm_reg_block b;
uvm_reg_block reg_model;
if(!uvm_config_db #(uvm_reg_block)::get(null,“toy_tc_top”, “driver_me_ral”,reg_model))
`uvm_fatal(msg_id, “Cannot get() reg_model”)
b = reg_model.get_block_by_name(“toy”);

And the test are using same reg model to write into register directly using reg model (not using axi writes here)

But iam facing issue while doing the below access; which is dirctly from reg model write
b.get_reg_by_name(“queue_cfg_addr”).get_field_by_name(“base_addr”).write(status, 'h400);

UVM_FATAL @ 12149000000: reporter@@default_parent_seq [SEQ] neither the item’s sequencer nor dedicated sequencer has been supplied to start item in default_parent_seq
and also i have tried creating handle of reg model in this sequence and trying to use in other way as test is using (for test reg model is local)
ral_model.toy.queuw_cfg_addr[0].base_addr.write(status, 'h400);

Error-[NOA] Null object access

and next to this line there are axi reads/write are accessing same reg model info and i can see those are happening.
axi_master_read_seq rd_seq = axi_master_read_seq::type_id::create(“rd_seq”);
rd_seq.read(rc_group_reg[0].get_address(), rcs[0], rresp, m_sequencer, 0, 0, 4);

Can anyone please let me know how to resolve this issue.

regards,
nivas.

In reply to nivas:

I believe you are doing som things wrong and others complicated.
(1) I do not see where you are getting the ral-model object from.
(2) What are you doing here:

db_name = drive_me;
uvm_config_db #(uvm_reg_block)::set(null, "toy_tc_top", db_name, ral_model);

db_name has to be a string. This is not shown.
You are setting the ral-model but it seems there is no object.
(3) In the virtual sequencer you do not need the ral-model, but you might need it in the virtual sequence. You can directly connect the ral-model in the virtual sequence when after creating it in the test, by passing the path to the env.
(3) You do not need the functions get_reg_by_name and get_field_by_name. You can directly call
reg-model.my_reg.my_field.write(…);

When you are using a ‘write’ from the testbench, this is a ral-model write which will be converted to an AXI write.

In reply to chr_sue:

Hi,

Thanks for quick response but still i did not get the point to resolve this, i have shared some code acrros usage.

class toy_env extends uvm_env;
`uvm_component_utils(toy_env)

extern function new(string name = “toy_env”, uvm_component parent = null);
extern function void build_phase(uvm_phase phase);
extern function void connect_phase(uvm_phase phase);

toy_AXIL4_SLAVE_CFG_S_mmap_block_type ral_model; //reg model

// Virtual sequencer to drive commands
toy_gen_virtual_sequencer toy_gen_vseqr;
endclass

function void toy_env::build_phase(uvm_phase phase);
string db_name;
super.build_phase(phase);

ral_model = new({cfg.uvm_db_prefix, "ral_model"});
ral_model.build();
ral_model.default_map.set_base_addr(cfg.ral_base_address);
ral_model.reset();
ral_model.set_hdl_path_root(cfg.hdl_path_root);
ral_model.lock_model();

db_name = "drive_me_ral";
uvm_config_db #(uvm_reg_block)::set(null, "toy_test_top", db_name, ral_model);

**//tried to set this way also**
//uvm_config_db #(toy_AXIL4_SLAVE_CFG_S_mmap_block_type)::set(null, "toy_test_top", db_name, ral_model);

toy_gen_vseqr = toy_gen_virtual_sequencer::type_id::create("toy_gen_vseqr", this);

endfunction : build_phase

function void toy_env::connect_phase(uvm_phase phase);
super.connect_phase(phase);

cfg.drive_ral_model.default_map.set_sequencer(axi_master_agt_s.sqr, ral_model_adapter);
cfg.drive_ral_model.default_map.set_auto_predict(1);

toy_gen_vseqr.axi_s_gen_seqr = axi_master_agt_s.sqr;

endfunction : connect_phase

//package
package toy_gen_seq_pkg;

import uvm_pkg::;
import axi_agent_pkg::
;

include "uvm_macros.svh" include “toy.sv” ///reg mmodel

`include “toy_gen_base_s_seq.sv”

`include "toy_gen_virtual_sequencer.sv"
`include "toy_gen_virtual_seq.sv"

endpackage

///// Virtual Sequencer Class
class toy_gen_virtual_sequencer extends uvm_sequencer;
`uvm_component_utils(toy_gen_virtual_sequencer)

uvm_sequencer #(axi_seq_item) axi_s_gen_seqr;
uvm_sequencer #(axi_seq_item) axi_h_gen_seqr;

/// Constructor
function new (string name = “toy_gen_virtual_sequencer”, uvm_component parent);
super.new(name, parent);
endfunction: new

endclass: toy_gen_virtual_sequencer
///// Virtual Sequencer Class ends

///// Virtual Sequence Class
class toy_gen_virtual_seq extends uvm_sequence;

uvm_object_utils(toy_gen_virtual_seq) uvm_declare_p_sequencer(toy_gen_virtual_sequencer)

extern function new(string name=“toy_gen_virtual_seq”);
endclass

task toy_gen_virtual_seq::gen_drive_trans();

toy_gen_base_s_seq s_seq = toy_gen_base_s_seq::type_id::create("s_seq");
s_seq.start(p_sequencer.axi_s_gen_seqr);

endtask : gen_drive_trans
//virtual sequence end

//toy base_s_seq
class toy_gen_base_s_seq extends uvm_sequence#(axi_seq_item);

extern virtual task gen_drive_trans();

toy_AXIL4_SLAVE_CFG_S_mmap_block_type ral_model; ///< Register model

endclass

task toy_gen_base_s_seq::gen_drive_trans();

uvm_reg_block b;
uvm_reg_block reg_model;
axi_master_read_seq rd_seq = axi_master_read_seq::type_id::create("rd_seq");

//config db to get reg blocks
    **//this config db is not working: not getting ral_model**
**//NOT WORKING:** if(!uvm_config_db #(toy_AXIL4_SLAVE_CFG_S_mmap_block_type)::get(null,"toy_test_top", "driver_me_ral",ral_model))

    **//WORKING:**
if(!uvm_config_db #(uvm_reg_block)::get(null,"toy_test_top", "drive_me_ral",ral_model))
	`uvm_fatal(msg_id, "Cannot get() reg_model")

    **//These two methods are not working**
b = reg_model.get_block_by_name("toy"); 
    b.get_reg_by_name("queue_cfg_addr").get_field_by_name("base_addr").write(status, 'h400);

//WORKING
rd_seq.read(rc_group_reg[0].get_address(), rcs[0], rresp, m_sequencer, 0, 0, 4);

endtask: gen_drive_trans
//toy base_s_seq ends

//sanity sequence
class toy_sanity_gen_seq extends toy_gen_virtual_seq;

`uvm_object_utils(toy_sanity_gen_seq)

extern function new(string name=“toy_sanity_gen_seq”);

// Body
extern virtual task body();
endclass

function toy_sanity_gen_seq::new(string name=“toy_sanity_gen_seq”);
super.new(name);
endfunction : new

task toy_sanity_gen_seq::body();

toy_top_gen_seq_item toy_top_gen_itm;

repeat(3) begin
toy_top_gen_itm = toy_top_gen_seq_item::type_id::create(“toy_top_gen_itm”);

`uvm_do_on_with(toy_top_gen_itm, CONSTRAINTS); //not fully shown

end

endtask
//sanity sequence end

class test_sanity_gen extends TOY_BASE_TEST; uvm_component_utils(test_sanity_gen)

extern function new(string name=“test_sanity_gen”, uvm_component parent);
extern virtual task main_phase(uvm_phase phase);

endclass

function test_sanity_gen::new(string name=“test_sanity_gen”,uvm_component parent);
super.new(name,parent);
endfunction // new

task test_sanity_gen::main_phase(uvm_phase phase);
uvm_status_e status;

toy_sanity_gen_seq vseq = toy_sanity_gen_seq::type_id::create(“vseq”);

vseq.starting_phase = phase;

phase.raise_objection(this);

//ral model handle is created in base test
ral.toy.queue_config_addr.base_addr.write(status, 'h0000_ffff);

vseq.start(this.tenv.toy_gen_vseqr);
phase.drop_objection(this);

endtask

I am looking to set and get from config_db directly reg_model itself not uvm_reg_block, how to use same ral model in the virtual sequence which is outside of the toy_env(which is using again same ral model…no issues here).

Please suggest.

regards,
nivas

In reply to nivas:

I’m trying to give you some advice how to improve your code.
It is not a good idea to construct your ral_model in the nev. Do this instead in the test like this:

class my_test extends uvm_test;
my_env env;
my_top_config cfg;
my_reg_block  my_regs;
.....
function void build_phase(uvm_phase phase);
  my_regs = my_reg_block::type_id::create("my_regs");
  my_regs.build();
  // Create top config
  cfg = my_top_config::type_id::create("cfg");
  cfg.regs = apb_regs;
  cfg.<..> = ....;
   uvm_config_db #(my_top_config)::set(this, "*env*", "my_top_config", cfg);
  ....
endfunction
endclass
class my_env extends uvm_env;
  my_top_config	cfg;
function void build_phase(uvm_phase phase);
  `uvm_info(get_type_name(), "In build_phase", UVM_HIGH)
  if (!uvm_config_db #(my_top_config)::get(this, "", "my_top_config", cfg)) 
    `uvm_error(get_type_name(), "unable to get my_top_config")
  acfg.regs = cfg.regs;
  uvm_config_db #(axi_config)::set(this, "*", "axi_config", cfg.regs);
......
endfunction
endclass

More improvements:
(1) In your virtual sequence the body method does not exist. Instead you are using your own task.
(2) This code block is mixing different things.

ral_model = new({cfg.uvm_db_prefix, "ral_model"});
ral_model.build();
ral_model.default_map.set_base_addr(cfg.ral_base_address);
ral_model.reset();
ral_model.set_hdl_path_root(cfg.hdl_path_root);
ral_model.lock_model();

– lock_model and set_hdl_path should be implemented in the RAL model itself.
– ral_model.reset belongs to the simulation. It should be in the body task of your register sequence.
Hope this helps you to resolve your issues.