UVM phase机制(三)objection机制

越高峻
2023-12-01

在上一篇博客UVM phase机制(二)中,我们有介绍到run_phase以及12个run_time_phase是如何运转起来的,但是留了一个小问题就是objection,想要run必须raise_objection,要想结束run必须drop_objection。下面我们详细分析一下为什么会这样
在运行到run_node的时候,是这样一个执行结构,

fork
   fork
            env.run_phase(uvm_phase phase);
   join_none
   fork
            uvm_test_top.run_phase(uvm_phase phase);
   join_none
   fork
            top.run_phase(uvm_phase phase);
   join_none

join_none

但是,最终完整的执行结构是

fork
   fork
            env.run_phase(uvm_phase phase);
   join_none
   fork
            uvm_test_top.run_phase(uvm_phase phase);
   join_none
   fork
            top.run_phase(uvm_phase phase);
   join_none

join_none
#0;
fork
    begin
	      fork
		         process(0);//junp
				 process(1);//objection
				 process(2);//timeout
		  join_any
		  disable fork
	end

join

所有的进程都是并行的,因此如果没有objection的话,那么进程process(1)直接结束,会直接disable fork。直接退出整个执行进程。下面介绍objection机制。有这么一行代码demo。

class my_test extends uvm_test;
.................
.................

task run_phase(uvm_phase phase);
     phase.raise_objection(this);
	 #1;
	 phase.drop_objection(this);
endtask
.................
.................
endclass

class my_env extends uvm_env;
.................
.................
task run_phase(uvm_phase phase);
      .........................
	  .........................
	  .........................
endtask
endclass

在my_test的run_phase中raise_objection。那么raise_objection是如何起作用的呢,在生成UVM phase结构的时候,phase树上会生成不同的node,比如build_node等,每个node在生成的时候内部有一个变量是uvm_objection phase_done会被例化生成,名字叫run,这个变量就是控制objection的句柄。下面看一下执行流程
->phase.raise_objection(this);
->phase_done.raise_objection(this);
phase_done.raise_objection主要做
(1)首先check一下this句柄是否是uvm_component或者uvm_sequence,只有这两个地方可以在run_phase中raise_objection。
(2)置位一些标志位
这里我们在my_test中调用raise_objection函数,那么在名为run的phase_done这个句柄中有两个重要的变量
int m_source_count[uvm_object]
int m_total_count[uvm_object]
最终的结果是
m_source_count[my_test]=1;
m_total_count[top]=1;
m_total_count[my_test]=1;

在上面的代码中process(1)控制objection的结束
当我们raise_objection(this)时,process(1)进程将会一直处于等待状态,当我们调用drop_objection(this)时,会触发process(1)结束,那么结束整个执行进程。
在#1,这个时候 process(1)进程结束,调用disable fork函数kill掉进程,执行结束。
我们来看另一种情况

class my_test extends uvm_test;
.................
.................

task run_phase(uvm_phase phase);
     phase.raise_objection(this);
	 #1;
	 phase.drop_objection(this);
endtask
.................
.................
endclass

class my_env extends uvm_env;
.................
.................
task run_phase(uvm_phase phase);
     phase.raise_objection(this);
	 #2;
	 phase.drop_objection(this);.
endtask
endclass

不仅在my_test中调用了objection机制,在my_env中也调用了objection机制。
在process(1)中,该进程结束的标志是m_total_count[top]=0;
起初m_total_count[top]=2;
my_test中#1时,drop_objection,此时m_total_count[top]=1;
my_env中#2时,drop_objection,此时m_total_count[top]=0;进程结束。所以整个进程会在#2时结束。

所以说要想run_phase结束,raise_objection和drop_objection必须成对出现

现在在谈谈12个run_time_phase,尤其是main_phase。

一般在main_phase之前的phase中不会进行什么操作,我们一般会在main_phase中执行一些操作,并且是与run_phase并行执行的,看下面一段代码

class my_test extends uvm_test;
.................
.................

task run_phase(uvm_phase phase);
.................
.................
     
endtask
.................
.................
endclass

class my_env extends uvm_env;
.................
.................
task main_phase(uvm_phase phase);
     phase.raise_objection(this);
	 #2;
	 phase.drop_objection(this);.
endtask
endclass

我们在run_phase中没有raise_objection,但是在main_phase中raise_objection,那么run_phase中的语句是否会执行呢,答案是肯定的。
首先在执行run_phase的时候,虽然没有raise_objection,但是进程process(1)并不会结束因为该进程会在post_shutdown的drop_objection结束,但是又在main_phase中raise_objection,那么main_phase会执行,那么在main_phase执行的时间内,run_phase依旧在执行,知道main_phase执行结束。

 类似资料: