//
//------------------------------------------------------------------------------
//   Copyright 2007-2011 Mentor Graphics Corporation
//   Copyright 2007-2011 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.
//------------------------------------------------------------------------------

// File: Algorithmic Comparator
//
// A common function of testbenches is to compare streams of transactions for
// equivalence. For example, a testbench may compare a stream of transactions
// from a DUT with expected results.
//
// The UVM library provides a base class called 
// <uvm_in_order_comparator #(T,comp_type,convert,pair_type)> and two
// derived classes, which are <uvm_in_order_built_in_comparator #(T)> for comparing
// streams of built-in types and <uvm_in_order_class_comparator #(T)> for comparing
// streams of class objects.
//
// The uvm_algorithmic_comparator also compares two streams of transactions;
// however, the transaction streams might be of different type objects. This
// device will use a user-written transformation function to convert one type
// to another before performing a comparison.


//------------------------------------------------------------------------------
//
// CLASS: uvm_algorithmic_comparator #(BEFORE,AFTER,TRANSFORMER)
//
// Compares two streams of data objects of different types, ~BEFORE~ and ~AFTER~.
//
// The algorithmic comparator is a wrapper around <uvm_in_order_class_comparator #(T)>.
// Like the in-order comparator, the algorithmic comparator compares two streams
// of transactions, the ~BEFORE~ stream and the ~AFTER~ stream. It is often the case
// when two streams of transactions need to be compared that the two streams are
// in different forms. That is, the type of the ~BEFORE~ transaction stream is
// different than the type of the ~AFTER~ transaction stream.
//
// The uvm_algorithmic_comparator's ~TRANSFORMER~ type parameter specifies the
// class responsible for converting transactions of type ~BEFORE~ into those of
// type ~AFTER~. This transformer class must provide a transform() method with the
// following prototype:
//
//|    function AFTER transform (BEFORE b);
//
// Matches and mismatches are reported in terms of the ~AFTER~ transactions.
// For more information, see the 
// <uvm_in_order_comparator #(T,comp_type,convert,pair_type)> class.
//
//------------------------------------------------------------------------------


class [docs]uvm_algorithmic_comparator #( type BEFORE=int,
                                    type AFTER=int,
                                    type TRANSFORMER=int) extends uvm_component;

  const static string type_name = "uvm_algorithmic_comparator #(BEFORE,AFTER,TRANSFORMER)";

  typedef uvm_algorithmic_comparator #( BEFORE , 
                                        AFTER , 
                                        TRANSFORMER ) this_type;
  
  `uvm_component_param_utils(this_type)


  // Port: before_export
  //
  // The export to which a data stream of type BEFORE is sent via a connected
  // analysis port. Publishers (monitors) can send in an ordered stream of
  // transactions against which the transformed BEFORE transactions will
  // (be compared.

  uvm_analysis_imp #(BEFORE, this_type) before_export;


  // Port: after_export
  //
  // The export to which a data stream of type AFTER is sent via a connected
  // analysis port. Publishers (monitors) can send in an ordered stream of
  // transactions to be transformed and compared to the AFTER transactions.

  uvm_analysis_export #(AFTER) after_export;

 
  local uvm_in_order_class_comparator #(AFTER) comp;
  local TRANSFORMER m_transformer;
     
  // Function: new
  //
  // Creates an instance of a specialization of this class.
  // In addition to the standard uvm_component constructor arguments, ~name~
  // and ~parent~, the constructor takes a handle to a ~transformer~ object,
  // which must already be allocated (handles can't be ~null~) and must implement
  // the transform() method.

 function [docs]new(string name, uvm_component parent=null, TRANSFORMER transformer=null);

    super.new( name , parent );
     
    m_transformer = transformer;
    comp = new("comp", this );
    
    before_export = new("before_analysis_export" , this );
    after_export = new("after_analysis_export" , this );
  endfunction

  virtual function string [docs]get_type_name();
    return type_name;
  endfunction

  virtual function void [docs]connect_phase(uvm_phase phase);
    after_export.connect( comp.after_export );
  endfunction

  function void [docs]write( input BEFORE b );
    comp.before_export.write( m_transformer.transform( b ) );
  endfunction
      
endclass