UVM验证平台的运行 | UVM笔记 3

Posted by Kion on January 29, 2020

phase机制

UVM中的phase,按照是否消耗仿真时间的特性,分为function phase以及task phase。以下灰色部分即为消耗时间的task phase。task phase是动态运行,即启动后同时运行。而function phase则是一次只有一个运行。高亮为常用的phase。

phase的执行顺序主要有自上而下和自下而上(相对树结构而言)。自上而下用于build phase等。实例化通常是在该phase执行,所以只能自上而下,防止调用未实例化的component。自下而上用于function phase。而对于同层次的component,执行顺序是按照实例化时的名字的字母顺序。对于不同component的同一类的task phase,只有全部运行结束后才会进入到下一个phase。UVM树的遍历遵循深度优先,在执行build_phase时,会将一个component及其后层的component先执行完,再执行其同层的。

另外,在编写build_phase时,通常加入super.build_phase,其作用主要是能够自动执行config_db的get操作,其他phase基本用不到。

phase的跳转可以向前或者向后,大部分phase都支持跳转,少部分比如build_phase,run_phase等则不行。

phase.jump(uvm_reset_phase::get())

可以利用set_timeout函数设置超时时间。

uvm_top.set_timeout(500ns,0);/*第二个参数表示能否被后面set_timeout语句覆盖*/
<sim command> +UVM_TIMEOUT="300ns,YES"

UVM之所以要引进phase机制,主要是为了规范验证平台的运行,保证各个工作有序执行。比如build_phase,主要进行实例化,connect_phase进行端口连接等。phase机制一来将工作分段,二来自动安排工作的执行顺序。通过这种规范化,可以简化验证平台搭建的复杂程度。如果没有phase机制,那么工程师就要花费时间细心安排每个过程有序执行,不能出一点差错,这样显然增加了工作量。

objection 机制

验证平台中,需要使用raise_objection以及drop_objection来启动关闭phase。objection主要用于task phase,因为这种phase消耗仿真时间,运用objection机制可以解决何时结束仿真的问题。

task main_phase (uvm_phase phase);
    phase.raise_objection(this);
    ...
    phase.drop_objection(this);
endtask

objection机制非常重要,关系到phase能否正常有序执行。当进入到一个phase后,UVM就会查找是否有objection被提起,如果有,就执行该phase,否则直接进入下一个phase。反之,则执行该phase,当检测到所有objection都被撤销之后,UVM就进入到下一个phase。

所以,component、phase和objection之间的关系可以明确了。验证开始,会按照规定顺序开始执行phase,UVM会根据深度优先原则,依次启动不同component的同一阶段的phase,根据objection机制提起撤销,控制该阶段phase的结束,然后整个验证平台进入下一个phase,如此往复,直到所有phase执行结束,验证平台关闭。

那么在哪个component中设置objection机制就成为了关键。一般有两种方法,第一种是在scoreboard中,当scoreboard接收到足够的transaction后就结束循环,撤销objection;另一种是伴随sequence的,sequence生成结束,则撤销objection。

为了保证sequence发出的transaction都能被DUT接收,要考虑DUT的处理延时,所以常在撤销objection之后设置等待时间,让DUT接收数据完毕后,才进入下一phase。

task base_test::main_phase(uvm_phase phase);
phase.phase_done.set_drain_time(this,200);
endtask

domain的应用

为了应对更多的验证环境,domain被引入了。domain可以使得验证平台分出独立的时钟域,在各个时钟域中,动态运行的phase互不影响。

一般在connect phase中设置domain。

class B extends uvm_component;
    `uvm_component_utils(B);
	uvm_domain new_domain;
    function new (string nanme, uvm_component parent);
        super.new(name,parent);
        new_domain = new("new_domain");
    endfunction
    virtual function void connect_phase (uvm_phase phase);
        set_domain(new_domain);
	endfunction
endclass