UVM:2.4 UVM的终极大作sequence->2.4.2 sequence机制

177 篇文章 139 订阅

1.sequence不属于验证平台的任何一部分,出于比较特殊的位置:


1).transaction 像一颗单独的子弹,包含数据元素。

2).sequence 是transaction 的 ”序列“。

3).sequencer 是一把枪,负责发射。

4).sequencer是一个uvm_component,sequence 是一个uvm_object。

5).sequence 生命周期比my_transaction 要长,因为是”序列“嘛!


2.sequence 如下:

`ifndef MY_SEQUENCE__SV
`define MY_SEQUENCE__SV

class my_sequence extends uvm_sequence #(my_transaction);
   my_transaction m_trans;

   function new(string name= "my_sequence");
      super.new(name);
   endfunction

   virtual task body();
      repeat (10) begin
         `uvm_do(m_trans)
      end
      #1000;
   endtask

   `uvm_object_utils(my_sequence)
endclass
`endif
1)循环 10次,弄出一个序列。

2)要指定transaction 类型。

3)每一个sequence都有一个body 任务(main_phase 是属于components之类的),当一个sequence 启动之后,会自动执行body 的代码。

4)uvm_do 宏:1)创建一个my_transaction 的实例m_trans;2)将其随机化;3)最终送给sequencer。

5)如果不使用uvm_do 宏,可以直接使用start_item 与finish_item 产生transaction。


3.sequencer过程

1)一个sequence 再向sequencer发送请求前,要先向sequencer发送一个请求(只是个请求,不是真的transaction),sequencer把这个请求放在一个仲裁队列中。

2)sequencer做两件事:1)检验队列是否有sequence发送transaction的请求;2)检验driver是否申请transaction。

3)如果仲裁队列有请求,但driver没有申请transaction,那sequencer会一直等待driver。如果driver申请,sequencer 同意sequence的发送请求,sequence得到sequencer的批准后,产生transaction 交给sequencer,sequencer把这个transaction 交给driver。

4) 反正也一样:仲裁队列没请求,driver申请,那么一直等sequence。

5)如果两边同时,也一样。


4.driver 如何向sequencer 申请transaction呢?


1)在uvm_driver 中有变量seq_item_port:


2)在uvm_sequencer 中有变量seq_item_export:


在这两者中建立通道。


5.在my_agent中的connect 把两者连接到一起:

function void my_agent::connect_phase(uvm_phase phase);
   super.connect_phase(phase);
   if (is_active == UVM_ACTIVE) begin
      drv.seq_item_port.connect(sqr.seq_item_export);
   end
   ap = mon.ap;
endfunction

好像永远是port 主动连接export。


6.在driver中通过get_next_item 任务向sequencer 申请新的transaction:

task my_driver::main_phase(uvm_phase phase);
   vif.data <= 8'b0;
   vif.valid <= 1'b0;
   while(!vif.rst_n)
      @(posedge vif.clk);
   while(1) begin
      seq_item_port.get_next_item(req);
      drive_one_pkt(req);
      seq_item_port.item_done();
   end
endtask

1)因为driver负责驱动transaction,不负责生产,只要拿到transaction 就驱动,所以必须是无限循环while(1)。

2)item_done:当driver 使用get_next_item得到transaction 时,sequencer 自己也保留一份刚刚送出去的transaction。当sequencer 发出transaction,而driver 并没有得到时,sequencer会把保留的这份transaction在发送出去(这一过程和sequence无关)。

3)sequencer怎么知道driver 是否成功得到transaction 呢?在下次调用get_next_item 之前,item_done 被调用,sequencer认为driver已得到transaction,会把这个transaction删除。握手机制。


7.sequence中的uvm_do 什么时候返回呢?uvm_do产生一个transaction 后交给sequencer,driver区总这个transaction后,uvm_do不会立刻返回执行下一次uvm_do宏,一直等待,直到driver返回item_done 信号。此时,uvm_do才执行完毕返回,开始下一次uvm_do,产生新的transaction。

1)不是之前想的产生所有的10个后,一起交给sequencer。

2)占内存的应该只是sequence,sequencer 和 driver 都应该是指针取地址吧!!


8.虽然在driver的seq_item_port 中使用了get_next_item 和 item_done,但是我没在seq_item_port 中见到它们的定义。后来在sequencer 中找到了:


怎么实现的呢?

应该是my_agent的connect_phase。


9.sequence 如何向sequencer中送出transaction呢?前面已定义sequence,只要在某个component(如my_sequencer,my_env)的main_phase中启动sequence即可。另一侧的driver一直想sequencer取transaction,只要这边对接好就行,以my_env为例:

task my_env::main_phase(uvm_phase phase);
   my_sequence seq;
   phase.raise_objection(this);
   seq = my_sequence::type_id::create("seq");
   seq.start(i_agt.sqr); 
   phase.drop_objection(this);
endtask

1)首先创建。

2)然后调用start任务,参数是一个sequencer指针。

3)在UVMZ中,objection一般伴随着sequence,之前的driver中也是这样。


10.也可以在sequencer中启动sequence:

task my_sequencer::main_phase(uvm_phase phase);
   my_sequence seq;
   phase.raise_objection(this);
   seq = my_sequence::type_id::create("seq");
   seq.start(this); 
   phase.drop_objection(this);
endtask
start的参数变成了this。

11代码使用了get_next_item,还可以使用try_next_item。get_next_item 是阻塞的,它会一直等;try_next_item是非阻塞的,如果没有新的transaction,直接返回:

task my_driver::main_phase(uvm_phase phase);
   vif.data <= 8'b0;
   vif.valid <= 1'b0;
   while(!vif.rst_n)
      @(posedge vif.clk);
   while(1) begin
      seq_item_port.try_next_item(req);
      if(req == null)
         @(posedge vif.clk);
      else begin
         drive_one_pkt(req);
         seq_item_port.item_done();
      end
   end
endtask
 try_next_item更加接近真实driver 行为:有数据,就驱动,否则总线一直处于空闲状态。(不懂啊,就算get 阻塞住,也没对总线有影响。。????)

  • 4
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值