| |
The Test
UVM构建过程的下一个阶段是build phase。对于SPI块级示例,这意味着构建spi_env组件,首先创建并准备将要由环境使用的所有配置对象。配置和构建过程可能在大多数测试用例中都很常见,因此通常最好创建一个 test base class,这个 test base class可以被扩展成我们所需的特定的tests。
在SPI示例中,spi_env的配置对象包含SPI和APB配置对象的句柄。这允许使用env配置对象将所有配置对象传递给env。然后spi_env中的build method负责传递这些子配置。使用这种“Russian Doll”嵌套配置方法,因为它可以扩展到许多层次结构。
在将agent的配置对象分配给env配置块中的句柄之前,将构造它们,使用uvm_config_db :: get method将别处传来的实际接口分配给虚拟接口,然后配置它们。APB agent可能在不同的测试用例之间需进行不同的配置,因此其配置过程已拆分为基类中的单独虚拟方法(方便到时候为不同需求的测试用例重载使用)。
以下代码是spi_test_base类:
//
// Class Description:
//
//
class spi_test_base extends uvm_test;
// UVM Factory Registration Macro
//
`uvm_component_utils(spi_test_base)
//------------------------------------------
// Data Members
//------------------------------------------
//------------------------------------------
// Component Members
//------------------------------------------
// The environment class
spi_env m_env;
// Configuration objects
spi_env_config m_env_cfg;
apb_agent_config m_apb_cfg;
spi_agent_config m_spi_cfg;
// Register map
spi_register_map spi_rm;
//------------------------------------------
// Methods
//------------------------------------------
extern virtual function void configure_apb_agent(apb_agent_config cfg);
// Standard UVM Methods:
extern function new(string name = "spi_test_base", uvm_component parent = null);
extern function void build_phase( uvm_phase phase );
endclass: spi_test_base
function spi_test_base::new(string name = "spi_test_base", uvm_component parent = null);
super.new(name, parent);
endfunction
// Build the env, create the env configuration
// including any sub configurations and assigning virtural interfaces
function void spi_test_base::build_phase( uvm_phase phase );
m_env_cfg = spi_env_config::type_id::create("m_env_cfg");
// Register map - Keep reg_map a generic name for vertical reuse reasons
spi_rm = new("reg_map", null);
m_env_cfg.spi_rm = spi_rm;
m_apb_cfg = apb_agent_config::type_id::create("m_apb_cfg");
configure_apb_agent(m_apb_cfg);
if( !uvm_config_db #(virtual apb_if)::get(this, "" , "APB_vif",m_apb_cfg.APB) ) `uvm_error(...)
m_env_cfg.m_apb_agent_cfg = m_apb_cfg;
// The SPI is not configured as such
m_spi_cfg = spi_agent_config::type_id::create("m_spi_cfg");
if( !uvm_config_db #(virtual spi_if)::get(this, "" , "SPI_vif",m_spi_cfg.SPI) ) `uvm_error(...)
m_spi_cfg.has_functional_coverage = 0;
m_env_cfg.m_spi_agent_cfg = m_spi_cfg;
// Insert the interrupt virtual interface into the env_config:
if( !uvm_config_db #(virtual intr_if)::get(this, "" , "INTR_vif",m_env_cfg.INTR) ) `uvm_error(...)
uvm_config_db #( spi_env_config )::set( this ,"*", "spi_env_config", m_env_cfg);
m_env = spi_env::type_id::create("m_env", this);
// Override for register adapter:
register_adapter_base::type_id::set_inst_override(apb_register_adapter::get_type(), "spi_bus.adapter");
endfunction: build_phase
//
// Convenience function to configure the apb agent
//
// This can be overloaded by extensions to this base class
function void spi_test_base::configure_apb_agent(apb_agent_config cfg);
cfg.active = UVM_ACTIVE;
cfg.has_functional_coverage = 0;
cfg.has_scoreboard = 0;
// SPI is on select line 0 for address range 0-18h
cfg.no_select_lines = 1;
cfg.start_address[0] = 32'h0;
cfg.range[0] = 32'h18;
endfunction: configure_apb_agent
为了创建特定的test case,扩展了spi_test_base类,这允许test编写者利用父类中定义的配置和构建过程,这意味着他只需要添加一个run method。在下面(简单的和待更新的)示例中,run方法实例化了一个虚拟sequence,并在env中的虚拟sequencer上启动此sequence。所有配置过程都是通过build method中的super.build() method调用来执行的。
//
// Class Description:
//
//
class spi_test extends spi_test_base;
// UVM Factory Registration Macro
//
`uvm_component_utils(spi_test)
//------------------------------------------
// Methods
//------------------------------------------
// Standard UVM Methods:
extern function new(string name = "spi_test", uvm_component parent = null);
extern function void build_phase( uvm_phase phase );
extern task reset_phase( uvm_phase phase );
extern task main_phase( uvm_phase phase );
endclass: spi_test
function spi_test::new(string name = "spi_test", uvm_component parent = null);
super.new(name, parent);
endfunction
// Build the env, create the env configuration
// including any sub configurations and assigning virtural interfaces
function void spi_test::build_phase( uvm_phase phase );
super.build_phase( phase );
endfunction: build_phase
task spi_test::reset_phase( uvm_phase phase );
check_reset_seq reset_test_seq = check_reset_seq::type_id::create("rest_test_seq");
phase.raise_objection( this , "Starting reset_test_seq in reset phase" );
reset_test_seq.start(m_env.m_v_sqr.apb);
phase.drop_objection( this , "Finished reset_test_seq in reset phase" );
endtask: reset_phase
task spi_test::main_phase( uvm_phase phase );
send_spi_char_seq spi_char_seq = send_spi_char_seq::type_id::create("spi_char_seq");
phase.raise_objection( this , "Starting spi_char_seq in main phase" );
spi_char_seq.start(m_env.m_apb_agent.m_sequencer);
#100ns;
phase.drop_objection( this , "Finished spi_char_seq in main phase" );
endtask: main_phase