6.4 sequence进阶应用
前面提到了uvm_do系列宏既可以用在uvm_sequence_item上也可以用于uvm_sequence,所以sequence可以嵌套。
sequence中可以有rand成员,并且可以把rand成员和transaction的rand成员约束起来。
通过上面的约束,上层sequence里可以约束下层sequence里transaction的成员:
sequence的参数代表了它的req和rsp的uvm_sequence_item派生类的类名。如果需要发送不同uvm_sequence_item派生类的对象,那么需要把sequence、sequencer和driver参数声明成基类uvm_sequence_item。由于是基类,所以在driver中seq_item_port.get_next_item(req)的时候要做$cast转换. 因为sequence默认参数就是uvm_sequence_item,所以不用写。 6.4.3示例代码:
driver中的cast操作
实际的testbench中,很可能会在sequencer里加入一些成员变量,一般这种情况下要declare p_sequencer这个指针。用macro – uvm_declare_p_sequencer(sequencer类名) 在sequence中可以实现: 6.4.4章节示例
问题: p_sequencer的声明macro 是不是一直加着 ----直接写在base_sequence里比较好。
可以做一个base_sequence,需要p_sequencer的声明的话,写在base_sequence里,这样就不用每个sequence都声明p_sequencer指针了。
6.5 virtual sequence
virtual sequence (virtual sequencer)是特色。 如下图所示: 系统级环境里可能有多个env,带来了多个sequencer/sequence, 这样在case里不好维护。实现一个virtual sequencer,里面包括指向各个sequencer的指针;而virtual sequence就像前面介绍的“sequence嵌套”一样实现。
由于virtual sequencer里有实际sequencer的指针,所以肯定不能用“typedef uvm_sequncer….”来实现。 同时,由于virtual sequencer有成员了,所以在virtual sequence里要declare p_sequencer,并且指向virtual sequencer.
base_test的connect_phase函数中,要把virtual sequencer里的成员赋值到各个env的sqr上。---- 所以virtual sequencer和各个env是同级的
所谓“virtual”是说它本身不会发送transaction,所以virtual sequencer和virtual sequence都不用写transaction的参数(用了默认的参数)。 6.5.3章节示例代码
virtual sequence: 声明p_sequencer指针,注意uvm_do_on的sequencer参数
virtual sequencer 声明指针
base_test 在connect_phase中连接sequencer
case:设置virtual sequencer的main_phase的default_sequence为virtual sequence.
前面提到了objection的控制在sequence的body task中实现。现在引入了virtual sequence以后,objection的控制就移到顶层virtual sequence的body task中。
sequence中尽量不要用fork join_none,避免执行到endtask
虽然sequence不是component,但是也可以在sequence中使用uvm_config_db (类似于tp_tb中使用)。
在case中对sequence的成员用uvm_config_db#(类型)::set()的时候要注意: sequence由于是一个object,它的名字可能不确定,所以这里一般用通配符。而在sequence中get的时候,则使用uvm_root::get()/或者null和get_full_name(),作为前两个参数。