当前位置: 首页 > news >正文

路科验证UVM入门与进阶详解实验0

一.代码编译

首先创建新项目,导入lab0 的UVM文件;

针对uvm_compile文件,先进行编译;

module uvm_compile;// NOTE:: it is necessary to import uvm package and macrosimport uvm_pkg::*;`include "uvm_macros.svh"initial begin`uvm_info("UVM", "Hello, welcome to RKV UVM training!", UVM_LOW)#1us;`uvm_info("UVM", "Bye, and more gifts waiting for you!", UVM_LOW)end
endmodule

无论在什么地方,UVM验证顶层都必须有下面这两行代码,代表着预编译的UVM库(包括UVM开源库和Questa的UVM定制部分库)。

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

uvm_macros.svh是包含了众多宏定义的头文件,将其include进来可以让宏定义识别成功,否则编译时会报错;
而uvm_pkg是UVM库的预编译库,很庞大,包括了uvm_factory、uvm_config_db、各种phase等。
仿真后可以在下方位置看到。

import uvm_pkg::*

上面语句表示把默认编译好的库mtiUvm.uvm_pkg导入到uvm_compile里。如果没有import进来,那么编译就会报错。

当我们编译并且仿真uvm_compile,有如下信息:

其中,

    sv_std.std指的是systemverilog的内建包,定义了一些class、task、function和变量;
    mtiUvm.uvm_pkg表示mentor已经编译好的库,mti表示mentor公司;
    mtiUvm.questa_uvm_pkg是questa专门针对uvm定制的库。

 当我们在使用questasim时,我们不需要独立编译uvm_pkg,因为已经提前帮我们编译好了。但如果我们使用的是其他仿真器,比如VCS时,就需要独立编译一下uvm_pkg。

run -all后,打印信息如下:

 二、SV与UVM之间的关系

添加sv_class_inst.sv文件,编译,仿真,看看发生了什么?实际上这个实验是SV模块实验环节的抽象,它只是在顶层module容器中要例化软件验证环境的顶层,即 SV class top。在接下来的阶段,从打印出的信息可以看得出来,相当于从测试的开始,到验证环境的搭建,激励的发送,检查的执行等,最后又到了测试的结束。因此这是SV模块实验的“一”,即一生二,二生三,三生万物的那个“顶层” 。
sv_class_inst.sv代码

module sv_class_inst;import uvm_pkg::*;`include "uvm_macros.svh"class top;function new();`uvm_info("SV_TOP", "SV TOP creating", UVM_LOW)endfunctionendclassinitial begintop t; `uvm_info("SV_TOP", "test started", UVM_LOW)t = new();`uvm_info("SV_TOP", "test finished", UVM_LOW)endendmodule

sv_class_inst.sv代码分析:

对文件sv_class_inst.sv进行编译、仿真、运行,结果如下:

如何查看类的例化情况?

有人可能想在仿真窗口查看一下t句柄指向的对象。

module sv_class_inst;import uvm_pkg::*;`include "uvm_macros.svh"class top;function new();`uvm_info("SV_TOP", "SV TOP creating", UVM_LOW)endfunctionendclassinitial begintop t; `uvm_info("SV_TOP", "test started", UVM_LOW)t = new();`uvm_info("SV_TOP", "test finished", UVM_LOW)end
endmodule

结果会发现object窗口啥都没有。这是因为此处是硬件的信号,无法查看软件信号。

方法一:
正确的方式应该是通过view-locals打开locals窗口,这里可以看到软件变量。并且,需要在仿真后在第17行设置断点(没有设断点那么运行后就结束了,也看不到t),运行,就可以在locals窗口看到了。@top代表这个对象是top类,@1表示是top类的第一个对象。

 

方法二:
首先,如下图打开class instances窗口。

然后在仿真命令中加入-classdebug选项后进行仿真,并在仿真后在第17行设置断点。

vsim -novopt work.sv_class_inst -classdebug

如下图操作后也能在class instances窗口看到断点处的类例化的情况,此处就是@top@1.

uvm_class_inst.sv代码


module uvm_class_inst;import uvm_pkg::*;`include "uvm_macros.svh"class top extends uvm_component;`uvm_component_utils(top)function new(string name = "top", uvm_component parent = null);super.new(name, parent);`uvm_info("UVM_TOP", "SV TOP creating", UVM_LOW)endfunctionendclassinitial begintop t; `uvm_info("UVM_TOP", "test started", UVM_LOW)t = new("t", null);`uvm_info("UVM_TOP", "test finished", UVM_LOW)endendmodule

uvm_class_inst.sv代码分析:

uvm_class_inst定义的top类看似没什么内容,但是仿真、设断点之后发现里面别有洞天,有一层又一层的结构。这是因为top继承了uvm_component,所以也继承了他的结构和内容。

如果想要看到层次结构,可以如下图点开class tree-sim.

在class tree窗口即可看到。

三、UVM验证顶层与SV验证顶层的对比

uvm_test_inst代码


package test_pkg;import uvm_pkg::*;`include "uvm_macros.svh"class top extends uvm_test;`uvm_component_utils(top);function new(string name = "top", uvm_component parent = null);super.new(name,parent);`uvm_info("UVM_TOP", "SV TOP creating", UVM_LOW)endfunctiontask run_phase(uvm_phase phase);phase.raise_objection(this);`uvm_info("UVM_TOP", "test is running", UVM_LOW)phase.drop_objection(this);      endtask //run_phaseendclassendpackagemodule uvm_test_inst;import uvm_pkg::*;`include "uvm_macros.svh"import test_pkg::*;initial begin`uvm_info("UVM_TOP", "test started", UVM_LOW)run_test("top");`uvm_info("UVM_TOP", "test finished", UVM_LOW)end
endmodule

uvm_test_inst代码分析:

仿真,运行后,消息如下:

可以发现打印消息按照重要程度以及id分别列出。此处UVM_TOP为什么只有3个,而不是4个呢?明明代码里有4个UVM_TOP出现啊?
因此下面这行代码没有被执行:

`uvm_info("UVM_TOP", "test finished", UVM_LOW)

原因如下:

整个运行过程从initial块开始,接着进入run_test(),开始执行class top的内容:先是function new,接着是task run_phase。需要注意的是,当run_phase drop_objection之后,因为没有别的phase进行raise_objection,因此运行到此结束。所以没有执行上述提到的代码,最后只出现了3个UVM_TOP。

去掉 raise/drop_objection会怎样?

我们将raise/drop_objection注释掉,并加入了10ns的延时以及UVM_TOP类型的uvm_info(注意,因为代码没有写仿真时间单位,默认是1ns,所以加入的延时如果小于1ns会被仿真器忽略)

task run_phase(uvm_phase phase);// phase.raise_objection(this);`uvm_info("UVM_TOP", "test is running", UVM_LOW)#10ns;`uvm_info("UVM_TOP", "test finished after 10ns", UVM_LOW);// phase.drop_objection(this);      endtask

并如下图设好断点。


一步一步运行,可以发现程序在完成第15行之后就退出了,并且最后退出的时间是在0 ns处。

这就是注释掉raise/drop_objection产生的后果,即,进入到run_phase之后,由于没有举手,所以程序会跳过有延时的地方并直接退出。

sv和uvm中仿真窗口的区别

在sv的仿真中,仿真窗口只会出现硬件层次结构,不会出现sv的层次结构;
而到了uvm,仿真窗口会有双顶层结构出现,也就是uvm层次——uvm_root和硬件层次uvm_test_inst。

其中,top就是我们继承于uvm_test的类名称。

四、启动UVM验证的必要步骤

相比于uvm_class_inst,uvm_test_inst更适合作为UVM验证顶层容器。原因如下:

  •     只有继承于uvm_test的类,才可以作为UVM验证环境的顶层
  •     创建顶层验证环境,有且只能依赖于run_test(“UVM_TEST_NAME”)来传递,或者通过仿真参数传递,而不是通过构建函数new()。尽管new()可以创建一个对象,但是不能做与顶层验证环境相关的其他工作。具体的原因需要等对UVM有更深入了解时才能体会。

搭建验证框架 -> 验证组件之间的连接和通信 -> 编写测试用例,继而完成复用和覆盖率收敛。

http://www.lryc.cn/news/42037.html

相关文章:

  • Linux之Shell编程(1)
  • Java问题诊断工具——JVisualVM
  • Python3实现简单的车牌检测
  • 基于支持向量机SVM多因子测量误差预测,支持向量机MATLAB代码编程实现
  • 新农具时代,拼多多的进击与本分
  • 质量工具之故障树分析FTA(2) - FTA的基本概念
  • 《高质量C/C++编程》读书笔记二
  • 常用的美颜滤镜sdk算法
  • 动态SQL必知必会
  • DML编程控制
  • 关于肺结节实时的目标检测
  • 利用 Rainbond 云原生平台简化 Kubernetes 业务问题排查
  • C++中的future和promise使用方法
  • Vue项目创建
  • 2 Vue组件化编程
  • 使用GPT-4生成QT代码
  • Golang每日一练(leetDay0013)
  • 7个Python中的隐藏小技巧分享
  • 学习系统编程No.8【bash实现】
  • 2023年顶级编程语言趋势
  • 网络安全之认识勒索病毒
  • C语言手撕一个Hash表(HashTable)
  • 代码随想录第二十七天(669、108、538、回溯算法介绍)
  • 【Leetcode】设计循环队列
  • 【Linux】浅谈shell命令以及运行原理
  • 【shell脚本】nginx服务管理及存活检测脚本实战
  • web服务器—nginx
  • 网络安全工具大合集
  • 什么是SHA256?比特币是如何应用SHA256算法的?
  • JDK20正式发布了GA版本,短期维护支持,以及JDK21预览