blob: c8651d8db9d47d711ad501c2e8ec147905dda40d [file] [log] [blame]
//------------------------------------------------------------------------------
// Copyright 2007-2014 Mentor Graphics Corporation
// Copyright 2014 Intel Corporation
// Copyright 2010-2014 Synopsys, Inc.
// Copyright 2007-2018 Cadence Design Systems, Inc.
// Copyright 2010-2018 AMD
// Copyright 2014-2018 NVIDIA Corporation
// 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.
//------------------------------------------------------------------------------
// Title -- NODOCS -- Sequence-Related Macros
//-----------------------------------------------------------------------------
//
// Group -- NODOCS -- Sequence on Sequencer Action Macros
//
// These macros are used to start sequences and sequence items on a specific
// sequencer. The sequence or item is created and executed on the given
// sequencer.
//-----------------------------------------------------------------------------
// MACRO -- NODOCS -- `uvm_create
//
//| `uvm_create(SEQ_OR_ITEM, SEQR=get_sequencer())
//
// This action creates the item or sequence using the factory. It also sets the
// parent sequence to the sequence in which the macro is invoked,
// and it sets the sequencer to the specified ~SEQR~ argument.
// It intentionally does zero processing. After this action completes,
// the user can manually set values, manipulate rand_mode and constraint_mode, etc.
// @uvm-ieee 1800.2-2017 auto B.3.1.1
`define uvm_create(SEQ_OR_ITEM, SEQR=get_sequencer()) \
begin \
uvm_object_wrapper w_; \
w_ = SEQ_OR_ITEM.get_type(); \
$cast(SEQ_OR_ITEM , create_item(w_, SEQR, `"SEQ_OR_ITEM`"));\
end
// MACRO -- NODOCS -- `uvm_do
//
//| `uvm_do(SEQ_OR_ITEM, SEQR=get_sequencer(), PRIORITY=-1, CONSTRAINTS={})
//
// This macro takes as an argument a uvm_sequence_item variable or object.
// The argument is created using <`uvm_create>, which sets the sequencer to
// the specified ~SEQR~ argument.
// In the case of an item, it is randomized after the call to
// <uvm_sequence_base::start_item()> returns.
// This is called late-randomization.
// In the case of a sequence, the sub-sequence is started using
// <uvm_sequence_base::start()> with ~call_pre_post~ set to 0.
// In the case of an item,
// the item is sent to the driver through the associated sequencer.
//
// For a sequence item, the following are called, in order
//
//|
//| `uvm_create(item)
//| sequencer.wait_for_grant(prior) (task)
//| this.pre_do(1) (task)
//| item.randomize()
//| this.mid_do(item) (func)
//| sequencer.send_request(item) (func)
//| sequencer.wait_for_item_done() (task)
//| this.post_do(item) (func)
//|
//
// For a sequence, the following are called, in order
//
//|
//| `uvm_create(sub_seq)
//| sub_seq.randomize()
//| sub_seq.pre_start() (task)
//| this.pre_do(0) (task)
//| this.mid_do(sub_seq) (func)
//| sub_seq.body() (task)
//| this.post_do(sub_seq) (func)
//| sub_seq.post_start() (task)
//|
// @uvm-ieee 1800.2-2017 auto B.3.1.4
`define uvm_do(SEQ_OR_ITEM, SEQR=get_sequencer(), PRIORITY=-1, CONSTRAINTS={}) \
begin \
`uvm_create(SEQ_OR_ITEM, SEQR) \
`uvm_rand_send(SEQ_OR_ITEM, PRIORITY, CONSTRAINTS) \
end
//-----------------------------------------------------------------------------
//
// Group -- NODOCS -- Sequence Action Macros for Pre-Existing Sequences
//
// These macros are used to start sequences and sequence items that do not
// need to be created.
//-----------------------------------------------------------------------------
// MACRO -- NODOCS -- `uvm_send
//
//| `uvm_send(SEQ_OR_ITEM, PRIORITY=-1)
//
// This macro processes the item or sequence that has been created using
// `uvm_create. The processing is done without randomization. Essentially, an
// `uvm_do without the create or randomization.
// @uvm-ieee 1800.2-2017 auto B.3.1.2
`define uvm_send(SEQ_OR_ITEM, PRIORITY=-1) \
begin \
uvm_sequence_base __seq; \
if (!$cast(__seq,SEQ_OR_ITEM)) begin \
start_item(SEQ_OR_ITEM, PRIORITY);\
finish_item(SEQ_OR_ITEM, PRIORITY);\
end \
else __seq.start(__seq.get_sequencer(), this, PRIORITY, 0);\
end
// MACRO -- NODOCS -- `uvm_rand_send
//
//| `uvm_rand_send(SEQ_OR_ITEM, PRIORITY=-1, CONSTRAINTS={})
//
// This macro processes the item or sequence that has been already been
// allocated (with `uvm_create). The processing is done with
// randomization.
// @uvm-ieee 1800.2-2017 auto B.3.1.3
`define uvm_rand_send(SEQ_OR_ITEM, PRIORITY=-1, CONSTRAINTS={}) \
begin \
uvm_sequence_base __seq; \
if ( SEQ_OR_ITEM.is_item() ) begin \
start_item(SEQ_OR_ITEM, PRIORITY);\
if ( ! SEQ_OR_ITEM.randomize() with CONSTRAINTS ) begin \
`uvm_warning("RNDFLD", "Randomization failed in uvm_rand_send action") \
end\
finish_item(SEQ_OR_ITEM, PRIORITY);\
end \
else if ( $cast( __seq, SEQ_OR_ITEM ) ) begin \
__seq.set_item_context(this,SEQ_OR_ITEM.get_sequencer()); \
if ( __seq.get_randomize_enabled() ) begin \
if ( ! SEQ_OR_ITEM.randomize() with CONSTRAINTS ) begin \
`uvm_warning("RNDFLD", "Randomization failed in uvm_rand_send action") \
end \
end \
__seq.start(__seq.get_sequencer(), this, PRIORITY, 0);\
end \
else begin \
`uvm_warning("NOT_SEQ_OR_ITEM", "Object passed uvm_rand_send appears to be neither a sequence or item." ) \
end \
end
//-----------------------------------------------------------------------------
//
// Group- Sequence Library
//
//-----------------------------------------------------------------------------
// MACRO -- NODOCS -- `uvm_add_to_sequence_library
//
// Adds the given sequence ~TYPE~ to the given sequence library ~LIBTYPE~
//
//| `uvm_add_to_seq_lib(TYPE,LIBTYPE)
//
// Invoke any number of times within a sequence declaration to statically add
// that sequence to one or more sequence library types. The sequence will then
// be available for selection and execution in all instances of the given
// sequencer types.
//
//| class seqA extends uvm_sequence_base #(simple_item);
//|
//| function new(string name=`"TYPE`");
//| super.new(name);
//| endfunction
//|
//| `uvm_object_utils(seqA)
//|
//| `uvm_add_to_seq_lib(seqA, simple_seq_lib_RST)
//| `uvm_add_to_seq_lib(seqA, simple_seq_lib_CFG)
//|
//| virtual task body(); \
//| `uvm_info("SEQ_START", {"Executing sequence '", get_full_name(),
//| "' (",get_type_name(),")"},UVM_HIGH)
//| #10;
//| endtask
//|
//| endclass
// @uvm-ieee 1800.2-2017 auto B.3.2.1
`define uvm_add_to_seq_lib(TYPE,LIBTYPE) \
static bit add_``TYPE``_to_seq_lib_``LIBTYPE =\
LIBTYPE::m_add_typewide_sequence(TYPE::get_type());
// MACRO -- NODOCS -- `uvm_sequence_library_utils
//
//| `uvm_sequence_library_utils(TYPE)
//
// Declares the infrastructure needed to define extensions to the
// <uvm_sequence_library> class. You define new sequence library subtypes
// to statically specify sequence membership from within sequence
// definitions. See also <`uvm_add_to_sequence_library> for more information.
//
//
//| typedef simple_seq_lib uvm_sequence_library #(simple_item);
//|
//| class simple_seq_lib_RST extends simple_seq_lib;
//|
//| `uvm_object_utils(simple_seq_lib_RST)
//|
//| `uvm_sequence_library_utils(simple_seq_lib_RST)
//|
//| function new(string name="");
//| super.new(name);
//| endfunction
//|
//| endclass
//
// Each library, itself a sequence, can then be started independently
// on different sequencers or in different phases of the same sequencer.
// See <uvm_sequencer_base::start_phase_sequence> for information on
// starting default sequences.
// @uvm-ieee 1800.2-2017 auto 14.4.2
// @uvm-ieee 1800.2-2017 auto B.3.2.2
`define uvm_sequence_library_utils(TYPE) \
\
static protected uvm_object_wrapper m_typewide_sequences[$]; \
\
function void init_sequence_library(); \
foreach (TYPE::m_typewide_sequences[i]) \
sequences.push_back(TYPE::m_typewide_sequences[i]); \
endfunction \
\
static function void add_typewide_sequence(uvm_object_wrapper seq_type); \
if (m_static_check(seq_type)) \
TYPE::m_typewide_sequences.push_back(seq_type); \
endfunction \
\
static function void add_typewide_sequences(uvm_object_wrapper seq_types[$]); \
foreach (seq_types[i]) \
TYPE::add_typewide_sequence(seq_types[i]); \
endfunction \
\
static function bit m_add_typewide_sequence(uvm_object_wrapper seq_type); \
TYPE::add_typewide_sequence(seq_type); \
return 1; \
endfunction
//-----------------------------------------------------------------------------
//
// Group -- NODOCS -- Sequencer Subtypes
//
//-----------------------------------------------------------------------------
// MACRO -- NODOCS -- `uvm_declare_p_sequencer
//
// This macro is used to declare a variable ~p_sequencer~ whose type is
// specified by ~SEQUENCER~.
//
//| `uvm_declare_p_sequencer(SEQUENCER)
//
// The example below shows using the `uvm_declare_p_sequencer macro
// along with the uvm_object_utils macros to set up the sequence but
// not register the sequence in the sequencer's library.
//
//| class mysequence extends uvm_sequence#(mydata);
//| `uvm_object_utils(mysequence)
//| `uvm_declare_p_sequencer(some_seqr_type)
//| task body;
//| //Access some variable in the user's custom sequencer
//| if(p_sequencer.some_variable) begin
//| ...
//| end
//| endtask
//| endclass
//
// @uvm-ieee 1800.2-2017 auto B.3.3
`define uvm_declare_p_sequencer(SEQUENCER) \
SEQUENCER p_sequencer;\
virtual function void m_set_p_sequencer();\
super.m_set_p_sequencer(); \
if( !$cast(p_sequencer, m_sequencer)) \
`uvm_fatal("DCLPSQ", \
$sformatf("%m %s Error casting p_sequencer, please verify that this sequence/sequence item is intended to execute on this type of sequencer", get_full_name())) \
endfunction