目录
1.1将monitor中用来与checker中的mailbox通信的mon_mb句柄换成对应的uvm_blocking_put_port类型
1.2在checker中声明和monitor通信的imp端口,与refmod通信的imp端口
1.4在mcdf_refmod中声明与checker连接的imp端口,例化
1.5在mcdf_env的connect_phase()完成monitor的port连接到mcdf_checker imp
1.6在mcdf_checker中完成mcdf_refmod的port连接到mcdf_checker的imp
2.1将mcdf_refmod中的out_mb替换成uvm_tlm_fifo
3.4定义继承于base test的两个test的两个回调函数cb_*********,这两个回调函数都继承于base test的回调函数
实验目标
实验任务
1.1将monitor中用来与checker中的mailbox通信的mon_mb句柄换成对应的uvm_blocking_put_port类型
首先在monitor中(这里以chnl_monitor为例),声明端口
uvm_blocking_put_port #(mon_data_t) mon_bp_port;
然后在new函数中例化这个PORT
function new(string name="chnl_monitor", uvm_component parent);
super.new(name, parent);
//TODO-1.1 instantiate the TLM port
mon_bp_port = new("mon_bp_port", this);
endfunction
将原来存放句柄的方式由mailbox改为端口
mon_mb.put(m);
mon_bp_port.put(m);
1.2在checker中声明和monitor通信的imp端口,与refmod通信的imp端口
checker对多个agent中的monitor,是一对多的多方向通信类型,需要使用宏声明
//在mcdf_checker前进行宏声明
`uvm_blocking_put_imp_decl(_chnl0)
`uvm_blocking_put_imp_decl(_chnl1)
`uvm_blocking_put_imp_decl(_chnl2)
`uvm_blocking_put_imp_decl(_fmt)
`uvm_blocking_put_imp_decl(_reg)
`uvm_blocking_get_peek_imp_decl(_chnl0)
`uvm_blocking_get_peek_imp_decl(_chnl1)
`uvm_blocking_get_peek_imp_decl(_chnl2)
`uvm_blocking_get_imp_decl(_reg)
//在mcdf_checker中进行端口声明
uvm_blocking_put_imp_chnl0 #(mon_data_t, mcdf_checker) chnl0_bp_imp;
uvm_blocking_put_imp_chnl1 #(mon_data_t, mcdf_checker) chnl1_bp_imp;
uvm_blocking_put_imp_chnl2 #(mon_data_t, mcdf_checker) chnl2_bp_imp;
uvm_blocking_put_imp_fmt #(fmt_trans , mcdf_checker) fmt_bp_imp ;
uvm_blocking_put_imp_reg #(reg_trans , mcdf_checker) reg_bp_imp ;
//
uvm_blocking_get_peek_imp_chnl0 #(mon_data_t, mcdf_checker) chnl0_bgpk_imp;
uvm_blocking_get_peek_imp_chnl1 #(mon_data_t, mcdf_checker) chnl1_bgpk_imp;
uvm_blocking_get_peek_imp_chnl2 #(mon_data_t, mcdf_checker) chnl2_bgpk_imp;
uvm_blocking_get_imp_reg #(reg_trans , mcdf_checker) reg_bg_imp ;
//在new函数中例化
chnl0_bp_imp = new("chnl0_bp_imp", this);
chnl1_bp_imp = new("chnl1_bp_imp", this);
chnl2_bp_imp = new("chnl2_bp_imp", this);
fmt_bp_imp = new("fmt_bp_imp", this);
reg_bp_imp = new("reg_bp_imp", this);
chnl0_bgpk_imp = new("chnl0_bgpk_imp", this);
chnl1_bgpk_imp = new("chnl1_bgpk_imp", this);
chnl2_bgpk_imp = new("chnl2_bgpk_imp", this);
reg_bg_imp = new("reg_bg_imp", this);
1.3对上面声明的imp实现对应的方法
task put_chnl0(mon_data_t t);
chnl_mbs[0].put(t);
endtask
task put_chnl1(mon_data_t t);
chnl_mbs[1].put(t);
endtask
task put_chnl2(mon_data_t t);
chnl_mbs[2].put(t);
endtask
task put_fmt(fmt_trans t);
fmt_mb.put(t);
endtask
task put_reg(reg_trans t);
reg_mb.put(t);
endtask
task peek_chnl0(output mon_data_t t);
chnl_mbs[0].peek(t);
endtask
task peek_chnl1(output mon_data_t t);
chnl_mbs[1].peek(t);
endtask
task peek_chnl2(output mon_data_t t);
chnl_mbs[2].peek(t);
endtask
task get_chnl0(output mon_data_t t);
chnl_mbs[0].get(t);
endtask
task get_chnl1(output mon_data_t t);
chnl_mbs[1].get(t);
endtask
task get_chnl2(output mon_data_t t);
chnl_mbs[2].get(t);
endtask
task get_reg(output reg_trans t);
reg_mb.get(t);
endtask
1.4在mcdf_refmod中声明与checker连接的imp端口,例化
//在mcdf_refmod类中声明
uvm_blocking_get_port #(reg_trans) reg_bg_port;
uvm_blocking_get_peek_port #(mon_data_t) in_bgpk_ports[3];
//在new函数中例化
reg_bg_port = new("reg_bg_port", this);
foreach(in_bgpk_ports[i]) in_bgpk_ports[i] = new($sformatf("in_bgpk_ports[%0d]", i), this);
//将mailbox换成PORT
this.reg_mb.get(t);
this.reg_bg_port.get(t);
this.in_mbs[id].peek(it);
this.in_bgpk_ports[id].get(it);
this.in_mbs[id].get(it);
this.in_bgpk_ports[id].get(it);
1.5在mcdf_env的connect_phase()完成monitor的port连接到mcdf_checker imp
function void connect_phase(uvm_phase phase);
super.connect_phase(phase);
//TODO-1.5 connect TLM ports between monitors and the checker
chnl_agts[0].monitor.mon_bp_port.connect(chker.chnl0_bp_imp);
chnl_agts[1].monitor.mon_bp_port.connect(chker.chnl1_bp_imp);
chnl_agts[2].monitor.mon_bp_port.connect(chker.chnl2_bp_imp);
reg_agt.monitor.mon_bp_port.connect(chker.reg_bp_imp);
fmt_agt.monitor.mon_bp_port.connect(chker.fmt_bp_imp);
endfunction
1.6在mcdf_checker中完成mcdf_refmod的port连接到mcdf_checker的imp
function void connect_phase(uvm_phase phase);
super.connect_phase(phase);
//TODO-1.6 connect checker TLM ports with the ones of reference model
refmod.in_bgpk_ports[0].connect(chnl0_bgpk_imp);
refmod.in_bgpk_ports[1].connect(chnl1_bgpk_imp);
refmod.in_bgpk_ports[2].connect(chnl2_bgpk_imp);
refmod.reg_bg_port.connect(reg_bg_imp);
2.1将mcdf_refmod中的out_mb替换成uvm_tlm_fifo
//先声明
uvm_tlm_fifo #(fmt_trans) out_tlm_fifos[3];
//new函数中例化
foreach(out_tlm_fifos[i]) out_tlm_fifos[i] = new($sformatf("out_tlm_fifos[%0d]", i), this);
//替代原来的mailbox
this.out_mbs[id].put(ot);
this.out_tlm_fifos[id].put(ot);
2.2同样的,mcdf_checker中的exp_mb[3]替换成uvm_blocking_get_port类型句柄数组。将mcdf_checker中的port连接到mcdf_refmod中uvm_tlm_fifo自带的blocking_get_export
uvm_blocking_get_port #(fmt_trans) exp_bg_ports[3];
foreach(exp_bg_ports[i]) exp_bg_ports[i] = new($sformatf("exp_bg_ports[%0d]", i), this);
// this.exp_mbs[mont.ch_id].get(expt);
this.exp_bg_ports[mont.ch_id].get(expt);
foreach(exp_bg_ports[i]) begin
exp_bg_ports[i].connect(refmod.out_tlm_fifos[i].blocking_get_export);
end
使用uvm_tlm_fifo就可以既使用tlm端口又不用自己实现具体的方法
3.1利用回调函数完成类的复用,先预定义几个虚方法
typedef class mcdf_base_test;
class cb_mcdf_base extends uvm_callback;
`uvm_object_utils(cb_mcdf_base)
mcdf_base_test test;
function new (string name = "cb_mcdf_base");
super.new(name);
endfunction
virtual task cb_do_reg();
// User to define the content
endtask
virtual task cb_do_formatter();
// User to define the content
endtask
virtual task cb_do_data();
// User to define the content
endtask
endclass
3.2关联回调类型和对应的test
在对应的test注册时使用callback对应的宏
`uvm_register_cb(mcdf_base_test, cb_mcdf_base)
3.3回调指定,也就是连接
在对应的test中的虚方法用回调指定宏,参数多了虚方法
virtual task do_reg();
//TODO-3.3 Use callback macro to link the callback method
`uvm_do_callbacks(mcdf_base_test, cb_mcdf_base, cb_do_reg())
endtask
// do external formatter down stream slave configuration
virtual task do_formatter();
//TODO-3.3 Use callback macro to link the callback method
`uvm_do_callbacks(mcdf_base_test, cb_mcdf_base, cb_do_formatter())
endtask
// do data transition from 3 channel slaves
virtual task do_data();
//TODO-3.3 Use callback macro to link the callback method
`uvm_do_callbacks(mcdf_base_test, cb_mcdf_base, cb_do_data())
endtask
3.4定义继承于base test的两个test的两个回调函数cb_*********,这两个回调函数都继承于base test的回调函数
把原来mcdf_data_consistence_basic_test完全复制到回调函数cb_mcdf_data_consistence_basic_test中,全部方法前面加上cb_前缀,相当于做了两次相同的mcdf_data_consistence_basic_test。也可以定义新的方法或修改原有方法,作为test的扩展
class cb_mcdf_data_consistence_basic extends cb_mcdf_base;
`uvm_object_utils(cb_mcdf_data_consistence_basic)
function new (string name = "cb_mcdf_data_consistence_basic");
super.new(name);
endfunction
task cb_do_reg();
bit[31:0] wr_val, rd_val;
super.cb_do_reg();
// slv0 with len=8, prio=0, en=1
wr_val = (1<<3)+(0<<1)+1;
test.write_reg(`SLV0_RW_ADDR, wr_val);
test.read_reg(`SLV0_RW_ADDR, rd_val);
void'(test.diff_value(wr_val, rd_val, "SLV0_WR_REG"));
// slv1 with len=16, prio=1, en=1
wr_val = (2<<3)+(1<<1)+1;
test.write_reg(`SLV1_RW_ADDR, wr_val);
test.read_reg(`SLV1_RW_ADDR, rd_val);
void'(test.diff_value(wr_val, rd_val, "SLV1_WR_REG"));
// slv2 with len=32, prio=2, en=1
wr_val = (3<<3)+(2<<1)+1;
test.write_reg(`SLV2_RW_ADDR, wr_val);
test.read_reg(`SLV2_RW_ADDR, rd_val);
void'(test.diff_value(wr_val, rd_val, "SLV2_WR_REG"));
// send IDLE command
test.idle_reg();
endtask
task cb_do_formatter();
super.cb_do_formatter();
void'(test.fmt_gen.randomize() with {fifo == LONG_FIFO; bandwidth == HIGH_WIDTH;});
test.fmt_gen.start();
endtask
task cb_do_data();
super.cb_do_data();
void'(test.chnl_gens[0].randomize() with {ntrans==100; ch_id==0; data_nidles==0; pkt_nidles==1; data_size==8; });
void'(test.chnl_gens[1].randomize() with {ntrans==100; ch_id==1; data_nidles==1; pkt_nidles==4; data_size==16;});
void'(test.chnl_gens[2].randomize() with {ntrans==100; ch_id==2; data_nidles==2; pkt_nidles==8; data_size==32;});
fork
test.chnl_gens[0].start();
test.chnl_gens[1].start();
test.chnl_gens[2].start();
join
#10us; // wait until all data haven been transfered through MCDF
endtask
endclass: cb_mcdf_data_consistence_basic
注意:原来test中用this.的地方表示当前类,在回调函数中改成test.1
4在mcdf_base_test中添加新的end_of_elaboration_phase函数;利用uvm_root类设置信息冗余度为UVM_high;利用uvm_root::set_report_max_quit_count()函数设置仿真退出的最大数值;利用uvm_root::set_timeout()设置仿真的最大时间长度
function void end_of_elaboration_phase(uvm_phase phase);
super.end_of_elaboration_phase(phase);
uvm_root::get().set_report_verbosity_level_hier(UVM_HIGH);
uvm_root::get().set_report_max_quit_count(1);
uvm_root::get().set_timeout(10ms);
endfunction