OVM序列项未被仲裁

时间:2018-02-16 23:06:14

标签: system-verilog methodology uvm

为长期问题道歉。我有一个测试平台设置,通过一个音序器发送大约15000个序列项,但每次我这样做,对于大约第12000个序列项,任务wait_for_arbitration_completed卡住了。我覆盖了本地sequencer中的所有任务,wait_for_arbitration_completed任务就像这样

对于附加到此序列器的所有序列项调用此任务,并且每次授予序列项时,序列器都会设置此arb_completed关联数组并递增m_lock_arb_size数。在此之后,每个未完成的request_id的所有任务都会唤醒,并检查该请求ID是否已完成并从任务返回。对于一个种子,对于请求ID为12015,即使在arb_completed数组中设置了特定的请求id,显示语句“从这个大的等待......”也不会发生,并且序列发生器被卡住了。以前有人遇到过这个吗?我做错事吗?每个音序器是否有最大数量的序列项?谢谢

驱动程序和音序器片段

class my_driver extends ovm_driver #(my_seq_item);
...
    forever begin
        seq_item_port.try_next_item(req);
        if(req != null) begin
            drive_item(req); // Here is the physical protocol
            seq_item_port.item_done();
        end
        else
            @(vif.driver_cb);
    end
endclass : my_driver

class my_sequencer extends ovm_sequencer #(my_seq_item);
....
   virtual task try_next_item(output REQ t);
    int selected_sequence;
    time arb_time;
    ovm_sequence_base seq;

    if (get_next_item_called == 1) begin
      ovm_report_error(get_full_name(), "get_next_item/try_next_item called twice without item_done or get in between", OVM_NONE);
      return;
    end

    wait_for_sequences();
    selected_sequence = choose_next_request();
    if (selected_sequence == -1) begin
      t = null;
      return;
    end
    set_arbitration_completed(arb_sequence_q[selected_sequence].request_id);
    seq = arb_sequence_q[selected_sequence].sequence_ptr;
    $display("Selected request_id is %0d\n", arb_sequence_q[selected_sequence].request_id);
    arb_sequence_q.delete(selected_sequence);
    $display("m_lock_arb_size value before updating the list is %0d\n", m_lock_arb_size);
    m_update_lists();
    $display("m_lock_arb_size value after updating the list is %0d\n", m_lock_arb_size);
    sequence_item_requested = 1;
    get_next_item_called = 1;
    m_req_fifo.peek(t);
    $display("Successfully peeked into the m_req_fifo\n");
    wait_for_sequences();

    // attempt to get the item; if it fails, produce an error and return
    if (!m_req_fifo.try_peek(t))
      ovm_report_error("TRY_NEXT_BLOCKED", {"try_next_item: the selected sequence '",
        seq.get_full_name(), "' did not produce an item during wait_for_sequences(). ",
        "Sequences should not consume time between calls to start_item and finish_item. ",
        "Returning null item."}, OVM_NONE);

   endtask

   virtual task wait_for_grant(ovm_sequence_base sequence_ptr, int item_priority = -1, bit lock_request = 0);
    seq_req_class req_s;
    int my_seq_id;

    if (sequence_ptr == null) begin
      ovm_report_fatal("ovm_sequencer", "wait_for_grant passed null sequence_ptr", OVM_NONE);
    end

    // Determine the number of drivers connected to this sequencer
    if(m_seq_item_port_connect_size < 0) begin
      m_seq_item_port_connect_size = m_find_number_driver_connections();
    end

`ifndef CDNS_NO_SQR_CON_CHK
    // If there are no drivers, then it is not possible to wait for grant
    if(m_seq_item_port_connect_size == 0) begin
      ovm_report_fatal("SQRWFG", "Wait_for_grant called on sequencer with no driver connected", OVM_NONE);
    end
`endif

    my_seq_id = register_sequence(sequence_ptr);

    // If lock_request is asserted, then issue a lock.  Don't wait for the response, since
    // there is a request immediately following the lock request
    if (lock_request == 1) begin
      req_s = new();
      req_s.grant = 0;
      req_s.sequence_id = my_seq_id;
      req_s.request = SEQ_TYPE_LOCK;
      req_s.sequence_ptr = sequence_ptr;
      req_s.request_id = req_s.g_request_id++;
      arb_sequence_q.push_back(req_s);
    end // lock_request == 1

    // Push the request onto the queue
    req_s = new();
    req_s.grant = 0;
    req_s.request = SEQ_TYPE_REQ;
    req_s.sequence_id = my_seq_id;
    req_s.item_priority = item_priority;
    req_s.sequence_ptr = sequence_ptr;
    req_s.request_id = req_s.g_request_id++;
    arb_sequence_q.push_back(req_s);
    m_update_lists();


    // Wait until this entry is granted
    // Continue to point to the element, since location in queue will change
    $display("waiting for arbitration for request id %0d\n", req_s.request_id);
    wait_for_arbitration_completed(req_s.request_id);
    $display("Arbitration completed for request id %0d\n", req_s.request_id);

    // The wait_for_grant_semaphore is used only to check that send_request
    // is only called after wait_for_grant.  This is not a complete check, since
    // requests might be done in parallel, but it will catch basic errors
    req_s.sequence_ptr.m_wait_for_grant_semaphore++;

  endtask // wait_for_grant

  task wait_for_arbitration_completed(int request_id);
    int lock_arb_size;

    // Search the list of arb_wait_q, see if this item is done
    forever
      begin
        lock_arb_size  = m_lock_arb_size;

        if (arb_completed.exists(request_id)) begin
          $display("Finally completed request_id of %0d lock_arb_size is %0d and m_lock_arb_size is %0d\n", request_id, lock_arb_size, m_lock_arb_size);
          arb_completed.delete(request_id);
          return;
        end
        else begin
          $display("Still not completed request_id %0d lock_arb_size is %0d and m_lock_arb_size is %0d\n", request_id, lock_arb_size, m_lock_arb_size);
        end
        wait (lock_arb_size != m_lock_arb_size);

        $display("Came out of this big wait request_id of %0d lock_arb_size %0d and m_lock_arb_size is %0d\n", request_id, lock_arb_size, m_lock_arb_size);
      end
  endtask // wait_for_arbitration_completed
endclass : my_sequencer

my_sequencer任务是从ovm_sequencer中盲目复制的,只为调试添加display语句。 request_id 12015在大约200us(假设)处启动,并且在400us左右被仲裁,此时该request_id的控制将等待仲裁(在等待语句中)。仲裁序列项后,调用update_lists()来增加m_arb_lock_size,并且控制器应该从wait语句中退出并从任务返回,但是wait_语句后面的显示永远不会为request_id 12015打印,因此下一个sequence_items被阻止。在DVE中,我看到12015作为arb_completed关联数组的一部分存在。我错过了什么?

0 个答案:

没有答案