UVM_COOKBOOK学习【UVM基础】

本文深入探讨了UVM测试平台的构建,重点介绍了Testbench基础、UVM组件、工厂机制和阶段执行流程。UVM组件遵循分层、面向对象的设计,允许在团队间分工明确。UVM工厂支持组件的动态替换,增强了testbench的灵活性。Phasing机制为仿真过程提供了有序的执行阶段,确保了验证的高效性和组件间的协调。此外,文章还详细阐述了配置数据库(uvm_config_db)的使用方法和重要性,以及如何通过包(package)组织和管理UVM相关的代码。
摘要由CSDN通过智能技术生成

这一部分主要介绍一些UVM的基础知识,其实《UVM实战》中已经有了足够的涉猎。所以这一章着重加注一些UVM的使用哲学探讨。

Testbench基础

UVM采用分层的、面向对象的方法进行testbench开发,允许在不同的团队成员之间进行“关注点分离”。UVM testbench中的每个组件都有特定的用途,以及和testbench其余部分的接口,以提高生产力并促进重用。把这些组件加入到testbench中,就得到一个模块化的可重用验证环境,它使编写测试用例的人在transaction级思考,专注于必须验证的功能,而testbench架构师则专注于test如何与DUT交互。

DUT被连接到一些事务器(driver、monitor、responder)上。这些事务器通过驱动和采样DUT信号在pin级与DUT通信,并通过传递transaction对象与UVM testbench的其余部分通信。它们在接口信号和transaction之间转换数据。在这些事务处理器之上的testbench的部分由专门在事务级进行交互的组件组成,如scoreboard, coverage collector, sequencer等。UVM testbench中的所有组件都是从uvm_component基类扩展而来。

UVM testbench的最低级别是特定于接口的。对每个接口而言,UVM提供一个uvm_agent,其中包括 driver, monitor, sequencer和coverage collector。因此,agent体现了与DUT的所有特定于协议的通信。agent和其他特定于设计的组件封装在uvm_env 组件中,该组件由顶层的uvm_test组件例化并配置。uvm_sequence_item是一个uvm_object,它包含实现协议和与DUT通信所需的数据字段。uvm_driver负责将sequence_item转换为信号级接口上的“pin wiggle”,以向DUT发送或从DUT接收数据。sequence_item由一个或多个uvm_sequence对象提供,这些对象在transaction级定义激励,并在agent的uvm_sequencer组件上执行。sequencer负责执行、仲裁sequences,并在sequences和driver之间传递sequence item。

uvm_sequence_item习惯上被称为transaction,实际上是由从uvm_object派生出的uvm_transaction类派生而来。

tb

uvm_monitor负责观察DUT接口上的信号级行为,并将其转换为sequence items,并将这些sequence items提供给agent或testbench上其他地方(如coverage collectors或scoreboard)中的analysis组件。UVM agent还有一个config object,该对象允许test编写人员在组装和执行testbench时配置agent。

通过为testbench提供统一的接口,UVM agent将testbench和UVM sequence与接口实现的细节隔离开来。例如,提供数据包的sequence可以在不同的UVM agent中重用,这些agent可能实现AHB、PCI或其他协议。UVM testbench通常为DUT的每个接口编写一个对应的agent。

对于给定的设计,UVM Agents和其他组件一起被封装在uvm_env组件中,该组件通常是特定于具体设计的。与agent一样,env通常也有一个与之相关联的config object,该对象允许test对env进行配置,包括在env中例化的agent。由于env本身就是UVM组件,所以也可以将其组装到更高级别的env中。模块级设计被组装成子系统和系统时,模块相关的模块级env可以作为子系统级env中的组件重用,而子系统级env本身也可以在系统级testbench上重用。

一旦定义了env,uvm_test将例化、配置并构建env,包括自定义整个testbench的关键方面,包括选择在env中使用的组件的变化。选择UVM sequences在后台运行或是作为test的主要部分。定义testbench上的env、sub_env(如果有)和agent的config object。

sequence包括验证环境执行的主体sequence以及一些用于响应DUT的挂在后台待调用的sequence。

UVM test通过在顶层initial块中调用run_test()启动。

UVM 组件

UVM testbench由扩展自uvm_component基类的组件对象构成。当创建uvm_component派生类的对象时,其成为testbench层次结构的一部分,会在整个仿真期间持续存在。这就与UVM类层次结构的sequence分支形成了对比,而后者涉及到瞬态对象(动态的),一旦解除引用,就会创建、使用和销毁的对象。

动态的: 笔者认为原文含义为,创建、使用的瞬态对象会在解除使用后(没有句柄指向该对象时,即原对象的句柄指向另一个新对象时)自动销毁。 例如,不同的sequencer上可能会挂载过多个sequence,而同一时间,只有一个sequence对象,执行过的sequence就会被自动销毁。同样地,sequence产生过的transaction(seq item),传递出去之后,就自动销毁。

uvm对象分类简介

UVM消息机制使用(准)静态uvm_component层次结构来打印发出报告消息的组件的作用域,配置过程使用它来确定哪些组件可以访问配置对象,UVM工厂使用它来应用工厂覆盖。这个组件层次结构由一个在创建每个组件时递增构建的链表表示。每个组件的层次位置由在构造时传递给其create方法的name和parent参数决定。

例如,在下面的代码片段中,在spi_env中创建了一个apb_agent组件。假设spi_env在顶层test组件中以名称“m_env”实例化,则agent的分层路径名是与spi_env组件名称“uvm_test_top.m_env”,(".")操作符,以及作为第一个参数传递给create()方法的name的拼接,最终agent的层次名称为"uvm_test_top.m_env.m_apb_agent"。对agent的任何引用都需要使用这个字符串名称。

即这个分层路径名由顶层test实例化名至当前组件的实例化名用(".")操作符逐级拼接。

// Hierarchical name example 

class spi_env extends uvm_env;

	apb_agent m_apb_agent;
// Declaration of the apb agent handle
// ... 

	function void build_phase(uvm_phase phase); 
// Create the apb_agent: 
// 
// Name string argument is the same as the handle name 
// The parent argument is 'this' - i.e. the spi_env 
// 
// The spi_env has a hierarchical path string "uvm_test_top.m_env" 
// is concatenated with the name string to arrive at 
// "uvm_test_top.m_env.m_apb_agent" as the
// hierarchical reference string for the apb_agent 
		m_apb_agent = apb_agent::type_id::create("m_apb_agent", this); 
// ... 
	endfunction: build_phase 
// ... 
endclass: spi_env

uvm_component类继承了uvm_report_object类,而该类位于UVM消息传递基础结构的核心。消息机制使用组件静态层次结构将组件的分层路径名添加到报告消息字符串中(即这条消息是由哪个组件(对象)报告的)。

uvm_component基类模板的每个UVM phase都有一个虚方法,用户可以根据需要实现这些方法。未实现的phase级虚方法将导致组件无法有效地参与该phase。

uvm_component基类中还嵌入了对配置表的支持,以存储与testbench层次结构中组件的子节点相关的配置对象。当使用uvm_config_db API时,这个静态层次结构(分层路径名)被用作路径机制的一部分,以控制哪些组件可以访问给定的配置对象。

为了在配置中提供灵活性并允许以智能的方式构建UVM testbench的层次结构,uvm_components需要被注册到UVM工厂。当在构建阶段创建UVM组件时,将会使用工厂来构造组件对象。UVM工厂允许使用工厂覆盖来把一个组件替换为它的一个兼容的派生类型。这种方式可以在不直接更改testbench源代码的情况下更改testbench的功能(直接更改testbench源代码需要重新编译并会阻碍重用)。工厂工作需要许多编码约定,在关于UVM工厂的内容中对这些约定做了概述。

UVM package包含许多uvm_component基类的扩展(即派生类),用于公共testbench组件。这些扩展中的大多数类都非常“瘦”,也就是说,它们实际上只是uvm_component类的一个小扩展,主要是用来添加一个新的名称空间。虽然这些不是很关键,原则上我们也仍然可以使用 uvm_component 类,但重要的是这些扩展类有助于实现组件的“自我分类”,因为其清楚地表明了实际表示的组件类型,例如driver或monitor。

通俗说就是是UVM强制为环境组件分类做引导,笔者认为UVM倡导的验证环境构建方式趋向于让单个组件处理单一类型的事务,这样环境结构清晰且易于分类维护

此外,还有一些可用的分析工具,它们也使用这些无关的基类来扩展,以帮助建立testbench层次结构的图像。另一方面,一些预构建的uvm_component扩展实际上是结构块,其通过实例化具体的子组件,来实现一组复杂的功能。下表总结了直接从uvm_component基类派生的可用的UVM组件类:

uvm_component

UVM 工厂

UVM工厂的目的是允许用派生类型的对象替换其基类的对象,且不需要更改testbench结构甚至testbench代码。这种机制称为覆盖(override)(按type或实例)。此功能对于更改sequence行为或用组件的一个版本替换另一个版本来说十分方便。但是,要交换的任何两个组件必须是多态兼容的。这就要求所有相同的TLM接口句柄和TLM对象必须由用来替换的派生组件声明及例化。此外,为了利用工厂的优势,我们必须遵循某些编码规范。

override的两种类型:替换这种class的实例,还是只替换该class的某个实例

工厂编码规范1:注册

组件或对象必须包含由以下元素组成的工厂注册代码:

  • 一个uvm_component_registry wrapper,typedef为type_id
  • 获取type_id的静态函数
  • 获取类名的函数

例如:

class my_component extends uvm_component; 

// Wrapper class around the component class that is used within the factory 

	typedef uvm_component_registry #(my_component, "my_component") type_id; 

// Used to get the type_id wrapper 

	static function type_id get_type(); 
		return type_id::get(); 
	endfunction 

// Used to get the type_name as a string 

	function string get_type_name(); 
		return "my_component"; 
	endfunction 
... 
endclass: my_component

注册代码有一个规则的模式,可以安全地用四个工厂注册宏中的一个生成:

// For a component 

class my_component extends uvm_component; 

// Component factory registration macro 

	`uvm_component_utils(my_component) 

// For a parameterized component 

class my_param_component #(int ADD_WIDTH=20, int DATA_WIDTH=23) extends uvm_component;

	typedef my_param_component #(ADD_WIDTH, DATA_WIDTH) this_t; 

// Parameterized component factory registration macro 

	`uvm_component_param_utils(this_t) 

// For a class derived from an object (i.e. uvm_object, uvm_transaction,

// uvm_sequence_item, uvm_sequence etc.)  

class my_item extends uvm_sequence_item; 
	`uvm_object_utils(my_item) 

// For a parameterized object class 

class my_item #(int ADD_WIDTH=20, int DATA_WIDHT=20) extends uvm_sequence_item; 
    
	typedef my_item #(ADD_WIDTH, DATA_WIDTH) this_t 
	`uvm_object_param_utils(this_t)

工厂编码规范2:构造函数默认值

uvm_component和uvm_object构造函数是带有原型模板的虚方法,用户必须遵守。为了在构建阶段支持延迟构造,工厂构造函数应该包含构造函数参数的默认值。这允许使用默认值在工厂内构建一个工厂注册类,然后可以将类属性重新赋值给通过uvm_component_registry wrapper类的create方法传递的参数。组件和对象的默认值是不同的:

// For a component: 

class my_component extends uvm_component; 

	function new(string name = "my_component", uvm_component parent = null); 
		super.new(name, parent); 
	endfunction 

// For an object: 

class my_item extends uvm_sequence_item; 

	function new(string name = "my_item"); 
		super.new(name); 
	endfunction
Table of Contents Articles Introduction 0 Cookbook/Introduction 0 Cookbook/Acknowledgements 1 Testbench Architecture 2 Testbench 2 Testbench/Build 9 Testbench/Blocklevel 19 Testbench/IntegrationLevel 29 Component 39 Agent 42 Phasing 48 Factory 53 UsingFactoryOverrides 56 SystemVerilogPackages 62 Connections to DUT Interfaces 65 Connections 65 SVCreationOrder 71 Connect/SystemVerilogTechniques 73 ParameterizedTests 75 Connect/Virtual Interface 78 Config/VirtInterfaceConfigDb 86 Connect/VirtInterfacePackage 90 Connect/VirtInterfaceConfigPkg 93 Connect/TwoKingdomsFactory 97 DualTop 103 VirtInterfaceFunctionCallChain 106 BusFunctionalModels 108 ProtocolModules 111 Connect/AbstractConcrete 115 Connect/AbstractConcreteConfigDB 118 Configuring a Test Environment 126 Configuration 126 Resources/config db 131 Config/Params Package 134 Config/ConfiguringSequences 139 ResourceAccessForSequences 142 MacroCostBenefit 145 Analysis Components & Techniques 146 Analysis 146 AnalysisPort 149 AnalysisConnections 152 MonitorComponent 158 Predictors 161 Scoreboards 163 MetricAnalyzers 170 PostRunPhases 172 Matlab/Integration 175 End Of Test Mechanisms 183 EndOfTest 183 Objections 185 Sequences 188 Sequences 188 Sequences/Items 193 Transaction/Methods 195 Sequences/API 200 Connect/Sequencer 204 Driver/Sequence API 206 Sequences/Generation 213 Sequences/Overrides 221 Sequences/Virtual 223 Sequences/VirtualSequencer 231 Sequences/Hierarchy 237 Sequences/SequenceLibrary 242 Driver/Use Models 246 Driver/Unidirectional 247 Driver/Bidirectional 250 Driver/Pipelined 255 Sequences/Arbitration 267 Sequences/Priority 276 Sequences/LockGrab 277 Sequences/Slave 284 Stimulus/Signal Wait 290 Stimulus/Interrupts 294 Sequences/Stopping 301 Sequences/Layering 302 Register Abstraction Layer 308 Registers 308 Registers/Specification 315 Registers/Adapter 317 Registers/Integrating 321 Registers/Integration 327 Registers/RegisterModelOverview 332 Registers/ModelStructure 334 Registers/QuirkyRegisters 344 Registers/ModelCoverage 349 Registers/BackdoorAccess 354 Registers/Generation 357 Registers/StimulusAbstraction 358 Registers/MemoryStimulus 370 Registers/SequenceExamples 375 Registers/BuiltInSequences 382 Registers/Configuration 386 Registers/Scoreboarding 389 Registers/FunctionalCoverage 395 Testbench Acceleration through Co-Emulation 401 Emulation 401 Emulation/SeparateTopLevels 404 Emulation/SplitTransactors 410 Emulation/BackPointers 415 Emulation/DefiningAPI 419 Emulation/Example 422 Emulation/Example/APBDriver 430 Emulation/Example/SPIAgent 435 Emulation/Example/TopLevel 441 Debug of SV and UVM 444 BuiltInDebug 444 Reporting/Verbosity 455 UVM/CommandLineProcessor 460 UVM Connect - SV-SystemC interoperability 464 UvmConnect 464 UvmConnect/Connections 466 UvmConnect/Conversion 468 UvmConnect/CommandAPI 472 UVM Express - step by step improvement 476 UvmExpress 476 UvmExpress/DUT 481 UvmExpress/BFM 485 UvmExpress/WritingBfmTests 490 UvmExpress/FunctionalCoverage 498 UvmExpress/ConstrainedRandom 503 Appendix - Deployment 516 OVM2UVM 516 OVM2UVM/DeprecatedCode 527 OVM2UVM/SequenceLibrary 528 OVM2UVM/Phasing 530 OVM2UVM/ConvertPhaseMethods 535 UVC/UvmVerificationComponent 537 Package/Organization 548 Appendix - Coding Guidelines 555 SV/Guidelines 555 UVM/Guidelines 569 Appendix - Glossary of Terms 579 Doc/Glossary 579
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值