uvm 用例选择机制(run_test)

发布时间 2023-09-25 10:38:38作者: 下夕阳

UVM的用例选择机制run_test()

1、编写基于UVM的最简单代码

harness.v

module harness(clk, rst);
input clk;
input rst;

endmodule
test_uvm.sv

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

class my_driver extends uvm_driver;
    `uvm_component_utils(my_driver);// 注册my_driver,让my_driver类型存在一张表中,这样run_test("my_driver")或者my_driver::type_id::create("my_driver",this)才能找到my_driver类型,然后通过factory例化my_driver。
    function new(string name="my_driver", uvm_component parent=null); // 必须定义new函数,因为如果不定义,那么默认的new函数是无参函数,但是在create的时候需要一个有两个参数的函数。
        super.new(name.parent);
    endfunction

endclass

class my_env extends uvm_env;
    `uvm_component_utils(my_env);
    my_driver m_driver;

    function new(string name="my_env", uvm_component parent=null);
        super.new(name, parent);
    endfunction

    function void build_phase(uvm_phase phase);
        m_driver = my_driver::type_id::create("my_driver", this);  // 在my_env下例化了,my_driver,那么my_driver就是my_env的子节点。
    endfunction

    task main_phase(uvm_phase phase);
      phase.raise_objection(this);// 为了harness中有时间
         uvm_top.print_topology();   // 打印环境的拓扑结构
      #100;               // 为了harness中有时间
      phase.drop_objection(this);
    endtask
endclass

program automatic test;
  
    initial begin
        $display("hello");
     force harness.clk = 1'b1;  // force rtl中的信号
     force harness.rst = 1'b0;
        run_test();               // run_test()根据+UVM_TESTNAME=xxx参数,选择例化的component,xxx必须是注册了的component类型。这个语句一般在harness的initial语句中。
    end
endprogram

2、编写编译和执行的Makefile脚本(基于VCS)

Makefile

export file := test

run: cmp # 第一个目标就是默认目标,只敲make就是执行这个目标,目标依赖cmp,所以会先去执行cmp目标
    @echo run simv ....
    ./simv +UVM_TESTNAME=my_env # VCS默认生成的可执行文件就是simv,+UVM_TESTNAME为参数,用于$value$plusargs()接收。

cmp:
    vcs -full64 -sverilog $(file).sv -ntb_opts uvm-1.1 # -ntb_opt uvm-1.1是VCS编译的参数,目的是要VCS去吃UVM的库文件,这样`include "uvm_pkg.sv"的时候才能找到。
    # 本来想用+incdir+/software/synopsys/vcs/2018.09.sp2/etc/uvm-1.1方式来加UVM的库文件,但这种方式加库文件不彻底,编译没问题,执行的时候报错。

写好Makefile后,直接敲make file=test_uvm即可完成编译和执行

3、执行结果

img

可以看到,uvm_test_top为my_env,my_env下面包含了my_driver,由于uvm_driver中例化了uvm_analysis_port和uvm_seq_item_pull_port所以my_driver下面还有子节点。

4、原理分析

在my_env中使用了`uvm_component_utils(my_driver)宏对my_env进行了注册,这样my_env这个类就添加到了uvm_factory中的表中,运行simv后,执行到run_test()函数时会根据+UVM_TESTNAME选择注册的component类进行例化。

img

调用的run_test任务在uvm_globals.svh中,接着直接调用了uvm_root的run_test任务。

img

在uvm_root的run_test中先用$value$plusargs任务获取UVM_TESTNAME参数赋给test_name,我们传的参数是my_env;然后用factory根据名字test_name调用create_component_by_name函数查表例化component对象,并把对象实例名设为uvm_test_top。这个节点节点的父节点为null所以说这是根节点(其实还有uvm_top节点)

img

后续开始执行各个phase,环境自动跑起来。