3.9 学习UVM中的uvm_env类分为几步?

文章目录

  • 前言
  • [1. 定义](#1. 定义)
  • [2. 核心功能](#2. 核心功能)
  • [3. 适用场景](#3. 适用场景)
  • [4. 使用方法](#4. 使用方法)
  • [5. 完整代码示例](#5. 完整代码示例)
    • [5.1 事务类定义](#5.1 事务类定义)
    • [5.2 Monitor 类定义](#5.2 Monitor 类定义)
    • [5.3 Scoreboard 类定义](#5.3 Scoreboard 类定义)
    • [5.4 Agent 类定义](#5.4 Agent 类定义)
    • [5.5 Env 类定义](#5.5 Env 类定义)
    • [5.6 测试平台](#5.6 测试平台)
  • [6. 代码说明](#6. 代码说明)
  • [7. 总结](#7. 总结)

前言

以下是关于 UVM 中 uvm_env 的详细解释、核心功能、适用场景、使用方法以及一个完整的代码示例:


1. 定义

uvm_env 是 UVM(Universal Verification Methodology)中的一个重要组件类,用于封装验证环境的顶层结构。它是一个容器类,用于组织和管理验证环境中的其他组件(如 uvm_agentuvm_scoreboarduvm_subscriber 等)。uvm_env 是验证环境的最高层次,通常包含多个 uvm_agent 和其他功能组件。

uvm_env 的主要特点:

  • 是验证环境的顶层容器。
  • 封装了验证环境中的所有组件。
  • 支持层次化结构,可以嵌套其他 uvm_env

2. 核心功能

uvm_env 提供了以下核心功能:

  • 组件组织 :将验证环境中的组件(如 uvm_agentuvm_scoreboard 等)组织在一起。
  • 配置管理:通过配置对象(configuration object)配置验证环境的行为。
  • 层次化结构 :支持嵌套其他 uvm_env,构建复杂的验证环境。
  • 测试平台集成 :与 uvm_test 配合使用,构建完整的测试平台。

3. 适用场景

uvm_env 通常用于以下场景:

  • 顶层验证环境:用于构建验证环境的顶层结构。
  • 复杂验证环境 :在复杂的验证环境中,嵌套多个 uvm_env 以管理不同的功能模块。
  • 配置管理:通过配置对象管理验证环境的行为。
  • 组件复用:封装通用的验证环境,便于在不同测试中复用。

4. 使用方法

使用 uvm_env 的步骤如下:

  1. 定义类 :从 uvm_env 派生一个类,并定义其属性和方法。
  2. 构建组件 :在 build_phase 中创建和配置子组件(如 uvm_agentuvm_scoreboard 等)。
  3. 连接组件 :在 connect_phase 中连接子组件的端口和接口。
  4. 配置环境:通过配置对象设置验证环境的行为。
  5. 集成测试 :在 uvm_test 中实例化并运行 uvm_env

5. 完整代码示例

以下是一个完整的代码示例,展示如何使用 uvm_env 构建验证环境。

5.1 事务类定义

c 复制代码
// 定义一个从 uvm_sequence_item 派生的事务类
class my_transaction extends uvm_sequence_item;

  bit [7:0] data;
  bit [3:0] addr;
  bit       valid;

  // 注册类到 UVM 工厂
  `uvm_object_utils(my_transaction)

  // 构造函数
  function new(string name = "my_transaction");
    super.new(name);
  endfunction

  // 实现 print 方法
  virtual function void do_print(uvm_printer printer);
    printer.print_field("data",  this.data,  8);
    printer.print_field("addr",  this.addr,  4);
    printer.print_field("valid", this.valid, 1);
  endfunction

endclass

5.2 Monitor 类定义

c 复制代码
// 定义一个从 uvm_monitor 派生的监控类
class my_monitor extends uvm_monitor;

  // 定义 analysis port
  uvm_analysis_port #(my_transaction) ap;

  // 虚拟接口(用于访问 DUT 信号)
  virtual my_interface vif;

  // 注册类到 UVM 工厂
  `uvm_component_utils(my_monitor)

  // 构造函数
  function new(string name, uvm_component parent);
    super.new(name, parent);
    ap = new("ap", this);
  endfunction

  // 实现 run_phase
  virtual task run_phase(uvm_phase phase);
    forever begin
      my_transaction tx;

      // 等待信号有效
      @(posedge vif.clock iff vif.valid);

      // 创建事务对象
      tx = my_transaction::type_id::create("tx");

      // 捕捉信号并转换为事务
      tx.data  = vif.data;
      tx.addr  = vif.addr;
      tx.valid = vif.valid;

      // 打印事务
      `uvm_info("MONITOR", $sformatf("Captured transaction: data=0x%0h, addr=0x%0h, valid=%b", 
                                    tx.data, tx.addr, tx.valid), UVM_LOW)

      // 通过 analysis port 广播事务
      ap.write(tx);
    end
  endtask

endclass

5.3 Scoreboard 类定义

c 复制代码
// 定义一个从 uvm_scoreboard 派生的记分板类
class my_scoreboard extends uvm_scoreboard;

  // 预期事务队列
  my_transaction expected_queue[$];

  // 注册类到 UVM 工厂
  `uvm_component_utils(my_scoreboard)

  // 构造函数
  function new(string name, uvm_component parent);
    super.new(name, parent);
  endfunction

  // 实现 write 方法(用于接收事务)
  virtual function void write(my_transaction tx);
    my_transaction expected_tx;

    // 检查预期队列是否为空
    if (expected_queue.size() == 0) begin
      `uvm_error("SCOREBOARD", "Unexpected transaction received")
      return;
    end

    // 获取预期事务
    expected_tx = expected_queue.pop_front();

    // 比较事务
    if (!tx.compare(expected_tx)) begin
      `uvm_error("SCOREBOARD", "Transaction mismatch")
      `uvm_info("SCOREBOARD", $sformatf("Expected: data=0x%0h, addr=0x%0h, valid=%b", 
                                       expected_tx.data, expected_tx.addr, expected_tx.valid), UVM_LOW)
      `uvm_info("SCOREBOARD", $sformatf("Received: data=0x%0h, addr=0x%0h, valid=%b", 
                                       tx.data, tx.addr, tx.valid), UVM_LOW)
    end else begin
      `uvm_info("SCOREBOARD", "Transaction matched", UVM_LOW)
    end
  endfunction

  // 添加预期事务
  function void add_expected(my_transaction tx);
    expected_queue.push_back(tx);
  endfunction

endclass

5.4 Agent 类定义

c 复制代码
// 定义一个从 uvm_agent 派生的 agent 类
class my_agent extends uvm_agent;

  my_monitor    monitor;
  my_scoreboard scoreboard;

  // 注册类到 UVM 工厂
  `uvm_component_utils(my_agent)

  // 构造函数
  function new(string name, uvm_component parent);
    super.new(name, parent);
  endfunction

  // 构建组件
  virtual function void build_phase(uvm_phase phase);
    monitor    = my_monitor::type_id::create("monitor", this);
    scoreboard = my_scoreboard::type_id::create("scoreboard", this);
  endfunction

  // 连接组件
  virtual function void connect_phase(uvm_phase phase);
    monitor.ap.connect(scoreboard.write);
  endfunction

endclass

5.5 Env 类定义

c 复制代码
// 定义一个从 uvm_env 派生的 env 类
class my_env extends uvm_env;

  my_agent agent;

  // 注册类到 UVM 工厂
  `uvm_component_utils(my_env)

  // 构造函数
  function new(string name, uvm_component parent);
    super.new(name, parent);
  endfunction

  // 构建组件
  virtual function void build_phase(uvm_phase phase);
    agent = my_agent::type_id::create("agent", this);
  endfunction

endclass

5.6 测试平台

c 复制代码
// 测试平台
module testbench;
  initial begin
    // 创建测试类
    class my_test extends uvm_test;
      my_env env;

      // 注册类到 UVM 工厂
      `uvm_component_utils(my_test)

      // 构造函数
      function new(string name, uvm_component parent);
        super.new(name, parent);
      endfunction

      // 构建组件
      virtual function void build_phase(uvm_phase phase);
        env = my_env::type_id::create("env", this);
      endfunction

      // 运行测试
      virtual task run_phase(uvm_phase phase);
        my_transaction tx;

        phase.raise_objection(this);

        // 添加预期事务
        tx = my_transaction::type_id::create("tx");
        tx.data  = 8'hAA;
        tx.addr  = 4'h1;
        tx.valid = 1;
        env.agent.scoreboard.add_expected(tx);

        #100; // 模拟测试运行时间
        phase.drop_objection(this);
      endtask
    endclass

    // 启动测试
    initial begin
      run_test("my_test");
    end
  end
endmodule

6. 代码说明

  • 事务类my_transaction 定义了事务的属性和方法。
  • Monitor 类my_monitor 监控 DUT 的信号并转换为事务。
  • Scoreboard 类my_scoreboard 接收事务并与预期事务进行比较。
  • Agent 类my_agent 封装了 uvm_monitoruvm_scoreboard
  • Env 类my_env 封装了 uvm_agent,是验证环境的顶层容器。
  • 测试平台my_test 类用于构建和运行测试环境。

7. 总结

uvm_env 是 UVM 中用于构建验证环境顶层结构的关键组件。它封装了验证环境中的所有组件,并支持层次化结构和配置管理。以上示例展示了如何定义和使用 uvm_env,适用于实际的验证场景。

相关推荐
饮长安千年月2 小时前
Linksys WRT54G路由器溢出漏洞分析–运行环境修复
网络·物联网·学习·安全·机器学习
红花与香菇2____2 小时前
【学习笔记】Cadence电子设计全流程(二)原理图库的创建与设计(上)
笔记·嵌入式硬件·学习·pcb设计·cadence·pcb工艺
一天八小时4 小时前
Docker学习进阶
学习·docker·容器
前端没钱4 小时前
前端需要学习 Docker 吗?
前端·学习·docker
拥有一颗学徒的心5 小时前
鸿蒙第三方库MMKV源码学习笔记
笔记·学习·性能优化·harmonyos
车端域控测试工程师5 小时前
【ISO 14229-1:2023 UDS诊断(ECU复位0x11服务)测试用例CAPL代码全解析⑰】
经验分享·学习·汽车·测试用例·capl
车端域控测试工程师5 小时前
【ISO 14229-1:2023 UDS诊断(ECU复位0x11服务)测试用例CAPL代码全解析⑪】
经验分享·学习·汽车·测试用例·capl
charlie1145141918 小时前
(萌新入门)如何从起步阶段开始学习STM32 —— 0.碎碎念
c语言·stm32·单片机·嵌入式硬件·学习·教程
网安Ruler10 小时前
泷羽Sec-黑客基础之html(超文本标记语言)
前端·学习·网络安全·html
啥也不会的菜鸟·11 小时前
Redis7——基础篇(五)
redis·学习·缓存