目录

  • sequence的启动与执行
  • 仲裁机制
    • 在同一sequencer上启动多个sequence
    • lock操作与grab操作
      • lock
      • grab
    • sequence的有效性
  • 相关宏及其实现

sequence的启动与执行

  • 完成sequence的定义后,使用start将其启动:
my_sequence my_seq;
my_seq = my_sequence::type_id::create("my_seq");
my_seq.start(sequencer);
  • 除了直接启动之外,还可以使用default_sequence启动,有两种调用方式:
uvm_config_db#(uvm_object_wrapper)::set(this,"env.i_agt.sqr.main_phase","default_sequence",case0_sequence::type_id::get());

另外一种方式是先实例化要启动的sequence,再通过default_sequence启动:

function void my_case0::build_phase(uvm_phase phase);case0_sequence cseq;super.build_phase(phase);cseq = new("cseq");uvm_config_db#(uvm_sequence_base)::set(this,"env.i_agt.sqr.main_phase","default_sequence",cseq);
endfunction

当一个sequence启动后会自动执行其body task,也就是具体定义激励产生的位置。

仲裁机制

在同一sequencer上启动多个sequence

当在同一sequencer上启动多个sequence时,便涉及到了sequence的优先级问题,可以通过uvm_do_pri及uvm_do_pri_with改变sequence所产生的transaction的优先级:

class sequence0 extends uvm_sequence #(my_transaction);
…virtual task body();
…repeat (5) begin`uvm_do_pri(m_trans, 100)`uvm_info("sequence0", "send one transaction", UVM_MEDIUM)end#100;
…endtask
…
endclassclass sequence1 extends uvm_sequence #(my_transaction);
…virtual task body();
…repeat (5) begin`uvm_do_pri_with(m_trans, 200, {m_trans.pload.size < 500;})`uvm_info("sequence1", "send one transaction", UVM_MEDIUM)end
…endtask
…
endclass

uvm_do_pri与uvm_do_pri_with的第二个参数是优先级,这个数值必须是一个大于等于-1的整数。数字越大,优先级越高。
sequencer的仲裁算法以下几种:

  • SEQ_ARB_FIFO:它会严格遵循先入先出的顺序,而不会考虑优先级,这也是sequencer的默认仲裁算法。
  • SEQ_ARB_WEIGHTED是加权的仲裁。
  • SEQ_ARB_RANDOM是完全随机选择。
  • SEQ_ARB_STRICT_FIFO是严格按照优先级的。当有多个同一优先级的sequence时,按照先入先出的顺序选择。
  • SEQ_ARB_STRICT_RANDOM是严格按照优先级的,当有多个同一优先级的sequence时,随机从最高优先级中选择。
  • SEQ_ARB_USER则是用户可以自定义一种新的仲裁算法。

若想使上述两个sequence的优先级起作用,应该设置仲裁算法为SEQ_ARB_STRICT_FIFO或者SEQ_ARB_STRICT_RANDOM:

task my_case0::main_phase(uvm_phase phase);
…env.i_agt.sqr.set_arbitration(SEQ_ARB_STRICT_FIFO);forkseq0.start(env.i_agt.sqr);seq1.start(env.i_agt.sqr);join
endtask

除transaction有优先级外,sequence也有优先级的概念。可以在sequence启动时指定其优先级:

task my_case0::main_phase(uvm_phase phase);
…env.i_agt.sqr.set_arbitration(SEQ_ARB_STRICT_FIFO);forkseq0.start(env.i_agt.sqr, null, 100);seq1.start(env.i_agt.sqr, null, 200);join
endtask

start任务的第一个参数是sequencer,第二个参数是parent sequence,可以设置为null,第三个参数是优先级,如果不指定则此值为-1,它同样不能设置为一个小于-1的数字。
即使不使用uvm_do_pri与uvm_do_pri_with宏中指定transaction的优先级,直接运行上述代码也可以达到目的,所以,对sequence设置优先级的本质即设置其内产生的transaction的优先级。

lock操作与grab操作

lock

sequence向sequencer发送一个请求,这个请求与其他sequence发送transaction的请求一同被放入sequencer的仲裁队列中。当其前面的所有请求被处理完毕后,sequencer就开始响应这个lock请求,此后sequencer会一直连续发送此sequence的transaction,直到unlock操作被调用。
一个使用lock操作的sequence为:

class sequence1 extends uvm_sequence #(my_transaction);
…virtual task body();
…repeat (3) begin`uvm_do_with(m_trans, {m_trans.pload.size < 500;})`uvm_info("sequence1", "send one transaction", UVM_MEDIUM)endlock();`uvm_info("sequence1", "locked the sequencer ", UVM_MEDIUM)repeat (4) begin`uvm_do_with(m_trans, {m_trans.pload.size < 500;})`uvm_info("sequence1", "send one transaction", UVM_MEDIUM)end`uvm_info("sequence1", "unlocked the sequencer ", UVM_MEDIUM)unlock();repeat (3) begin`uvm_do_with(m_trans, {m_trans.pload.size < 500;})`uvm_info("sequence1", "send one transaction", UVM_MEDIUM)end
…endtask
…
endclass

将此sequence1与其他sequence在env.i_agt.sqr上启动,会发现在lock语句前,其它sequence和seuquence1交替产生transaction;在lock语句后,一直发送sequence1的transaction,直到unlock语句被调用后,其他sequence和seuquence1又开始交替产生transaction。

如果两个sequence都试图使用lock任务来获取sequencer的所有权则,则先获得所有权的sequence在执行完毕后才会将所有权交还给另外一个sequence。

grab

与lock操作一样,grab操作也用于暂时拥有sequencer的所有权,只是grab操作比lock操作优先级更高。lock请求是被插入sequencer仲裁队列的最后面,等到它时,它前面的仲裁请求都已经结束了。grab请求则被放入sequencer仲裁队列的最前面,它几乎是一发出就拥有了sequencer的所有权:

class sequence1 extends uvm_sequence #(my_transaction);
…virtual task body();
…repeat (3) begin`uvm_do_with(m_trans, {m_trans.pload.size < 500;})`uvm_info("sequence1", "send one transaction", UVM_MEDIUM)endgrab();`uvm_info("sequence1", "grab the sequencer ", UVM_MEDIUM)repeat (4) begin`uvm_do_with(m_trans, {m_trans.pload.size < 500;})`uvm_info("sequence1", "send one transaction", UVM_MEDIUM)end`uvm_info("sequence1", "ungrab the sequencer ", UVM_MEDIUM)ungrab();repeat (3) begin`uvm_do_with(m_trans, {m_trans.pload.size < 500;})`uvm_info("sequence1", "send one transaction", UVM_MEDIUM)end
…endtask`uvm_object_utils(sequence1)
endclass
  • 如果两个sequence同时试图使用grab任务获取sequencer的所有权,则在先获得所有权的sequence执行完毕后才会将所有权交还给另外一个试图所有权的sequence。
  • 如果一个sequence在使用grab任务获取sequencer的所有权前,另外一个sequence已经使用lock任务获得了sequencer的所有权,grab任务则会一直等待lock的释放。

sequence的有效性

通过lock任务和grab任务,sequence可以独占sequencer,强行使sequencer发送自己产生的transaction。同样的,UVM也提供措施使sequence可以在一定时间内不参与仲裁,即令此sequence失效。

  • sequencer在仲裁时,会查看sequence的is_relevant函数的返回结果。如果为1,说明此sequence有效,否则无效。因此可以通过重载is_relevant函数来使sequence失效:
class sequence0 extends uvm_sequence #(my_transaction);my_transaction m_trans;int num;bit has_delayed;
…virtual function bit is_relevant();if((num >= 3)&&(!has_delayed)) return 0;else return 1;endfunctionvirtual task body();forkrepeat (10) beginnum++;`uvm_do(m_trans)`uvm_info("sequence0", "send one transaction", UVM_MEDIUM)endwhile(1) beginif(!has_delayed) beginif(num >= 3) begin`uvm_info("sequence0", "begin to delay", UVM_MEDIUM)#500000;has_delayed = 1'b1;`uvm_info("sequence0", "end delay", UVM_MEDIUM)break;endelse#1000;endendjoin
…endtask
…
endclass

通过设置is_relevant,可以使sequence主动放弃sequencer的使用权,而grab任务和lock任务则强占sequencer的所有权。

  • 除了is_relevant外,sequence中还有一个任务wait_for_relevant也与sequence的有效性相关:
class sequence0 extends uvm_sequence #(my_transaction);
…virtual function bit is_relevant();if((num >= 3)&&(!has_delayed)) return 0;else return 1;endfunctionvirtual task wait_for_relevant();#10000;has_delayed = 1;endtaskvirtual task body();
…repeat (10) beginnum++;`uvm_do(m_trans)`uvm_info("sequence0", "send one transaction", UVM_MEDIUM)end
…endtask
…
endclass

当sequencer发现在其上启动的所有sequence都无效时,此时会调用wait_for_relevant并等待sequence变有效。

is_relevant与wait_for_relevant一般应成对重载,不能只重载其中的一个。

相关宏及其实现

  • uvm_do系列宏

uvm_do_on:用于显式地指定使用哪个sequencer发送此transaction。它有两个参数,第一个是transaction的指针,第二个是sequencer的指针。当在sequence中使用uvm_do等宏时,其默认的sequencer就是此sequence启动时为其指定的sequencer,sequence将这个sequencer的指针放在其成员变量m_sequencer中。事实上,uvm_do等价于:

`uvm_do_on(tr, this.m_sequencer)

uvm_do_on_pri:它有三个参数,第一个参数是transaction的指针,第二个是sequencer的指针,第三个是优先级:

`uvm_do_on(tr, this, 100)

uvm_do_on_with:它有三个参数,第一个参数是transaction的指针,第二个是sequencer的指针,第三个是约束:

`uvm_do_on_with(tr, this, {tr.pload.size == 100;})

uvm_do_on_pri_with:它有四个参数,是所有uvm_do宏中参数最多的一个。第一个参数是transaction的指针,第二个是sequencer的指针,第三个是优先级,第四个是约束:

`uvm_do_on_pri_with(tr, this, 100, {tr.pload.size == 100;})

uvm_do系列的其他七个宏其实都是用uvm_do_on_pri_with宏来实现的。如uvm_do宏:

`define uvm_do(SEQ_OR_ITEM) \`uvm_do_on_pri_with(SEQ_OR_ITEM, m_sequencer, -1, {})
  • uvm_create与uvm_send

除了使用uvm_do宏产生transaction,还可以使用uvm_create宏与uvm_send宏来产生:

class case0_sequence extends uvm_sequence #(my_transaction);
…virtual task body();int num = 0;int p_sz;
…repeat (10) beginnum++;`uvm_create(m_trans)assert(m_trans.randomize());p_sz = m_trans.pload.size();{m_trans.pload[p_sz - 4],m_trans.pload[p_sz - 3],m_trans.pload[p_sz - 2],m_trans.pload[p_sz - 1]}= num;`uvm_send(m_trans)end
…endtask
…
endclass

uvm_create宏的作用是实例化transaction。当一个transaction被实例化后,可以对其做更多的处理,处理完毕后使用uvm_send宏发送出去。这种使用方式比uvm_do系列宏更加灵活。如在上例中,就将pload的最后4个byte替换为此transaction的序号。

也可以使用uvm_send_pri宏将transaction交给sequencer时设定优先级:

virtual task body();
…m_trans = new("m_trans");assert(m_trans.randomize());p_sz = m_trans.pload.size();{m_trans.pload[p_sz - 4],m_trans.pload[p_sz - 3],m_trans.pload[p_sz - 2],m_trans.pload[p_sz - 1]}= num;`uvm_send_pri(m_trans, 200)
…
endtask
  • uvm_rand_send系列宏

uvm_rand_send宏与uvm_send宏类似,唯一的区别是它会对transaction进行随机化。这个宏使用的前提是transaction已经被分配了空间,换言之,即已经实例化了:

m_trans = new("m_trans");
`uvm_rand_send(m_trans)

uvm_rand_send_pri宏:用于指定transaction的优先级。它有两个参数,第一个是transaction的指针,第二个是优先级:

m_trans = new("m_trans");
`uvm_rand_send_pri(m_trans, 100)

uvm_rand_send_with宏:用于指定使用随机化时的约束,它有两个参数,第一个是transaction的指针,第二个是约束:

m_trans = new("m_trans");
`uvm_rand_send_with(m_trans, {m_trans.pload.size == 100;})

uvm_rand_send_pri_with宏:用于指定优先级和约束,它有三个参数,第一个是transaction的指针,第二个是优先级,第三个是约束:

m_trans = new("m_trans");
`uvm_rand_send_pri_with(m_trans, 100, {m_trans.pload.size == 100;})

uvm_rand_send系列宏及uvm_send系列宏的意义主要在于,如果一个transaction占用的内存比较大,那么很可能希望前后两次发送的transaction都使用同一块内存,只是其中的内容可以不同,这样比较节省内存。

  • start_item与finish_item

在使用宏来产生transaction时,实际上是隐藏了start_item和finish_item这两个task, uvm_do系列宏其实是将下述动作封装在了一个宏中:

virtual task body();
…tr = new("tr");start_item(tr);assert(tr.randomize() with {tr.pload.size() == 200;});finish_item(tr);
…
endtask
  • pre_do、mid_do与post_do
    uvm_do宏封装了从transaction实例化到发送的一系列操作,封装的越多,则其灵活性越差。为了增加uvm_do系列宏的功能,UVM提供了三个接口:pre_do、mid_do与post_do。

    • pre_do是一个task,在start_item中被调用,它是start_item返回前执行的最后一行代码,在它执行完毕后才对transaction进行随机化。
    • mid_do是一个function,位于finish_item的最开始。在执行完此函数后,finish_item才进行其他操作。
    • post_do也是一个function,也位于finish_item中,它是finish_item返回前执行的最后一行代码。它们的执行顺序大致为:
sequencer.wait_for_grant(prior) (task) \ start_item \
parent_seq.pre_do(1)            (task) /              \`uvm_do* macros
parent_seq.mid_do(item)         (func) \              /
sequencer.send_request(item)    (func)  \finish_item /
sequencer.wait_for_item_done()  (task)  /
parent_seq.post_do(item)        (func) /

这三个接口function/task的使用示例如下:

class case0_sequence extends uvm_sequence #(my_transaction);my_transaction m_trans;int num;
…virtual task pre_do(bit is_item);#100;`uvm_info("sequence0", "this is pre_do", UVM_MEDIUM)endtaskvirtual function void mid_do(uvm_sequence_item this_item);my_transaction tr;int p_sz;`uvm_info("sequence0", "this is mid_do", UVM_MEDIUM)void'($cast(tr, this_item));p_sz = tr.pload.size();{tr.pload[p_sz - 4],tr.pload[p_sz - 3],tr.pload[p_sz - 2],tr.pload[p_sz - 1]} = num;tr.crc = tr.calc_crc();tr.print();endfunctionvirtual function void post_do(uvm_sequence_item this_item);`uvm_info("sequence0", "this is post_do", UVM_MEDIUM)endfunctionvirtual task body();repeat (10) beginnum++;`uvm_do(m_trans)end
…endtask
…
endclass

pre_do有一个参数,此参数用于表明uvm_do宏是在对一个transaction还是在对一个sequence进行操作。mid_do和post_do的两个参数是正在操作的sequence或者item的指针,但是其类型是uvm_sequence_item类型。通过cast可以转换成目标类型(示例中为my_transaction)。

sequence基础相关推荐

  1. mysql怎么用sequence_mysql实现sequence功能的代码

    mysql实现sequence功能 1.建立sequence记录表 CREATE TABLE `sys_sequence` ( `seq_name` varchar(50) CHARACTER SET ...

  2. UVM中的sequence

    sequence基础 1. 如果将激励放在driver的main_phase中,是可行的,但是如果要对激励作修改,那么扩展性较差,所以我们将激励改为放在sequence中去写. driver就负责驱动 ...

  3. 2020-12-11 keras通过model.fit_generator训练模型(节省内存)

    keras通过model.fit_generator训练模型(节省内存) 前言 前段时间在训练模型的时候,发现当训练集的数量过大,并且输入的图片维度过大时,很容易就超内存了,举个简单例子,如果我们有2 ...

  4. Swift 里集合类型协议的关系

      Sequence A type that provides sequential, iterated access to its elements. 是最基础的协议,可以通过迭代来获取它的元素 ...

  5. 自然语言处理--keras实现一维卷积网络对IMDB 电影评论数据集构建情感分类器

    为什么在 NLP 分类任务中选择 CNN 呢? 1.CNN神经网络可以像处理图像一样处理文本并"理解"它们 2.主要好处是高效率 3.在许多方面,由于池化层和卷积核大小所造成的限制 ...

  6. 电商的1000+篇文章总结

    电商的1000+篇文章总结 本文收集和总结了有关电商的1000+篇文章,由于篇幅有限只能总结近期的内容,想了解更多内容可以访问:http://www.ai2news.com/, 其分享了有关AI的论文 ...

  7. POJ题目分类(按初级\中级\高级等分类,有助于大家根据个人情况学习)

    本文来自:http://www.cppblog.com/snowshine09/archive/2011/08/02/152272.spx 多版本的POJ分类 流传最广的一种分类: 初期: 一.基本算 ...

  8. UE4 Sequence添加基础动画效果 (03-主序列的使用)

    在上一篇的基础上添加一些摄像头的跟拍效果 效果: 步骤: 1.鼠标右键新建 Animation->关卡序列 命名为主序列 2.双击打开主序列 3.点击 窗口->内容浏览器->内容浏览 ...

  9. UVM基础-Sequence、Sequencer(二)

    目录 sequence和sequencer 将sequence挂载到sequencer 将item挂载到sequencer 宏定义使用实例 sequencer仲裁特性 实例 sequencer的锁定机 ...

最新文章

  1. android 固定底部导航,Android如何实现底部菜单固定到底部
  2. Java实现数据序列化工具Avro的例子
  3. 上元节的灯会(灭)-区间dp
  4. Java扫描仪toString()方法及示例
  5. 关于Zookeeper的几个问题
  6. JavaScript逻辑运算符“”和“||”短路原则的应用
  7. 漫画让你秒懂5G黑科技....
  8. 什么是 Stack Overflow,什么情况下会造成 Stack Overflow
  9. TechWeb祝大家新年快乐!愿你心有光亮 自予光芒!
  10. combox数据过滤 wpf_- - WPF:筛选ItemCollection的ComboBox也会筛选绑定到同一ComboBoxes的其他ItemsSource_c#_酷徒编程知识库...
  11. SharePoint And Ajax Technology(2):Ajax Control Toolkit学习
  12. linux批量分区,Linux磁盘批量分区格式化和挂载脚本
  13. idea使用jrebel热部署插件
  14. 最常见的12道计算机基础面试题
  15. cat /proc/cpuinfo命令详解
  16. linux网络电视软件sopcast的安装
  17. 32位qt程序, 利用32位mysql驱动,连接64位mysql8.0
  18. 前端工程师如何提升能力 提高效率有哪些方法
  19. Ray-分布式的SGD
  20. GMSSL :SM2椭圆曲线公钥密码算法-密钥交换协议

热门文章

  1. 设备管理 设备管理概述
  2. 第58届日本红白歌会印象记
  3. mysql bitmap位图索引_Oracle位图索引(Bitmap Index)
  4. 解决:You have 18 unapplied migration(s). Your project may not work properly until you apply
  5. 【Linux】Linux根目录下各个目录的含义
  6. FastJson 配置
  7. 关于H.264 x264 h264 AVC1之间的那些事
  8. string substitution
  9. Java 校验EMAIL格式方法,真为正确
  10. bug解决-Vue中img图片加载失败解决方案