Source code for uvm.seq.uvm_sequence_item

#----------------------------------------------------------------------
#   Copyright 2007-2011 Mentor Graphics Corporation
#   Copyright 2007-2010 Cadence Design Systems, Inc.
#   Copyright 2010 Synopsys, Inc.
#   Copyright 2019 Tuomas Poikela
#   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.
#----------------------------------------------------------------------

from typing import Any

from ..base.uvm_transaction import UVMTransaction
from ..base.uvm_globals import *


UVMSequencerBase = Any
UVMSequenceBase = Any

#------------------------------------------------------------------------------
#
# CLASS: UVMSequenceItem
#
# The base class for user-defined sequence items and also the base class for
# the uvm_sequence class. The UVMSequenceItem class provides the basic
# functionality for objects, both sequence items and sequences, to operate in
# the sequence mechanism.
#
#------------------------------------------------------------------------------

[docs]class UVMSequenceItem(UVMTransaction): # protected uvm_sequencer_base self.m_sequencer # protected uvm_sequence_base self.m_parent_sequence # bit self.print_sequence_info # static bit issued1,issued2 issued1 = False issued2 = False def __init__(self, name="UVMSequenceItem") -> None: """ Function: new The constructor method for UVMSequenceItem. Args: name: """ UVMTransaction.__init__(self, name) self.m_sequence_id = -1 self.m_use_sequence_info = False self.m_depth = -1 self.m_sequencer: UVMSequencerBase = None self.p_sequencer: UVMSequenceBase = None self.m_parent_sequence = None self.print_sequence_info = False # endfunction
[docs] def get_type_name(self) -> str: return "UVMSequenceItem"
[docs] def set_sequence_id(self, id: int) -> None: """ Function- set_sequence_id Args: id: """ self.m_sequence_id = id
[docs] def get_sequence_id(self) -> int: """ 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 uvm_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. `uvm_do_*, 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. Returns: """ return (self.m_sequence_id)
[docs] def set_item_context(self, parent_seq, sequencer=None) -> None: """ Function: set_item_context Set the sequence and sequencer execution context for a sequence item Args: parent_seq: sequencer: """ self.set_use_sequence_info(1) if parent_seq is not None: self.set_parent_sequence(parent_seq) if (sequencer is None and self.m_parent_sequence is not None): sequencer = self.m_parent_sequence.get_sequencer() self.set_sequencer(sequencer) if (self.m_parent_sequence is not None): self.set_depth(self.m_parent_sequence.get_depth() + 1) self.reseed()
[docs] def set_use_sequence_info(self, value) -> None: """ Function: set_use_sequence_info Args: value: """ self.m_use_sequence_info = value
[docs] def get_use_sequence_info(self) -> bool: """ 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. """ return (self.m_use_sequence_info)
[docs] def set_id_info(self, item: 'UVMSequenceItem') -> None: """ 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. Args: item: """ if item is None: uvm_report_fatal(self.get_full_name(), "set_id_info called with None parameter", UVM_NONE) self.set_transaction_id(item.get_transaction_id()) self.set_sequence_id(item.get_sequence_id())
# // Function: set_sequencer # // # // Sets the default sequencer for the sequence to sequencer. It will take # // effect immediately, so it should not be called while the sequence is # // actively communicating with the sequencer.
[docs] def set_sequencer(self, sequencer: UVMSequencerBase) -> None: self.m_sequencer = sequencer self.m_set_p_sequencer()
# // Function: get_sequencer # // # // Returns a reference to the default sequencer used by this sequence.
[docs] def get_sequencer(self) -> UVMSequencerBase: return self.m_sequencer
# // Function: set_parent_sequence # // # // Sets the parent sequence of this sequence_item. This is used to identify # // the source sequence of a sequence_item.
[docs] def set_parent_sequence(self, parent: UVMSequenceBase) -> None: self.m_parent_sequence = parent
[docs] def get_parent_sequence(self) -> UVMSequenceBase: """ 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 `None`. Returns: UVMSequenceBase: Parent sequence of this item. """ return (self.m_parent_sequence)
[docs] def set_depth(self, value: int) -> None: """ 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. Args: value: """ self.m_depth = value
# endfunction
[docs] def get_depth(self) -> int: """ Function: get_depth Returns the depth of a sequence from its parent. A parent sequence will have a depth of 1, its child will have a depth of 2, and its grandchild will have a depth of 3. Returns: """ # If depth has been set or calculated, then use that if self.m_depth != -1: return (self.m_depth) # Calculate the depth, store it, and return the value if self.m_parent_sequence is None: self.m_depth = 1 else: self.m_depth = self.m_parent_sequence.get_depth() + 1 return self.m_depth
[docs] def is_item(self) -> bool: """ 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). Returns: """ return True
[docs] def get_full_name(self) -> str: """ Function- get_full_name Internal method; overrides must follow same naming convention Returns: """ get_full_name = "" if self.m_parent_sequence is not None: get_full_name = self.m_parent_sequence.get_full_name() + "." elif self.m_sequencer is not None: get_full_name = self.m_sequencer.get_full_name() + "." if self.get_name() != "": get_full_name = get_full_name + self.get_name() else: get_full_name = get_full_name + "_item" return get_full_name
[docs] def get_root_sequence_name(self) -> str: """ Function: get_root_sequence_name Provides the name of the root sequence (the top-most parent sequence). Returns: """ #uvm_sequence_base root_seq root_seq = self.get_root_sequence() if root_seq is None: return "" else: return root_seq.get_name()
# endfunction
[docs] def m_set_p_sequencer(self) -> None: """ Function- m_set_p_sequencer Internal method """ self.p_sequencer = self.m_sequencer
[docs] def get_root_sequence(self) -> Any: """ Function: get_root_sequence Provides a reference to the root sequence (the top-most parent sequence). Returns: """ root_seq_base = None # UVMSequenceItem root_seq = None root_seq_base = self while True: if (root_seq_base.get_parent_sequence() is not None): root_seq_base = root_seq_base.get_parent_sequence() #$cast(root_seq, root_seq_base) root_seq = root_seq_base else: return root_seq
[docs] def get_sequence_path(self) -> str: """ 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. Returns: """ this_item = None # UVMSequenceItem seq_path = "" this_item = self seq_path = self.get_name() while True: if this_item.get_parent_sequence() is not None: this_item = this_item.get_parent_sequence() seq_path = this_item.get_name() + "." + seq_path else: return seq_path
# //--------------------------- # // Group: Reporting Interface # //--------------------------- # // # // Sequence items and sequences will use the sequencer which they are # // associated with for reporting messages. If no sequencer has been se # // for the item/sequence using <set_sequencer> or indirectly via # // <uvm_sequence_base::start_item> or <uvm_sequence_base::start>), # // then the global reporter will be used. # # virtual function uvm_report_object uvm_get_report_object() # if(self.m_sequencer == None): # uvm_coreservice_t cs = uvm_coreservice_t::get() # return cs.get_root() # end else # return self.m_sequencer # endfunction # # function int uvm_report_enabled(int verbosity, # uvm_severity severity=UVM_INFO, string id="") # uvm_report_object l_report_object = uvm_get_report_object() # if (l_report_object.get_report_verbosity_level(severity, id) < verbosity) # return 0 # return 1 # endfunction # # // Function: uvm_report # virtual function void uvm_report( uvm_severity severity, # string id, # string message, # int verbosity = (severity == uvm_severity'(UVM_ERROR)) ? UVM_LOW : # (severity == uvm_severity'(UVM_FATAL)) ? UVM_NONE : UVM_MEDIUM, # string filename = "", # int line = 0, # string context_name = "", # bit report_enabled_checked = 0) # uvm_report_message l_report_message # if (report_enabled_checked == 0): # if (!uvm_report_enabled(verbosity, severity, id)) # return # end # l_report_message = uvm_report_message::new_report_message() # l_report_message.set_report_message(severity, id, message, # verbosity, filename, line, context_name) # uvm_process_report_message(l_report_message) # # endfunction # # // Function: uvm_report_info # # virtual function void uvm_report_info( string id, # string message, # int verbosity = UVM_MEDIUM, # string filename = "", # int line = 0, # string context_name = "", # bit report_enabled_checked = 0) # # this.uvm_report(UVM_INFO, id, message, verbosity, filename, line, # context_name, report_enabled_checked) # endfunction # # // Function: uvm_report_warning # # virtual function void uvm_report_warning( string id, # string message, # int verbosity = UVM_MEDIUM, # string filename = "", # int line = 0, # string context_name = "", # bit report_enabled_checked = 0) # # this.uvm_report(UVM_WARNING, id, message, verbosity, filename, line, # context_name, report_enabled_checked) # endfunction # # // Function: uvm_report_error # # virtual function void uvm_report_error( string id, # string message, # int verbosity = UVM_LOW, # string filename = "", # int line = 0, # string context_name = "", # bit report_enabled_checked = 0) # # this.uvm_report(UVM_ERROR, id, message, verbosity, filename, line, # context_name, report_enabled_checked) # endfunction # # // Function: uvm_report_fatal # // # // These are the primary reporting methods in the UVM. UVMSequenceItem # // derived types delegate these functions to their associated sequencer # // if they have one, or to the global reporter. See <uvm_report_object::Reporting> # // for details on the messaging functions. # # virtual function void uvm_report_fatal( string id, # string message, # int verbosity = UVM_NONE, # string filename = "", # int line = 0, # string context_name = "", # bit report_enabled_checked = 0) # # this.uvm_report(UVM_FATAL, id, message, verbosity, filename, line, # context_name, report_enabled_checked) # endfunction # # virtual function void uvm_process_report_message (uvm_report_message report_message) # uvm_report_object l_report_object = uvm_get_report_object() # report_message.set_report_object(l_report_object) # if (report_message.get_context() == "") # report_message.set_context(get_sequence_path()) # l_report_object.m_rh.process_report_message(report_message) # endfunction # # # // Function- do_print # // # // Internal method # # function void do_print (uvm_printer printer) # string temp_str0, temp_str1 # int depth = get_depth() # super.do_print(printer) # if(self.print_sequence_info || self.m_use_sequence_info): # printer.print_field_int("depth", depth, $bits(depth), UVM_DEC, ".", "int") # if(self.m_parent_sequence != None): # temp_str0 = self.m_parent_sequence.get_name() # temp_str1 = self.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(self.m_sequencer != None): # temp_str1 = self.m_sequencer.get_full_name() # end # printer.print_string("sequencer", temp_str1) # end # endfunction # #endclass # Macro for factory creation # uvm_object_registry(UVMSequenceItem, "UVMSequenceItem")