news 2026/10/15 21:19:54

11. UVM Test [uvm_test]

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
11. UVM Test [uvm_test]

现在,你已经准备好学习UVM的“总指挥”了——uvm_test。它是整个验证工厂的最高指挥官,负责设定任务、调配资源并下令开工。

简单来说,uvm_test不是一个具体的测试动作,而是一个可配置、可重用的“测试方案”或“作战计划”。它不直接驱动信号,而是通过配置环境、启动不同的“作战指令”(序列)来验证DUT的不同功能。

🎯 Test的本质:一个可执行的“验证方案”

你可以把验证计划(Verification Plan)里的一条条功能点(Feature)想象成需要攻克的“战略目标”。一个uvm_test就是一个针对其中一个战略目标的完整作战计划。它包含:

  • 作战环境:需要哪些“部队”(Agent)参与。
  • 部队配置:各部队用什么“装备”、以什么“模式”(主动/被动)作战。
  • 作战指令:具体的进攻顺序和策略(Sequence)。
  • 战果评估:如何判断目标是否达成(通过Scoreboard等检查)。

🏗️ 编写一个UVM Test的四步核心流程

下图展示了创建一个“作战计划”(Test)从搭建指挥部到下达作战指令的完整流程:

第一步:建立指挥部
你的 Test 类需要从uvm_test继承,并进行工厂注册。注意,它虽然不叫uvm_component,但本质上是一个顶级组件。

class my_base_test extends uvm_test;`uvm_component_utils(my_base_test)// 使用组件宏注册functionnew(string name=“my_base_test”,uvm_component parent=null);super.new(name,parent);endfunction// ... 后续步骤写在这里endclass

第二步:组建与配置部队 (核心)
在build_phase中,你需要:

  1. 创建环境(env)和配置对象(cfg)。
  2. 为配置对象赋值(如设置工作模式、获取虚拟接口等)。
  3. 通过uvm_config_db将配置对象“下发”到环境中的具体Agent。
virtual functionvoidbuild_phase(uvm_phase phase);super.build_phase(phase);// 1. 创建m_env=my_env::type_id::create(“m_env”,this);m_cfg=my_cfg::type_id::create(“m_cfg”);// 2. 配置if(!uvm_config_db #(virtual dut_if)::get(this,“”,“dut_vif”,m_cfg.vif))`uvm_error(“CFG”,“Interface not found!”)m_cfg.is_active=UVM_ACTIVE;// 3. 下发uvm_config_db #(my_cfg)::set(this,“m_env.m_agent”,“cfg”,m_cfg);endfunction

第三步:战前检阅(调试)
在end_of_elaboration_phase中,所有组件已创建并连接好。此时打印拓扑结构,可以清晰地看到你搭建的整个“部队编制”是否正确。

virtual functionvoidend_of_elaboration_phase(uvm_phase phase);uvm_top.print_topology();// 打印出完整的UVM组件树endfunction

第四步:下达作战指令(核心)
在run_phase(这是一个task,会消耗仿真时间)中,你需要:

  1. 申请作战时间:通过raise_objection(this)防止仿真立刻结束。
  2. 创建并启动主序列:这是测试的灵魂,决定了要发送什么数据。
  3. 结束作战:序列执行完毕后,drop_objection(this)。
virtual taskrun_phase(uvm_phase phase);my_main_sequence main_seq;super.run_phase(phase);// 好习惯phase.raise_objection(this);main_seq=my_main_sequence::type_id::create(“main_seq”);main_seq.start(m_env.v_sqr);// 通常启动在虚拟序列器上phase.drop_objection(this);endtask

🚀 如何“启动”一个Test:两种方式

Test 的启动不是在你代码里调用一个函数,而是在顶层模块(tb_top)的initial块中,通过run_test()这个全局任务来“召唤”。

方式一:代码内指定(不灵活)

initial beginrun_test(“my_base_test”);// 固定运行 my_base_testend

方式二(推荐):命令行指定

initial beginrun_test();// 参数为空,从命令行获取end

然后在仿真时通过命令行指定:

# 使用不同的 +UVM_TESTNAME 来运行不同的测试,无需重新编译!<simulator_command>+UVM_TESTNAME=my_base_test<simulator_command>+UVM_TESTNAME=test_feature_a<simulator_command>+UVM_TESTNAME=test_stress

这是UVM框架灵活性的重要体现,一定要掌握。

🔄 衍生测试:实现极致的重用

这是UVM测试策略最强大的地方。你不需要为每个功能点从头写一个Test,而是通过继承来复用和调整。

假设你有一个验证寄存器读写功能的测试reg_test:

// 1. 基础测试:搭建通用环境,启动基础序列class reg_test extends uvm_test;`uvm_component_utils(reg_test)reg_env m_env;reg_cfg m_cfg;virtual functionvoidbuild_phase(uvm_phase phase);super.build_phase(phase);m_env=reg_env::type_id::create(“m_env”,this);m_cfg=reg_cfg::type_id::create(“m_cfg”);m_cfg.reg_model=“RAL”;// 使用寄存器模型uvm_config_db #(reg_cfg)::set(this,“*”,“cfg”,m_cfg);endfunction virtual taskrun_phase(uvm_phase phase);base_reg_seq seq=base_reg_seq::type_id::create(“seq”);phase.raise_objection(this);seq.start(m_env.v_sqr);phase.drop_objection(this);endtask endclass// 2. 衍生测试A:复用环境,但更换更复杂的“作战指令”class test_reg_stress extends reg_test;// 关键:继承`uvm_component_utils(test_reg_stress)virtual taskrun_phase(uvm_phase phase);stress_reg_seq seq=stress_reg_seq::type_id::create(“seq”);// 更换序列phase.raise_objection(this);seq.start(m_env.v_sqr);// 环境 m_env 是从父类继承来的!phase.drop_objection(this);endtask endclass// 3. 衍生测试B:复用环境和序列,但调整“部队配置”class test_reg_passive extends reg_test;`uvm_component_utils(test_reg_passive)virtual functionvoidbuild_phase(uvm_phase phase);super.build_phase(phase);// 先调用父类,完成通用搭建m_cfg.is_active=UVM_PASSIVE;// 然后覆盖配置:将Agent设为被动模式endfunction endclass

⚠️ 核心要点与总结

概念说明关键点
uvm_test角色验证环境的总指挥和配置中心。不直接干活,只负责“排兵布阵”。
配置下发通过uvm_config_db::set在build_phase将配置对象(cfg)下发。实现环境行为的动态控制。
启动序列在run_phase中create并start序列。必须使用raise/drop_objection包裹。
运行方式通过run_test()++UVM_TESTNAME命令行参数。实现不修改代码、不重新编译即可切换测试。
测试重用通过类继承创建衍生测试。可重写build_phase以修改配置,或重写run_phase以更换主序列。

给你的最终建议:
现在,请将你之前搭建的env、agent、sequence组合起来。

  1. 创建一个my_base_test,在build_phase中创建你的env。
  2. 在run_phase中启动你的序列,并确保有raise/drop_objection。
  3. 在tb_top中,使用run_test(“my_base_test”)启动仿真。
  4. 成功后,尝试用run_test()+ 命令行参数+UVM_TESTNAME=my_base_test的方式再次运行。
  5. 最后,创建一个衍生测试,仅仅更换另一个不同的序列,并通过命令行运行它。

当你成功运行起第一个由Test指挥的完整UVM环境时,你就真正打通了UVM从底层到顶层的任督二脉。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/15 8:13:20

Markn轻量级Markdown查看器:简单高效的文档预览解决方案

Markn轻量级Markdown查看器&#xff1a;简单高效的文档预览解决方案 【免费下载链接】markn Lightweight markdown viewer. 项目地址: https://gitcode.com/gh_mirrors/ma/markn 在日常文档编写过程中&#xff0c;你是否厌倦了频繁切换编辑器和预览模式&#xff1f;Mark…

作者头像 李华
网站建设 2026/10/15 1:50:25

企业文档AI化进程中的隐私困局与PrivateGPT技术解构

企业文档AI化进程中的隐私困局与PrivateGPT技术解构 【免费下载链接】private-gpt 项目地址: https://gitcode.com/gh_mirrors/pr/private-gpt 问题诊断→解决方案→实操验证 当企业文档管理遭遇AI技术升级需求&#xff0c;数据安全与功能效率的平衡成为核心矛盾。据行…

作者头像 李华
网站建设 2026/10/15 14:33:21

如何快速构建专业级聊天界面:Chat UI Kit React终极指南

如何快速构建专业级聊天界面&#xff1a;Chat UI Kit React终极指南 【免费下载链接】chat-ui-kit-react Build your own chat UI with React components in few minutes. Chat UI Kit from chatscope is an open source UI toolkit for developing web chat applications. 项…

作者头像 李华
网站建设 2026/10/15 3:00:34

FLUX模型INT8量化实战指南:从理论到部署的完整解决方案

FLUX模型INT8量化实战指南&#xff1a;从理论到部署的完整解决方案 【免费下载链接】flux Official inference repo for FLUX.1 models 项目地址: https://gitcode.com/GitHub_Trending/flux49/flux 在AI图像生成领域&#xff0c;FLUX模型以其卓越的生成质量赢得了广泛关…

作者头像 李华
网站建设 2026/10/14 21:29:44

AI如何帮你高效处理Python时间计算问题

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容&#xff1a; 创建一个Python脚本&#xff0c;使用datetime和pytz库处理时间相关任务。要求实现以下功能&#xff1a;1) 将用户输入的字符串时间转换为指定时区的datetime对象&#xff1b;2) 计算…

作者头像 李华