UVM建造测试用例

(1)加入base_test

        在一个实际应用的UVM验证平台中,my_env并不是树根,通常来说,树根是一个基于uvm_test派生的类真正的测试用例都是基于base_test派生的一个类

class base_test extends uvm_test;

   my_env         env;
   
   function new(string name = "base_test", uvm_component parent = null);
      super.new(name,parent);
   endfunction
   
   extern virtual function void build_phase(uvm_phase phase);
   extern virtual function void report_phase(uvm_phase phase);
   `uvm_component_utils(base_test)
endclass


function void base_test::build_phase(uvm_phase phase);
   super.build_phase(phase);
   env  =  my_env::type_id::create("env", this); 
   uvm_config_db#(uvm_object_wrapper)::set(this,
                                           "env.i_agt.sqr.main_phase",
                                           "default_sequence",
                                            my_sequence::type_id::get());
endfunction

function void base_test::report_phase(uvm_phase phase);
   uvm_report_server server;
   int err_num;
   super.report_phase(phase);

   server = get_report_server();
   err_num = server.get_severity_count(UVM_ERROR);

   if (err_num != 0) begin
      $display("TEST CASE FAILED");
   end
   else begin
      $display("TEST CASE PASSED");
   end
endfunction

        base_test派生自uvm_test,使用uvm_component_utils宏来注册到factory中。在build_phase中实例化my_env,并设置sequencer的 default_sequence。需要注意的是,这里设置了default_sequence,其他地方就不需要再设置了。
        除了实例化env外,base_test中做的事情在不同的公司各不相同。上面的代码中出现了report_phase,在report_phase中根据 UVM_ERROR的数量来打印不同的信息。一些日志分析工具可以根据打印的信息来判断DUT是否通过了某个测试用例的检查。report_phase也是UVM内建的一个phase,它在main_phase结束之后执行。
        除了上述操作外,还通常在base_test中做如下事情:第一,设置整个验证平台的超时退出时间;第二,通过config_db设置验 证平台中某些参数的值。这些根据不同的验证平台及不同的公司而不同,没有统一的答案。
        在把my_env放入base_test中之后,UVM树的层次结构变为如图2-11所示的形式。
        top_tb中run_test的参数从my_env变成了base_test,并且config_db中设置virtual interface的路径参数要做如下改变:

 

initial begin
   run_test("base_test");
end

initial begin
   uvm_config_db#(virtual my_if)::set(null, "uvm_test_top.env.i_agt.drv", "vif", input_if);
   uvm_config_db#(virtual my_if)::set(null, "uvm_test_top.env.i_agt.mon", "vif", input_if);
   uvm_config_db#(virtual my_if)::set(null, "uvm_test_top.env.o_agt.mon", "vif", output_if);
end

(2)UVM中测试用例的启动

        要测试一个DUT是否按照预期工作,需要对其施加不同的激励,这些激励被称为测试向量或pattern。一种激励作为一个测试 用例,不同的激励就是不同的测试用例。测试用例的数量是衡量验证人员工作成果的最直接目标。
        伴随着验证的进行,测试用例的数量一直在增加,在增加的过程中,很重要的一点是保证后加的测试用例不影响已经建好的 测试用例。在前面所有的例子中,通过设置default_sequence的形式启动my_sequence。假如现在有另外一个my_sequence2,如何在 不影响my_sequence的前提下将其启动呢?最理想的办法是在命令行中指定参数来启动不同的测试用例。
        无论是在my_env中设置default_sequence,还是在base_test中或者top_tb中设置,都必须修改相关的设置代码才能启动 my_sequence2,这与预期相去甚远。为了解决这个问题,先来看两个不同的测试用例。my_case0的定义如下:

`ifndef MY_CASE0__SV
`define MY_CASE0__SV
class case0_sequence extends uvm_sequence #(my_transaction);
   my_transaction m_trans;

   function  new(string name= "case0_sequence");
      super.new(name);
   endfunction 
   
   virtual task body();
      if(starting_phase != null) 
         starting_phase.raise_objection(this);
      repeat (10) begin
         `uvm_do(m_trans)
      end
      #100;
      if(starting_phase != null) 
         starting_phase.drop_objection(this);
   endtask

   `uvm_object_utils(case0_sequence)
endclass


class my_case0 extends base_test;

   function new(string name = "my_case0", uvm_component parent = null);
      super.new(name,parent);
   endfunction 
   extern virtual function void build_phase(uvm_phase phase); 
   `uvm_component_utils(my_case0)
endclass


function void my_case0::build_phase(uvm_phase phase);
   super.build_phase(phase);

   uvm_config_db#(uvm_object_wrapper)::set(this, 
                                           "env.i_agt.sqr.main_phase", 
                                           "default_sequence", 
                                           case0_sequence::type_id::get());
endfunction

`endif

my_case1的定义如下:

`ifndef MY_CASE1__SV
`define MY_CASE1__SV
class case1_sequence extends uvm_sequence #(my_transaction);
   my_transaction m_trans;

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

   virtual task body();
      if(starting_phase != null) 
         starting_phase.raise_objection(this);
      repeat (10) begin
         `uvm_do_with(m_trans, { m_trans.pload.size() == 60;})
      end
      #100;
      if(starting_phase != null) 
         starting_phase.drop_objection(this);
   endtask

   `uvm_object_utils(case1_sequence)
endclass

class my_case1 extends base_test;
  
   function new(string name = "my_case1", uvm_component parent = null);
      super.new(name,parent);
   endfunction 
   
   extern virtual function void build_phase(uvm_phase phase); 
   `uvm_component_utils(my_case1)
endclass


function void my_case1::build_phase(uvm_phase phase);
   super.build_phase(phase);

   uvm_config_db#(uvm_object_wrapper)::set(this, 
                                           "env.i_agt.sqr.main_phase", 
                                           "default_sequence", 
                                           case1_sequence::type_id::get());
endfunction

`endif

        在case1_sequence中出现了uvm_do_with宏,它是uvm_do系列宏中的一个,用于在随机化时提供对某些字段的约束
        要启动my_case0,需要在top_tb中更改run_test的参数:

initial begin
run_test("my_case0");
end

        而要启动my_case1,也需要更改:

initial begin
run_test("my_case1");
end

        当my_case0运行的时候需要修改代码,重新编译后才能运行;当my_case1运行时也需如此,这相当不方便。事实上,UVM提 供对不加参数的run_test的支持:

initial begin
   run_test();
end

        在这种情况下,UVM会利用UVM_TEST_NAME从命令行中寻找测试用例的名字,创建它的实例并运行。如下所示的代码可 以启动my_case0:

<sim command>
… +UVM_TEST_NAME=my_case0

        而如下所示的代码可以启动my_case1:

<sim command>
… +UVM_TEST_NAME=my_case1

        整个启动及执行的流程如下图所示

                                                图1 测试用例的启动及执行流程
启动后,整棵UVM树的结构如下图所示。

                                        图2 每个测试用例建立的UVM树

        图2-13与图2-11的唯一区别在于树根的类型从base_test变成了my_casen。

  • 21
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值