blob: afccc1ee67af13a9750c33ca9b17e9e9901988da [file] [log] [blame]
//----------------------------------------------------------------------
// Copyright 2007-2009 Mentor Graphics Corporation
// Copyright 2007-2009 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.
//----------------------------------------------------------------------
`ifndef OVM_SEQUENCE_ITEM_SVH
`define OVM_SEQUENCE_ITEM_SVH
typedef class ovm_sequence_base;
typedef class ovm_sequencer_base;
//------------------------------------------------------------------------------
//
// CLASS: ovm_sequence_item
//
// The base class for user-defined sequence items and also the base class for
// the ovm_sequence class. The ovm_sequence_item class provides the basic
// functionality for objects, both sequence items and sequences, to operate in
// the sequence mechanism.
//
//------------------------------------------------------------------------------
class ovm_sequence_item extends ovm_transaction;
local int m_sequence_id = -1;
protected bit m_use_sequence_info = 0;
protected int m_depth = -1;
protected ovm_sequencer_base m_sequencer = null;
protected ovm_sequence_base m_parent_sequence = null;
static bit issued1=0,issued2=0;
bit print_sequence_info = 0;
// Function: new
//
// The constructor method for ovm_sequence_item. The sequencer and
// parent_sequence may be specified in the constructor, or directly using
// ovm_sequence_item methods.
function new (string name = "ovm_sequence_item",
ovm_sequencer_base sequencer = null,
ovm_sequence_base parent_sequence = null);
super.new(name);
if (sequencer != null) begin
if (!issued1) begin
issued1=1;
ovm_report_warning("deprecated",
{"ovm_sequence_item::new()'s sequencer_ptr argument has been deprecated. ",
"The sequencer is now specified at the time a sequence is started ",
"using the start() task."});
end
m_sequencer = sequencer;
end
if (parent_sequence != null) begin
if (!issued2) begin
issued2=1;
ovm_report_warning("deprecated",
{"ovm_sequence_item::new()'s parent_sequence argument has been deprecated. ",
"The parent sequence is now specified at the time a sequence is started ",
"using the start() task."});
end
m_parent_sequence = parent_sequence;
end
endfunction // new
function string get_type_name();
return "ovm_sequence_item";
endfunction
// Macro for factory creation
`ovm_object_registry(ovm_sequence_item, "ovm_sequence_item")
// Function- set_sequence_id
function void set_sequence_id(int id);
m_sequence_id = id;
endfunction
// Function: get_sequence_id
//
// private
//
// Get_sequence_id is an internal method that is not intended for user code.
// The sequence_id is not a simple integer. The get_transaction_id is meant
// for users to identify specific transactions.
//
// These methods allow access to the sequence_item sequence and transaction
// IDs. get_transaction_id and set_transaction_id are methods on the
// ovm_transaction base_class. These IDs are used to identify sequences to
// the sequencer, to route responses back to the sequence that issued a
// request, and to uniquely identify transactions.
//
// The sequence_id is assigned automatically by a sequencer when a sequence
// initiates communication through any sequencer calls (i.e. `ovm_do_xxx,
// wait_for_grant). A sequence_id will remain unique for this sequence
// until it ends or it is killed. However, a single sequence may have
// multiple valid sequence ids at any point in time. Should a sequence
// start again after it has ended, it will be given a new unique sequence_id.
//
// The transaction_id is assigned automatically by the sequence each time a
// transaction is sent to the sequencer with the transaction_id in its
// default (-1) value. If the user sets the transaction_id to any non-default
// value, that value will be maintained.
//
// Responses are routed back to this sequences based on sequence_id. The
// sequence may use the transaction_id to correlate responses with their
// requests.
function int get_sequence_id();
return (m_sequence_id);
endfunction
// Function: set_use_sequence_info
//
function void set_use_sequence_info(bit value);
m_use_sequence_info = value;
endfunction
// Function: get_use_sequence_info
//
// These methods are used to set and get the status of the use_sequence_info
// bit. Use_sequence_info controls whether the sequence information
// (sequencer, parent_sequence, sequence_id, etc.) is printed, copied, or
// recorded. When use_sequence_info is the default value of 0, then the
// sequence information is not used. When use_sequence_info is set to 1,
// the sequence information will be used in printing and copying.
function bit get_use_sequence_info();
return (m_use_sequence_info);
endfunction
// Function: set_id_info
//
// Copies the sequence_id and transaction_id from the referenced item into
// the calling item. This routine should always be used by drivers to
// initialize responses for future compatibility.
function void set_id_info(ovm_sequence_item item);
if (item == null) begin
ovm_report_fatal(get_full_name(), "set_id_info called with null parameter", OVM_NONE);
end
this.set_transaction_id(item.get_transaction_id());
this.set_sequence_id(item.get_sequence_id());
endfunction
// Function: set_sequencer
function void set_sequencer(ovm_sequencer_base sequencer);
m_sequencer = sequencer;
m_set_p_sequencer();
endfunction // void
// Function: get_sequencer
//
// These routines set and get the reference to the sequencer to which this
// sequence_item communicates.
function ovm_sequencer_base get_sequencer();
return (m_sequencer);
endfunction // ovm_sequencer_base
// Function: set_parent_sequence
//
// Sets the parent sequence of this sequence_item. This is used to identify
// the source sequence of a sequence_item.
function void set_parent_sequence(ovm_sequence_base parent);
m_parent_sequence = parent;
endfunction
// Function: get_parent_sequence
//
// Returns a reference to the parent sequence of any sequence on which this
// method was called. If this is a parent sequence, the method returns null.
function ovm_sequence_base get_parent_sequence();
return (m_parent_sequence);
endfunction
// Function: set_depth
//
// The depth of any sequence is calculated automatically. However, the user
// may use set_depth to specify the depth of a particular sequence. This
// method will override the automatically calculated depth, even if it is
// incorrect.
function void set_depth(int value);
m_depth = value;
endfunction
// Function: get_depth
//
// Returns the depth of a sequence from it's parent. A parent sequence will
// have a depth of 1, it's child will have a depth of 2, and it's grandchild
// will have a depth of 3.
function int get_depth();
// If depth has been set or calculated, then use that
if (m_depth != -1) begin
return (m_depth);
end
// Calculate the depth, store it, and return the value
if (m_parent_sequence == null) begin
m_depth = 1;
end else begin
m_depth = m_parent_sequence.get_depth() + 1;
end
return (m_depth);
endfunction
// Function: is_item
//
// This function may be called on any sequence_item or sequence. It will
// return 1 for items and 0 for sequences (which derive from this class).
virtual function bit is_item();
return(1);
endfunction
// Function: start_item
//
// start_item and finish_item together will initiate operation of either
// a sequence_item or sequence object. If the object has not been initiated
// using create_item, then start_item will be initialized in start_item
// to use the default sequencer specified by m_sequencer. Randomization
// may be done between start_item and finish_item to ensure late generation
virtual task start_item(ovm_sequence_item item, int set_priority = -1);
if(item == null)
m_sequencer.ovm_report_fatal("NULLITM", {"attempting to start a null item from item/sequence '", get_full_name(), "'"}, OVM_NONE);
item.m_start_item(m_sequencer, this, set_priority);
endtask
// Function: finish_item
//
// finish_item, together with start_item together will initiate operation of
// either a sequence_item or sequence object. Finish_item must be called
// after start_item with no delays or delta-cycles. Randomization, or other
// functions may be called between the start_item and finish_item calls.
virtual task finish_item(ovm_sequence_item item, int set_priority = -1);
item.m_finish_item(item.get_sequencer(), this, set_priority);
endtask // finish_item
// Function- m_start_item
//
// Internal method.
virtual task m_start_item(ovm_sequencer_base sequencer_ptr, ovm_sequence_item sequence_ptr,
int set_priority);
ovm_sequence_base this_seq;
ovm_sequencer_base target_seqr;
target_seqr = this.get_sequencer();
if (!$cast(this_seq, sequence_ptr))
ovm_report_fatal ("CASTFL", "start_item failed to cast sequence_ptr to sequence type", OVM_NONE);
if (target_seqr == null) begin
if (sequencer_ptr == null) begin
ovm_report_fatal("STRITM", "sequence_item has null sequencer", OVM_NONE);
end else begin
target_seqr = sequencer_ptr;
set_use_sequence_info(1);
set_sequencer(sequencer_ptr);
set_parent_sequence(this_seq);
reseed();
end
end
target_seqr.wait_for_grant(this_seq, set_priority);
`ifdef INCA
void'(target_seqr.begin_tr(this, "aggregate items"));
`else // QUESTA
void'(target_seqr.begin_tr(this, "aggregate_items"));
`endif // INCA-QUESTA
sequence_ptr.pre_do(1);
endtask
// Function- m_finish_item
//
// Internal method.
virtual task m_finish_item(ovm_sequencer_base sequencer_ptr, ovm_sequence_item sequence_ptr, int set_priority = -1);
ovm_sequence_base this_seq;
ovm_sequencer_base target_seqr;
target_seqr = this.get_sequencer();
if (!$cast(this_seq, sequence_ptr))
ovm_report_fatal ("CASTFL", "finish_item failed to cast sequence_ptr to sequence type", OVM_NONE);
sequence_ptr.mid_do(this);
target_seqr.send_request(this_seq, this);
target_seqr.wait_for_item_done(this_seq, -1);
target_seqr.end_tr(this);
sequence_ptr.post_do(this);
endtask // m_finish_item
// Function- get_full_name
//
// Internal method; overrides must follow same naming convention
function string get_full_name();
if(m_parent_sequence != null)
get_full_name = {m_parent_sequence.get_full_name(), "."};
else if(m_sequencer!=null)
get_full_name = {m_sequencer.get_full_name(), "."};
if(get_name() != "")
get_full_name = {get_full_name, get_name()};
else begin
get_full_name = {get_full_name, "_item"};
end
endfunction
// Function: get_root_sequence_name
//
// Provides the name of the root sequence (the top-most parent sequence).
function string get_root_sequence_name();
ovm_sequence_base root_seq;
root_seq = get_root_sequence();
if (root_seq == null)
return "";
else
return root_seq.get_name();
endfunction
// Function- m_set_p_sequencer
//
// Internal method
virtual function void m_set_p_sequencer();
return;
endfunction
// Function: get_root_sequence
//
// Provides a reference to the root sequence (the top-most parent sequence).
function ovm_sequence_base get_root_sequence();
ovm_sequence_item root_seq_base;
ovm_sequence_base root_seq;
root_seq_base = this;
while(1) begin
if(root_seq_base.get_parent_sequence()!=null) begin
root_seq_base = root_seq_base.get_parent_sequence();
$cast(root_seq, root_seq_base);
end
else
return root_seq;
end
endfunction
// Function: get_sequence_path
//
// Provides a string of names of each sequence in the full hierarchical
// path. A "." is used as the separator between each sequence.
function string get_sequence_path();
ovm_sequence_item this_item;
string seq_path;
this_item = this;
seq_path = this.get_name();
while(1) begin
if(this_item.get_parent_sequence()!=null) begin
this_item = this_item.get_parent_sequence();
seq_path = {this_item.get_name(), ".", seq_path};
end
else
return seq_path;
end
endfunction
// Function- do_print
//
// Internal method
function void do_print (ovm_printer printer);
string temp_str0, temp_str1;
int depth = get_depth();
super.do_print(printer);
if(print_sequence_info || m_use_sequence_info) begin
printer.print_field("depth", depth, $bits(depth), OVM_DEC, ".", "int");
if(m_parent_sequence != null) begin
temp_str0 = m_parent_sequence.get_name();
temp_str1 = m_parent_sequence.get_full_name();
end
printer.print_string("parent sequence (name)", temp_str0);
printer.print_string("parent sequence (full name)", temp_str1);
temp_str1 = "";
if(m_sequencer != null) begin
temp_str1 = m_sequencer.get_full_name();
end
printer.print_string("sequencer", temp_str1);
end
endfunction
//----------------------------------------------------------------------------
// Deprecated Methods
//
// These methods, which are sequence-centric, were moved to ovm_sequence_base.
//----------------------------------------------------------------------------
function void set_parent_seq(ovm_sequence_base parent);
static bit issued=0;
if (!issued) begin
issued=1;
ovm_report_warning("deprecated",
{"ovm_sequence_item::set_parent_seq() has been deprecated and ",
"replaced by set_parent_sequence()"});
end
set_parent_sequence(parent);
endfunction
function ovm_sequence_base get_parent_seq();
static bit issued=0;
if (!issued) begin
issued=1;
ovm_report_warning("deprecated",
{"ovm_sequence_item::get_parent_seq() has been deprecated and ",
"replaced by get_parent_sequence()"});
end
return(get_parent_sequence());
endfunction // ovm_sequence_base
virtual task pre_do(bit is_item);
return;
endtask // pre_body
virtual task body();
return;
endtask
virtual function void mid_do(ovm_sequence_item this_item);
return;
endfunction
virtual function void post_do(ovm_sequence_item this_item);
return;
endfunction
virtual task wait_for_grant(int item_priority = -1, bit lock_request = 0);
return;
endtask
virtual function void send_request(ovm_sequence_item request, bit rerandomize = 0);
return;
endfunction
virtual task wait_for_item_done(int transaction_id = -1);
return;
endtask // wait_for_item_done
endclass
`endif