参数化的Interfaces和可重用VIP(1/3)

本篇是讨论SystemVerilog接口和接口参数化处理策略的三部分系列的第一部分。

背景

基于SystemVerilog的验证引入了接口的概念来表示模块之间的通信。在最基本的形式中,SystemVerilog接口只是一个命名的信号包,可以通过模块端口作为单个项目进行通信。接收此接口的模块可以通过此接口访问信号。但是,接口的更高级功能还可以提供更强类型的通信,以更好地表示设计意图。以下是SystemVerilog接口中可用的高阶函数的子集:

  • 可以通过使用clocking blocksmodports在信号列表上强制执行访问规则
  • 函数和任务可用于封装高阶控制序列或访问控制
  • 初始块( initial blocks)和始终块(always blocks)等进程可以添加功能
  • 连续赋值语句还可以添加功能
  • 断言可以确保正确的集成

SystemVerilog接口的一个非常重要的用途是将静态设计元素连接到动态测试平台。动态测试平台需要访问静态设计元素才能采样和驱动信号,但可重用的测试平台除了通过名为虚拟接口的特殊构造外,无法访问静态设计元素。虚拟接口是测试平台代码中的接口的句柄,可以使用接口实例进行分配。虚拟接口是动态属性,可以分配给不同测试平台中的不同接口实例,从而提高可重用性。

设计可重用模块的常用技术是使用参数来使具有独特特征的模块的不同实例化成为可能。例如,可以对模块进行参数化,以允许在声明模块并提供参数值时定义数据总线宽度。SystemVerilog接口也支持参数化,但参数化接口的使用在测试平台引入了无法预料的复杂性。为了兼容赋值,参数化虚拟接口必须专门使用与接口实例专用的值相同的值。除非采取预防措施,否则这可能会导致一些非常难看的测试平台代码甚至更加丑陋的使用模型。

参数增殖:蛮力方法

参数化的虚拟接口引入的问题是访问它的testbench元素必须知道强类型接口。因此,当尚不知道接口规范时,不能编写泛型类以使用虚拟接口参数化。该问题的一个解决方案是参数化访问参数化虚拟接口的类。例如,可以使用必须使用的虚拟接口类型来参数化UVM驱动程序。这只是将问题向上移动一层,因为现在实例化该参数化驱动程序(driver)的代理(agent)也必须进行参数化,以便它可以创建一个正确专用的驱动程序实例。这会继续向上移动层,直到您到达顶层测试平台组件,该组件“知道”正在测试的特定规范存在。以下代码段演示了此问题。

首先我们定义参数化虚拟接口:

interface param_if#(int width = 8);
  logic clk;
  logic[width-1:0] data;
 
  clocking active_cb @(posedge clk);
    default input #1 output #1;
    output data;
  endclocking
 
  modport active_mp (clocking active_cb);
endinterface
 
typedef virtual param_if param_vif

接下来,我们定义可重用的VIP代码。此测试平台代码必须设计为可在任何可以使用参数化接口的环境中重用,因此VIP代码本身也必须参数化,以便可以访问正确的接口。以下代码段显示了如何参数化UVM驱动程序类和包含驱动程序的代理程序(agent):

//=======================================================================
class param_driver#(type vif_t=param_vif) extends uvm_driver#(cust_data);
  `uvm_component_param_utils(param_driver#(vif_t))
 
  vif_t vif;
 
  function void build_phase(uvm_phase phase);
    if (!uvm_config_db#(vif_t)::get(this, "", "vif", vif))
      `uvm_fatal("build", "A valid interface was not received.");
  endfunction
endclass
 
//=======================================================================
class cust_agent#(type vif_t=param_vif) extends uvm_agent;
  `uvm_component_param_utils(param_agent#(vif_t))
 
  vif_t vif;
  param_driver#(vif_t) param_driver;
 
  function void build_phase(uvm_phase phase);
    if (!uvm_config_db#(vif_t)::get(this, "", "vif", vif))
      `uvm_fatal("build", "A valid interface was not received.");
 
    uvm_config_db#(vif_t)::set(this, "param_driver", "vif", vif);
    param_driver = param_driver#(vif_t)::type_id::create("param_driver", this);
  endfunction
endclass

到目前为止,这看起来并不那么糟糕!它为类定义增加了一点复杂性,但不是太多。但是,在检查测试台必须如何访问这些参数化类之前,这些问题并不明显。以下部分显示了测试如何根据接口参数化的方式唯一访问VIP的每个实例:

//=======================================================================
class cust_test extends uvm_test;
  `uvm_component_utils(cust_test)
 
  param_agent#(virtual param_if#(8)) param_agent8;
  param_agent#(virtual param_if#(16)) param_agent16;
  param_agent#(virtual param_if#(32)) param_agent32;
 
  virtual function void build_phase(uvm_phase phase);
    param_agent8 = param_agent#(virtual param_if#(8))::type_id::create("param_agent8", this);
    param_agent16 = param_agent#(virtual param_if#(16))::type_id::create("param_agent16", this);
    param_agent32 = param_agent#(virtual param_if#(32))::type_id::create("param_agent32", this);
  endfunction
endclass
 
//=======================================================================
module test_top;
  param_if#(8) if8();
  param_if#(16) if16();
  param_if#(32) if32();
 
  initial begin
    uvm_config_db#(virtual param_if#(8))::set(uvm_root::get(), "uvm_test_top.param_agent8", "vif", if8);
    uvm_config_db#(virtual param_if#(16))::set(uvm_root::get(), "uvm_test_top.param_agent16", "vif", if16);
    uvm_config_db#(virtual param_if#(32))::set(uvm_root::get(), "uvm_test_top.param_agent32", "vif", if32);
 
    run_test("cust_test");
  end
endmodule

正如您所看到的,每个对VIP的引用都必须使用适当的接口类型进行参数化。这不仅会影响VIP构造,还会影响回调注册,工厂重载等。这给测试平台开发人员带来了很大的负担,并限制了这些环境的可重用性。

向验证组件添加参数是可重用VIP的有效技术解决方案,但它使使用模型大大复杂化并限制了测试台的可重用性。在本系列的下一篇文章中,我们将研究这个问题的可能解决方法,但这需要付出代价!

您可以在Synopsys Verification IP  和  VC Verification IP数据表中获得更多信息。 

  • 2
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 这两个文件都是用来配置网络接口的文件,但是它们所处的位置和使用方法有所不同。 /root/Local/interfaces是Ubuntu下的网络接口配置文件,它通常用于配置静态IP地址,DNS服务器等网络参数。这个文件只对当前登录的用户可见,而不是全局设置,因此每个用户都可以有自己的网络配置。 /etc/network/interfaces则是Debian系列操作系统中的网络接口配置文件,它通常用于配置系统全局的网络参数。这个文件可以设置多个网络接口的配置信息,包括IP地址、子网掩码、网关等等。 需要注意的是,这两个文件都需要root权限才能编辑和保存,因为它们涉及到系统的网络配置。 ### 回答2: 在Linux中,root/Local/interfaces和etc/network/interfaces是两个不同的文件,用于配置网络接口。 /root/Local/interfaces是root用户的个人配置文件,它仅适用于当前用户,不会影响其他用户或整个系统。在该文件中,可以设置特定用户的网络接口配置,比如设置IP地址、子网掩码、网关等。这个文件的路径是/root/Local/interfaces。 /etc/network/interfaces是系统级别的网络接口配置文件,它适用于整个系统的所有用户和网络接口。在这个文件中,可以定义和配置系统中的各个网络接口(如eth0、eth1等),包括设置静态IP地址、动态获取IP地址(DHCP)、网络协议版本(IPv4或IPv6)等。这个文件的路径是/etc/network/interfaces。 通常情况下,我们更常用的是/etc/network/interfaces文件来配置网络接口,因为它可以一次性设置整个系统中的所有接口,便于系统管理。而/root/Local/interfaces则是用于特定用户的个人配置,适合个性化的需求。 总的来说,这两个文件都是配置Linux系统中网络接口的重要文件,但是它们的作用范围和使用方式略有不同。 ### 回答3: 在Linux中,root/Local/interfaces和/etc/network/interfaces都是与网络配置相关的文件。然而,它们位于不同的位置并具有不同的作用。 root/Local/interfaces是一个私有的网络配置文件,仅对当前用户有效。在该文件中,可以定义与当前用户相关的网络接口、IP地址、子网掩码、网关等信息。这个文件通常不会影响到系统的整体网络配置。用户可以根据需求自定义这个文件,如指定某个网络接口的静态IP地址。 而/etc/network/interfaces是系统级别的网络配置文件,它适用于整个系统的网络接口。在该文件中,可以定义系统的网络接口、IP地址、子网掩码、网关以及DNS服务器等信息。这个文件的配置会影响到整个系统的网络行为。通常,系统管理员会根据具体需求来修改该文件,如配置服务器的网络接口为静态IP地址。 总结起来,root/Local/interfaces是当前用户的私有网络配置文件,而/etc/network/interfaces是系统级别的网络配置文件。前者用于自定义当前用户相关的网络接口信息,后者用于配置整个系统的网络接口信息。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值