目录
uvm_domain
控制run_phase对应的细分phase异步执行,适用于DUT含有多个时钟域时,独立的进行细分phase操作,如复位,配置,启动执行。
默认情况下,两个driver类中的复位phase 和main phase必须同时执行。
使用方法:
- uvm_domain xxx_domain;//组件里定义
- xxx_domain = new(“xxx_domain”);//实例化 function new中
- set_domain(xxx_domain);//将当前组件加入xxx_domain中,一般在connect_phase中使用
UVM机制学习之Objection, Domain机制_15的月亮的博客-CSDN博客
UVM:5.3.1 domain 简介_tingtang13的博客-CSDN博客
UVM:5.3.2 多domain 的例子_tingtang13的博客-CSDN博客
UVM:5.3.3 多domain中phase 的跳转_tingtang13的博客-CSDN博客
main phase 跳转到reset phase:
phase.jump(uvm_reset_phase::get());
sequencer 的仲裁特性
可以通过uvm_sequencer::set_arbitration(UVM_SEQ_ARB_TYPE val)函数来设置仲裁模式,这里的仲裁模式UVM_SEQ_ARB_TYPE 有下面几种值可以选择:
- UVM_SEQ_ARB_FIFO:默认模式,来自于sequences的发送请求,按照FIFO先进先出的方式被依次授权,和优先级没有关系。
- UVM_SEQ_ARB_WEIGHTED:不同sequeces的发送请求,将按照它们的优先级权重随机授权。
- UVM_SEQ_ARB_RANDOM:不同的请求会被随机授权,而无视它们的抵达顺序和优先级。
- UVM_SEQ_ARB_STRICT_FIFO:不同的请求,会按照它们的优先级以及抵达顺序来依次授权,因此与优先级和抵达时间都有关。
- UVM_SEQ_ARB_STRICT_RANDOM:不同的请求,会按照它们的最高优先级随机授权,与抵达时间无关。
- UVM_SEQ_ARB_USER:用户可以自定义仲裁方法user_priority_arbitration来裁定哪个sequencer的请求被优先授权。
uvm_event
与event 相比,uvm event类有下面几个重要特性:
event | uvm_event |
event被->触发之后,触发使用@等待该事件的对象; 再次触发,只需再次用->触发 | 通过trigger()来触发,触发使用wait trigger()等待该事件的对象。 再次触发,t需要先通过reset()方法重置初始状态,再使用trigger()来触发 |
无法携带更多的信息 | 可以通过trigger(T data = null)的可选参数,将伴随触发的数据对象都写入到该触发事件中,而等待该事件的对象可以通过方法wait trigger data(output T data)来获取事件触发时写入的数据对象。 |
t触发时无法直接触发回调函数 | 可以通过add_callback(uvm_event_callback cb,bit append =1)函数来添加回调函数。 |
无法直接获取等待它的进程数目 | 可以通过 get num waiters()来获取等待它的进程数目。 |
TLM 传输必须是在组件和组件之间进行的,然而,要在sequence和sequence之间进行同步,或sequence与driver之间进行同步,可以借助uvm_event来实现。
module uvm_event_sync;
import uvm_pkg::*;
`include "uvm_macros.svh"
class edata extends uvm_object;
int data;
`uvm_object_utils(edata)
function new(string name = "edata");
super.new(name);
endfunction
endclass
class ecb extends uvm_event_callback;
`uvm_object_utils(ecb)
function new(string name = "ecb");
super.new(name);
endfunction
function bit pre_trigger(uvm_event e, uvm_object data = null);
`uvm_info("EPRETRIG", $sformatf("before trigger event %s", e.get_name()), UVM_LOW)
return 0;
endfunction
function void post_trigger(uvm_event e, uvm_object data = null);
`uvm_info("EPOSTRIG", $sformatf("after trigger event %s", e.get_name()), UVM_LOW)
endfunction
endclass
class comp1 extends uvm_component;
uvm_event e1;
`uvm_component_utils(comp1)
function new(string name, uvm_component parent);
super.new(name, parent);
endfunction
function void build_phase(uvm_phase phase);
super.build_phase(phase);
e1 = uvm_event_pool::get_global("e1");
endfunction
task run_phase(uvm_phase phase);
edata d = new();
ecb cb = new();
d.data = 100;
#10ns;
e1.add_callback(cb);
e1.trigger(d);
`uvm_info("ETRIG", $sformatf("trigger sync event at %t ps", $time), UVM_LOW)
endtask
endclass
class comp2 extends uvm_component;
uvm_event e1;
`uvm_component_utils(comp2)
function new(string name, uvm_component parent);
super.new(name, parent);
endfunction
function void build_phase(uvm_phase phase);
super.build_phase(phase);
e1 = uvm_event_pool::get_global("e1");
endfunction
task run_phase(uvm_phase phase);
uvm_object tmp;
edata d;
`uvm_info("ESYNC", $sformatf("wait sync event at %t ps", $time), UVM_LOW)
e1.wait_trigger_data(tmp);
void'($cast(d, tmp));
`uvm_info("ESYNC", $sformatf("get data %0d after sync at %t ps", d.data, $time), UVM_LOW)
endtask
endclass
class env1 extends uvm_env;
comp1 c1;
comp2 c2;
`uvm_component_utils(env1)
function new(string name, uvm_component parent);
super.new(name, parent);
endfunction
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);
endfunction: build_phase
endclass
class test1 extends uvm_test;
`uvm_component_utils(test1)
env1 env;
function new(string name, uvm_component parent);
super.new(name, parent);
endfunction
function void build_phase(uvm_phase phase);
env = env1::type_id::create("env", this);
endfunction
task run_phase(uvm_phase phase);
super.run_phase(phase);
phase.raise_objection(phase);
#1us;
phase.drop_objection(phase);
endtask
endclass
initial begin
run_test("test1");
end
endmodule
// UVM_INFO @ 0: reporter [RNTST] Running test test1...
// UVM_INFO @ 0: uvm_test_top.env.c2 [ESYNC] wait sync event at 0 ps
// UVM_INFO @ 10000: reporter [EPRETRIG] before trigger event e1
// UVM_INFO @ 10000: reporter [EPOSTRIG] after trigger event e1
// UVM_INFO @ 10000: uvm_test_top.env.c1 [ETRIG] trigger sync event at 10000 ps
// UVM_INFO @ 10000: uvm_test_top.env.c2 [ESYNC] get data 100 after sync at 10000 ps
uvm_barrier
多个组件的同步。barrier.wait_for 顶层设置 barrier.set_threshold()触发
module uvm_barrier_sync;
import uvm_pkg::*;
`include "uvm_macros.svh"
class comp1 extends uvm_component;
uvm_barrier b1;
`uvm_component_utils(comp1)
function new(string name, uvm_component parent);
super.new(name, parent);
endfunction
function void build_phase(uvm_phase phase);
super.build_phase(phase);
b1 = uvm_barrier_pool::get_global("b1");
endfunction
task run_phase(uvm_phase phase);
#10ns;
`uvm_info("BSYNC", $sformatf("c1 wait for b1 at %0t ps", $time), UVM_LOW)
b1.wait_for();
`uvm_info("BSYNC", $sformatf("c1 is activated at %0t ps", $time), UVM_LOW)
endtask
endclass
class comp2 extends uvm_component;
uvm_barrier b1;
`uvm_component_utils(comp2)
function new(string name, uvm_component parent);
super.new(name, parent);
endfunction
function void build_phase(uvm_phase phase);
super.build_phase(phase);
b1 = uvm_barrier_pool::get_global("b1");
endfunction
task run_phase(uvm_phase phase);
#20ns;
`uvm_info("BSYNC", $sformatf("c2 wait for b1 at %0t ps", $time), UVM_LOW)
b1.wait_for();
`uvm_info("BSYNC", $sformatf("c2 is activated at %0t ps", $time), UVM_LOW)
endtask
endclass
class env1 extends uvm_env;
comp1 c1;
comp2 c2;
uvm_barrier b1;
`uvm_component_utils(env1)
function new(string name, uvm_component parent);
super.new(name, parent);
endfunction
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_barrier_pool::get_global("b1");
endfunction: build_phase
task run_phase(uvm_phase phase);
b1.set_threshold(3);
`uvm_info("BSYNC", $sformatf("env set b1 threshold %d at %0t ps", b1.get_threshold(), $time), UVM_LOW)
#50ns;
b1.set_threshold(2);
`uvm_info("BSYNC", $sformatf("env set b1 threshold %d at %0t ps", b1.get_threshold(), $time), UVM_LOW)
endtask
endclass
class test1 extends uvm_test;
`uvm_component_utils(test1)
env1 env;
function new(string name, uvm_component parent);
super.new(name, parent);
endfunction
function void build_phase(uvm_phase phase);
env = env1::type_id::create("env", this);
endfunction
task run_phase(uvm_phase phase);
super.run_phase(phase);
phase.raise_objection(phase);
#1us;
phase.drop_objection(phase);
endtask
endclass
initial begin
run_test("test1");
end
endmodule
// UVM_INFO @ 0: reporter [RNTST] Running test test1...
// UVM_INFO @ 0: uvm_test_top.env [BSYNC] env set b1 threshold 3 at 0 ps
// UVM_INFO @ 10000: uvm_test_top.env.c1 [BSYNC] c1 wait for b1 at 10000 ps
// UVM_INFO @ 20000: uvm_test_top.env.c2 [BSYNC] c2 wait for b1 at 20000 ps
// UVM_INFO @ 50000: uvm_test_top.env [BSYNC] env set b1 threshold 2 at 50000 ps
// UVM_INFO @ 50000: uvm_test_top.env.c1 [BSYNC] c1 is activated at 50000 ps
// UVM_INFO @ 50000: uvm_test_top.env.c2 [BSYNC] c2 is activated at 50000 ps
uvm_callback
- 定义callback空壳函数,extends uvm_callback;
- 在使用cb 的 component中注册绑定`uvm_register_cb(comp,cb)
- 预留函数入口:`uvm_do_callbacks(comp,cb,function) ,cb中的function
- 在顶层例化cb,comp,在build_phase中关联绑定,uvm_callbacks #(comp) ::add(compxx,cbxx)。
module uvm_callback_sync;
import uvm_pkg::*;
`include "uvm_macros.svh"
class edata extends uvm_object;
int data;
`uvm_object_utils(edata)
function new(string name = "edata");
super.new(name);
endfunction
endclass
class cb1 extends uvm_callback;
`uvm_object_utils(cb1)
function new(string name = "cb1");
super.new(name);
endfunction
virtual function void do_trans(edata d);
d.data = 200;
`uvm_info("CB", $sformatf("cb1 executed with data %0d", d.data), UVM_LOW)
endfunction
endclass
class cb2 extends cb1;
`uvm_object_utils(cb2)
function new(string name = "cb2");
super.new(name);
endfunction
function void do_trans(edata d);
d.data = 300;
`uvm_info("CB", $sformatf("cb2 executed with data %0d", d.data), UVM_LOW)
endfunction
endclass
class comp1 extends uvm_component;
`uvm_component_utils(comp1)
`uvm_register_cb(comp1, cb1)
function new(string name, uvm_component parent);
super.new(name, parent);
endfunction
function void build_phase(uvm_phase phase);
super.build_phase(phase);
endfunction
task run_phase(uvm_phase phase);
edata d = new();
d.data = 100;
`uvm_info("RUN", $sformatf("proceeding data %0d", d.data), UVM_LOW)
`uvm_do_callbacks(comp1, cb1, do_trans(d))
endtask
endclass
class env1 extends uvm_env;
comp1 c1;
cb1 m_cb1;
cb2 m_cb2;
`uvm_component_utils(env1)
function new(string name, uvm_component parent);
super.new(name, parent);
m_cb1 = new("m_cb1");
m_cb2 = new("m_cb2");
endfunction
function void build_phase(uvm_phase phase);
super.build_phase(phase);
c1 = comp1::type_id::create("c1", this);
uvm_callbacks #(comp1)::add(c1, m_cb1);
uvm_callbacks #(comp1)::add(c1, m_cb2);
endfunction: build_phase
endclass
class test1 extends uvm_test;
`uvm_component_utils(test1)
env1 env;
function new(string name, uvm_component parent);
super.new(name, parent);
endfunction
function void build_phase(uvm_phase phase);
env = env1::type_id::create("env", this);
endfunction
task run_phase(uvm_phase phase);
super.run_phase(phase);
phase.raise_objection(phase);
#1us;
phase.drop_objection(phase);
endtask
endclass
initial begin
run_test("test1");
end
endmodule
// UVM_INFO @ 0: reporter [RNTST] Running test test1...
// UVM_INFO @ 0: uvm_test_top.env.c1 [RUN] proceeding data 100
// UVM_INFO @ 0: reporter [CB] cb1 executed with data 200
// UVM_INFO @ 0: reporter [CB] cb2 executed with data 300
sequence的通信时序
域的自动化声明