| |
Config/ConfiguringSequences
A Configurable Sequence
配置sequences的最通用方法是默认使用完整的层次结构名称,但允许sequences的创建者使用任何其他名称。
class my_bus_seq extends uvm_sequence #( my_bus_sequence_item );
string scope_name = "";
task body();
my_bus_config m_config;
if( scope_name == "" ) begin
scope_name = get_full_name(); // this is { sequencer.get_full_name() , get_name() }
end
if( !uvm_config_db #( my_bus_config )::get( null , scope_name , "my_bus_config" , m_config ) ) begin
`uvm_error(...)
end
endtask
endclass
假设我们在“uvm_test_top.env.sub_env.agent1.sequencer”上的sequencer上运行了一个名为“initialization_sequence”的sequence。默认情况下,上面代码中的scope_name是“uvm_test_top.env.sub_env.agent1.sequencer.initialization_sequence”。sequence配置最常见的情况是我们想要获取已在agent及其所有子代上设置的agent的配置类。
class sub_env extends uvm_env;
...
function void build_phase( uvm_phase phase );
...
my_bus_config agent1_config;
...
uvm_config_db #( my_bus_config )::set( this , "agent1*" , "my_bus_config" , agent1_config );
...
endfunction
task main_phase( uvm_phase phase );
my_bus_sequence seq = my_bus_sequence::type_id::create("my_bus_sequence");
seq.start( agent1.sequencer );
endtask
...
endclass
由于我们使用sub_env作为context,因此可配置sequence中的set和默认get将匹配上,因此sequence将可以访问agent的配置对象。
Per Sequence Configuration
我们可以使用上面可配置sequence的默认模式来不同地配置不同的sequence,但是如果sequence的名称不同,我们只能这样做。
例如,环境类可能像这种情形:
class sub_env extends uvm_env;
...
function void build_phase( uvm_phase phase );
...
my_bus_config agent1_config , agent1_error_config;
...
agent1_config.enable_error_injection = 0;
agent1_error_config.enable_error_injection =10;
// most sequences do not enable error injection
uvm_config_db #( my_bus_config )::set( this , "agent1*" , "my_bus_config" , agent1_config );
// sequences with "error" in their name will enable error injection
uvm_config_db #( my_bus_config )::set( this , "agent1.sequencer.error*" , "my_bus_config" , agent1_error_config );
...
endfunction
task main_phase( uvm_phase phase );
my_bus_sequence normal_seq = my_bus_sequence::type_id::create("normal_seq");
my_bus_sequence error_seq = my_bus_sequence::type_id::create("error_seq");
normal_seq.start( agent1.sequencer );
error_seq.start( agent1.sequencer );
endtask
...
endclass
由于可配置sequence使用sequence名称来执行get,因此正常sequence将选择不启用错误注入的配置,而错误sequence将获取错误配置。
Ignoring the Component Hierarchy Altogether
配置sequences时完全可以忽略组件层次结构。这样做的好处是,我们实际上可以定义仅用于配置sequences的行为,并且我们可以将这些行为范围与组件层次结构完全分开。上述可配置序列将在该context以及基于组件层次结构的context中起作用。
因此,例如在虚拟sequence中,我们可能会执行以下操作:
class my_virtual_sequence extends uvm_sequence #( uvm_sequence_item_base );
...
task body();
my_bus_sequence normal_seq = my_bus_sequence::type_id::create("normal_seq");
my_bus_sequence error_seq = my_bus_sequence::type_id::create("error_seq");
normal_seq.scope_name = "sequences::my_bus_config.no_error_injection";
error_seq.scope_name = "sequences::my_bus_config.enable_error_injection";
normal_seq.start( agent1.sequencer );
error_seq.start( agent1.sequencer );
endtask
...
endclass
这种自由的缺点是该测试平台中的每个序列和组件都必须就命名方案达成一致,或者至少足够灵活以处理这种任意命名方案。由于这些范围名称不再保证唯一性,因此从块级转移到集成级别时可能存在一些重用问题。