Hi all
I meet a problem when solve this problem.
I extend a child class on uvm_reg and put extension variable into it and override the write/read task.
typedef enum {FORMAT_A, FORMAT_B, FORMAT_C} user_rw_type;
class user_reg_extension extends uvm_object;
user_rw_type rw_type;
`uvm_object_utils_begin(user_reg_extension)
`uvm_field_enum(user_rw_type, rw_type, UVM_DEFAULT)
`uvm_object_utils_end
function new(string name="user_reg_extension");
super.new(name);
endfunction
endclass : user_reg_extension
class user_reg extends uvm_reg;
user_reg_extension user_extension; //user_reg_extension is a class extends uvm_object
...
virtual task write(output uvm_status_e status,
input uvm_reg_data_t value,
input uvm_path_e path = UVM_DEFAULT_PATH,
input uvm_reg_map map = null,
input uvm_sequence_base parent = null,
input int prior = -1,
input uvm_object extension = user_extension, //in parent uvm_reg class this code is extension = null
input string fname = "",
input int lineno = 0);
super.write(status,
value,
path,
map,
parent,
prior,
extension,
fname,
lineno);
endtask
...
endclass : user_reg
//Then put a user_reg into map
class user_reg_xxh extends user_reg;
...
function new(string name = "user_reg_xxh");
super.new(name, 8, UVM_NO_COVERAGE);
user_extension.rw_type = xx; //set user extension property for this register
endfunction
endclass : user_reg_xxh
class user_reg_map extends uvm_reg_block;
rand user_reg_xxh user_reg_xxh;
uvm_reg_map map;
...
virtual function build();
user_reg_xxh= user_reg_xxh::type_id::create("user_reg_xxh");
user_reg_xxh.configure(this);
user_reg_xxh.build();
// map name, offset, number of bytes, endianess
map = create_map("map", 'h0, 2, UVM_LITTLE_ENDIAN);
map.add_reg(user_reg_xxh, addr, "RW");
lock_model();
endfunction
endclass : user_reg_map
//sequence
class user_seq extends user_reg_sequence;
user_reg_map reg_map;
...
task body();
uvm_status_e status;
uvm_reg_data_t data;
uvm_reg rg;
...
rg = reg_map.user_reg_xxh;
$display("user_reg_xxh type name:", reg_map.user_reg_xxh.get_type_name()); //get the name user_reg_xxh
$display("rg type name:", rg.get_type_name()); //Also get the name user_reg_xxh
#1us;
// register model access write()/read()
reg_map.user_reg_xxh.write(status, 16'hxxxx, UVM_FRONTDOOR, .parent(this)); //first write command, RIGHT NO PROBLEM
rg.write(status, 16'hxxxx, UVM_FRONTDOOR, .parent(this)); //second write command MEET PROBLEM IN THIS COMMAND
endtask
endclass : user_seq
class reg2user_adapter extends uvm_reg_adapter;
...
function uvm_sequence_item reg2bus(const ref uvm_reg_bus_op rw);
user_base_trans_item tmp;
uvm_reg_item item;
user_reg_extension ext_tmp;
logic [7:0] data_buf;
tmp = user_base_trans_item::type_id::create("tmp");
item = this.get_item();
void'($cast(ext_tmp, item.extension));
if (ext_tmp.rw_type == FORMAT_A) //Error occurs in second write command
...
else if (ext_tmp.rw_type == FORMAT_B)
...
else
...
...
return tmp;
endfunction
...
endclass : reg2user_adapter
When run the test, first write command is right and adapter can get the extension property from uvm_reg_item. But second write command is wrong, Fatal: (SIGSEGV) Bad handle or reference message on the if condition sentence related to ext_tmp in adapter class, see code above.
I’m confused because uvm_reg variable rg has pointed to user_reg_xxh before write and it also get the right type name, but why user_extension member variable can’t be sent and it seems that child class user_reg::write wasn’t called???
Any advice pls point out.
Thanks all.