首页 > 代码库 > *2.2.3 加入objection机制

*2.2.3 加入objection机制

在上一节中,虽然输出了“main_phase is called”,但是“data is drived”并没有输出。而main_phase是一个完整的任务,没有理由只执行第一句,而后面的代码不执行。看上去似乎main_phase在执行的过程中被外力“杀死”了,事实上也确实如此。

UVM中通过objection机制来控制验证平台的关闭。细心的读者可能发现,在上节的例子中,并没有如2.2.1节所示显式地调用finish语句来结束仿真。但是在运行上节例子时,仿真平台确实关闭了。在每个phase中,UVM会检查是否有objection被提起(raise_objection),如果有,那么等待这个objection被撤销(drop_objection)后停止仿真;如果没有,则马上结束当前phase。

加入了objection机制的driver如下所示:

代码清单 2-9
文件:src/ch2/section2.2/2.2.3/my_driver.sv
 13 task my_driver::main_phase(uvm_phase phase);
 14   phase.raise_objection(this);
 15   `uvm_info("my_driver", "main_phase is called", UVM_LOW);
 16   top_tb.rxd <= 8‘b0;
 17   top_tb.rx_dv <= 1‘b0;
 18   while(!top_tb.rst_n)
 19     @(posedge top_tb.clk);
 20   for(int i = 0; i < 256; i++)begin
 21     @(posedge top_tb.clk);
 22     top_tb.rxd <= $urandom_range(0, 255);
 23     top_tb.rx_dv <= 1‘b1;
 24     `uvm_info("my_driver", "data is drived", UVM_LOW);
 25   end
 26   @(posedge top_tb.clk);
 27   top_tb.rx_dv <= 1‘b0;
 28   phase.drop_objection(this);
 29 endtask

在开始学习时,读者可以简单地将drop_objection语句当成是finish函数的替代者,只是在drop_objection语句之前必须先调用raise_objection语句,raise_objection和drop_objection总是成对出现。加入objection机制后再运行验证平台,可以发现“data is drived”按照预期输出了256次。

raise_objection语句必须在main_phase中第一个消耗仿真时间的语句之前。

如$display语句是不消耗仿真时间的,这些语句可以放在raise_objection之前,但是类似@(posedge top.clk)等语句是要消耗仿真时间的。

按照如下的方式使用raise_objection是无法起到作用的:

代码清单 2-10
task my_driver::main_phase(uvm_phase phase);
   @(posedge top_tb.clk);
   phase.raise_objection(this);
   `uvm_info("my_driver", "main_phase is called", UVM_LOW);
   top_tb.rxd <= 8‘b0;
   top_tb.rx_dv <= 1‘b0;
   while(!top_tb.rst_n)
      @(posedge top_tb.clk);
   for(int i = 0; i < 256; i++)begin
      @(posedge top_tb.clk);
      top_tb.rxd <= $urandom_range(0, 255);
      top_tb.rx_dv <= 1‘b1;
      `uvm_info("my_driver", "data is drived", UVM_LOW);
   end
   @(posedge top_tb.clk);
   top_tb.rx_dv <= 1‘b0;
   phase.drop_objection(this);
endtask

*2.2.3 加入objection机制