第九段:Virtual_sequencer的调用(二次更新)

 

 

初版内容:

     1)基础用法:

     在virtual_sequencer中将各个env的sequencer包括进来,同时base_test在connect_phase中将各个env放入指针中,在case在main_phase中设置default_sequence,让其进入phase时自启动。

     平常的uvm的object的控制放到sequence的body中实现,引入virtual sequencer后,则将其放入顶层的virtual sequence的body中,而且注意fork join_none的使用,避免提前运行结束。

     虽然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(),作为前两个参数。

     在sequence中可以对testbench中的component的成员使用uvm_config_db#(类型)::set(),同样因为路径的问题,第一个参数一般是null或者uvm_root::get()

     2)项目升级用法:与上一致;

     3)底层原理分析:

     为了解决sequence同步,之前是使用send_over全局变量解决,而vir_sequencer按顺序启动,无需刻意同步。此外config中只需调用一次,就可以将对应的sequence和sequencer匹配上。Object的raise和drop只需在vir_sequence中即可。

     virtual sequence本质也就是一个sequence,我们就叫它virtual sequence好了。它里面声明了不同的sequence,把普通sequence的一次create再start的过程做了很多次。同时声明一个virtual sequencer的句柄,再start函数中将自己肚子里不同的sequence跟virtual sequencer句柄联系起来。如果要用普通的sequence类方法来实现生产多个sequence的效果,就需要搞一个新sequence子类,拓展自旧sequence,这种事情搞多了容易混。所以用virtual sequence会方便一点,核心就是在类里搞了个vitual 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 sequencervirtual sequence都不用写transaction的参数(用了默认的参数)。

二次更新:

     1.virtual sequence本质也就是一个sequence,我们就叫它virtual sequence好了。它里面声明了不同的sequence,把普通sequence的一次create再start的过程做了很多次。同时声明一个virtual sequencer的句柄,再start函数中将自己肚子里不同的sequence跟virtual sequencer句柄联系起来。

     (如果要用普通的sequence类方法来实现生产多个sequence的效果,就需要搞一个新sequence子类,拓展自旧sequence,这种事情搞多了容易混。所以用virtual sequence会方便一点,核心就是在类里搞了个vitual sequencer句柄。)

class my_virtual_seq extends uvm_sequence;
    `uvm_object_utils (my_virtual_seq)
    `uvm_declare_p_sequencer (my_virtual_sequencer)
 
    function new (string name = "my_virtual_seq");
      super.new (name);
    endfunction
 
    apb_rd_wr_seq   m_apb_rd_wr_seq;
    wb_reset_seq   m_wb_reset_seq;
    pcie_gen_seq   m_pcie_gen_seq;
 
    task pre_body();
      m_apb_rd_wr_seq = apb_rd_wr_seq::type_id::create ("m_apb_rd_wr_seq");
      m_wb_reset_seq  = wb_reset_seq::type_id::create ("m_wb_reset_seq");
      m_pcie_gen_seq  = pcie_gen_seq::type_id::create ("m_pcie_gen_seq");
    endtask
 
    task body();
      ...
      m_apb_rd_wr_seq.start (p_sequencer.m_apb_seqr);
      fork
        m_wb_reset_seq.start (p_sequencer.m_wb_seqr);
        m_pcie_gen_seq.start (p_sequencer.m_pcie_seqr);
      join 
      ...
    endtask
  endclass

    2.在agent中create一个virtual sequencer,这个东西本质还是sequencer。我们在virtual sequencer里面声明不同的sequencer,在与driver相连的时候就通过virtual sequencer来着手对应相连。(这里其实就是套个套子)

class my_virtual_sequencer extends uvm_sequencer;
    `uvm_component_utils (my_virtual_sequencer)
 
    function new (string name = "my_virtual_sequencer", uvm_component parent);
      super.new (name, parent);
    endfunction
 
    // Declare handles to other sequencers here
    apb_sequencer       m_apb_seqr;
    reg_sequencer       m_reg_seqr;
    wb_sequencer        m_wb_seqr;
    pcie_sequencer      m_pcie_seqr;
  endclass
class top_env extends uvm_env;
    ...
 
    my_virtual_sequencer   m_virt_seqr;
 
    virtual function void build_phase (uvm_phase phase);
      ...
      m_virt_seqr = my_virtual_sequencer::type_id::create ("m_virt_seqr", this);
      ...
    endfunction
 
    // Connect virtual sequencer handles to actual sequencers
    virtual function void connect_phase (uvm_phase phase);
      ...
      m_virt_seqr.m_apb_seqr   = m_apb_agent.m_apb_seqr;
      m_virt_seqr.m_reg_seqr   = m_reg_env.m_reg_seqr;
      m_virt_seqr.m_pcie_seqr  = m_pcie_env.m_pcie_agent.m_pcie_seqr;
      ...
    endfunction
  endclass

    3.在test中的run_phase中create出多个sequence,然后通过第1步里声明的virtual sequencer句柄来使用start函数。

(说白了还是就套个套,图个方便统一管理吧)

class my_test extends uvm_test;
    `uvm_component_utils (my_test)

    my_env   m_env;

    task run_phase (uvm_phase phase);
      my_virtual_seq m_vseq = my_virtual_seq::type_id::create ("m_vseq");
      phase.raise_objection (this);
      m_vseq.start (m_env.m_virtual_seqr);
      phase.drop_objection (this);
    endtask
  endclass

    暂时写到这,以后持续补充。

  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

爱吃辣椒的年糕

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值