📄 ovm_sequencer_base.svh
字号:
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 /////////////////////////////////// if (arbitration == SEQ_ARB_WEIGHTED) begin sum_priority_val = 0; for (i = 0; i < avail_sequences.size(); i++) begin sum_priority_val += get_seq_item_priority(arb_sequence_q[avail_sequences[i]]); end // Pick an available sequence based on weighted priorities of available sequences temp = $urandom_range(sum_priority_val-1, 0); sum_priority_val = 0; for (i = 0; i < avail_sequences.size(); i++) begin if ((get_seq_item_priority(arb_sequence_q[avail_sequences[i]]) + sum_priority_val) > temp) begin return (avail_sequences[i]); end sum_priority_val += get_seq_item_priority(arb_sequence_q[avail_sequences[i]]); end ovm_report_fatal("Sequencer", "OVM Internal error in weighted arbitration code"); end // if (arbitration == SEQ_ARB_WEIGHTED) /////////////////////////////////// // Random Distribution /////////////////////////////////// if (arbitration == SEQ_ARB_RANDOM) begin i = $urandom_range(avail_sequences.size()-1, 0); return (avail_sequences[i]); end /////////////////////////////////// // Strict Fifo /////////////////////////////////// if ((arbitration == SEQ_ARB_STRICT_FIFO) || 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 (get_seq_item_priority(arb_sequence_q[avail_sequences[i]]) > highest_pri) begin // New highest priority, so start new list `ovm_clear_queue(highest_sequences) highest_sequences.push_back(i); highest_pri = get_seq_item_priority(arb_sequence_q[avail_sequences[i]]); end else if (get_seq_item_priority(arb_sequence_q[avail_sequences[i]]) == highest_pri) begin highest_sequences.push_back(i); end end // Now choose one based on arbitration type if (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 ((arbitration == SEQ_ARB_STRICT_FIFO) || arbitration == SEQ_ARB_STRICT_RANDOM) if (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 ovm_report_fatal("Sequencer", $psprintf("Error in User arbitration, sequence %0d not available\n%s", i, display_queues())); end return(i); end ovm_report_fatal("Sequencer", "Internal error: Failed to choose sequence"); endfunction // int protected task m_wait_arb_not_equal(); wait (m_arb_size != m_lock_arb_size); endtask // m_wait_arb_not_equal protected task wait_for_available_sequence(); integer i; integer is_relevant_entries[$]; // This routine will wait for a change in the request list, or for // wait_for_relevant to return on any non-relevant, non-blocked sequence m_arb_size = m_lock_arb_size; for (i = 0; i < arb_sequence_q.size(); i++) begin if (arb_sequence_q[i].request == SEQ_TYPE_REQ) begin if (is_blocked(arb_sequence_q[i].sequence_ptr) == 0) begin if (arb_sequence_q[i].sequence_ptr.is_relevant() == 0) begin is_relevant_entries.push_back(i); end end end end // Typical path - don't need fork if all queued entries are relevant if (is_relevant_entries.size() == 0) begin m_wait_arb_not_equal(); return; end fork // isolate inner fork block for disabling begin fork begin fork // One path in fork is for any wait_for_relevant to return for(i = 0; i < is_relevant_entries.size(); i++) begin fork begin arb_sequence_q[is_relevant_entries[i]].sequence_ptr.wait_for_relevant(); end join_any end // The other path in the fork is for any queue entry to change begin m_wait_arb_not_equal(); end join_any end join_any disable fork; end // fork join endtask // wait_for_available_sequence protected function integer get_seq_item_priority(seq_req_class seq_q_entry); // If the priority was set on the item, then that is used if (seq_q_entry.item_priority != -1) begin return (seq_q_entry.item_priority); end // Otherwise, use the priority of the calling sequence return (seq_q_entry.sequence_ptr.get_priority()); endfunction /////////////////////////////////////////////////// // // arbitration completed tasks // Used to tell the wait_for_grant function when // a new arbitration is available /////////////////////////////////////////////////// task wait_for_arbitration_completed(integer 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 arb_completed.delete(request_id); return; end wait (lock_arb_size != m_lock_arb_size); end endtask // wait_for_arbitration_completed function void set_arbitration_completed(integer request_id); arb_completed[request_id] = 1; endfunction // void/////////////////////////////////////////////////////// is_child// Determine if a scenario is a child of a parent///////////////////////////////////////////////////function bit is_child (ovm_sequence_base parent, ovm_sequence_base child); ovm_sequence_base sequence_ptr; if (child == null) begin ovm_report_fatal("ovm_sequencer", "is_child passed null child"); end if (parent == null) begin ovm_report_fatal("ovm_sequencer", "is_child passed null parent"); end sequence_ptr = child.get_parent_sequence(); while (sequence_ptr != null) begin if (sequence_ptr.m_get_sqr_sequence_id(m_sequencer_id, 0) == (parent.m_get_sqr_sequence_id(m_sequencer_id, 0))) begin return (1); end sequence_ptr = sequence_ptr.get_parent_sequence(); end return (0);endfunction // bit /////////////////////////////////////////////////// // // Methods available to Sequences // /////////////////////////////////////////////////// task wait_for_grant(ovm_sequence_base sequence_ptr, integer item_priority = -1, bit lock_request = 0); seq_req_class req_s; integer my_seq_id; if (sequence_ptr == null) begin ovm_report_fatal("ovm_sequencer", "wait_for_grant passed null sequence_ptr"); end 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 = sequence_ptr.get_sequence_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 wait_for_arbitration_completed(req_s.request_id); endtask // wait_for_grant task wait_for_item_done(ovm_sequence_base sequence_ptr, integer transaction_id); integer sequence_id; sequence_id = sequence_ptr.m_get_sqr_sequence_id(m_sequencer_id, 1); m_wait_for_item_sequence_id = -1; m_wait_for_item_transaction_id = -1; if (transaction_id == -1) begin wait (m_wait_for_item_sequence_id == sequence_id); end else begin wait ((m_wait_for_item_sequence_id == sequence_id && m_wait_for_item_transaction_id == transaction_id)); end endtask // wait_for_item_done/////////////////////////////////////////////////////// function bit is_blocked(ovm_sequence_base sequence_ptr);//// is_blocked will return 1 if the sequence refered to in the parameter// is currently locked out of the sequencer. It will return 0 if the// sequence is currently allowed to issue operations//// Note that even when a sequence is not blocked, it is possible// for another sequence to issue a lock before this sequence is able// to issue a request or lock///////////////////////////////////////////////////// function bit is_blocked(ovm_sequence_base sequence_ptr); if (sequence_ptr == null) ovm_report_fatal("ovm_sequence_controller", "is_blocked passed null sequence_ptr"); foreach (lock_list[i]) begin if ((lock_list[i].m_get_sqr_sequence_id(m_sequencer_id, 0) != sequence_ptr.m_get_sqr_sequence_id(m_sequencer_id, 0)) && (is_child(lock_list[i], sequence_ptr) == 0)) begin return (1); end end return (0);endfunction ///////////////////////////////////////////////////////// function bit is_locked(ovm_sequence_base sequence_ptr);//// is_locked returns 1 if the sequence refered to in the parameter// currently has a lock on this sequencer. It will return 0 if the// sequence does not currently have a lock.// // Note that even if this sequence has a lock, a child sequence may// also have a lock, in which case the sequence is still blocked from// issueing operations on the sequencer///////////////////////////////////////////////////// function bit is_locked(ovm_sequence_base sequence_ptr); integer my_seq_id; if (sequence_ptr == null) ovm_report_fatal("ovm_sequence_controller", "is_locked passed null sequence_ptr"); my_seq_id = register_sequence(sequence_ptr); foreach (lock_list[i]) begin if (lock_list[i].m_get_sqr_sequence_id(m_sequencer_id, 0) == sequence_ptr.m_get_sqr_sequence_id(m_sequencer_id, 0)) begin return (1); end end return (0);endfunction // bit/////////////////////////////////////////////////////// lock_req// Internal Call by a sequence to request a lock. Puts// the lock request onto the arbitration queue
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -