[UVM]put_response () 如何从seq_item_port调用到sequencer的put(t) method

可结合 uvm_do分析 来看此文章~~

好了,开始正题~~~

 

driver:

     seq_item_port.get_next_item(req);

     $cast(rsp,req.clone());

     drive_one_pkt(req); 

     rsp.set_id_info(req);//回response 一定要加上这句!!!

     seq_item_port.put(rsp);

     seq_item_port.item_done();

 -------------------------------------------------------------------------------------------------

     Q: uvm_driver中get()与get_next_item()的区别

     A: get()中调用了item_done(), 而get_next_item没有;

 ------------------------------------------------------------------------------------------------

class uvm_driver #(type REQ=uvm_sequence_item,
                   type RSP=REQ) extends uvm_component;

  uvm_seq_item_pull_port #(REQ, RSP) seq_item_port;

  uvm_seq_item_pull_port #(REQ, RSP) seq_item_prod_if; // alias

  uvm_analysis_port #(RSP) rsp_port;

  REQ req;
  RSP rsp;


  function new (string name, uvm_component parent);
    super.new(name, parent);
    seq_item_port    = new("sqr_pull_port", this);
    rsp_port         = new("rsp_port", this);
    seq_item_prod_if = seq_item_port;

  endfunction // new

 ------------------------------------------------------------------------------------------------

在agent中将调用driver.seq_item_port.connect(sequencer.seq_item_export)将两个port连接

这样,driver中seq_item_port.put(rsp)实际是调用seq_item_export的put函数。

 ------------------------------------------------------------------------------------------------

sequencer: 

    //通过在seq_item_export new时获取sequencer的handle

    class uvm_sequencer #(type REQ=uvm_sequence_item, RSP=REQ)
                                   extends uvm_sequencer_param_base #(REQ, RSP);

          typedef uvm_sequencer #( REQ , RSP) this_type;
          bit sequence_item_requested;
          bit get_next_item_called;


          `uvm_component_param_utils(this_type)

           uvm_seq_item_pull_imp #(REQ, RSP, this_type) seq_item_export;

           function new (string name, uvm_component parent=null);
              super.new(name, parent);
              seq_item_export = new ("seq_item_export", this);

           endfunction

     endclass

   ------------------------------------------------------------------------------------------------

    class uvm_seq_item_pull_imp #(type REQ=int, type RSP=REQ, type IMP=int)
       extends uvm_port_base #(uvm_sqr_if_base #(REQ, RSP));
        // Function: new
       `UVM_IMP_COMMON(`UVM_SEQ_ITEM_PULL_MASK, "uvm_seq_item_pull_imp",IMP)
       `UVM_SEQ_ITEM_PULL_IMP(m_imp, REQ, RSP, t, t)

   endclass

------------------------------------------------------------------------------------------------

`define UVM_IMP_COMMON(MASK,TYPE_NAME,IMP) \
  local IMP m_imp; \
  function new (string name, IMP imp); \
    super.new (name, imp, UVM_IMPLEMENTATION, 1, 1); \
    m_imp = imp; \
    m_if_mask = MASK; \
  endfunction \

  `UVM_TLM_GET_TYPE_NAME(TYPE_NAME)

------------------------------------------------------------------------------------------------

`define UVM_SEQ_ITEM_PULL_IMP(imp, REQ, RSP, req_arg, rsp_arg) \
  task get_next_item(output REQ req_arg); imp.get_next_item(req_arg); endtask \
  task try_next_item(output REQ req_arg); imp.try_next_item(req_arg); endtask \
  function void item_done(input RSP rsp_arg = null); imp.item_done(rsp_arg); endfunction \
  task wait_for_sequences(); imp.wait_for_sequences(); endtask \
  function bit has_do_available(); return imp.has_do_available(); endfunction \
  function void put_response(input RSP rsp_arg); imp.put_response(rsp_arg); endfunction \
  task get(output REQ req_arg); imp.get(req_arg); endtask \
  task peek(output REQ req_arg); imp.peek(req_arg); endtask \

  task put(input RSP rsp_arg); imp.put(rsp_arg); endtask

------------------------------------------------------------------------------------------------

task uvm_sequencer :: put (RSP t);
    put_response(t);

endtask

------------------------------------------------------------------------------------------------

function void uvm_sequencer_param_base :: put_response (RSP t);
  uvm_sequence_base sequence_ptr;
  
  if (t == null) begin
    uvm_report_fatal("SQRPUT", "Driver put a null response", UVM_NONE);
  end

  m_last_rsp_push_front(t);
  m_num_rsps_received++;


  // Check that set_id_info was called
  if (t.get_sequence_id() == -1) begin
  `ifndef CDNS_NO_SQR_CHK_SEQ_ID
      uvm_report_fatal("SQRPUT", "Driver put a response with null sequence_id", UVM_NONE);
  `endif
    return;
  end
    
  sequence_ptr = m_find_sequence(t.get_sequence_id());  

  if (sequence_ptr != null) begin
    // If the response_handler is enabled for this sequence, then call the response handler
    if (sequence_ptr.get_use_response_handler() == 1) begin
      sequence_ptr.response_handler(t);
      return;
    end
    
    sequence_ptr.put_response(t);
  end
  else begin
    uvm_report_info("Sequencer", 
    $sformatf("Dropping response for sequence %0d, sequence not found.  Probable cause: sequence      exited or has been killed", 
     t.get_sequence_id()));
  end

endfunction

------------------------------------------------------------------------------------------------

//在driver 中调用 set_id_info 设置当前transaction的transaction id 和 sequence id;

  function void set_id_info(uvm_sequence_item item);
    if (item == null) begin
      uvm_report_fatal(get_full_name(), "set_id_info called with null parameter", UVM_NONE);
    end

    this.set_transaction_id(item.get_transaction_id());
    this.set_sequence_id(item.get_sequence_id());

  endfunction

------------------------------------------------------------------------------------------------

//sequence 向sequencer发出请求时(wait_for_granted task),通过调用set_sequence_id找到當前sequence 的sequence id。

在finish_item中通過調用send_request為當前transaction設定transaction_id.

 

function void uvm_sequencer_param_base :: send_request(uvm_sequence_base sequence_ptr,
                                                     uvm_sequence_item t,
                                                     bit rerandomize = 0);
  REQ param_t;


  if (sequence_ptr == null) begin
    uvm_report_fatal("SNDREQ", "Send request sequence_ptr is null", UVM_NONE);
  end


  if (sequence_ptr.m_wait_for_grant_semaphore < 1) begin
    uvm_report_fatal("SNDREQ", "Send request called without wait_for_grant", UVM_NONE);
  end
  sequence_ptr.m_wait_for_grant_semaphore--;

  
  if ($cast(param_t, t)) begin
    if (rerandomize == 1) begin
      if (!param_t.randomize()) begin
        uvm_report_warning("SQRSNDREQ", "Failed to rerandomize sequence item in send_request");
      end
    end
    if (param_t.get_transaction_id() == -1) begin
      param_t.set_transaction_id(sequence_ptr.m_next_transaction_id++);
    end
    m_last_req_push_front(param_t);
  end else begin
    uvm_report_fatal(get_name(),$sformatf("send_request failed to cast sequence item"), UVM_NONE);
  end


  param_t.set_sequence_id(sequence_ptr.m_get_sqr_sequence_id(m_sequencer_id, 1));
  t.set_sequencer(this);
  if (m_req_fifo.try_put(param_t) != 1) begin
    uvm_report_fatal(get_full_name(), 
                     $sformatf("Sequencer send_request not able to put to fifo, depth; %0d", m_req_fifo.size()), UVM_NONE);
  end


  m_num_reqs_sent++;
  // Grant any locks as soon as possible
  grant_queued_locks();

endfunction

 

------------------------------------------------------------------------------------------------

function void set_sequence_id(int id);// from uvm_sequence_item
    m_sequence_id = id;

endfunction

------------------------------------------------------------------------------------------------

  function int get_sequence_id();
      return (m_sequence_id);
  endfunction

  • 7
    点赞
  • 39
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值