UVM Basics
在我们开始讨论UVM食谱中的食谱之前,我们必须确保我们谈论的都是相同的食材。本章介绍了UVM的概念,读者应该了解这些概念,以便理解本文介绍的食谱。这一部分对新的UVM用户来说非常有价值,但经验丰富的UVM使用者可以直接进入UVM测试台章节。
Testbench Basics
UVM测试台基础
UVM采用分层、面向对象的方法进行测试台开发,允许不同团队成员之间“分离关注点”。UVM测试台中的每个组件都有特定的用途,并与测试台的其余部分有一个定义良好的接口,以提高生产力并促进重用。当这些组件组装到测试台中时,结果是一个模块化的可重复使用的验证环境,它允许测试编写者在事务级别思考,专注于必须验证的功能,而测试台架构师则专注于测试如何与被测设计(DUT)交互。
被测设计(DUT)连接到一层交易器(驱动器、监视器、响应器)。这些交易器通过驱动和采样DUT信号在引脚级别与DUT通信,并通过传递交易对象与UVM测试台的其余部分通信。它们在引脚和事务之间转换数据,即从/到信号到/从事务级别。transactor层之上的测试台层由专门在事务级别交互的组件组成,如记分板、覆盖收集器、刺激生成器等。UVM测试台中的所有结构元素都是从UVM_component基类扩展而来的。
UVM测试台的最低级别是特定于接口的。对于每个接口,UVM提供一个UVM_agent,包括驱动器、监视器、刺激发生器(测序仪)和(可选)覆盖收集器。因此,Agent体现了与DUT的所有协议特定通信。Agent和其他特定于设计的组件封装在uvm_env环境组件中,该组件又由顶级uvm_test组件实例化和自定义。
uvm_sequence_item(有时称为事务)是一个uvm_object,包含实现协议和与DUT通信所需的数据字段。uvm_driver负责将sequence_item转换为信号电平接口上的“pin wiggles”,以便向DUT发送数据和从DUT接收数据。sequence_items由一个或多个uvm_sequence对象提供,这些对象在事务级别定义刺激并在代理的uvm_segmenter组件上执行。定序器负责执行序列,在它们之间进行仲裁,并在驱动程序和序列之间路由序列项。
uvm_monitor负责被动观察DUT接口上的引脚级行为,将其转换为序列项,并将这些序列项提供给代理中的分析组件或测试台中的其他位置,如覆盖收集器或记分板。UVM代理还有一个配置对象,允许测试编写器在组装和执行测试台时控制代理的各个方面。
通过向测试台提供统一的接口,UVM Agent将测试台和UVM序列与接口实现的细节隔离开来。例如,提供数据包的序列可以与可以实现AHB、PCI或其他协议的不同UVM代理一起重用。UVM测试台通常每个DUT接口有一个试剂。
对于给定的设计,UVM代理和其他组件封装在UVM_env环境组件中,该组件通常是特定于设计的。与代理一样,环境通常具有与其相关联的配置对象,该配置对象允许测试控制环境的各个方面以及控制在环境中实例化的代理。因为环境本身就是UVM组件,所以可以将它们组装到更高级别的环境中。随着块级设计被组装成子系统和系统,与块相关联的块级UVM环境可以被重新用作子系统级环境中的组件,其本身可以在系统级测试台中被重新使用。
一旦定义了环境,uvm_test将实例化、配置和构建环境,包括自定义整个测试台的关键方面,包括*选择要在环境中使用的组件的变体*选择要在后台或作为测试的主要部分运行的UVM序列*在测试台中定义环境、子环境(如果有)和代理的配置对象
UVM测试是通过调用run_test()从顶级HVL模块中的初始块开始的。
UVM components
UVM测试台由从UVM_component基类扩展而来的组件对象组成。创建uvm_component派生的类对象时,它将成为在模拟期间持续存在的测试台层次结构的一部分。这与UVM类层次结构的序列分支形成了对比,后者涉及瞬态对象——一旦取消引用,就会创建、使用和销毁(即垃圾收集)的对象。
(准)静态uvm_component层次结构由uvm报告基础结构用于打印发布报告消息的组件的范围,由配置过程用于确定哪些组件可以访问配置对象,以及由uvm工厂用于应用工厂覆盖。该组件层次结构由一个链表表示,该链表是随着每个组件的创建而逐步建立的。每个组件的层次结构位置由构建时传递给其创建方法的名称和父参数决定。
例如,在下面的代码片段中,在spi_env中创建了一个apb_agent组件。假设spi_env在顶级测试组件中实例化,名称为“m_env”,则代理的分层路径名称是spi_envs组件名称、“uvm_test_top.m_env”、“dot”(“.”)运算符和作为第一个参数传递给“create()”方法的名称的串联,导致代理的层次结构名称为“uvm_test_top.m_env.m_apb_agent”。对代理的任何引用都需要使用此字符串名称。
uvm_component类继承自uvm_report_object类,后者位于uvm消息传递基础结构的核心。报告过程使用组件静态层次结构将组件的作用域添加到报告消息字符串中。
uvm_component基类模板为每个uvm阶段都有一个虚拟方法,这些方法将由用户根据需要实现。未实现的阶段级虚拟方法会导致组件实际上不参与该阶段。
uvm_component基类中还嵌入了对配置表的支持,该配置表用于存储与测试台层次结构中组件的子节点相关的配置对象。当使用uvm_config_db API时,该静态层次结构被用作路径机制的一部分,以控制哪些组件可以访问给定的配置对象。
为了提供配置灵活性,并允许以智能方式构建UVM测试台层次结构,UVM_components在UVM工厂注册。在构建阶段创建UVM零部件时,将使用factory来构建零部件对象。UVM工厂允许使用工厂替代将一个零部件替换为另一个兼容的派生类型。这是一种有用的技术,可以在不直接更改测试台源代码的情况下更改测试台的功能,这将需要重新编译并阻碍重用。工厂工作需要许多编码约定,这些约定在UVM工厂的文章中有概述。
UVM包包含通用测试台组件的UVM_component基类的许多扩展(即派生类)。这些扩展中的大多数都非常“瘦”,即它们实际上只是uvm_component类的一个小扩展,用于添加新的名称空间。虽然这些都不是关键的,原则上仍然可以使用uvm_component类,但它们确实有助于“自我文档”,因为它们清楚地表明了这一点