//**********************************************************************
// Searchable FIFO
//----------------------------------------------------------------------
// $Id: _SFIFO.bsv,v 1.1 2007/03/21 22:27:21 jrk Exp $
//

import FIFO::*;
import EHR2::*;

//-----------------------------------------------------------
// SFIFO interface
//-----------------------------------------------------------

interface SFIFO#( type item_t, type search_t );

  method Action enq( item_t item );

  method Action deq();

  method item_t first();

  method Bool find( search_t searchItem );   

  method Bool find2( search_t searchItem );

endinterface

//-----------------------------------------------------------
// SFIFO 2 element module with Pipeline schedule
//-----------------------------------------------------------
// first < deq < { find CF find2 } < enq 
// 

module mkSFIFO2_Psched#( function Bool searchfunc( search_t sitem, item_t item ) )
                       ( SFIFO#( item_t, search_t ) )
                       provisos ( Bits#(item_t,item_sz_t) );

  EHR2_Reg#(item_t) data0 <- mkEHR2_Reg(?);
  EHR2_Reg#(item_t) data1 <- mkEHR2_Reg(?);

  EHR2_Reg#(Bool) valid0 <- mkEHR2_Reg(False);
  EHR2_Reg#(Bool) valid1 <- mkEHR2_Reg(False);

  method Action enq( item_t item ) if ( !valid0.read_1() || !valid1.read_1() );

    if ( !valid0.read_1() )
     begin
      valid0.write_1( True );
      data0.write_1( item );
     end
    else if ( !valid1.read_1() )
     begin
      valid1.write_1( True );
      data1.write_1( item );
     end

    if ( !valid0.read_1() && valid1.read_1() )
      $display( " RTL-ERROR : %m : !valid0 && valid1 " );

  endmethod

  method Action deq() if ( valid0.read_0() );
    valid0.write_0( valid1.read_0() );
    valid1.write_0( False );
    data0.write_0( data1.read_0() );    
  endmethod

  method item_t first() if ( valid0.read_0() );
    return data0.read_0();
  endmethod

  method Bool find( search_t searchItem );
    Bool match0 = valid0.read_1() && searchfunc( searchItem, data0.read_1() );
    Bool match1 = valid1.read_1() && searchfunc( searchItem, data1.read_1() );
    return ( match0 || match1 );
  endmethod

  method Bool find2( search_t searchItem );
    Bool match0 = valid0.read_1() && searchfunc( searchItem, data0.read_1() );
    Bool match1 = valid1.read_1() && searchfunc( searchItem, data1.read_1() );
    return ( match0 || match1 );
  endmethod

endmodule
