| //------------------------------------------------------------------------------ |
| // Copyright 2007-2011 Mentor Graphics Corporation |
| // Copyright 2007-2010 Cadence Design Systems, Inc. |
| // Copyright 2010 Synopsys, 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. |
| //------------------------------------------------------------------------------ |
| |
| // Title: Sequence-Related Macros |
| |
| |
| |
| //----------------------------------------------------------------------------- |
| // |
| // Group: Sequence Action Macros |
| // |
| // These macros are used to start sequences and sequence items on the default |
| // sequencer, ~m_sequencer~. This is determined a number of ways. |
| // - the sequencer handle provided in the <uvm_sequence_base::start> method |
| // - the sequencer used by the parent sequence |
| // - the sequencer that was set using the <uvm_sequence_item::set_sequencer> method |
| //----------------------------------------------------------------------------- |
| |
| // MACRO: `uvm_create |
| // |
| //| `uvm_create(SEQ_OR_ITEM) |
| // |
| // This action creates the item or sequence using the factory. It intentionally |
| // does zero processing. After this action completes, the user can manually set |
| // values, manipulate rand_mode and constraint_mode, etc. |
| |
| `define uvm_create(SEQ_OR_ITEM) \ |
| `uvm_create_on(SEQ_OR_ITEM, m_sequencer) |
| |
| |
| // MACRO: `uvm_do |
| // |
| //| `uvm_do(SEQ_OR_ITEM) |
| // |
| // This macro takes as an argument a uvm_sequence_item variable or object. |
| // The argument is created using <`uvm_create> if necessary, |
| // then randomized. |
| // 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) |
| //| |
| |
| `define uvm_do(SEQ_OR_ITEM) \ |
| `uvm_do_on_pri_with(SEQ_OR_ITEM, m_sequencer, -1, {}) |
| |
| |
| // MACRO: `uvm_do_pri |
| // |
| //| `uvm_do_pri(SEQ_OR_ITEM, PRIORITY) |
| // |
| // This is the same as `uvm_do except that the sequence item or sequence is |
| // executed with the priority specified in the argument |
| |
| `define uvm_do_pri(SEQ_OR_ITEM, PRIORITY) \ |
| `uvm_do_on_pri_with(SEQ_OR_ITEM, m_sequencer, PRIORITY, {}) |
| |
| |
| // MACRO: `uvm_do_with |
| // |
| //| `uvm_do_with(SEQ_OR_ITEM, CONSTRAINTS) |
| // |
| // This is the same as `uvm_do except that the constraint block in the 2nd |
| // argument is applied to the item or sequence in a randomize with statement |
| // before execution. |
| |
| `define uvm_do_with(SEQ_OR_ITEM, CONSTRAINTS) \ |
| `uvm_do_on_pri_with(SEQ_OR_ITEM, m_sequencer, -1, CONSTRAINTS) |
| |
| |
| // MACRO: `uvm_do_pri_with |
| // |
| //| `uvm_do_pri_with(SEQ_OR_ITEM, PRIORITY, CONSTRAINTS) |
| // |
| // This is the same as `uvm_do_pri except that the given constraint block is |
| // applied to the item or sequence in a randomize with statement before |
| // execution. |
| |
| `define uvm_do_pri_with(SEQ_OR_ITEM, PRIORITY, CONSTRAINTS) \ |
| `uvm_do_on_pri_with(SEQ_OR_ITEM, m_sequencer, PRIORITY, CONSTRAINTS) |
| |
| |
| //----------------------------------------------------------------------------- |
| // |
| // Group: 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: `uvm_create_on |
| // |
| //| `uvm_create_on(SEQ_OR_ITEM, SEQR) |
| // |
| // This is the same as <`uvm_create> except that 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. |
| |
| `define uvm_create_on(SEQ_OR_ITEM, SEQR) \ |
| begin \ |
| uvm_object_wrapper w_; \ |
| w_ = SEQ_OR_ITEM.get_type(); \ |
| $cast(SEQ_OR_ITEM , create_item(w_, SEQR, `"SEQ_OR_ITEM`"));\ |
| end |
| |
| |
| // MACRO: `uvm_do_on |
| // |
| //| `uvm_do_on(SEQ_OR_ITEM, SEQR) |
| // |
| // This is the same as <`uvm_do> except that 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. |
| |
| `define uvm_do_on(SEQ_OR_ITEM, SEQR) \ |
| `uvm_do_on_pri_with(SEQ_OR_ITEM, SEQR, -1, {}) |
| |
| |
| // MACRO: `uvm_do_on_pri |
| // |
| //| `uvm_do_on_pri(SEQ_OR_ITEM, SEQR, PRIORITY) |
| // |
| // This is the same as <`uvm_do_pri> except that 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. |
| |
| `define uvm_do_on_pri(SEQ_OR_ITEM, SEQR, PRIORITY) \ |
| `uvm_do_on_pri_with(SEQ_OR_ITEM, SEQR, PRIORITY, {}) |
| |
| |
| // MACRO: `uvm_do_on_with |
| // |
| //| `uvm_do_on_with(SEQ_OR_ITEM, SEQR, CONSTRAINTS) |
| // |
| // This is the same as <`uvm_do_with> except that 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. |
| // The user must supply brackets around the constraints. |
| |
| `define uvm_do_on_with(SEQ_OR_ITEM, SEQR, CONSTRAINTS) \ |
| `uvm_do_on_pri_with(SEQ_OR_ITEM, SEQR, -1, CONSTRAINTS) |
| |
| |
| // MACRO: `uvm_do_on_pri_with |
| // |
| //| `uvm_do_on_pri_with(SEQ_OR_ITEM, SEQR, PRIORITY, CONSTRAINTS) |
| // |
| // This is the same as `uvm_do_pri_with except that 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. |
| |
| `define uvm_do_on_pri_with(SEQ_OR_ITEM, SEQR, PRIORITY, CONSTRAINTS) \ |
| begin \ |
| uvm_sequence_base __seq; \ |
| `uvm_create_on(SEQ_OR_ITEM, SEQR) \ |
| if (!$cast(__seq,SEQ_OR_ITEM)) start_item(SEQ_OR_ITEM, PRIORITY);\ |
| if ((__seq == null || !__seq.do_not_randomize) && !SEQ_OR_ITEM.randomize() with CONSTRAINTS ) begin \ |
| `uvm_warning("RNDFLD", "Randomization failed in uvm_do_with action") \ |
| end\ |
| if (!$cast(__seq,SEQ_OR_ITEM)) finish_item(SEQ_OR_ITEM, PRIORITY); \ |
| else __seq.start(SEQR, this, PRIORITY, 0); \ |
| end |
| |
| |
| //----------------------------------------------------------------------------- |
| // |
| // Group: 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: `uvm_send |
| // |
| //| `uvm_send(SEQ_OR_ITEM) |
| // |
| // 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. |
| |
| `define uvm_send(SEQ_OR_ITEM) \ |
| `uvm_send_pri(SEQ_OR_ITEM, -1) |
| |
| |
| // MACRO: `uvm_send_pri |
| // |
| //| `uvm_send_pri(SEQ_OR_ITEM, PRIORITY) |
| // |
| // This is the same as `uvm_send except that the sequence item or sequence is |
| // executed with the priority specified in the argument. |
| |
| `define uvm_send_pri(SEQ_OR_ITEM, PRIORITY) \ |
| 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: `uvm_rand_send |
| // |
| //| `uvm_rand_send(SEQ_OR_ITEM) |
| // |
| // This macro processes the item or sequence that has been already been |
| // allocated (possibly with `uvm_create). The processing is done with |
| // randomization. Essentially, an `uvm_do without the create. |
| |
| `define uvm_rand_send(SEQ_OR_ITEM) \ |
| `uvm_rand_send_pri_with(SEQ_OR_ITEM, -1, {}) |
| |
| |
| // MACRO: `uvm_rand_send_pri |
| // |
| //| `uvm_rand_send_pri(SEQ_OR_ITEM, PRIORITY) |
| // |
| // This is the same as `uvm_rand_send except that the sequence item or sequence |
| // is executed with the priority specified in the argument. |
| |
| `define uvm_rand_send_pri(SEQ_OR_ITEM, PRIORITY) \ |
| `uvm_rand_send_pri_with(SEQ_OR_ITEM, PRIORITY, {}) |
| |
| |
| // MACRO: `uvm_rand_send_with |
| // |
| //| `uvm_rand_send_with(SEQ_OR_ITEM, CONSTRAINTS) |
| // |
| // This is the same as `uvm_rand_send except that the given constraint block is |
| // applied to the item or sequence in a randomize with statement before |
| // execution. |
| |
| `define uvm_rand_send_with(SEQ_OR_ITEM, CONSTRAINTS) \ |
| `uvm_rand_send_pri_with(SEQ_OR_ITEM, -1, CONSTRAINTS) |
| |
| |
| // MACRO: `uvm_rand_send_pri_with |
| // |
| //| `uvm_rand_send_pri_with(SEQ_OR_ITEM, PRIORITY, CONSTRAINTS) |
| // |
| // This is the same as `uvm_rand_send_pri except that the given constraint block |
| // is applied to the item or sequence in a randomize with statement before |
| // execution. |
| |
| `define uvm_rand_send_pri_with(SEQ_OR_ITEM, PRIORITY, CONSTRAINTS) \ |
| begin \ |
| uvm_sequence_base __seq; \ |
| if (!$cast(__seq,SEQ_OR_ITEM)) start_item(SEQ_OR_ITEM, PRIORITY);\ |
| else __seq.set_item_context(this,SEQ_OR_ITEM.get_sequencer()); \ |
| if ((__seq == null || !__seq.do_not_randomize) && !SEQ_OR_ITEM.randomize() with CONSTRAINTS ) begin \ |
| `uvm_warning("RNDFLD", "Randomization failed in uvm_rand_send_with action") \ |
| end\ |
| if (!$cast(__seq,SEQ_OR_ITEM)) finish_item(SEQ_OR_ITEM, PRIORITY);\ |
| else __seq.start(__seq.get_sequencer(), this, PRIORITY, 0);\ |
| end |
| |
| |
| `define uvm_create_seq(UVM_SEQ, SEQR_CONS_IF) \ |
| `uvm_create_on(UVM_SEQ, SEQR_CONS_IF.consumer_seqr) \ |
| |
| `define uvm_do_seq(UVM_SEQ, SEQR_CONS_IF) \ |
| `uvm_do_on(UVM_SEQ, SEQR_CONS_IF.consumer_seqr) \ |
| |
| `define uvm_do_seq_with(UVM_SEQ, SEQR_CONS_IF, CONSTRAINTS) \ |
| `uvm_do_on_with(UVM_SEQ, SEQR_CONS_IF.consumer_seqr, CONSTRAINTS) \ |
| |
| |
| |
| //----------------------------------------------------------------------------- |
| // |
| // Group- Sequence Library |
| // |
| //----------------------------------------------------------------------------- |
| |
| |
| // MACRO: `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 |
| |
| |
| `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: `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. |
| |
| `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: Sequencer Subtypes |
| // |
| //----------------------------------------------------------------------------- |
| |
| |
| // MACRO: `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 |
| // |
| |
| `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 |
| |