目录
实验目标
完成SV到UVM的移植转化
chnl_pkg的变化
首先在package下面要植入uvm_pkg和uvm_macros.svh
import uvm_pkg::*;
`include "uvm_macros.svh"
每个class都有对应的继承的父类,driver是参数类,需要标明发送的是chnl_trans
class chnl_trans extends uvm_sequence_item;
class chnl_driver extends uvm_driver #(chnl_trans);
class chnl_generator extends uvm_component;
class chnl_monitor extends uvm_monitor;
class chnl_agent extends uvm_agent;
每个组件都要进行注册
`uvm_component_utils(chnl_driver)
`uvm_component_utils(chnl_monitor)
`uvm_component_utils(chnl_agent)
sequence item由于经常要对数据进行拷贝等操作,在注册时要有域的自动化。SV中对数据进行克隆和打印等函数被uvm提供的数据处理和消息管理替代替代。
`uvm_object_utils_begin(chnl_trans)
`uvm_field_array_int(data, UVM_ALL_ON)
`uvm_field_int(ch_id, UVM_ALL_ON)
`uvm_field_int(pkt_id, UVM_ALL_ON)
`uvm_field_int(data_nidles, UVM_ALL_ON)
`uvm_field_int(pkt_nidles, UVM_ALL_ON)
`uvm_field_int(rsp, UVM_ALL_ON)
`uvm_object_utils_end
`uvm_component_utils_begin(chnl_generator)
`uvm_field_int(pkt_id, UVM_ALL_ON)
`uvm_field_int(ch_id, UVM_ALL_ON)
`uvm_field_int(data_nidles, UVM_ALL_ON)
`uvm_field_int(pkt_nidles, UVM_ALL_ON)
`uvm_field_int(data_size, UVM_ALL_ON)
`uvm_field_int(ntrans, UVM_ALL_ON)
`uvm_component_utils_end
driver中的方法,由于clone()返回的是uvm_object类型,而rsp是chnl_trans的句柄,类型是sequence_item,需要进行动态转换$cast。
打印消息由$display变成uvm的消息管理`uvm_info
task do_drive();
chnl_trans req, rsp;
@(posedge intf.rstn);
forever begin
this.req_mb.get(req);
this.chnl_write(req);
void'($cast(rsp, req.clone()));//clone返回的是uvm object类型(父类句柄)
rsp.rsp = 1;
this.rsp_mb.put(rsp);
end
endtask
task chnl_write(input chnl_trans t);
foreach(t.data[i]) begin
@(posedge intf.clk);
intf.drv_ck.ch_valid <= 1;
intf.drv_ck.ch_data <= t.data[i];
@(negedge intf.clk);
wait(intf.ch_ready === 'b1);
`uvm_info(get_type_name(), $sformatf("sent data 'h%8x", t.data[i]), UVM_HIGH)
repeat(t.data_nidles) chnl_idle();
end
repeat(t.pkt_nidles) chnl_idle();
endtask
根据uvm的phase机制,driver中响应的run任务也要变成run_phase(uvm_phase phase)
task run_phase(uvm_phase phase);
fork
this.do_drive();
this.do_reset();
join
endtask
由于有了继承关系,new函数中都要调用父类的new函数。继承于component的要多一个parent参数,继承于object的则没有。
function new (string name = "chnl_trans");
super.new(name);
endfunction
function new (string name = "chnl_driver", uvm_component parent);
super.new(name, parent);
endfunction
function new (string name = "chnl_generator", uvm_component parent);
super.new(name, parent);
this.req_mb = new();
this.rsp_mb = new();
endfunction
function new(string name="chnl_monitor", uvm_component parent);
super.new(name, parent);
endfunction
function new(string name = "chnl_agent", uvm_component parent);
super.new(name, parent);
endfunction
agent中多了build_phase,例化了driver和monitor。在SV中这部分是放在new函数中
function void build_phase(uvm_phase phase);
super.build_phase(phase);
driver = chnl_driver::type_id::create("driver", this);
monitor = chnl_monitor::type_id::create("monitor", this);
endfunction
arb_pkg的变化
和上面的一样,由于本身就是空的,所以各个组件加上继承、注册、new函数即可
mcdf_pkg的变化
例化refmod用工厂的方法
function void build_phase(uvm_phase phase);
super.build_phase(phase);
foreach(this.chnl_mbs[i]) this.chnl_mbs[i] = new();
this.fmt_mb = new();
this.reg_mb = new();
this.refmod = mcdf_refmod::type_id::create("refmod", this);
endfunction
其他文件也是类似
tb的变化
通过uvm的配置完成接口在硬件tb到软件验证环境mcdf_env的传递
uvm_config_db#(virtual chnl_intf)::set(uvm_root::get(), "uvm_test_top", "ch0_vif", chnl0_if);
uvm_config_db#(virtual chnl_intf)::set(uvm_root::get(), "uvm_test_top", "ch1_vif", chnl1_if);
uvm_config_db#(virtual chnl_intf)::set(uvm_root::get(), "uvm_test_top", "ch2_vif", chnl2_if);
uvm_config_db#(virtual reg_intf)::set(uvm_root::get(), "uvm_test_top", "reg_vif", reg_if);
uvm_config_db#(virtual arb_intf)::set(uvm_root::get(), "uvm_test_top", "arb_vif", arb_if);
uvm_config_db#(virtual fmt_intf)::set(uvm_root::get(), "uvm_test_top", "fmt_vif", fmt_if);
uvm_config_db#(virtual mcdf_intf)::set(uvm_root::get(), "uvm_test_top", "mcdf_vif", mcdf_if);
原来在tb中的test已经被UVM的run_test()替代了,不需要再调用test中的run