文章目录
1. sequence与sequencer
1.1 sequence和item发送实例
- top_seq这个顶层的seq中有两个底层的成分(挂载到top_seq)
- 一个是child_seq(是uvm_seq)即cseq,先创建后通过start发送;
- 另一个是bus_trans(是uvmseq_item)调用create_item创建、通过start_item发送,最后经过finish_item结束。
- 虽然child_seq在这里发送方式不同了,但是可以注意到在其class中的task body中,也是通过调用create_item创建、通过start_item发送,最后经过finish_item结束。
- start的方法解释后面有
- 在top_seq中需要根据发送成分类型决定发送方式,但是在driver中不需要区分
- 在driver中流过的最细小颗粒都是seq_item
1.2 sequence和item方法
- start_item只是获得授权,并不发送item。他的意义是若有多个seq挂载到同一个seqr,那么只有获得授权的seq才可以获得seqr的句柄,获得seqr方法使用权,从而发送item。
- finish_item中可以看到其所挂载的seqr的句柄,那么就可以调用其send_request和wait_for_item_done,这些都是uvm预定义的。
- 不关心pre_do/mid_do/post_do,免得变复杂。
- `uvm_do实际上也是调用了start_item/finish_item
- 该图中,初学者只关注seqr.方法
- 获取seqr授权,可以获得seqr句柄调用其方法
- 发送item
- 获取driver的item_done,结束一次item发送
1.3 发送序列的uvm宏
- 上表中的函数有一个前提,只有seq可以调用这些宏,默认seq调用这些宏挂载到该seq所在的seqr上
- 带x代表包括这个功能
- 可见一个完整的发送过程,`uvm_do就可实现
- `uvm_do可以发送item和seq
- 每次发送一个item会申请一次优先级
- uvm_do_on表示将当前的seq挂载到特定的seqr上面。
1.4 序列宏实例
- 相比本博文一开始的实例,本例子有2优势:
- 使用宏全面代替自带的方法,代码量更少。
- 不需要对发送item、seq做区分,宏会自动调用对应的方法
1.5 seqr的仲裁机制
- 默认仲裁机制是按照fifo的,以先后顺序来定。
- repeat(2),因此是发送两个item
- uvm_do_pri_with是拥有优先级的,如后面的500/300
- 注意uvm_do只有在seq中才可以调用,test中不行,test中必须用new、start
- 在0时刻,seqr获得了6个item。根据优先级决定哪个item先到driver中,若优先级一样,那就是交叉到达。
1.6 seqr的仲裁锁定
- 之前相同优先级的seq中item是交叉发送的,若锁定住,那一旦seq拿到权限后就可以一直发送item,直到发送完毕获得item_Done
- 这里的lock,grabs都是发3个item
- lock优先级是300,grab无须指定优先级,在某一时刻没人争得过。
- 这里@后面跟时间,单位是ps
- lock在10ns的时候也要拿权限,但是此时seq1/2也要发item,因为后者的优先级更高,所以先发送了之后lock才拿到权限。
- seq3和lock优先级相同,随机一个先
- 一旦lock获得了权限,锁定了seqr,那么每隔10ns都发送一次item
- 在20ns时候,grab就想获得权限,但是已经被lock锁定了,所以只能等,等到lock释放,grab获取
- lock必须遵照优先级获得权限,grab在同一时刻,是至高优先级。
2. sequencer的层次化
2.1 概述
2.2 hseq
- 两个seq的body中都使用了同一个bus_trans,那么以为这他们会挂载到同一个seqr上面
- vseq和hseq的相同点是他们都可以有多个底层的seq
- 不同点在于vseq中的seq,vseq可以将他们挂载到不同的seqr上;hseq将他们挂载到同一个seqr上。
2.3 vseqr
- vseqr中包含着很多seqr的句柄,起到路由的作用。
- vseq可以找到vseqr
- 这里normal_seq就是vseq,可见其中包括了很多其他的seq句柄
- m_sequencer的类型是uvm_sequencer_base。这意味着如果你有自己的sequencer,并且你已经在sequencer中定义了新的属性,那么你不能通过m_sequencer访问它们,因为它不知道它们。现在p_sequencer开始显示威力了。
- m_seqr类型是uvm_sequencer_base,是预定义好的;p_seqr不是预定义好的,是`uvm_declare_p_sequencer定义的。
- `uvm_declare_p_sequencer有两个任务:
- 定义了p_seqr,是mcdf_virtual_sequencer类型
- 将m_seqr这个父类句柄转换为了p_seqr这个子类句柄
- 父类句柄m_seqr、子类句柄p_seqr都指向了vseqr这个实例,但是父类句柄无法访问子类的成员变量(这些成员就是各个其他seqr),因此必须要做句柄转换。如此,我们通过p_seqr这个子类句柄就可以访问到vseqr实例中所有成员变量了(也就是vseqr包括各个seqr的句柄,vseqr的路由特性就在此)。
- uvm_do_on往往伴随vseqr一起用,指明参数1中seq挂载到参数2中的哪一个seqr中
- 可见vseqr中包括了多个seqr,下面的env中定义、创建了多个agent句柄,以及vseqr
- 在env中的connect_phase中将vseqr中各个seqr和agent中各个seqr连接,避免句柄悬空
- 在test1中的run_phase,定义了vseq句柄,mcdf_normal_seq就是vseq,通过seq_start(e.virt_sqr)挂载到了vseqr上面
- 再次重申,类似uvm_do的宏只能在seq中使用。这里test中只能new和start。