寄存器模型的用法:多层次的block
`ifndef REG_MODEL__SV
`define REG_MODEL__SV
//first reg
class reg_invert extends uvm_reg;
rand uvm_reg_field reg_data;
rand uvm_reg_field reg_status;
//如果是RO,则可以不加rand修饰符;
//不同的reg内的field名字可以一样;
virtual function void build();
reg_data = uvm_reg_field::type_id::create("reg_data");
reg_data.configure(this, 1, 0, "RW", 1, 0, 1, 1, 0);
reg_status = uvm_reg_field::type_id::create("reg_status"); //多个field在一个reg内例化
reg_status.configure(this, 1, 0, "RW", 1, 0, 1, 1, 0); //多个field在一个reg内configure
endfunction
`uvm_object_utils(reg_invert)
function new(input string name="reg_invert");
super.new(name, 16, UVM_NO_COVERAGE);
endfunction
endclass
//second reg
class reg_depth extends uvm_reg;
rand uvm_reg_field reg_data;
rand uvm_reg_field reg_status;
virtual function void build();
reg_data = uvm_reg_field::type_id::create("reg_data");
reg_status = uvm_reg_field::type_id::create("reg_status");//多个field在上层block内例化
endfunction
`uvm_object_utils(reg_depth)
function new(input string name="reg_depth");
super.new(name, 16, UVM_NO_COVERAGE);
endfunction
endclass
//third reg
class reg_vlan extends uvm_reg;
rand uvm_reg_field reg_data;
virtual function void build();
reg_data = uvm_reg_field::type_id::create("reg_data");
reg_data.configure(this, 10, 0, "RW", 1, 0, 1, 1, 0);
endfunction
`uvm_object_utils(reg_vlan)
function new(input string name="reg_vlan");
super.new(name, 16, UVM_NO_COVERAGE);
endfunction
endclass
//first block
class global_blk extends uvm_reg_block;
rand reg_invert invert;
virtual function void build();
default_map = create_map("default_map", 0, 2, UVM_BIG_ENDIAN, 0);
invert = reg_invert::type_id::create("invert", , get_full_name());
invert.configure(this, null, "");
invert.build();
default_map.add_reg(invert, 'h9, "RW");
endfunction
`uvm_object_utils(global_blk)
function new(input string name="global_blk");
super.new(name, UVM_NO_COVERAGE);
endfunction
endclass
//second block
class buf_blk extends uvm_reg_block;
rand reg_depth depth;
rand uvm_reg_field reg_data;
rand uvm_reg_field reg_status;
virtual function void build();
default_map = create_map("default_map", 0, 2, UVM_BIG_ENDIAN, 0);
depth = reg_depth::type_id::create("depth", , get_full_name());
depth.configure(this, null, "");//在这里第三个参数原来是指定后门的访问路径,在这里应变成空的字符串
depth.build();
//////将field的config放在block的内部,而不是reg内
depth.reg_data.configure(depth, 2, 0, "RW", 1, 0, 1, 1, 0);//field的configure放在了block内执行
depth.add_hdl_path_slice("reg_data", 0, 2);//指定后门访问的路径,补充depth.configure的第三个参数
depth.reg_status.configure(depth, 3, 2, "RW", 1, 0, 1, 1, 0);
depth.add_hdl_path_slice("reg_status", 2, 3);
//////要加入的路径,此路径对应的域在此寄存器中的起始位置,此路径对应的域的宽度;
default_map.add_reg(depth, 'h3, "RW");
this.reg_data = this.depth.reg_data; //用指针指向reg内的field
this.reg_status = this.depth.reg_status;//用这样的方法可以通过block直接访问field
endfunction
`uvm_object_utils(buf_blk)
function new(input string name="buf_blk");
super.new(name, UVM_NO_COVERAGE);
endfunction
endclass
//third block
class mac_blk extends uvm_reg_block;
rand reg_vlan vlan;
virtual function void build();
default_map = create_map("default_map", 0, 2, UVM_BIG_ENDIAN, 0);
vlan = reg_vlan::type_id::create("vlan", , get_full_name());
vlan.configure(this, null, "");
vlan.build();
default_map.add_reg(vlan, 'h40, "RW");
endfunction
`uvm_object_utils(mac_blk)
function new(input string name="mac_blk");
super.new(name, UVM_NO_COVERAGE);
endfunction
endclass
class reg_model extends uvm_reg_block;
rand global_blk gb_ins;
rand buf_blk bb_ins;
rand mac_blk mb_ins;
virtual function void build();
default_map = create_map("default_map", 0, 2, UVM_BIG_ENDIAN, 0);
gb_ins = global_blk::type_id::create("gb_ins");
gb_ins.configure(this, "");
//此block所在的block的指针,相对于父block的用来后门访问的相对路径
gb_ins.build();
gb_ins.lock_model();
default_map.add_submap(gb_ins.default_map, 16'h0);
bb_ins = buf_blk::type_id::create("bb_ins");
bb_ins.configure(this, "");
bb_ins.build();
bb_ins.lock_model();
default_map.add_submap(bb_ins.default_map, 16'h1000);
mb_ins = mac_blk::type_id::create("mb_ins");
mb_ins.configure(this, "");
mb_ins.build();
mb_ins.lock_model();
default_map.add_submap(mb_ins.default_map, 16'h2000);
//this.lock_model();
//上面这句话可以替代上面所有的*.lock_model();
endfunction
`uvm_object_utils(reg_model)
function new(input string name="reg_model");
super.new(name, UVM_NO_COVERAGE);
endfunction
endclass
`endif
后面访问需要添加的内容:
`ifndef BASE_TEST__SV
`define BASE_TEST__SV
class base_test extends uvm_test;
my_env env;
my_vsqr v_sqr;
reg_model rm;
my_adapter reg_sqr_adapter;
function new(string name = "base_test", uvm_component parent = null);
super.new(name,parent);
endfunction
extern virtual function void build_phase(uvm_phase phase);
extern virtual function void connect_phase(uvm_phase phase);
extern virtual function void report_phase(uvm_phase phase);
`uvm_component_utils(base_test)
endclass
function void base_test::build_phase(uvm_phase phase);
super.build_phase(phase);
env = my_env::type_id::create("env", this);
v_sqr = my_vsqr::type_id::create("v_sqr", this);
rm = reg_model::type_id::create("rm", this);//regmodel
rm.configure(null, ""); //regmodel
rm.build(); //regmodel
rm.lock_model(); //regmodel
rm.reset(); //regmodel
rm.set_hdl_path_root("top_tb.my_dut"); //regmodel:添加后门访问的路径
reg_sqr_adapter = new("reg_sqr_adapter"); //regmodel:实例化adapter
env.p_rm = this.rm;
endfunction
function void base_test::connect_phase(uvm_phase phase);
super.connect_phase(phase);
v_sqr.p_my_sqr = env.i_agt.sqr;
v_sqr.p_bus_sqr = env.bus_agt.sqr;
v_sqr.p_rm = this.rm;
rm.default_map.set_sequencer(env.bus_agt.sqr, reg_sqr_adapter);//regmodel
rm.default_map.set_auto_predict(1); //regmodel
endfunction
function void base_test::report_phase(uvm_phase phase);
uvm_report_server server;
int err_num;
super.report_phase(phase);
server = get_report_server();
err_num = server.get_severity_count(UVM_ERROR);
if (err_num != 0) begin
$display("TEST CASE FAILED");
end
else begin
$display("TEST CASE PASSED");
end
endfunction
`endif
浙公网安备 33010602011771号