| |
The env
SPI UVM environment中的下一个层次是spi_env。该类包含许多子组件,即SPI和APB agents, a scoreboard, a functional coverage monitor 和 a virtual sequencer。构建这些子组件中的哪一个由spi_env配置对象中的变量确定。
在这个case里,spi_env配置对象还包含虚拟接口和用于检测中断的method。这将被在虚拟sequencer上运行的sequence使用。spi_env_config类的内容如下所示:
//
// Class Description:
//
//
class spi_env_config extends uvm_object;
localparam string s_my_config_id = "spi_env_config";
localparam string s_no_config_id = "no config";
localparam string s_my_config_type_error_id = "config type error";
// UVM Factory Registration Macro
//
`uvm_object_utils(spi_env_config)
// Interrupt Virtual Interface - used in the wait for interrupt task
//
virtual intr_if INTR;
//------------------------------------------
// Data Members
//------------------------------------------
// Whether env analysis components are used:
bit has_functional_coverage = 0;
bit has_spi_functional_coverage = 1;
bit has_reg_scoreboard = 0;
bit has_spi_scoreboard = 1;
// Whether the various agents are used:
bit has_apb_agent = 1;
bit has_spi_agent = 1;
// Configurations for the sub_components
apb_agent_config m_apb_agent_cfg;
spi_agent_config m_spi_agent_cfg;
// SPI Register model
uvm_register_map spi_rm;
//------------------------------------------
// Methods
//------------------------------------------
extern task wait_for_interrupt;
extern function bit is_interrupt_cleared;
// Standard UVM Methods:
extern function new(string name = "spi_env_config");
endclass: spi_env_config
function spi_env_config::new(string name = "spi_env_config");
super.new(name);
endfunction
// This task is a convenience method for sequences waiting for the interrupt
// signal
task spi_env_config::wait_for_interrupt;
@(posedge INTR.IRQ);
endtask: wait_for_interrupt
// Check that interrupt has cleared:
function bit spi_env_config::is_interrupt_cleared;
if(INTR.IRQ == 0)
return 1;
else
return 0;
endfunction: is_interrupt_cleared
在该示例中,存在用于每个子组件的build配置字段位。这为env提供了最大的重用灵活性。
在spi_env的build phase期间,使用uvm_config_db get()从配置空间中检索spi_env_config的句柄。然后,build过程测试配置对象中的各种has_ <sub_component>字段,以确定是否构建子组件。对于APB和SPI agent,还有一个步骤是从envs配置对象解每个代理的配置对象,然后在任何本地修改后在envs配置表中设置agent配置对象。
在connect phase里,spi_env配置对象再次用于确定要进行与哪个子组件的TLM连接。
//
// Class Description:
//
//
class spi_env extends uvm_env;
// UVM Factory Registration Macro
//
`uvm_component_utils(spi_env)
//------------------------------------------
// Data Members
//------------------------------------------
apb_agent m_apb_agent;
spi_agent m_spi_agent;
spi_env_config m_cfg;
spi_register_coverage m_reg_cov_monitor;
spi_reg_functional_coverage m_func_cov_monitor;
spi_scoreboard m_scoreboard;
//------------------------------------------
// Constraints
//------------------------------------------
//------------------------------------------
// Methods
//------------------------------------------
extern function new(string name = "spi_env", uvm_component parent = null);
extern function void build_phase( uvm_phase phase );
extern function void connect_phase( uvm_phase phase );
endclass:spi_env
function spi_env::new(string name = "spi_env", uvm_component parent = null);
super.new(name, parent);
endfunction
function void spi_env::build_phase( uvm_phase phase);
if(!uvm_config_db #( spi_env_config )::get( this , "", "spi_env_config" , m_cfg ) begin
`uvm_error("build_phase", "unable to get spi_env_config")
end
if(m_cfg.has_apb_agent) begin
uvm_config_db #( apb_agent_config )::set( this , "m_apb_agent*", "apb_agent_config", m_cfg.m_apb_agent_cfg );
m_apb_agent = apb_agent::type_id::create("m_apb_agent", this);
end
if(m_cfg.has_spi_agent) begin
uvm_config_db #( spi_agent_config )::set("m_spi_agent*", "spi_agent_config", m_cfg.m_spi_agent_cfg );
m_spi_agent = spi_agent::type_id::create("m_spi_agent", this);
end
if(m_cfg.has_functional_coverage) begin
m_reg_cov_monitor = spi_register_coverage::type_id::create("m_reg_cov_monitor", this);
end
if(m_cfg.has_spi_functional_coverage) begin
m_func_cov_monitor = spi_reg_functional_coverage::type_id::create("m_func_cov_monitor", this);
end
if(m_cfg.has_spi_scoreboard) begin
m_scoreboard = spi_scoreboard::type_id::create("m_scoreboard", this);
end
endfunction:build_phase
function void spi_env::connect_phase( uvm_phase phase );
if(m_cfg.has_functional_coverage) begin
m_apb_agent.ap.connect(m_reg_cov_monitor.analysis_export);
end
if(m_cfg.has_spi_functional_coverage) begin
m_apb_agent.ap.connect(m_func_cov_monitor.analysis_export);
end
if(m_cfg.has_spi_scoreboard) begin
m_apb_agent.ap.connect(m_scoreboard.apb.analysis_export);
m_spi_agent.ap.connect(m_scoreboard.spi.analysis_export);
m_scoreboard.spi_rm = m_cfg.spi_rm;
end
endfunction: connect_phase
The Agents
由于UVM build过程是自顶向下的,因此接下来才构建SPI和APB agent。agent build过程中的文章描述了如何配置和构建APB agent,SPI agent遵循相同的过程。agent中的组件位于测试平台层次结构的底层,因此build过程终止于agent中的组件。
(在http://verificationacademy.com/uvm-ovm上在线下载源代码示例)。