首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >UVM(九)之sequence机制续2

UVM(九)之sequence机制续2

作者头像
瓜大三哥
发布2018-02-26 14:42:28
2K0
发布2018-02-26 14:42:28
举报
文章被收录于专栏:瓜大三哥瓜大三哥

UVM(九)之sequence机制续2

1. 用事件做sequence之间的同步

到目前为止,sequence机制就是一个sequence启动之后对应一个sequencer,这个sequence发出transaction,sequencer把这个transaction转交给driver。

但是考虑这样一种情况,验证平台中有两个driver,这个连哥哥driver分别做不同的事情,第一个driver相当于一个CPU,它要在DUT刚启动的时候,配置DUT的寄存器,当它配置完成后,另外一个driver才能发激励。这种情况下在现实中是很常见的。一块DUT在上电复位后虽然其默认的参数就可以工作,但是大部分情况下,CPU还要对DUT做一些配置,这样才能DUT工作在我们期望的方式下。这个问题中,主要的就是一个同步的过程,一种很自然的想法就是把这个同步的过程使用一个event来完成:

之后,通过uvm_config_db的方式分别把两个sequence作为cpu_sequence和mac_sequence的default_sequence:

uvm_config_db#(uvm_objection_wrapper)::set(this,”env_sqr.main_phase”,”default_sequence”,cpu_seq::type_id::get());

uvm_config_db#(uvm_objection_wrapper)::set(this,”env_sqr.main_phase”,”default_sequence”,mac_seq::type_id::get());

当进入到main_phase时,这两个sequence会同步的启动,但是由于mac_seq要config_over事件的到来,所以它并不会马上产生transaction。而cpu_seq则会直接产生transaction,交给cpu_driver。当所有的配置工作完成后,config_over事件被触发,于是mac_seq开始产生transaction。

2. 复杂的同步:virtual sequence

上面的解决同步方法看起来非常的简单实用,不过这里有两个问题,第一个问题就是使用了一个全局的事件config_over。全局变量对于初写代码的人来说是非常受欢迎的,但是应该尽量避免使用全局变量的使用。

第二个问题是上面只是实现了一次同步,如果是有多次同步怎么办?如sequence A要先执行,之后是B,B完了才能是C,C完了才是D,这样显得很笨拙。

实现sequence之间同步的最好的方式就是使用virtual sequence。从字面上理解,虚拟的sequence。虚拟的意思就是它根本不发送transaction,它只是控制其他的sequence,起统一调度的作用。

如图所示,为了使用virtual sequence,一般的需要一个virtual sequencer。virtual sequencer里面包含指向其他实际sequencer的指针。

在test中,可以例化vsqr,并把相应的sequencer赋值给vsqr中的sequencer的指针。

3. 在sequence中慎用fork....join_none

假设DUT中有四个完全相同的MAC,那么相应的验证平台也要有4个完全相同的driver,sequencer。那么vsequencer就要这样定义:

当DUT上电复位,CPU把寄存器配置完成后,需要四个mac_driver同时发送数据,在vseq中可以使用fork来使四个driver同时发送数据:

这里使用了join_none,由于join_none的特性,系统并不等fork起来的进程结束就进入了下一次的fork循环,因此上面的for循环展开后如下:

现在我们要写一个新的sequence,他可以替代上面的两种包,可以这样写:

当sequence启动起来的时候,会自动执行这个sequence的body任务。当body任务完成的时候,那么这个sequence就相当于完成了其使命,已经结束了。如果使用fork...join_none,当使用uvm_do_on宏把四个mseq分别放在四个mac_sqr上执行时,系统会新启动4个进程,但是系统并不等待这4个mseq执行完毕就直接返回了。返回之后就到了endtask,此时系统认为这个sequence已经执行完成了。执行完成之后,系统会清理这个sequence之前占据的内存空间,杀死由其启动起来的进程,由于这4个启动起来的mseq还没有完成就直接被系统杀死掉了,也就是说,看似分别往4个mac_sqr分别丢了一个sequence,但是事实上这个sequence根本没有执行,这就是关键所在!

要避免这个问题可以使用wait fork或者fork....join

4. 在virtual sequence中控制验证平台的关闭

在sequence中使用starting_phase来控制验证平台的关闭。只有把此sequence作为sequencer的某动态运行phase的default_sequence时,其starting_phase才不为NULL。所以如果把某sequence作为uvm_do宏的参数,那么此sequence中的starting_phase是为null的。在此sequence中使用starting_phase.raise_objection是会产生问题。这个问题是比较容易解决的,只要把父sequence的starting_phase赋值给子sequence的starting_phase就可以了,这样只要最顶层的sequence的starting_phase不为null,那么下面所有由其启动的sequence的starting_phase也不为null。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2017-10-24,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 瓜大三哥 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档