添加通信的端口和变量 uvm_seq_item_pull_port #(REQ, RSP) seq_item_port; uvm_analysis_port #(RSP) rsp_port; REQ req; RSP rsp;driver与sequencer通信
driver.seq_item_port.connect(sequencer.seq_item_export); driver.rsp_port.connect(sequencer.rsp_export);uvm_driver示例
class dut_driver extends uvm_driver #(basic_transaction)//sequence_item类型 virtual chip_if vif; bit[7:0] addr, data; `uvm_component_utils(dut_driver) function new(string name, uvm_component parent); super.new(name,parent); endfunction extern task run_phase(uvm_phase phase); endclass:dut_driveruvm_monitor
没有添加其他变量或端口
UVM_monitor示例class serial_monitor extends uvm_monitor;
virtual serial_if.monitor mi;//interface + modport
`uvm_component_utils(serial_monitor)
function new(string name, uvm_component parent);
super.new(name,parent);
endfuntion
function void build_phase(uvm_phase phase);
super.build_phase(phase);
endfunction
extern run_phase(uvm_phase phase);
endclass: serial_monitor
task serial_monitor::run_phase(uvm_phase phase);
serial_transaction tr;
tr = new();
forever begin
wait(mi.line);
#(bit_period/2);
for(int i = 0; i <= 7; i++) begin
#(bit_period);
tr.parity_error ^= mi.line;
tr.data[i] = mi.line;//数据监测
end
#(bit_period) assert(mi.line == 1'b1) else//协议检查
`uvm_warning("MON","Framing error")
endtask
uvm_sequencer
sequencer既管理着sequence,同时也将sequence中产生的transaction_item传送到driver侧,可以说是整个激励环节中的“路由器”
uvm_sequencer实例class my_sequencer extends uvm_sequencer #(basic_transaction); `uvm_component_utils(my_sequencer) function new(string name, uvm_component parent); super.new(name,parent); endfuntion endclassuvm_agent
· uvm_agent通常包含一个driver、一个monitor以及一个sequencer。
· uvm_agent中有时只需要包含一个monitor, 而不需要driver和sequencer,这就需要通过一个变量来进行有条件的例化。
· uvm_active_passive_enum is_active = UVM_ACTIVE;
is_active是agent的一个成员,缺省值是UVM_ACTIVE,这表示处在active模式的agent需要例化driver、monitor和sequencer;
is_active是UVM_PASSIVE, 这表示agent是passive模式,只可以例化monitor。
active模式的agent既有激励功能也有监测功能,passive模式的agent只具有监测功能。
active模式对应着DUT的接口暴露给agent且需要激励的场景,而passive模式对应着DUT的接口已经与其它设计连接而只需要监测的场景。
通过is_active变量,agent需要在build_ phase()和connect_phase()等函数中通过选择语句来对driver和sequencer进行有条件的例化和连接
uvm_agent实例
class my_agent extends uvm_agent;
//定义所包含的常见组件
my_sequencer m_sqr;
my_driver m_drv;
my_monitor m_mon;
dut_if vif;
uvm_active_passive_enum is_active = UVM_ACTIVE;
extern function void build_phase(uvm_phase phase) ;
extern function void connect_phase(uvm_phase phase) ;
function new(string name, uvm_component parent);
super.new(name,parent);
endfuntion
`uvm_component_utils(my_agent)//为什么要最后注册呢
endclass
function void my_agent::bui1d() ;
super.build() ;
monitor = my_monitor::type_id::create("monitor" , this) ;
if(is_active == UVM_ACTIVE) begin
sequencer = my_sequencer::type_id::create (" sequencer" , this) ;
driver = my_driver::type_id::create("driver" ,this) ;
end
endfunction : build
function void my_agent::connect() ;
if(is_active == UVM_ACTIVE) begin
driver.seq_item_port.connect(sequencer.seq_item_export) ;
end
endfunction : connect
uvm_scoreboard
相对component没有添加其他变量
uvm自带的数据比较方法uvm_in_order_comparator # (type T) uvm_algorithm_comparator # (type BEFORE,type AFTER, type TRANSFORMER) uvm_in_order_comparator是一个参数类,并且它有两个端口before_export和after_export分别从DUT的输入端monitor和输出端 monitor获取观测到的数据事务。这些数据事务是将多个时钟周期内的数据整合为更高抽象级的数据对象,而且要求前后端监测到数据事务类型应该相同。 uvm_algorithm_comparator也是一个参数类,它的参数数目要更多,这是为了贴合在更多实际场景中,DUT的输入端监测数据格式不同于输出端数据格式,因此type BEFORE与type AFTER两个事务类可以不相同,同时用户也应该提供用来将BEFORE类转换为AFTER类的转换类type TRANSFORMER。uvm_scoreboard示例
● 在scoreboard中通常会声明TLM端口以供monitor传输数据。 ● 简易比较的方法,可以采用UVM预定义的comparator。 ● 对于复杂的设计,参考SV模块中的做法,可以在scoreboard中分别创建reference model和comparator。 ● 如果一个组件中有子一级的组件,应该考虑它们的创建、连接和通信问题。
class my_scoreboard extends uvm_scoreboard;
uvm_analysis_export #(bus_xact) in_export;
uvm_analysis_export #(bus_xact) out_export;
typedef uvm_in_order_comparator #(bus_xact) com_t;//这种方法定义可以避免在创建调用类型的时候忽略参数类型
comp_t m_comp;
function void build_phase(uvm_phase phase);
super.build_phase(phase);
in_export = new("in_export",this);//实例化通信接口
out_export = new("out_export",this);
m_comp = comp_t::type_id::create("m_comp",this);
endfunction
function void connect_phase(uvm_phase phase);
super.connect_phase(phase);
in_export.connect(m_comp.before_export);
out_export.connect(m_comp.after_export);
endfunction
endclass
uvm_env
uvm_env可能包含多个uvm_agent和其它component, agent。
class top_env extends uvm_env;
sub_env m_se;
my_agent m_agt;
my_scoreboard m_sb;
`uvm_component_utils(top_env)
extern function new(string name, uvm_component parent);
function void build_phase(uvm_phase phase);
m_se = sub_env::type_id::create("m_se",this);
m_agt = my_agent::type_id::create("m_agt",this);
m_sb = my_scoreboard::type_id::create("m_sb",this);
endfunction
endclass
uvm_test
uvm_test示例
class env extends uvm_env;
endclass
class agent extends uvm_agent;
endclass
class test1 extends uvm_test;
uvm_component_utils(test1)
env e1,e2;
agent a1;
function void build_phase(uvm_phase phase);
e1 = env::type_id::create("c1",this);
e2 = env::type_id::create("c2",this);
a1 = agent::type_id::create("a1",this);
endfunction
endclass
MCDF顶层验证
class mcdf_env1 extends uvm_env;
`uvm_component_utils(mcdf_env1)
reg_master_agent reg_mst;
chnl_master_agent chnl_mst1;
chnl_master_agent chnl_mst2;
chnl_master_agent chnl mst3;
fmt_slave_agent fmt_slv;
mcdf_virtual_sequencer virt_sqr;
mcdf_scoreboard sb;
function void build_phase(uvm_phase phase);
super.build_phase(phase);
res_mst = reg_master_agent::type_id::create("reg_mst",this);
chnl_mst1 = chnl_master_agent::type_id::create("chnl_mst1",this);
chnl_mst2 = chnl_master_agent::type_id::create("chnl_mst2",this);
chnl_mst3 = chnl_master_agent::type_id::create("chnl_mst3",this);
fmt_slv = fmt_slave_agent::type_id::create("fmt_slv",this);
virt_sqr = mcdf_virtual_sequencer::type_id::create("virt_sqr",this);
sb = mcdf_scoreboard::type_id::create("sb",this);
endfunction
function void connect_phase(uvm_phase phase);
super.connect_phase(phase);
//virtual sequencer connection
virt_sqr.reg_sqr = reg_mst.sequencer;
virt_sqr.chnl_sqr1 = chnl_mst1.sequencer;
virt_sqr.chnl_sqr2 = chnl_mst2.sequencer;
virt_sqr.chnl_sqr3 = chnl_mst3.sequencer;
virt_sqr.fmt_sqr = fmt_slv.sequencer;
//monitor transactions to scoreboard
reg_mst.monitor.ap.connect(sb.reg_export);
chnl_mst1.monitor.ap.connect(sb.chnl1_export);
chnl_mst2.monitor.ap.connect(sb.chnl2_export);
chnl_mst3.monitor.ap.connect(sb.chnl3_export);
fmt_slv.monitor.ap.connect(sb.fmt_export);
endfunction
endclass



