| |
Setting Virtual Interface Properties in the Testbench
【此处需一幅图】
可能会问这样的问题:“为什么不让agent直接从DUT获取连接信息?为什么要通过test class来中转传输它?这看起来不是更复杂和额外的工作吗?”
agent直接有效地获取信息的方法难以在agent或事务传输器(如driver,monitor等)中编码关于DUT的信息,并降低可扩展性和重用。如果在DUT配置中进行了更改,则可能需要在agent中进行更改。可以将DUT连接和配置信息视为由DUT提供给测试平台的信息“池”。在推荐的方法中,test class从该池中获取信息并将其分发给正确的agent。如果信息池发生变化,则在一个位置进行适当的更改即可 - the test。agent不会受到影响,因为他们以相同的方式获取信息 - 来自test。相反,如果每个agent都直接从池中获取信息,则需要知道要获取哪些信息。如果信息池发生更改,则需要在agent中进行更改。
将接口实例的位置传递给test class有两种方法。建议的方法是此处列出的第一个使用config_db API的方法。
Bus Functional Models (BFM)
有时,DUT连接不是直接连接到DUT的端口,而是通过BFM进行。通常,BFM将具有生成DUT事务的tasks。这里讨论与BFM的DUT-TB通信。
Multiple Interface Instance Considerations
当一个接口有多个实例时,每个实例都需要具有唯一ID,以便事务传输器(如driver,monitor等)可以知道要连接到哪个接口。如果接口实例在array中声明或在同一层次声明,则可以通过简单地将数值附加到实例名称的末尾来完成。当有多个DUT实例并因此将多个接口实例包装在包装器模块中时,通常会更方便。可以对包装器模块进行参数化以在多个实例的包装器内部形成唯一的id。在上面显示的wishbone包装器模块代码中,WB_ID参数用于统一wishbone总线接口实例,并使用uvm_container促进在配置数据库中的放置。下面的代码显示了包含模块实例的顶层模块:
module top_mac;
wb_bus_wrapper #(0) wb_bus_0();
wb_bus_wrapper #(1) wb_bus_1();
endmodule
在test class中,提取适当的虚拟接口并将其分配给适当的wishbone配置对象。
class test_mac_simple_duplex extends uvm_test;
...
mac_env env_0; //environment for WISHBONE bus 0
mac_env env_1; //environment for WISHBONE bus 1
wb_config wb_config_0; // config object for WISHBONE BUS 0
wb_config wb_config_1; // config object for WISHBONE BUS 1
...
function void set_wishbone_config_params();
//set configuration info for WISHBONE 0
wb_config_0 = new();
wb_config_0.m_wb_id = 0; // WISHBONE 0
// Get the virtual interface handle that was set in the top module or protocol module
if (!uvm_config_db #(virtual wishbone_bus_bfm_if)::get(this, "",
"WB_BFM_IF_0",
wb_config_0.m_v_wb_bus_bfm_if)) // virtual interface
`uvm_fatal("TEST_MAC_SIMPLE_DUPLEX", "Can't read WB_BFM_IF_0");
uvm_config_db#(wb_config)::set(this, "env_0*", "wb_config", wb_config_0); // put in config
...
wb_config_1 = new();
wb_config_1.m_wb_id = 1; // WISHBONE 1
if (!uvm_config_db #(virtual wishbone_bus_bfm_if)::get(this, "",
"WB_BFM_IF_1",
wb_config_1.m_v_wb_bus_bfm_if)) // virtual interface
`uvm_fatal("TEST_MAC_SIMPLE_DUPLEX", "Can't read WB_BFM_IF_1");
uvm_config_db#(wb_config)::set(this, "env_1*", "wb_config", wb_config_1); // put in config
...
endfunction
...
endclass
(在http://verificationacademy.com/uvm-ovm上在线下载源代码示例)
如果使用generate语句,则还必须在generate块内完成虚拟接口分配,因为不允许对生成块实例进行变量索引。
genvar i;
for (i = 0; i<NUM_INTERFACES; i++) begin : gen
// alu_if instance
alu_if a_if(.clk(clk));
// DUT instance
alu_rtl alu (
.val1(a_if.val1),
.val2(a_if.val2),
.mode(a_if.mode),
.clk(a_if.clk),
.valid_i(a_if.valid_i),
.valid_o(a_if.valid_o),
.result(a_if.result)
);
initial begin
// Each virtual interface must have a unique name, so use $sformatf
uvm_config_db #(virtual alu_if)::set(null, "uvm_test_top",
$sformatf("ALU_IF_%0d",i), a_if);
end
end