#//
#//------------------------------------------------------------------------------
#//   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.
#//------------------------------------------------------------------------------
#
#//------------------------------------------------------------------------------
#// CLASS: uvm_random_stimulus #(T)
#//
#// A general purpose unidirectional random stimulus class.
#//
#// The uvm_random_stimulus class generates streams of T transactions. These streams
#// may be generated by the randomize method of T, or the randomize method of
#// one of its subclasses.  The stream may go indefinitely, until terminated
#// by a call to stop_stimulus_generation, or we may specify the maximum number
#// of transactions to be generated.
#//
#// By using inheritance, we can add directed initialization or tidy up after
#// random stimulus generation. Simply extend the class and define the run task,
#// calling super.run() when you want to begin the random stimulus phase of
#// simulation.
#//
#// While very useful in its own right, this component can also be used as a
#// template for defining other stimulus generators, or it can be extended to
#// add additional stimulus generation methods and to simplify test writing.
#//
#//------------------------------------------------------------------------------
#
#class uvm_random_stimulus #(type T=uvm_transaction) extends uvm_component;
#
#  const static string type_name = "uvm_random_stimulus #(T)";
#
#  typedef uvm_random_stimulus #(T) this_type;
#  `uvm_component_param_utils(this_type)
#
#  // Port: blocking_put_port
#  //
#  // The blocking_put_port is used to send the generated stimulus to the rest
#  // of the testbench.
#                                                      
#  uvm_blocking_put_port #(T) blocking_put_port;
#
#
#  // Function: new
#  //
#  // Creates a new instance of a specialization of this class.
#  // Also, displays the random state obtained from a get_randstate call.
#  // In subsequent simulations, set_randstate can be called with the same
#  // value to reproduce the same sequence of transactions.
#
#  function new(string name, uvm_component parent);
#
#    super.new(name, parent);
#
#    blocking_put_port=new("blocking_put_port", this);
#    
#    uvm_report_info("uvm_stimulus", {"rand state is ", get_randstate()});
#
#  endfunction
#
#
#  local bit m_stop;
#
#
#  // Function: generate_stimulus
#  //
#  // Generate up to max_count transactions of type T.
#  // If t is not specified, a default instance of T is allocated and used.
#  // If t is specified, that transaction is used when randomizing. It must
#  // be a subclass of T.
#  //
#  // max_count is the maximum number of transactions to be
#  // generated. A value of zero indicates no maximum - in
#  // this case, generate_stimulus will go on indefinitely
#  // unless stopped by some other process
#  //
#  // The transactions are cloned before they are sent out 
#  // over the blocking_put_port
#
#  virtual task generate_stimulus(T t=null, int max_count=0);
#
#    T temp;
#    
#    if (t == null)
#      t = new;
#    
#    for (int i=0; (max_count == 0 || i < max_count) && !m_stop; i++) begin
#
#       if (! t.randomize() )
#          uvm_report_warning ("RANDFL", "Randomization failed in generate_stimulus");
#      
#       $cast(temp, t.clone());
#       uvm_report_info("stimulus generation", temp.convert2string()); 
#       blocking_put_port.put(temp);
#    end
#  endtask
#  
#
#  // Function: stop_stimulus_generation
#  //
#  // Stops the generation of stimulus.
#  // If a subclass of this method has forked additional
#  // processes, those processes will also need to be
#  // stopped in an overridden version of this method
#  
#  virtual function void stop_stimulus_generation;
#    m_stop = 1;
#  endfunction
#  
#
#  virtual function string get_type_name();
#    return type_name;
#  endfunction
#
#endclass : uvm_random_stimulus
