[UVM]driver与sequencer的交互

上次文章写道uvm_do macro,主要涉及sequence与sequencer的交互,这次讲driver与sequencer的交互。

在driver中会调用sequencer的task get_next_item,其主要包括task m_select_sequence

task uvm_sequencer::get_next_item(output REQ t);
  REQ req_item;

  // If a sequence_item has already been requested, then get_next_item()
  // should not be called again until item_done() has been called.

  if (get_next_item_called == 1)
    uvm_report_error(get_full_name(),
      "Get_next_item called twice without item_done or get in between", UVM_NONE);
  
  if (!sequence_item_requested)
    m_select_sequence();

  // Set flag indicating that the item has been requested to ensure that item_done or get
  // is called between requests
  sequence_item_requested = 1;
  get_next_item_called = 1;
  m_req_fifo.peek(t);//在finish_item中send_request把request item放入m_req_fifo中,在item_done中pop出
endtask
task uvm_sequencer_base::m_select_sequence();
   int selected_sequence;

    // Select a sequence
    do begin
      wait_for_sequences();
      selected_sequence = m_choose_next_request();
      if (selected_sequence == -1) begin
        m_wait_for_available_sequence();
      end
    end while (selected_sequence == -1);
    // issue grant
    if (selected_sequence >= 0) begin
      m_set_arbitration_completed(arb_sequence_q[selected_sequence].request_id);
      arb_sequence_q.delete(selected_sequence);
      m_update_lists();
    end
endtask

此task 的核心是m_choose_next_request,用于选择合适的request,主要根据指定优先级,lock,grab等方式进行选择

function int uvm_sequencer_base::m_choose_next_request();
  int i, temp;
  int avail_sequence_count;
  int sum_priority_val;
  integer avail_sequences[$];
  integer highest_sequences[$];
  int highest_pri;
  string  s;

  avail_sequence_count = 0;

  grant_queued_locks();

  for (i = 0; i < arb_sequence_q.size(); i++) begin

    if((arb_sequence_q[i].process_id.status == process::KILLED)||
       (arb_sequence_q[i].process_id.status == process::FINISHED))begin
      `uvm_error("SEQREQZMB",$sformatf("The task reponsible for requesting a wait_for_grant on sequencer '%s' for sequence '%s' has been killed,to avoid a deadlock the sequence will be removed from the arbitration queues",this,get_full_name(),arb_sequence_q[i].sequence_ptr.get_full_name))
     
      remove_sequence_from_queues(arb_sequence_q[i].sequence_ptr);
      continue;
    end

    // Search for available sequences.  If in SEQ_ARB_FIFO arbitration,
    // then just return the first available sequence.  Otherwise,
    // create a list for arbitration purposes.
    if (i < arb_sequence_q.size())
      if (arb_sequence_q[i].request == SEQ_TYPE_REQ)
        if (is_blocked(arb_sequence_q[i].sequence_ptr) == 0)
          if (arb_sequence_q[i].sequence_ptr.is_relevant() == 1) begin
            if (m_arbitration == SEQ_ARB_FIFO) begin
              return i;
            end
            else avail_sequences.push_back(i);
          end
  end

  // Return immediately if there are 0 or 1 available sequences
  if (m_arbitration == SEQ_ARB_FIFO) begin
    return -1;
  end
  if (avail_sequences.size() < 1)  begin
    return -1;
  end
  
  if (avail_sequences.size() == 1) begin
    return avail_sequences[0];
  end
  
  // If any locks are in place, then the available queue must
  // be checked to see if a lock prevents any sequence from proceeding
  if (lock_list.size() > 0) begin
    for (i = 0; i < avail_sequences.size(); i++) begin
      if (is_blocked(arb_sequence_q[avail_sequences[i]].sequence_ptr) != 0) begin
        avail_sequences.delete(i);
        i--;
      end
    end
    if (avail_sequences.size() < 1)
      return -1;
    if (avail_sequences.size() == 1)
      return avail_sequences[0];
  end

  //  Weighted Priority Distribution
  // Pick an available sequence based on weighted priorities of available sequences
  if (m_arbitration == SEQ_ARB_WEIGHTED) begin
    sum_priority_val = 0;
    for (i = 0; i < avail_sequences.size(); i++) begin
      sum_priority_val += m_get_seq_item_priority(arb_sequence_q[avail_sequences[i]]);
    end
    
    temp = $urandom_range(sum_priority_val-1, 0);

    sum_priority_val = 0;
    for (i = 0; i < avail_sequences.size(); i++) begin
      if ((m_get_seq_item_priority(arb_sequence_q[avail_sequences[i]]) + 
           sum_priority_val) > temp) begin
        return avail_sequences[i];
      end
      sum_priority_val += m_get_seq_item_priority(arb_sequence_q[avail_sequences[i]]);
    end
    uvm_report_fatal("Sequencer", "UVM Internal error in weighted arbitration code", UVM_NONE);
  end
  
  //  Random Distribution
  if (m_arbitration == SEQ_ARB_RANDOM) begin
    i = $urandom_range(avail_sequences.size()-1, 0);
    return avail_sequences[i];
  end

  //  Strict Fifo
  if ((m_arbitration == SEQ_ARB_STRICT_FIFO) || m_arbitration == SEQ_ARB_STRICT_RANDOM) begin
    highest_pri = 0;
    // Build a list of sequences at the highest priority
    for (i = 0; i < avail_sequences.size(); i++) begin
      if (m_get_seq_item_priority(arb_sequence_q[avail_sequences[i]]) > highest_pri) begin
        // New highest priority, so start new list
        highest_sequences.delete();
        highest_sequences.push_back(avail_sequences[i]);
        highest_pri = m_get_seq_item_priority(arb_sequence_q[avail_sequences[i]]);
      end
      else if (m_get_seq_item_priority(arb_sequence_q[avail_sequences[i]]) == highest_pri) begin
        highest_sequences.push_back(avail_sequences[i]);
      end
    end

    // Now choose one based on arbitration type
    if (m_arbitration == SEQ_ARB_STRICT_FIFO) begin
      return(highest_sequences[0]);
    end
    
    i = $urandom_range(highest_sequences.size()-1, 0);
    return highest_sequences[i];
  end

  if (m_arbitration == SEQ_ARB_USER) begin
    i = user_priority_arbitration( avail_sequences);

    // Check that the returned sequence is in the list of available sequences.  Failure to
    // use an available sequence will cause highly unpredictable results.
    highest_sequences = avail_sequences.find with (item == i);
    if (highest_sequences.size() == 0) begin
      uvm_report_fatal("Sequencer",
          $sformatf("Error in User arbitration, sequence %0d not available\n%s",
                    i, convert2string()), UVM_NONE);
    end
    return(i);
  end
    
  uvm_report_fatal("Sequencer", "Internal error: Failed to choose sequence", UVM_NONE);

endfunction

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值