virtual seq和virtual sqr是比较难理解的两个东西
一直以来,对virtual sequence和virtual sequencer的理解都不是很到位,看了很多资料,也做过项目,还是有些不是很透彻。拿“笔”记录下来,梳理的过程有可能会加深理解。后面会持续学习并补充更新。
什么时候需要virtual seq和virtual sqr?
-
如果只有一个驱动端agent,显然是不需要使用virtual sequencer的。
-
如果有多的驱动端agent,但是多个激励之间并无协调关系,virtual sequencer 也并无必要。
-
如果有多的驱动端agent,而且多个激励之间存在协调关系,那么virtual sequencer就很有必要了。这个时候环境中需要包含一个甚至多个virtual sequencer了。
virtual sequence 和virtual sequencer的“virtual”有何含义呢?
Virtual sequencer 有三个属性:
-
Virtual sequencer 控制其他的sequencer
-
Virtual sequencer并不和任何driver相连
-
Virtual sequencer本身并不处理item
并不像正常的sequencer那样,将sequence item 通过sequencer port传递给driver。
Virtual sequencer 通过一个指向subsequencer目标的句柄来指定sequence。这里的subsequencer就是和driver相连接的真实sequencer。所谓的virtual 就是指真正的sequence并不是在Virtual sequencer里产生和传递的。一个virtual sequencer 可以通过它的subsequencer产生许多种不同类型的tranction。
而virtual sequence 的作用就是在协调不同的subsequencer中sequence的执行秩序了。
如何实现一个virtual sequencer?
上面的例子是virtual sequencer的典型结构,设定的名字是vsequencer。
Virtual sequencer派生自UVM_sequencer,而不是uvm_virtual_sequencer(当然,并没有这个类)。
virtual sequencer 与其他普通的sequencer最显著的区别就在于,virtual sequencer 并没有指定具体的tranction类型,因为virtual sequencer会执行多种类型的tranction。这里派生时未指定参数,意味着virtual sequencer会使用uvm_sequence_item的默认参数值。
将virtual sequencer连接到subsequencers上
要连接一个virtual sequencer和它的subsequencers,需要在验证环境的connect_phase将sequencer的实例赋值给virtual sequencer中指定的sequencer指针。
v_sequencer.cpu_seqr = cpu_seqr; v_sequencer.eth_seqr = eth_seqr
下面这个例子显示了一个top-level environment,它实例化了ethernet和cpu验证组件以及控制这两个组件的virtual sequencer。
如何实现一个virtual sequence?
virtual sequence是用来实现sequence之间的同步。从字面上理解,即虚拟的sequence。虚拟的意思就是它根本就不发送transaction,它只是控制其他的sequence,起统一调度的作用。
如下图所示,为了使用virtual sequence,一般需要一个virtual sequencer。virtual sequencer里面包含指向其他真实sequencer的指针:
在base_test中,实例化vsqr,并将相应的sequencer赋值给vsqr中的sequencer的指针:
在virtual sequence中则可以使用uvm_do_on系统宏来发送transaction,uvm_do_on用于显式地指定使用哪个sequencer发送此transaction,它有两个参数,第一个是transaction的指针,第二个sequencer的指针。virtual sequence是uvm_do_on宏用得最多地方(P175-P176)
在使用uvm_do_on宏的情况下,虽然seq0是在case0_vseq中启动,但是它最终会被交给p_sequencer.p_sqr0,也即env0.i_agt.sqr而不是v_sqr。这个就是virtual sequence和virtual sequencer中virtual的来源。它们各自并不产生transaction,而只是控制其他的sequence为相应的sequencer产生transaction。virtual sequence和virtual sequencer只是起一个调度作用。由于根本不直接产生transaction,所以virtual sequence和virtual sequencer在定义时根本无需指明要发送的transaction数据类型。
virtual sequence的使用可以减少config_db语句的使用。virtual sequence作为一种特殊的sequence,也可以在其中启动其他的virtual sequence。
另外一个需要注意的是最好只在最顶层的virtual sequence中控制objection。因为virtual sequence是起统一调度作用的,这种统一调度不只体现在transaction上,也应该体现在objection的控制上。
要创建一个virtual sequence:
- 从uvm_sequence派生出一个sequence类。
- 定义一个body()方法。
- 使用`uvm_ do_on(或` uvm_do_on_with)宏来调用subsequencers的sequences。
- 使用`uvm_do(或`uvm_do_with)宏来调用当前virtual sequencer中的其他virtual sequences。
一个virtual sequence不能使用`uvm_do或`uvm_do_with来执行数据项的发送,只能执行sequences。
上面的例子显示了一个简单的virtual sequence调用两个subsequencers的sequence。