1、一条数据供应链
在uvm国家中,sequence是一个劳动者,他负责生产激励的原料(sequence item),sequencer是一个采购商,他负责从劳动者手中采购原料再卖给生产商driver,而driver收购到这些原料后,将他们加工生产成产品(数据),经过经销商(interface),出口到另一个国家(DUT)。
2、劳动者(sequence)和采购商(sequencer)之间的关系
sequence是一个劳动者,能获取的资源有限(不属于uvm树,无法获取uvm组件信息),他想把作物卖出去,就需要依附于(挂载)采购商(sequencer),间接和生产商(driver)进行交易。
劳动者(sequence)通过采购商(sequencer)将原料(sequence item)出售给生产商(driver)有两种方式:
1)、劳动者(sequence)依附:start()方法
劳动者(sequence)管理着这些原料(sequence item),采购商(sequencer)通过劳动者来间接获取这些原料。
sequenc通过start()方法依附sequencer:
//| start()方法中执行的方法
//| sub_seq.pre_start() (task)
//| sub_seq.pre_body() (task) if call_pre_post==1
//| parent_seq.pre_do(0) (task) if parent_sequence!=null
//| parent_seq.mid_do(this) (func) if parent_sequence!=null
//| sub_seq.body (task) YOUR STIMULUS CODE
//| parent_seq.post_do(this) (func) if parent_sequence!=null
//| sub_seq.post_body() (task) if call_pre_post==1
//| sub_seq.post_start() (task)
task uvm_sequence::start(uvm_sequencer_base sequencer, //要挂载的sequencer的句柄
uvm_sequence_base parent_sequence=null, //当前sequence的父sequence
int this_priority=-1, //当前sequence的优先级,-1则表示继承父类优先级,没有父类则设为100
bit call_pre_post=1); //为1表示在执行sequence的body()前后自动执行pre_body()和post_body()两个方法
set_item_context(parent_sequence, sequencer);
if (m_parent_sequence != null) begin
m_parent_sequence.children_array[this] = 1;
end
if (this_priority < 0) begin
if (parent_sequence == null) this_priority = 100;
else this_priority = parent_sequence.get_priority();
end
fork
pre_start();
if (call_pre_post == 1) begin
m_sequence_state = UVM_PRE_BODY;
#0;
pre_body();
end
if (parent_sequence != null) begin
parent_sequence.pre_do(0); // task
parent_sequence.mid_do(this); // function
end
body();
if (parent_sequence != null) begin
parent_sequence.post_do(this);
end
if (call_pre_post == 1) begin
m_sequence_state = UVM_POST_BODY;
#0;
post_body();
end
join
......
endtask
2)、原料(sequence item)托付:start_item()、finish_item()
sequence有时候嫌麻烦,就把原料(sequence item)直接托付给采购商(sequencer)管理。
相比于start()方法的一键式解决方案,将item()挂载到sequencer,需要用户的操作比较多,具体流程如下:
①、创建item,通过uvm_object::create()或者uvm_sequence::create_item()方法。
②、通过start_item()方法等待获得sequencer的授权许可,其后执行parent sequence的方法pre_do()。
task uvm_sequence::start_item(uvm_sequencer_item item,int set_priority=-1,uvm_sequencer_base sequencer=null);
uvm_sequence_base seq;
'void($cast(seq, item));
//若将item和其parent sequence挂载到不同的sequencer上,需要指定第三个参数sequencer。
//如果参数中没有指定sequencer,先从item中获取sequencer句柄
if (sequencer == null)
sequencer = item.get_sequencer();
//如果item中也没有指定sequencer,则从sequence中获取sequencer句柄
if (sequencer == null)
sequencer = get_sequencer();
item.set_item_context(this, sequencer);
if (set_priority < 0)
set_priority = get_priority();
sequencer.wait_for_grant(this, set_priority);
pre_do(1);
endtask
③、对item进行随机化处理。
④、通过finish_item()方法,执行parent sequence的mid_do(),以及调用uvm_sequencer::send_request()和uvm_sequencer::wait_for_item_done()来将item发送至sequencer,最后执行parent_sequence的post_do()。
task uvm_sequence::finish_item(uvm_sequence_item item,int set_priority=-1);
uvm_sequencer_base sequencer;
sequencer = item.get_sequencer();
mid_do(item);
sequencer.send_request(this, item);
sequencer.wait_for_item_done(this, -1);
post_do(item);
endtask
3)、先进的管理工具:宏
上面看到将原料(sequence item)托付给采购商(sequencer)管理,流程复杂,于是对托付管理流程进行了优化,实现了采购商(sequencer)对原料(item)的一键管理。
图片取自《芯片验证漫游指南》
宏除了可以用来发送item,也可以用来发送子sequence。