uvm-1.2 examples —— 2.12 phase - timeout

2.12 phase - timeout



前言

本文以uvm-1.2/examples/simple/phases/timeout为例,通过代码了解UVM中的phases机制。通过这个例子可以基本了解以下知识点:

  • phase的“举手”和“放手”机制
  • phase运行的时间控制方法

一、基本介绍

在UVM中,执行仿真通过phase控制,phase的分类和执行顺序在《2.11 phase - basic》节中有具体介绍。在每个phase内部,则是通过raise_objection()和drop_objection()这对函数来控制,即我们常说的“举手”和“放手”,这两个函数通常成对出现,这一点和《2.10 objections》节类似,但是这里是通过phase来进行控制。

二、代码分析

这个测试用例一共有三个文件,包括:test.sv、tb_env.svh和tb_timer.svh。下面自顶向下分别介绍这三个文件的代码。

2.1 test.sv

program test;

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

tb_env env;


class test extends uvm_test;
   `uvm_component_utils(test)

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

   task pre_main_phase(uvm_phase phase);
      phase.raise_objection(this);
      #100;
      phase.drop_objection(this);
   endtask
   
   task main_phase(uvm_phase phase);
      phase.raise_objection(this);
      // Will cause a time-out
      // because we forgot to drop the objection
      //phase.drop_objection(this);
   endtask
   
   task shutdown_phase(uvm_phase phase);
      phase.raise_objection(this);
      #100;
      phase.drop_objection(this);
   endtask
endclass


initial
begin
   env = new("env");
   run_test("test");
end

endprogram

第1行,通过一个program关键字,将测试代码打成一个test包;
第3到6行,导入UVM包,以及另外tb_env.svh和tb_timer.svh两个文件;
第8行,声明tb_env,tb_env的实现位于tb_env.svh文件中;
第11到36行,test测试用例的实现,分别在pre_main_phase、main_phase和shutdown_phase中,通过phase.raise_objection(this)加入仿真时间,但是在main_phase中估计丢掉了;phase.drop_objection(this)函数,让其仿真无法结束;
第39到43行,实例化env并启动test的仿真。

2.2 tb_env.svh

class tb_env extends uvm_env;
   `uvm_component_utils(tb_env)

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

   function void build_phase(uvm_phase phase);
      uvm_config_db#(time)::set(null, "global_timer.*",    "timeout", 1000);
      uvm_config_db#(time)::set(null, "global_timer.main", "timeout", 3000);
      uvm_config_db#(time)::set(null, "global_timer.run",  "timeout", 0);
   endfunction

   
   task reset_phase(uvm_phase phase);
      phase.raise_objection(this);
      #20;
      phase.drop_objection(this);
   endtask
   
   task configure_phase(uvm_phase phase);
      phase.raise_objection(this);
      #200;
      phase.drop_objection(this);
   endtask
   
   task main_phase(uvm_phase phase);
      phase.raise_objection(this);
      #1000;
      phase.drop_objection(this);
   endtask

   task shutdown_phase(uvm_phase phase);
      phase.raise_objection(this);
      #10;
      phase.drop_objection(this);
   endtask
endclass

这个文件是tb_env的具体实现。
其中,值得注意的是:
第8到12行,在build_phase中通过config_db机制,配置了global_timer中各个phase机制的timeout参数,global_timer的实现在tb_timer.svh中;
第15到37行,分别在reset_phase、configure_phase、main_phase、shutdown_phase中,通过phase.raise_objection(this)和phase.drop_objection(this)这对函数,加入了仿真时间。

2.3 tb_timer.svh

//
// Generic phase timer
//
// All time-out values are interprted in ns
//
// To set time-out values:
//
// - For one phase:
//
//   uvm_config_db#(time)::set(null, "global_timer.main", "timeout", 100);
//
// - For multiple phases:
//
//   uvm_config_db#(time)::set(null, "global_timer.pre*", "timeout", 100);
//

class tb_timer extends uvm_component;

   `uvm_component_utils(tb_timer)

   local static tb_timer m_global = new("global_timer", null);

   function new(string name, uvm_component parent = null);
      super.new(name, parent);
   endfunction
      
   task run_phase(uvm_phase phase);
      time t;
      if (uvm_config_db#(time)::get(this, "run", "timeout", t) &&
          t > 0) begin
         #(t * 1ns);
         `uvm_fatal("TIMEOUT", "Time-out expired in run phase")
      end
   endtask

   task pre_reset_phase(uvm_phase phase);
      time t;
      if (uvm_config_db#(time)::get(this, "pre_reset", "timeout", t) &&
          t > 0) begin
         #(t * 1ns);
         `uvm_fatal("TIMEOUT", "Time-out expired in pre_reset phase")
      end
   endtask

   task reset_phase(uvm_phase phase);
      time t;
      if (uvm_config_db#(time)::get(this, "reset", "timeout", t) &&
          t > 0) begin
         #(t * 1ns);
         `uvm_fatal("TIMEOUT", "Time-out expired in reset phase")
      end
   endtask

   task post_reset_phase(uvm_phase phase);
      time t;
      if (uvm_config_db#(time)::get(this, "post_reset", "timeout", t) &&
          t > 0) begin
         #(t * 1ns);
         `uvm_fatal("TIMEOUT", "Time-out expired in post_reset phase")
      end
   endtask

   task pre_configure_phase(uvm_phase phase);
      time t;
      if (uvm_config_db#(time)::get(this, "pre_configure", "timeout", t) &&
          t > 0) begin
         #(t * 1ns);
         `uvm_fatal("TIMEOUT", "Time-out expired in pre_configure phase")
      end
   endtask

   task configure_phase(uvm_phase phase);
      time t;
      if (uvm_config_db#(time)::get(this, "configure", "timeout", t) &&
          t > 0) begin
         #(t * 1ns);
         `uvm_fatal("TIMEOUT", "Time-out expired in configure phase")
      end
   endtask

   task post_configure_phase(uvm_phase phase);
      time t;
      if (uvm_config_db#(time)::get(this, "post_configure", "timeout", t) &&
          t > 0) begin
         #(t * 1ns);
         `uvm_fatal("TIMEOUT", "Time-out expired in post_configure phase")
      end
   endtask
   
   task pre_main_phase(uvm_phase phase);
      time t;
      if (uvm_config_db#(time)::get(this, "pre_main", "timeout", t) &&
          t > 0) begin
         #(t * 1ns);
         `uvm_fatal("TIMEOUT", "Time-out expired in pre_main phase")
      end
   endtask

   task main_phase(uvm_phase phase);
      time t;
      if (uvm_config_db#(time)::get(this, "main", "timeout", t) &&
          t > 0) begin
         #(t * 1ns);
         `uvm_fatal("TIMEOUT", "Time-out expired in main phase")
      end
   endtask

   task post_main_phase(uvm_phase phase);
      time t;
      if (uvm_config_db#(time)::get(this, "post_main", "timeout", t) &&
          t > 0) begin
         #(t * 1ns);
         `uvm_fatal("TIMEOUT", "Time-out expired in post_main phase")
      end
   endtask

   task pre_shutdown_phase(uvm_phase phase);
      time t;
      if (uvm_config_db#(time)::get(this, "pre_shutdown", "timeout", t) &&
          t > 0) begin
         #(t * 1ns);
         `uvm_fatal("TIMEOUT", "Time-out expired in pre_shutdown phase")
      end
   endtask

   task shutdown_phase(uvm_phase phase);
      time t;
      if (uvm_config_db#(time)::get(this, "shutdown", "timeout", t) &&
          t > 0) begin
         #(t * 1ns);
         `uvm_fatal("TIMEOUT", "Time-out expired in shutdown phase")
      end
   endtask

   task post_shutdown_phase(uvm_phase phase);
      time t;
      if (uvm_config_db#(time)::get(this, "post_shutdown", "timeout", t) &&
          t > 0) begin
         #(t * 1ns);
         `uvm_fatal("TIMEOUT", "Time-out expired in post_shutdown phase")
      end
   endtask

endclass

这个文件主要是tb_timer 的具体实现。
其中,值得注意的是:
第19行,将tb_timer注册到UVM的工厂机制中,这是为什么在env中没有例化m_global,却能够传递参数过来的原因;
第27到142行,代码实现上基本上都类似,意思是在每个phase中通过config_db机制获取到一个timeout的变量,并检测改phase执行的时间,是否超过了timeout的值,如果phase提前结束,则不会打印uvm_fatal相关的信息,否则打印在哪个phase超时的fatal信息。

2.4 仿真结果

UVM_INFO @ 0: reporter [RNTST] Running test test...
UVM_FATAL tb_timer.svh(126) @ 3320: global_timer [TIMEOUT] Time-out expired in main phase
UVM_INFO ../../../../src/base/uvm_report_server.svh(847) @ 3320: reporter [UVM/REPORT/SERVER] 
--- UVM Report Summary ---

** Report counts by severity
UVM_INFO :    2
UVM_WARNING :    0
UVM_ERROR :    0
UVM_FATAL :    1
** Report counts by id
[RNTST]     1
[TIMEOUT]     1
[UVM/RELNOTES]     1

$finish called from file "../../../../src/base/uvm_root.svh", line 135.
$finish at simulation time                 3320
           V C S   S i m u l a t i o n   R e p o r t 
Time: 3320 ns

通过仿真结果,可以看到打印了一个UVM_FATAL的信息,提示main phase执行超时,这是因为在test.sv文件的main phase中,我们故意丢了一个phase.drop_objection(this)函数。

另外,值得注意的是,仿真结束的时间是3320ns,这个时间是tb_env中reset_phase的20ns,加上tb_env中configure_phase的200ns,加上test中pre_main_phase的100ns,加上tb_env中build_phase给global_timer.main配置的3000ns,一共是20+200+100+3000=3320ns。


总结

通过这个测试用例,可以比较直观的看到,在phase内部,我们通过phase.raise_objection(this)和phase.drop_objection(this)这对函数来控制仿真执行的时间;另外,通过tb_timer 这个单独的类,来控制各个phase执行的时间,一旦超时则报UVM FATAL的错误信息。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值