目录
完成SV到UVM的移植转化

首先在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
和上面的一样,由于本身就是空的,所以各个组件加上继承、注册、new函数即可
例化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
通过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