3.2.2 具体的案例展示uvm_object在实际验证中的应用?


前言

以下是几个具体的案例或项目,展示 uvm_object 在实际验证中的应用:


一、案例一:使用 uvm_object_utils() 简化对象类设计

在 SystemVerilog 中,uvm_object_utils() 是一个宏函数,用于简化 UVM 中对象类的设计。它帮助我们在创建 UVM 对象时自动处理一些基本的初始化、复制、终结等操作,如设置默认值、分配内存以及释放资源。

1.1 示例代码

// 定义一个基础 UVM Object
class base_obj extends uvm_object;
  `uvm_object_utils(base_obj)
  // 类中的其他成员变量和方法...
endclass

// 使用 base_obj 派生的新类
class derived_obj extends base_obj;
  // 新增加的成员变量或方法...
endclass

// 实现 uvm_object_utils 自动生成的方法
function new();
  super.new(); // 调用基类的构造函数
endfunction

function void build();
  // 自动执行的构建操作...
endfunction

// 当对象不再需要时会自动调用这个方法
function void destroy();
  // 自动释放资源...
endfunction

通过 uvm_object_utils,我们可以避免手动编写这些繁琐的底层操作,使得代码更简洁易维护。然而,当需要添加特殊的初始化逻辑或者需要定制某些特定行为时,还是需要在类中显式地实现相应的函数 。

二、案例二:基于《UVM实战》的验证平台

在《UVM实战》中,有一个示例展示了如何使用 uvm_object 和 uvm_component 构建验证平台。以下是一个简化的示例,展示了如何使用 uvm_object 定义事务类和配置类。

2.1 示例代码

// 定义事务类
class my_transaction extends uvm_object;
  `uvm_object_utils(my_transaction)

  // 定义事务的属性
  rand bit [7:0] data;
  rand bit [3:0] addr;
  bit valid;

  function new(string name = "my_transaction");
    super.new(name);
  endfunction

  // 实现 copy 方法
  virtual function void do_copy(uvm_object rhs);
    my_transaction tx;
    if (!$cast(tx, rhs)) begin
      `uvm_fatal("COPY", "Copy failed: wrong type")
    end
    this.data = tx.data;
    this.addr = tx.addr;
    this.valid = tx.valid;
  endfunction

  // 实现 compare 方法
  virtual function bit do_compare(uvm_object rhs, uvm_comparer comparer);
    my_transaction tx;
    if (!$cast(tx, rhs)) return 0;
    return (this.data == tx.data) && (this.addr == tx.addr) && (this.valid == tx.valid);
  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

// 定义配置类
class my_config extends uvm_object;
  `uvm_object_utils(my_config)

  // 定义配置参数
  bit [3:0] bus_width;
  bit clk_freq;

  function new(string name = "my_config");
    super.new(name);
  endfunction

  // 实现 copy 方法
  virtual function void do_copy(uvm_object rhs);
    my_config cfg;
    if (!$cast(cfg, rhs)) begin
      `uvm_fatal("COPY", "Copy failed: wrong type")
    end
    this.bus_width = cfg.bus_width;
    this.clk_freq = cfg.clk_freq;
  endfunction

  // 实现 compare 方法
  virtual function bit do_compare(uvm_object rhs, uvm_comparer comparer);
    my_config cfg;
    if (!$cast(cfg, rhs)) return 0;
    return (this.bus_width == cfg.bus_width) && (this.clk_freq == cfg.clk_freq);
  endfunction

  // 实现 print 方法
  virtual function void do_print(uvm_printer printer);
    printer.print_field("bus_width", this.bus_width, 4);
    printer.print_field("clk_freq", this.clk_freq, 1);
  endfunction
endclass

在这个示例中,my_transaction 和 my_config 都是从 uvm_object 派生的类,分别用于定义事务和配置参数。通过使用 uvm_object_utils 宏,可以简化类的实现,使其更易于维护和扩展 。

三、案例三:以太网验证平台

在以太网验证平台中,uvm_object 被广泛用于定义事务类和配置类。以下是一个简化的示例,展示了如何使用 uvm_object 定义事务类 my_transaction 和配置类 my_config。

3.1 示例代码

// 定义事务类
class my_transaction extends uvm_object;
  `uvm_object_utils(my_transaction)

  // 定义事务的属性
  rand bit [7:0] data;
  rand bit [3:0] addr;
  bit valid;

  function new(string name = "my_transaction");
    super.new(name);
  endfunction

  // 实现 copy 方法
  virtual function void do_copy(uvm_object rhs);
    my_transaction tx;
    if (!$cast(tx, rhs)) begin
      `uvm_fatal("COPY", "Copy failed: wrong type")
    end
    this.data = tx.data;
    this.addr = tx.addr;
    this.valid = tx.valid;
  endfunction

  // 实现 compare 方法
  virtual function bit do_compare(uvm_object rhs, uvm_comparer comparer);
    my_transaction tx;
    if (!$cast(tx, rhs)) return 0;
    return (this.data == tx.data) && (this.addr == tx.addr) && (this.valid == tx.valid);
  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

// 定义配置类
class my_config extends uvm_object;
  `uvm_object_utils(my_config)

  // 定义配置参数
  bit [3:0] bus_width;
  bit clk_freq;

  function new(string name = "my_config");
    super.new(name);
  endfunction

  // 实现 copy 方法
  virtual function void do_copy(uvm_object rhs);
    my_config cfg;
    if (!$cast(cfg, rhs)) begin
      `uvm_fatal("COPY", "Copy failed: wrong type")
    end
    this.bus_width = cfg.bus_width;
    this.clk_freq = cfg.clk_freq;
  endfunction

  // 实现 compare 方法
  virtual function bit do_compare(uvm_object rhs, uvm_comparer comparer);
    my_config cfg;
    if (!$cast(cfg, rhs)) return 0;
    return (this.bus_width == cfg.bus_width) && (this.clk_freq == cfg.clk_freq);
  endfunction

  // 实现 print 方法
  virtual function void do_print(uvm_printer printer);
    printer.print_field("bus_width", this.bus_width, 4);
    printer.print_field("clk_freq", this.clk_freq, 1);
  endfunction
endclass

在这个示例中,my_transaction 和 my_config 都是从 uvm_object 派生的类,分别用于定义事务和配置参数。通过使用 uvm_object_utils 宏,可以简化类的实现,使其更易于维护和扩展 。

四、案例四:验证一个简单的总线接口

以下为你详细介绍一个基于 UVM(Universal Verification Methodology)验证平台的简单案例,该案例将充分展示 uvm_object 在实际验证中的具体应用,此案例主要针对一个简单的总线接口进行验证。

我们要验证的是一个简单的总线接口,该接口支持读写操作。验证的目标是确保总线接口在各种读写操作场景下都能正常工作。

4.1、具体实现

1. 定义派生自 uvm_object 的事务类

`include "uvm_macros.svh"
import uvm_pkg::*;

// 定义事务类,派生自 uvm_sequence_item
class bus_transaction extends uvm_sequence_item;
    // 定义事务的成员变量
    rand bit [31:0] addr;
    rand bit [31:0] data;
    rand bit        wr_rd;  // 1 表示写,0 表示读

    // 工厂注册,便于 UVM 管理对象创建
    `uvm_object_utils_begin(bus_transaction)
        `uvm_field_int(addr, UVM_ALL_ON)
        `uvm_field_int(data, UVM_ALL_ON)
        `uvm_field_int(wr_rd, UVM_ALL_ON)
    `uvm_object_utils_end

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

解释

  • bus_transaction 类继承自 uvm_sequence_itemuvm_sequence_item 派生自 uvm_object),用于封装总线事务的相关信息,如地址、数据和读写标志。
  • uvm_object_utils_beginuvm_object_utils_end 宏将该类注册到 UVM 工厂,方便后续使用 UVM 的自动化机制。
  • uvm_field_int 宏指定了哪些成员变量参与 UVM 的自动化操作,如打印、复制等。

2. 定义序列类

// 定义序列类,派生自 uvm_sequence
class bus_sequence extends uvm_sequence #(bus_transaction);
    // 工厂注册
    `uvm_object_utils(bus_sequence)

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

    // 序列主体任务,用于生成事务并发送
    virtual task body();
        bus_transaction tr;
        repeat (5) begin
            // 创建事务对象
            tr = bus_transaction::type_id::create("tr");
            // 随机化事务
            assert(tr.randomize());
            // 发送事务
            start_item(tr);
            finish_item(tr);
        end
    endtask
endclass

解释

  • bus_sequence 类派生自 uvm_sequence,并指定事务类型为 bus_transaction
  • body 任务中,通过 UVM 工厂创建 bus_transaction 对象,对其进行随机化,然后将事务发送给 sequencer。

3. 定义驱动类

// 定义驱动类,派生自 uvm_driver
class bus_driver extends uvm_driver #(bus_transaction);
    // 工厂注册
    `uvm_component_utils(bus_driver)

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

    // 运行任务,接收事务并驱动到 DUT
    virtual task run_phase(uvm_phase phase);
        bus_transaction tr;
        forever begin
            // 从 sequencer 获取事务
            seq_item_port.get_next_item(tr);
            // 模拟驱动操作
            $display("Driving transaction: addr = %h, data = %h, wr_rd = %b", tr.addr, tr.data, tr.wr_rd);
            // 完成事务处理
            seq_item_port.item_done();
        end
    endtask
endclass

解释

  • bus_driver 类派生自 uvm_driver,用于将从 sequencer 接收到的事务驱动到被测设计(DUT)上。
  • run_phase 任务中,通过 seq_item_port.get_next_item 方法获取事务,模拟驱动操作,然后使用 seq_item_port.item_done 方法通知 sequencer 事务处理完成。

4. 定义环境类

// 定义环境类,派生自 uvm_env
class bus_env extends uvm_env;
    bus_driver    drv;
    uvm_sequencer #(bus_transaction) sqr;

    // 工厂注册
    `uvm_component_utils(bus_env)

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

    // build_phase 阶段创建组件
    virtual function void build_phase(uvm_phase phase);
        super.build_phase(phase);
        drv = bus_driver::type_id::create("drv", this);
        sqr = uvm_sequencer #(bus_transaction)::type_id::create("sqr", this);
    endfunction

    // connect_phase 阶段连接组件
    virtual function void connect_phase(uvm_phase phase);
        super.connect_phase(phase);
        drv.seq_item_port.connect(sqr.seq_item_export);
    endfunction
endclass

解释

  • bus_env 类派生自 uvm_env,用于管理验证环境中的组件。
  • build_phase 中创建 bus_driveruvm_sequencer 组件。
  • connect_phase 中,将驱动的 seq_item_port 与 sequencer 的 seq_item_export 连接起来,实现事务的传递。

5. 定义测试类

// 定义测试类,派生自 uvm_test
class bus_test extends uvm_test;
    bus_env env;

    // 工厂注册
    `uvm_component_utils(bus_test)

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

    // build_phase 阶段创建环境组件
    virtual function void build_phase(uvm_phase phase);
        super.build_phase(phase);
        env = bus_env::type_id::create("env", this);
    endfunction

    // run_phase 阶段启动序列
    virtual task run_phase(uvm_phase phase);
        bus_sequence seq;
        phase.raise_objection(this);
        seq = bus_sequence::type_id::create("seq");
        seq.start(env.sqr);
        phase.drop_objection(this);
    endtask
endclass

解释

  • bus_test 类派生自 uvm_test,是验证的入口点。
  • build_phase 中创建 bus_env 环境组件。
  • run_phase 中,创建 bus_sequence 序列对象,并使用 start 方法将其启动在 sequencer 上,同时使用 raise_objectiondrop_objection 来控制验证的执行时间。

6. 顶层测试平台

module tb;
    import uvm_pkg::*;
    `include "uvm_macros.svh"
    `include "bus_transaction.sv"
    `include "bus_sequence.sv"
    `include "bus_driver.sv"
    `include "bus_env.sv"
    `include "bus_test.sv"

    initial begin
        // 运行 UVM 测试
        run_test("bus_test");
    end
endmodule

解释

  • 顶层测试平台通过 run_test 函数启动 bus_test 测试。

4.2、总结

在这个案例中,uvm_object 的应用体现在多个方面:

  • bus_transaction 类派生自 uvm_object,用于封装总线事务信息,利用了 uvm_object 的自动化功能,如打印、复制等。
  • bus_sequence 类通过创建和发送 bus_transaction 对象,实现了事务的生成和传输。
  • 整个验证平台通过 UVM 的组件化和序列驱动机制,将 uvm_object 派生的事务对象在不同组件之间传递和处理,完成对总线接口的验证。

五、总结

通过上述案例,我们可以看到 uvm_object 在实际验证项目中的广泛应用,包括定义事务类、配置类、寄存器模型等。通过合理使用 uvm_object,可以提高验证平台的灵活性和可维护性。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值