| |
Connect/Virtual Interface
irtual Interfaces
虚拟接口是一个动态变量,它包含对静态接口实例的引用。对于所有意图和目的,可以将其视为SystemVerilog接口实例的句柄或引用。注意,这里使用的术语"virtua”的使用方式与面向对象编程中常规使用的意义不同,而是IEEE 1800委员会选择它来调用这些引用。
Virtual Interface Use
使用虚拟接口是因为基于测试平台的类无法引用verilog / vhdl ports,因此无法直接连接到Verilog或VHDL DUT。而是将SystemVerilog接口实例连接到DUT的ports,并且测试平台通过接口实例与DUT通信。使用虚拟接口作为接口实例的引用或句柄,测试平台可以访问SystemVerilog接口的tasks、functions、ports和内部变量。当接口实例连接到DUT引脚时,测试平台可以通过接口信号间接监视和控制DUT引脚。
DUT可以具有连接到其ports的一个或多个接口。如果DUT具有多个逻辑接口(不同的总线等),则建议为每个逻辑接口使用单独的接口。还应考虑将接口实例封装在协议模块中。
【此处需一幅图】
示例DUT(图中的WISHBONE bus slave memory)具有以下ports:
module wb_slave_mem #(parameter mem_size = 13)
(clk, rst, adr, din, dout, cyc, stb, sel, we, ack, err, rty);
input clk, rst;
input [31:0] adr, din;
output [31:0] dout;
input cyc, stb;
input [3:0] sel;
input we;
output ack, err, rty;
...
endmodule
在WISHBONE总线环境中,有许多参数在DUT和测试平台之间共享。它们在下面显示的test parameters package(test_params_pkg)中定义。这里让人感兴趣的是mem_slave_size和mem_slave_wb_id参数。mem_slave_size用于设置slave memory device的大小。WISHBONE总线具有主设备和从设备,每个主设备和从设备分别具有主设备和从设备ID。mem_slave_wb_id用于设置slave memory的WISHBONE从设备ID。
package test_params_pkg;
import uvm_pkg::*;
// WISHBONE general slave parameters
parameter slave_addr_space_sz = 32'h00100000;
// WISHBONE slave memory parameters
parameter mem_slave_size = 18; // 2**slave_mem_size = size in words(32 bits) of wb slave memory
parameter mem_slave_wb_id = 0; // WISHBONE bus slave id of wb slave memory
...
endpackage
下面是连接到此DUT的WISHBONE总线互连接口。此互连最多支持8个主设备和8个从设备。这里未示出仲裁,时钟,复位和从解码逻辑。仅显示互连变量。本文将进一步介绍完整源代码的链接。
// Wishbone bus system interconnect (syscon)
// for multiple master, multiple slave bus
// max 8 masters and 8 slaves
interface wishbone_bus_syscon_if #(int num_masters = 8, int num_slaves = 8,
int data_width = 32, int addr_width = 32) ();
// WISHBONE common signals
bit clk;
bit rst;
bit [7:0] irq;
// WISHBONE master outputs
logic [data_width-1:0] m_wdata[num_masters];
logic [addr_width-1:0] m_addr [num_masters];
bit m_cyc [num_masters];
bit m_lock[num_masters];
bit m_stb [num_masters];
bit m_we [num_masters];
bit m_ack [num_masters];
bit [7:0] m_sel[num_masters];
// WISHBONE master inputs
bit m_err;
bit m_rty;
logic [data_width-1:0] m_rdata;
// WISHBONE slave inputs
logic [data_width-1:0] s_wdata;
logic [addr_width-1:0] s_addr;
bit [7:0] s_sel;
bit s_cyc;
bit s_stb[num_slaves]; //only input not shared since it is the select
bit s_we;
// WISHBONE slave outputs
logic [data_width-1:0] s_rdata[num_slaves];
bit s_err[num_slaves];
bit s_rty[num_slaves];
bit s_ack[num_slaves];
...
endinterface
要将接口连接到DUT,可以从DUT的引脚到接口中的变量进行分层连接,如下所示。请注意,test_params_pkg中的mem_slave_wb_id参数用作从属“slot id”,用于将slave memory连接到接口中的正确信号。
module top_mac;
import uvm_pkg::*;
import tests_pkg::*;
import uvm_container_pkg::*;
import test_params_pkg::*;
// WISHBONE interface instance
// Supports up to 8 masters and up to 8 slaves
wishbone_bus_syscon_if wb_bus_if();
//-----------------------------------
// WISHBONE 0, slave 0: 000000 - 0fffff
// this is 1 Mbytes of memory
wb_slave_mem #(mem_slave_size) wb_s_0 (
// inputs
.clk ( wb_bus_if.clk ),
.rst ( wb_bus_if.rst ),
.adr ( wb_bus_if.s_addr ),
.din ( wb_bus_if.s_wdata ),
.cyc ( wb_bus_if.s_cyc ),
.stb ( wb_bus_if.s_stb[mem_slave_wb_id] ),
.sel ( wb_bus_if.s_sel[3:0] ),
.we ( wb_bus_if.s_we ),
// outputs
.dout( wb_bus_if.s_rdata[mem_slave_wb_id] ),
.ack ( wb_bus_if.s_ack[mem_slave_wb_id] ),
.err ( wb_bus_if.s_err[mem_slave_wb_id] ),
.rty ( wb_bus_if.s_rty[mem_slave_wb_id] )
);
...
endmodule
在测试平台中,事务传输器(例如包含在agent中的drivers 和 monitors)通常需要访问DUT。假设在下面的代码示例中,虚拟接口属性m_v_wb_bus_if指向连接到DUT的wishbone_bus_syscon_if的实例(下一节讨论设置虚拟接口属性)。然后在WISHBONE bus driver中,代码可能如下所示。注意访问接口变量的virtual interface属性的应用:
class wb_m_bus_driver extends uvm_driver #(wb_txn, wb_txn);
...
uvm_analysis_port #(wb_txn) wb_drv_ap;
virtual wishbone_bus_syscon_if m_v_wb_bus_if; // Virtual Interface
bit [2:0] m_id; // Wishbone bus master ID
wb_config m_config;
...
//WRITE 1 or more write cycles
virtual task wb_write_cycle(ref wb_txn req_txn);
wb_txn orig_req_txn;
$cast(orig_req_txn, req_txn.clone()); //save off copy of original req transaction
for(int i = 0; i<req_txn.count; i++) begin
if(m_v_wb_bus_if.rst) begin
reset(); // clear everything
return; //exit if reset is asserted
end
m_v_wb_bus_if.m_wdata[m_id] = req_txn.data[i];
m_v_wb_bus_if.m_addr[m_id] = req_txn.adr;
m_v_wb_bus_if.m_we[m_id] = 1; //write
m_v_wb_bus_if.m_sel[m_id] = req_txn.byte_sel;
m_v_wb_bus_if.m_cyc[m_id] = 1;
m_v_wb_bus_if.m_stb[m_id] = 1;
@ (posedge m_v_wb_bus_if.clk)
while (!(m_v_wb_bus_if.m_ack[m_id] & m_v_wb_bus_if.gnt[m_id])) @ (posedge m_v_wb_bus_if.clk);
req_txn.adr = req_txn.adr + 4; // byte address so increment by 4 for word addr
end
`uvm_info($sformatf("WB_M_DRVR_%0d",m_id),
$sformatf("req_txn: %s",orig_req_txn.convert2string()),
351 )
wb_drv_ap.write(orig_req_txn); //broadcast orignal transaction
m_v_wb_bus_if.m_cyc[m_id] = 0;
m_v_wb_bus_if.m_stb[m_id] = 0;
endtask
...
endclass
(在http://verificationacademy.com/uvm-ovm上在线下载源代码示例)。
Setting Virtual Interface Properties in the Testbench
为了在测试平台的事务传输器(driver, monitor等)中设置虚拟接口属性以指向连接到DUT的接口实例,发生了两个独立且不同的活动。
首先,DUT向测试平台提供连接信息。出于模块化和重用的目的,这应该以DUT对测试平台一无所知的方式进行。DUT应以不需要对DUT或其相关逻辑进行额外连接或修改的方式向测试平台提供必要的连接信息。
其次,连接信息必须在测试平台中与其事务传输器(driver,monitor等)一起传输给特定的agent。理想情况下,在测试平台中设置和分配配置和连接信息应该在一个地方完成 - the test class。test class从DUT获取信息并将其传输到适当的测试平台组件。 test class应该是唯一具有关于DUT及其接口的硬编码信息的测试平台组件。当DUT配置发生变化时,对测试平台的更改可能仅限于test class。这有助于扩展测试平台的可扩展性和可重用性。