原理
objection顾名思义就是"反对/异议"。如有人提出异议,必定需要解决,直到撤销异议为止。
objection执行过程:
在UVM的task phase机制里(为何只提task phase?埋个伏笔,值得思考),进入某一个phase,UVM会收集所有提出的objection,并监听所有的objection是否撤销完毕?撤销完毕,则关闭当前phase并自动进入下个phase。直到最后一个phase完成后,自动调用$finish关闭验证平台。
理解
UVM reference的介绍如下:
意思就是说协调多个对象之间的状态信息,可以简单理解为“同步”。
Objection实质是UVM框架中用来同步不同组件的相同phase,以及决定当前测试用例什么时候结束的机制。
同步机制:以task phase为例,从左向右顺序执行,相同的phase是在同一时刻开始往后执行,即实现了“同步”。
用法
最常见方法:raise_objection(),drop_objection() 和 set_drain_time()。
Objection计数器在每次调用raise_objection()和drop_objection()会进行增减。
应用的位置
方法1:不建议在每个task phase中去raise-drop objection。主要是因为objection的控制会比较分散,不便于objection的管理,另一个是反复的调用会使得仿真效率比较低。
方法2:建议在顶层的sequence中或者scoreboard中控制objection(采用uvm_sequence_base:: starting_phase这个变量)
//uvm1.1
class my_test extends uvm_test;
...
virtual task main_phase(uvm_phase phase);
uvm_objection objection;
my_sequence my_seq;
...
my_seq = my_sequence::type_id::create("my_seq");
my_seq.starting_phase = phase; //设置seq中的starting_phase变量句柄
objection = phase.get_objection();//当前phase结束的objection句柄(phase.done)
objection.set_drain_time(this,1us);//撤销objection后,延迟仿真时间
endtask
endclass
class my_sequence extends uvm_sequence #(my_transaction);
...
virtual task body();
if(starting_phase!=null) begin
starting_phase.rasise_objection(this);
end
...
if(starting_phase!=null) begin
starting_phase.drop_objection(this);
end
endtask
endclass
以上是UVM 1.1对objection的用法。
UVM 1.2相比于UVM 1.1
弃用了uvm_sequence_base:: starting_phase这个变量,改用set_starting_phase和get_starting_phase两个方法;弃用了raise_objection和drop_objection两个方法,改用uvm_sequence_base:: set_automatic_phase_objection。
这些改进的目的是优化objection的使用体验,UVM library帮你多省掉了一些代码和出错的机会。示例代码如下:
//uvm1.2
class my_test extends uvm_test;
virtual task main_phase(uvm_phase phase);
uvm_objection objection;
my_sequence my_seq;
bit phase_objection_status;
my_seq = my_sequence::type_id::create("my_seq");
my_seq.set_starting_phase(phase);//设置starting_phase变量,一旦设置后,
//uvm_sequence_base::uvm_get_to_lock_dap保护在读取后不被修改
my_seq.set_automatic_phase_objection(1);//代替了seq中raise-drop objection
my_seq.start(my_agent.sqr);
phase_objection_status = my_seq.get_automatic_phase_objection();//获取
//objection状态,如果为1,立即raise objection
objection = phase.get_objection();
objection.set_drain_time(this,1us);//撤销objection后,延迟仿真时间
endtask
endclass
set_drain_time()
使用场景是在objection都撤销了之后,往后延长仿真结束的时间。这么做的目的是让DUT有多余的时间去完成动作,使其完整响应我们输入的测试激励。
objection非常规手段(debug)
+UVM_OBJECTION_TRAC:追踪Objection状态用的命令行参数,当仿真命令加上该参数,就可以在仿真日志中看到谁谁谁置起了objection,谁谁谁撤销了objection,以及objection计数器的数值等等。
phase.get_objection():可以拿到负责当前phase的objection句柄,之后就可以调用该句柄有的一些方法,比如get_drain_time()方法可以返回当前objection对象的排空时间(drain time);display_objections()方法可以打印该objection对象的具体信息等。
拓展
component类中的phase参数必要性:raise/drop_objection是属于uvm_phase类中的方法,需要通过phase句柄来调用。否则调用就比较麻烦。
run_phase 如何控制同步?
被动接受其他task phase的控制。
主动在run_phase中定义raise/drop_objection。
建议monitor/driver中不做objection控制:无限循环的特点,不利于objection控制。