uvm白皮书练习_ch2_ch224_加入virtual interface

news/2024/5/19 17:12:41 标签: UVM, systemverilog

记录

参考使用uvm白皮书内容

从根本上来说,应该杜绝在验证平台中使用绝对路径

避免绝对路径一个方法是使用宏

`define TOP top_tb

`define TOP top_tb
task my_driver::main_phase(uvm_phase phase);
   phase.raise_objection(this);
   `uvm_info("my_driver", "main_phase is called", UVM_LOW);
   `TOP.rxd <= 8'b0;
   `TOP.rx_dv <= 1'b0;
   while(!`TOP.rst_n)
      @(posedge `TOP.clk);
   for(int i = 0; i < 256; i++)begin
      @(posedge `TOP.clk);
      `TOP.rxd <= $urandom_range(0, 255);
      `TOP.rx_dv <= 1'b1;
      `uvm_info("my_driver", "data is drived", UVM_LOW);
   end
   @(posedge `TOP.clk);
   `TOP.rx_dv <= 1'b0;
   phase.drop_objection(this);
endtask

避免绝对路径的另外一种方式是使用interface。

注意点记录

class my_driver extends uvm_driver;
  my_if  drv_if;
  …
endclass

因为my_driver是一个类,在类中不能使用上述方式声明一个interface,只有在类似top_tb这样的模块(module)中才可以。

正确使用方式

文件:src/ch2/section2.2/2.2.4/my_driver.sv
3 class my_driver extends uvm_driver;
4 5   virtual my_if vif;

如何把top_tb中的input_if和my_driver中的vif对应起来呢?

最简单的方法莫过于直接赋值。此时一个新的问题又摆在了面前:在top_tb中,通过run_test语句建立了一个my_driver的实例,但是应该如何引用这个实例呢?不可能像引用my_dut那样直接引用my_driver中的变量:top_tb.my_dut.xxx是可以的,但是top_tb.my_ driver.xxx是不可以的。这个问题的终极原因在于UVM通过run_test语句实例化了一个脱离了top_tb层次结构的实例,建立了一个新的层次结构。

对于这种脱离了top_tb层次结构,同时又期望在top_tb中对其进行某些操作的实例,UVM引进了config_db机制。在config_db机制中,分为set和get两步操作。所谓set操作,可以简单地理解成是“寄信”,而get则相当于是“收信”。在top_tb中执行set操作

寄信
文件:src/ch2/section2.2/2.2.4/top_tb.sv
44 initial begin
45   uvm_config_db#(virtual my_if)::set(null,"uvm_test_top", "vif", input_if);
46 end
收信
文件:src/ch2/section2.2/2.2.4/my_driver.sv
13   virtual function void build_phase(uvm_phase phase);
14     super.build_phase(phase);
15     `uvm_info("my_driver", "build_phase is called", UVM_LOW);
16     if(!uvm_config_db#(virtual my_if)::get(this, "", "vif", vif))
17        `uvm_fatal("my_driver", "virtual interface must be set for vif!!!")
18   endfunction

config_db的set和get函数都有四个参数,这两个函数的第三个参数必须完全一致。

set函数的第四个参数表示要将哪个interface通过config_db传递给my_driver,

get函数的第四个参数表示把得到的interface传递给哪个my_driver的成员变量。

set函数的第二个参数表示的是路径索引

dut.sv

module dut (
    clk,
    rst_n,
    rxd,
    rx_dv,
    txd,
    tx_en
);
    input clk    ;   
    input rst_n  ;   
    input [7:0]rxd    ; 
    input rx_dv  ;   
    output txd   ;  
    output tx_en ; 

reg [7:0]   txd;
reg         tx_en;  

always @(posedge clk) begin
    if(!rst_n)begin
        txd     <=  8'h00;
        tx_en   <=  1'b0;
    end
    else begin
        txd     <=  rxd;
        tx_en   <=  rx_dv;
    end
end
endmodule

TB

my_driver.sv

`ifndef MY_DRIVER__SV
`define MY_DRIVER__SV
class my_driver extends uvm_driver;

   virtual my_if vif;

   `uvm_component_utils(my_driver)
   function new(string name = "my_driver", uvm_component parent = null);
      super.new(name, parent);
      `uvm_info("my_driver", "new is called", UVM_LOW);
   endfunction

   virtual function void build_phase(uvm_phase phase);
      super.build_phase(phase);
      `uvm_info("my_driver", "build_phase is called", UVM_LOW);
      if(!uvm_config_db#(virtual my_if)::get(this, "", "vif", vif))
         `uvm_fatal("my_driver", "virtual interface must be set for vif!!!")
   endfunction

   extern virtual task main_phase(uvm_phase phase);
endclass

task my_driver::main_phase(uvm_phase phase);
   phase.raise_objection(this);
   `uvm_info("my_driver", "main_phase is called", UVM_LOW);
   vif.data <= 8'b0; 
   vif.valid <= 1'b0;
   while(!vif.rst_n)
      @(posedge vif.clk);
   for(int i = 0; i < 256; i++)begin
      @(posedge vif.clk);
      vif.data <= $urandom_range(0, 255);
      vif.valid <= 1'b1;
      `uvm_info("my_driver", "data is drived", UVM_LOW);
   end
   @(posedge vif.clk);
   vif.valid <= 1'b0;
   phase.drop_objection(this);
endtask
`endif

my_if.sv

`ifndef MY_IF__SV
`define MY_IF__SV

interface my_if(input clk, input rst_n);

   logic [7:0] data;
   logic valid;
endinterface

`endif

top_tb.sv

`timescale 1ns/1ps
`include "uvm_macros.svh"

import uvm_pkg::*;
`include "my_if.sv"
`include "my_driver.sv"

module top_tb;

reg clk;
reg rst_n;
reg[7:0] rxd;
reg rx_dv;
wire[7:0] txd;
wire tx_en;

my_if input_if(clk, rst_n);
my_if output_if(clk, rst_n);

dut my_dut(.clk(clk),
           .rst_n(rst_n),
           .rxd(input_if.data),
           .rx_dv(input_if.valid),
           .txd(output_if.data),
           .tx_en(output_if.valid));

initial begin
   clk = 0;
   forever begin
      #100 clk = ~clk;
   end
end

initial begin
   rst_n = 1'b0;
   #1000;
   rst_n = 1'b1;
end

initial begin
   run_test("my_driver");
end

initial begin
   uvm_config_db#(virtual my_if)::set(null, "uvm_test_top", "vif", input_if);
end

endmodule

仿真结果

将发送激励改成了25次

UVM_INFO my_driver.sv(11) @ 0: uvm_test_top [my_driver] new is called
UVM_INFO @ 0: reporter [RNTST] Running test my_driver...

fsdbDumpfilrs is start at                    0
UVM_INFO my_driver.sv(16) @ 0: uvm_test_top [my_driver] virtual interface must be set for vif!!!
UVM_INFO my_driver.sv(36) @ 13000: uvm_test_top [my_driver] data is driver
UVM_INFO my_driver.sv(36) @ 15000: uvm_test_top [my_driver] data is driver
UVM_INFO my_driver.sv(36) @ 17000: uvm_test_top [my_driver] data is driver
UVM_INFO my_driver.sv(36) @ 19000: uvm_test_top [my_driver] data is driver
UVM_INFO my_driver.sv(36) @ 21000: uvm_test_top [my_driver] data is driver
UVM_INFO my_driver.sv(36) @ 23000: uvm_test_top [my_driver] data is driver
UVM_INFO my_driver.sv(36) @ 25000: uvm_test_top [my_driver] data is driver
UVM_INFO my_driver.sv(36) @ 27000: uvm_test_top [my_driver] data is driver
UVM_INFO my_driver.sv(36) @ 29000: uvm_test_top [my_driver] data is driver
UVM_INFO my_driver.sv(36) @ 31000: uvm_test_top [my_driver] data is driver
UVM_INFO my_driver.sv(36) @ 33000: uvm_test_top [my_driver] data is driver
UVM_INFO my_driver.sv(36) @ 35000: uvm_test_top [my_driver] data is driver
UVM_INFO my_driver.sv(36) @ 37000: uvm_test_top [my_driver] data is driver
UVM_INFO my_driver.sv(36) @ 39000: uvm_test_top [my_driver] data is driver
UVM_INFO my_driver.sv(36) @ 41000: uvm_test_top [my_driver] data is driver
UVM_INFO my_driver.sv(36) @ 43000: uvm_test_top [my_driver] data is driver
UVM_INFO my_driver.sv(36) @ 45000: uvm_test_top [my_driver] data is driver
UVM_INFO my_driver.sv(36) @ 47000: uvm_test_top [my_driver] data is driver
UVM_INFO my_driver.sv(36) @ 49000: uvm_test_top [my_driver] data is driver
UVM_INFO my_driver.sv(36) @ 51000: uvm_test_top [my_driver] data is driver
UVM_INFO my_driver.sv(36) @ 53000: uvm_test_top [my_driver] data is driver
UVM_INFO my_driver.sv(36) @ 55000: uvm_test_top [my_driver] data is driver
UVM_INFO my_driver.sv(36) @ 57000: uvm_test_top [my_driver] data is driver
UVM_INFO my_driver.sv(36) @ 59000: uvm_test_top [my_driver] data is driver
UVM_INFO my_driver.sv(36) @ 61000: uvm_test_top [my_driver] data is driver

--- UVM Report Summary ---

** Report counts by severity
UVM_INFO :   28
UVM_WARNING :    0
UVM_ERROR :    0
UVM_FATAL :    0
** Report counts by id
[RNTST]     1
[my_driver]    27

http://www.niftyadmin.cn/n/5055732.html

相关文章

计算机网络第五节 网络层

一&#xff0c;网络引入的目的 1.网络层以下层次解决的问题&#xff0c;未解决的问题 从7层结构上看&#xff0c;网络层下是数据链路层 从4层结构上看&#xff0c;网络层下面是网络接口层 至少我们看到的网络层下面是以太网 以太网解决了什么问题&#xff1f; 答&#xff1…

Spring Boot集成Redis集群报错UnsupportedOperationException

项目场景&#xff1a; Spring Boot集成Redis集群 单节点配置&#xff1a; spring.redis.database 0 spring.redis.host 127.0.0.1 spring.redis.password testredis spring.redis.port 8003 # 连接超时时间 单位 ms&#xff08;毫秒&#xff09; spring.redis.timeout …

常用中间件-OAuth2

1. 微服务权限校验Session共享 1.1 微服务权限校验 实现2号方案。使用Redis作为Session统一存储。 首先配置一下Nacos&#xff0c;参考https://blog.csdn.net/weixin_43917045/article/details/132852850 然后为每个服务添加验证机制&#xff0c;先导入依赖 <!-- SpringS…

n个骰子掷出m点的概率,C++实现

一.在骰子游戏中&#xff0c;我们会有猜点数的问题。我们该如何用算法来描述呢&#xff1f; 加入我们当前只有一个骰子&#xff0c;我们该如何算概率呢&#xff1f; 我们现在开始推导一下吧&#xff1a; 首先是一个骰子的情况&#xff0c;我们可以简单的知道n个骰子一共可以掷出…

NAS文件的名称或路径过长导致文件同步被挂起

将文件复制到群晖设备时遇到文件名长度限制问题&#xff0c;NTFS文件系统&#xff08;通过Samba等方式在群晖上使用&#xff09;: 在Windows系统上广泛使用的NTFS文件系统也支持较长的文件名&#xff0c;最大长度为255个字符。然而&#xff0c;要注意的是&#xff0c;使用Samba…

vue3-ts-vite:Google 多语言调试 / 网页中插入谷歌翻译元素 / 翻译

一、实现目标 二、代码实现 2.1、项目vue3 - ts - vite 2.2、index.html 引入文件 <script>window.onload function () {const script document.createElement(SCRIPT)script.src https://translate.google.com/translate_a/element.js?cbgoogleTranslateElementI…

【Element-UI】CUD(增删改)及form 表单验证(附源码)

目录 一、导言 1、引言 2、作用 二、CUD 1、增加修改 1.1、添加弹窗 1.2、定义变量 1.3、定义方法 1.4、完整代码 2、删除 2.1、定义方法 三、表单验证 1、添加规则 2、定义规则 3、提交事件 4、前端完整代码 一、导言 1、引言 增删改是计算机编程和数据库管理…

VC++判断程序是否已经运行;仅运行一次

VC判断程序是否已经运行&#xff1b;仅运行一次 BOOL CClientApp::InitInstance() {...//判断程序是否已经运行&#xff1b;仅运行一次CreateMutex(NULL,true,_T("xxxxx")); //xxxxx&#xff1a;为程序标识码if(GetLastError()ERROR_ALREADY_EXISTS) { AfxMess…