📄 ovm_sequencer_base.svh
字号:
//----------------------------------------------------------------------// Copyright 2007-2008 Mentor Graphics Corporation// Copyright 2007-2008 Cadence Design Systems, Inc.// All Rights Reserved Worldwide//// Licensed under the Apache License, Version 2.0 (the// "License"); you may not use this file except in// compliance with the License. You may obtain a copy of// the License at//// http://www.apache.org/licenses/LICENSE-2.0//// Unless required by applicable law or agreed to in// writing, software distributed under the License is// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR// CONDITIONS OF ANY KIND, either express or implied. See// the License for the specific language governing// permissions and limitations under the License.//----------------------------------------------------------------------typedef class ovm_sequencer_base;typedef enum {SEQ_TYPE_REQ, SEQ_TYPE_LOCK, SEQ_TYPE_GRAB} SEQ_REQ_TYPE;typedef enum {SEQ_ARB_FIFO, SEQ_ARB_WEIGHTED, SEQ_ARB_RANDOM, SEQ_ARB_STRICT_FIFO, SEQ_ARB_STRICT_RANDOM, SEQ_ARB_USER} SEQ_ARB_TYPE;class seq_req_class; static integer g_request_id = 0; bit grant; integer sequence_id; integer request_id; integer item_priority; SEQ_REQ_TYPE request; ovm_sequence_base sequence_ptr; function new(string name= ""); endfunctionendclass class ovm_sequencer_base extends ovm_component; protected seq_req_class arb_sequence_q[$]; // The arb_completed associative array is used to indicate when a particular request_id // has been completed. The array in indexed by request_id, and sequences will wait based // on the request_id assigned in the arb_sequence_q protected bit arb_completed[integer]; protected ovm_sequence_base lock_list[$]; local SEQ_ARB_TYPE arbitration = SEQ_ARB_FIFO; local ovm_sequence_base reg_sequences[integer]; local static integer g_sequence_id = 1; local static integer g_sequencer_id = 1; protected integer m_sequencer_id; protected integer m_lock_arb_size; // used for waiting processes protected integer m_arb_size; // used for waiting processes protected integer m_wait_for_item_sequence_id, m_wait_for_item_transaction_id; integer unsigned pound_zero_count = 4; ///// Copied from ovm_sequencer //set main and random sequence count variable if != -1 //also accessed by ovm_main/random_sequence integer count = -1; // testing fields integer m_random_count = 0; integer m_exhaustive_count = 0; integer m_simple_count = 0; //user settable property to limit main/random subsequences //also accessed by ovm_main/random_sequence integer unsigned max_random_count = 10; //Used for setting the maximum depth inside random sequences. //(Beyond that depth, random creates only simple sequences.) int unsigned max_random_depth = 4; // This property defines which sequence will be auto-started (default=main). protected string default_sequence = "ovm_random_sequence"; // The sequeunce aray holds the type names of the sequence types registered // to this sequencer; the factory will actually create the instances on demand. string sequences[$]; // The ids array associates each sequence entry (above) with an integer // number. This allows sequences to be randomly selected by randomizing // a number between 0 and the sequences array size. protected integer sequence_ids[string]; // variable used to randomly select a sequence from the sequences array protected rand integer seq_kind;///// End of Copied from ovm_sequencer /////////////////////////////////////////////////// function new (string name, ovm_component parent); super.new(name, parent); void'(get_config_string("default_sequence", default_sequence)); void'(get_config_int("count", count)); void'(get_config_int("max_random_count", max_random_count)); void'(get_config_int("max_random_depth", max_random_depth)); void'(get_config_int("pound_zero_count", pound_zero_count)); m_sequencer_id = g_sequencer_id++; m_lock_arb_size = -1; endfunction // new function void do_print (ovm_printer printer); super.do_print(printer); if(sequences.size() != 0) begin printer.print_string("default_sequence", default_sequence); printer.print_field("count", count, $bits(count), OVM_DEC); printer.print_field("max_random_count", max_random_count, $bits(max_random_count), OVM_DEC); printer.print_array_header("sequences", sequences.size()); for(int i=0; i<sequences.size(); ++i) printer.print_string($psprintf("[%0d]", i), sequences[i], "["); printer.print_array_footer(); printer.print_field("max_random_depth", max_random_depth, $bits(max_random_depth), OVM_DEC); end endfunction /////////////////////////////////////////////////// // // Local functions // /////////////////////////////////////////////////// protected function void m_update_lists(); m_lock_arb_size++; endfunction // void function string display_queues(); string s; $sformat(s, " -- arb i/id/type: "); foreach (arb_sequence_q[i]) begin $sformat(s, "%s %0d/%0d/%s ", s, i, arb_sequence_q[i].sequence_id, arb_sequence_q[i].request); end // UNMATCHED !! $sformat(s, "%s\n -- lock_list i/id: ", s); foreach (lock_list[i]) begin $sformat(s, "%s %0d/%0d",s, i, lock_list[i].get_sequence_id()); end // UNMATCHED !! return(s); endfunction // string local function integer next_sequence_id(); return(g_sequence_id++); endfunction // int /////////////////////////////////////////////////// // // Local Sequence Registration Functions // /////////////////////////////////////////////////// protected function integer register_sequence(ovm_sequence_base sequence_ptr); if (sequence_ptr.m_get_sqr_sequence_id(m_sequencer_id, 1) > 0) begin return (sequence_ptr.get_sequence_id()); end sequence_ptr.m_set_sqr_sequence_id(m_sequencer_id, next_sequence_id()); reg_sequences[sequence_ptr.get_sequence_id()] = sequence_ptr; return(sequence_ptr.get_sequence_id()); endfunction protected function ovm_sequence_base find_sequence(integer sequence_id); ovm_sequence_base seq_ptr; integer i; // When sequence_id is -1, return the first available sequence. This is used // when deleting all sequences if (sequence_id == -1) begin if (reg_sequences.first(i)) begin return(reg_sequences[i]); end return(null); end if (reg_sequences.exists(sequence_id) == 0) begin// ovm_report_warning("find_sequence", // $psprintf("Sequence %d doesn't exist (find_sequence)", sequence_id)); return (null); end return(reg_sequences[sequence_id]); endfunction protected function void unregister_sequence(integer sequence_id); if (reg_sequences.exists(sequence_id) == 0) begin// ovm_report_warning("unregister_sequence", // $psprintf("Sequence %d doesn't exist (unregister_sequence)", sequence_id)); end reg_sequences.delete(sequence_id); endfunction /////////////////////////////////////////////////// // // virtual function integer user_priority_arbitration(integer avail_sequences[$]); // // If a user specifies that the sequencer is to use user_priority_arbitration // through the call set_arbitration(SEQ_ARB_USER), then the sequencer will // call this function each time that it needs to arbitrate among sequences. // // This function must return an integer that matches one of the available // sequences that is passed into the call through the avail_sequences parameter // // Each integer in avail_sequences points to an entry in the arb_sequence_q, // which is a protected queue that may be accessed from this function. // // To modify the operation of user_priority_arbitration, the function may // arbitrarily choose any sequence among the list of avail_sequences. It is // important to choose only an available sequence. // // The default implementation is FIFO, which simply returns the first integer // in the avail_sequences array /////////////////////////////////////////////////// virtual function integer user_priority_arbitration(integer avail_sequences[$]); return (avail_sequences[0]); endfunction // user_priority_arbitration /////////////////////////////////////////////////// // // grant_queued_locks // Any lock or grab requests that are at the front of the // queue will be granted at the earliest possible time. // // This function grants any queues at the front that are // not locked out /////////////////////////////////////////////////// protected function void grant_queued_locks(); integer i, temp; for (i = 0; i < arb_sequence_q.size(); i++) begin // Check for lock requests. Any lock request at the head // of the queue that is not blocked will be granted immediately. temp = 0; if (i < arb_sequence_q.size()) begin if (arb_sequence_q[i].request == SEQ_TYPE_LOCK) begin temp = (is_blocked(arb_sequence_q[i].sequence_ptr) == 0); end end // Grant the lock request and remove it from the queue. // This is a loop to handle multiple back-to-back locks. // Since each entry is deleted, i remains constant while (temp) begin lock_list.push_back(arb_sequence_q[i].sequence_ptr); set_arbitration_completed(arb_sequence_q[i].request_id); arb_sequence_q.delete(i); m_update_lists(); temp = 0; if (i < arb_sequence_q.size()) begin if (arb_sequence_q[i].request == SEQ_TYPE_LOCK) begin temp = is_blocked(arb_sequence_q[i].sequence_ptr) == 0; end end end end // for (i = 0; i < arb_sequence_q.size(); i++) endfunction // void /////////////////////////////////////////////////// // // choose_next_request // When a driver requests an operation, this function // must find the next available, unlocked, relevant sequence // // This function returns -1 if no sequences are available // or the entry into arb_sequence_q for the chosen sequence /////////////////////////////////////////////////// protected function integer choose_next_request(); integer i, temp; integer avail_sequence_count; integer sum_priority_val; integer avail_sequences[$]; integer highest_sequences[$]; integer highest_pri; string s; avail_sequence_count = 0; grant_queued_locks(); for (i = 0; i < arb_sequence_q.size(); i++) begin // 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 (arbitration == SEQ_ARB_FIFO) begin return (i); end else avail_sequences.push_back(i); end end // for (i = 0; i < arb_sequence_q.size(); i++) // Return immediately if there are 0 or 1 available sequences if (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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -