UVMagent可以被认为是特定interface的验证组件工具包(package),其中包括一个用于连接DUT的SystemVerilog interface以及一个组成整个agent 组件类的SystemVerilogpackage。
agent类是一个容器类,包含driver、sequencer和monitor。agent类还具有一个analysis port,该端口连接到monitor上的analysis port。
我们使用一个APB总线agent 展示它是如何封装、配置、构建和连接的。APBagent使用一个名为apb_if的接口(apb_if.sv)。agent的各种类模板文件一起收集在一个SystemVerilog package中(apb_agent_pkg.sv)。
package apb_agent_pkg;
import uvm_pkg::*;
`include "uvm_macros.svh"
`include "apb_seq_item.svh"
`include "apb_agent_config.svh"
`include "apb_driver.svh"
`include "apb_coverage_monitor.svh"
`include "apb_monitor.svh"
`include "apb_sequencer.svh"
`include "apb_agent.svh"
`include "apb_seq.svh"
endpackage: apb_agent_pkg
agent 有一个配置对象,可用于定义:
1、agent的拓扑接口。
UVM agent中有一个类型为UVM_ACTIVE_PASSIVE_e的变量,UVM_ACTIVE会构建sequencer和driver,UVM_PASSIVE则不会。此参数默认情况下为UVM_ACTIVE,当然也可以不去使用。
2、virtual interface句柄
配置对象还会包含一个driver和monitor需要使用的virtual interface句柄。配置对象在Testcase中构造和配置,并将virtual interface赋值给agent中的virtual interface。
3、子组件的行为
配置对象还可以包含影响agent的行为的其他变量。例如,在apb agent的配置对象中,有一些变量可以设置哪些内存地址是有效的。
class apb_agent_config extends uvm_object;
`uvm_object_utils(apb_agent_config)virtual apb_if APB;
uvm_active_passive_enum active = UVM_ACTIVE;
bit has_functional_coverage = 0;
bit has_scoreboard = 0;
int no_select_lines = 1;
logic[31:0] start_address[15:0];
logic[31:0] range[15:0];
extern function new(string name = "apb_agent_config");
endclass: apb_agent_configfunction
apb_agent_config::new(string name = "apb_agent_config");
super.new(name);
endfunction
一旦构建了agent的子组件,就需要连接它们。通常需要的连接有:
1、Monitor analysis port到agent's analysis port
2、sequencer的seq_item_pull_export到driver的seq_item_pull_port
3、将agent配置对象中的virtual interface赋值给driver和monitor中virtual interfaces句柄
上述连接方式只是一个示例,具体项目可能有所不同,但是本质上是一样的。
以下示例了apb agent的build phase和connect phase:
class apb_agent extends uvm_component;
`uvm_component_utils(apb_agent)apb_agent_config m_cfg;
uvm_analysis_port #(apb_seq_item) ap;
apb_monitor m_monitor;
apb_sequencer m_sequencer;
apb_driver m_driver;
apb_coverage_monitor m_fcov_monitor;
extern function new(string name = "apb_agent", uvm_component parent = null);
extern function void build_phase( uvm_phase phase );
extern function void connect_phase( uvm_phase phase );
endclass: apb_agent
function apb_agent::new(string name = "apb_agent", uvm_component parent = null);
super.new(name, parent);
endfunction
function void apb_agent::build_phase( uvm_phase phase );
if( !uvm_config_db #( apb_agent_config )::get(this,"apb_agent_config",m_cfg) )
`uvm_error(...)
m_monitor = apb_monitor::type_id::create("m_monitor", this);
if(m_cfg.active == UVM_ACTIVE) begin
m_driver = apb_driver::type_id::create("m_driver", this);
m_sequencer = apb_sequencer::type_id::create("m_sequencer", this);
end
if(m_cfg.has_functional_coverage) begin
m_fcov_monitor = apb_coverage_monitor::type_id::create("m_fcov_monitor", this);
end
endfunction: build_phase
function void apb_agent::connect_phase( uvm_phase phsae );
m_monitor.APB = m_cfg.APB;
ap = m_monitor.ap;
if(m_cfg.active == UVM_ACTIVE) begin
m_driver.seq_item_port.connect(m_sequencer.seq_item_export);
m_driver.APB = m_cfg.APB;end
if(m_cfg.has_functional_coverage) begin
m_monitor.ap.connect(m_fcov_monitor.analysis_export);
end
endfunction: connect_phase
作者:验证哥布林
原文链接:https://mp.weixin.qq.com/s/l5zqUSv51gbEf5Q2s6xgUQ
微信公众号:
推荐阅读
更多IC设计技术干货请关注IC设计技术专栏