为长期问题道歉。我有一个测试平台设置,通过一个音序器发送大约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关联数组的一部分存在。我错过了什么?