/*
 * $Id: Parameters.cpp 111 2009-02-27 18:37:40Z rosiere $
 *
 * [ Description ]
 * 
 */

#include "Behavioural/Core/Multi_Front_end/Front_end/Prediction_unit/Direction/include/Parameters.h"

namespace morpheo {
namespace behavioural {
namespace core {
namespace multi_front_end {
namespace front_end {
namespace prediction_unit {
namespace direction {


#undef  FUNCTION
#define FUNCTION "Direction::Parameters"
  Parameters::Parameters (Tpredictor_t predictor_scheme          ,
			  uint32_t     nb_inst_predict           ,
			  uint32_t     nb_inst_update            ,
			  uint32_t     size_address              ,
			  bool         have_bht               [3],
			  uint32_t     bht_size_shifter       [3],
			  uint32_t     bht_nb_shifter         [3],
			  bool         have_pht               [3],
			  uint32_t     pht_size_counter       [3],
			  uint32_t     pht_nb_counter         [3],
			  uint32_t     pht_size_address_share [3],
                          bool         is_toplevel)
  {
    log_printf(FUNC,Direction,FUNCTION,"Begin");

    _predictor_scheme       = predictor_scheme      ;
    _nb_inst_predict        = nb_inst_predict       ;
    _nb_inst_update         = nb_inst_update        ;
//  _size_address           = size_address          ;
    
    for (uint32_t i=0; i<3; i++)
      {
	_have_bht               [i] = have_bht               [i];
	_bht_size_shifter       [i] = bht_size_shifter       [i];
	_bht_nb_shifter         [i] = bht_nb_shifter         [i];
	_have_pht               [i] = have_pht               [i];
	_pht_size_counter       [i] = pht_size_counter       [i];
	_pht_nb_counter         [i] = pht_nb_counter         [i];
	_pht_size_address_share [i] = pht_size_address_share [i];
      }

    switch (predictor_scheme)
      {
      case PREDICTOR_NEVER_TAKE  :
      case PREDICTOR_ALWAYS_TAKE :
      case PREDICTOR_STATIC      :
      case PREDICTOR_LAST_TAKE   : 
	{
	  _have_component_meta_predictor = false;

	  for (uint32_t i=0; i<3; i++)
	    {
	      _have_bht [i] = false;
	      _have_pht [i] = false;
	    }

	  break;
	}
      case PREDICTOR_COUNTER     :
	{
	  _have_bht [0] = false;
	  _have_pht [0] = true ;
	  for (uint32_t i=1; i<3; i++)
	    {
	      _have_bht [i] = false;
	      _have_pht [i] = false;
	    }

	  _have_component_meta_predictor = true;
	  break;
	}
      case PREDICTOR_LOCAL       :
	{
	  _have_bht       [0] = true;
	  _have_pht       [0] = true;
	  _bht_nb_shifter [0] = (_bht_nb_shifter [0]<2)?2:_bht_nb_shifter [0]; // min : 2
	  for (uint32_t i=1; i<3; i++)
	    {
	      _have_bht [i] = false;
	      _have_pht [i] = false;
	    }

	  _have_component_meta_predictor = true;
	  break;
	}
      case PREDICTOR_GLOBAL      :
	{
	  
	  _have_bht       [0] = true;
	  _have_pht       [0] = true;
	  _bht_nb_shifter [0] = 1; // one global shifter
	  for (uint32_t i=1; i<3; i++)
	    {
	      _have_bht [i] = false;
	      _have_pht [i] = false;
	    }

	  _have_component_meta_predictor = true;
	  break;
	}
      case PREDICTOR_META        :
	{
	  // predictor_0 = global
	  // predictor_1 = local
	  // predictor_2 = counter : select between predictor_0 and predictor_1
	  _have_bht       [0] = true;
	  _have_pht       [0] = true;
	  _bht_nb_shifter [0] = (_bht_nb_shifter [0]<2)?2:_bht_nb_shifter [0]; // min : 2
	  _have_bht       [1] = true;
	  _have_pht       [1] = true;
	  _bht_nb_shifter [1] = 1; // one global shifter
	  _have_bht       [2] = false;
	  _have_pht       [2] = true;

	  _have_component_meta_predictor = true;
	  break;
	}
      case PREDICTOR_CUSTOM      :
	{
	  // keep user define
	  _have_component_meta_predictor = true;
	  break;
	}
      }

    test();

    if (_have_component_meta_predictor)
      _param_meta_predictor = new morpheo::behavioural::core::multi_front_end::front_end::prediction_unit::direction::meta_predictor::Parameters
        (
         _nb_inst_predict       ,
         _nb_inst_update        ,
          size_address          ,
         _have_bht              ,
         _bht_size_shifter      ,
         _bht_nb_shifter        ,
         _have_pht              ,
         _pht_size_counter      ,
         _pht_nb_counter        ,
         _pht_size_address_share
         );
    
    _size_history = (_have_component_meta_predictor)?_param_meta_predictor->_size_history:0;

    log_printf(TRACE,Direction,FUNCTION,"  * size_history : %d",_size_history);

//     _size_history = 0;
//     for (uint32_t i=0; i<3; i++)
//       _size_history += (((_have_bht [i])?_bht_size_shifter [i]:0) + 
// 			   ((_have_pht [i])?_pht_size_counter [i]:0));
   
     _have_port_history = (_size_history > 0);

    _param_glue = new morpheo::behavioural::core::multi_front_end::front_end::prediction_unit::direction::direction_glue::Parameters
      (_predictor_scheme,
       _nb_inst_predict ,
       _nb_inst_update  ,
        size_address    ,
       _size_history    );

    if (is_toplevel)
      {
        _size_instruction_address = size_address;

        copy ();
      }
    
    log_printf(FUNC,Direction,FUNCTION,"End");
  };
  
// #undef  FUNCTION
// #define FUNCTION "Direction::Parameters (copy)"
//   Parameters::Parameters (Parameters & param)
//   {
//     log_printf(FUNC,Direction,FUNCTION,"Begin");
//     test();
//     log_printf(FUNC,Direction,FUNCTION,"End");
//   };

#undef  FUNCTION
#define FUNCTION "Direction::~Parameters"
  Parameters::~Parameters () 
  {
    log_printf(FUNC,Direction,FUNCTION,"Begin");

    delete _param_glue;
    if (_have_component_meta_predictor)
    delete _param_meta_predictor;

    log_printf(FUNC,Direction,FUNCTION,"End");
  };

#undef  FUNCTION
#define FUNCTION "Direction::copy"
  void Parameters::copy (void) 
  {
    log_printf(FUNC,Direction,FUNCTION,"Begin");

    COPY(_param_glue);

    log_printf(FUNC,Direction,FUNCTION,"End");
  };

}; // end namespace direction
}; // end namespace prediction_unit
}; // end namespace front_end
}; // end namespace multi_front_end
}; // end namespace core

}; // end namespace behavioural
}; // end namespace morpheo              
