uvm_barrier用法
UVM还提供了一个新的类uvm_barrier用来对多个组件进行同步协调,同时为了解决组件独立运作的封闭性需要,也定义了新的类uvm_barrier_pool来全局管理这些uvm_barrier对象。这里的uvm_barrier_pool同之前的uvm_event_pool一样,也是基于uvm_object_string_pool的通用参数类来进一步定义的。
- uvm_barrier可以设置一定的等待阈值(threshold),待有不少于该阈值的进程在等待该对象时,才触发该事件,同时激活所有正在等待的进程,使得可以继续进行。
class comp1 extends uvm_component; //组件comp1
...
uvm_barrier b1; //**1.声明事件阻塞变量(句柄)**
function void build_phase(uvm_phase phase);
super.build_phase(phase);
b1 = uvm_event_pool::get_global("b1"); //**2.在资源池中创建一个共享阻塞事件b1,并赋值给本地阻塞事件b1**
endfunction
task run_phase(uvm_phase phase);
#10ns;
`uvm_info("BSYNC",$sformatf("c1 wait for b1 at %t ps",$time),UVM_LOW)
b1.wait_for(); //**3. 在达到阻塞阈值threshold之前,一直阻塞语句执行**
`uvm_info("BSYNC",$sformatf("c1 is activated at %t ps",$time),UVM_LOW)
endtask
endclass
class comp2 extends uvm_component; //组件comp1
...
uvm_barrier b1;
function void build_phase(uvm_phase phase);
super.build_phase(phase);
b1 = uvm_event_pool::get_global("b1"); //共享资源池中的阻塞事件b1
endfunction
task run_phase(uvm_phase phase);
#20ns;
`uvm_info("BSYNC",$sformatf("c2 wait for b1 at %t ps",$time),UVM_LOW)
b1.wait_for(); //**3. 在达到阻塞阈值threshold之前,一直阻塞语句执行**
`uvm_info("BSYNC",$sformatf("c2 is activated at %t ps",$time),UVM_LOW)
endtask
endclass
class env1 extends uvm_env;
comp1 c1;
comp2 c2;
uvm_barrier b1;
...
function void build_phase(uvm_phase phase);
super.build_phase(phase);
c1 = comp1::type_id::create("c1",this);
c2 = comp2::type_id::create("c2",this);
b1 = uvm_event_pool::get_global("b1"); //共享资源池中的阻塞事件b1
endfunction
task run_phase(uvm_phase phase);
b1.set_threshold(3); //**4. 设置阈值为3,即需要有三个等待事件**
`uvm_info("BSYNC",$sformatf("env set b1 threshold %d at %t ps",b1.get_threshold(),$time),UVM_LOW)
#50ns;
b1.set_threshold(2); //**4. 修改,设置阈值为2,即需要两个等待事件**
`uvm_info("BSYNC",$sformatf("env set b1 threshold %d at %t ps",b1.get_threshold(),$time),UVM_LOW)
endtask
endclass
c1和c2的run_phase任务之间需要同步,而同步它们的则是顶层的一个uvm_barrier b1。由于c1、c2和env1都共享该对象,这使得c1和c2可以通过wait_for()来等待激活,而env1则可以设置阈值来调控什么时间来“开阀”。从仿真结果可以看到,在一开始的时候,阈值设置为3,但由于等待该barrier的进程只有2个,无法达到阈值条件,使得两个进程都无法激活。而在env1将b1的阈值调低为2时,则等待该barrier的两个进程都被激活。因此通过set_threshold()和wait_for()这样的方式,可以实现多个组件之间的同步,同时又可以保持各个组件之间的独立性。