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

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

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


#undef  FUNCTION
#define FUNCTION "Meta_Predictor::Parameters"
  Parameters::Parameters (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_begin(Meta_Predictor,FUNCTION);

    _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] = (_have_bht [i])?bht_size_shifter       [i]:0;
    _bht_nb_shifter         [i] = (_have_bht [i])?bht_nb_shifter         [i]:0;
    _have_pht               [i] =                 have_pht               [i];
    _pht_size_counter       [i] = (_have_pht [i])?pht_size_counter       [i]:0;
    _pht_nb_counter         [i] = (_have_pht [i])?pht_nb_counter         [i]:0;
    _pht_size_address_share [i] = (_have_bht[i] and _have_pht [i])?pht_size_address_share [i]:0;
      }

    test();

    _have_meta_predictor        = (_have_bht [2] or _have_pht [2]);
    _nb_predictor               = (_have_meta_predictor)?3:1;
    
    ALLOC1(_predictor_update_on_prediction,bool    , _nb_predictor);
    ALLOC1(_predictor_size_history        ,uint32_t, _nb_predictor);
    
    // All predictor can update on prediction ....
    for (uint32_t i=0; i<_nb_predictor; ++i)
      _predictor_update_on_prediction [i] = true;

    // ... But the selector prediction can't
    if (_have_meta_predictor)
      _predictor_update_on_prediction [_nb_predictor-1] = false;

    _param_two_level_branch_predictor = new morpheo::behavioural::core::multi_front_end::front_end::prediction_unit::direction::meta_predictor::two_level_branch_predictor::Parameters * [_nb_predictor];
    for (uint32_t i=0; i<_nb_predictor; ++i)
      {
        _param_two_level_branch_predictor [i] = new morpheo::behavioural::core::multi_front_end::front_end::prediction_unit::direction::meta_predictor::two_level_branch_predictor::Parameters
          (_nb_inst_predict                   ,
           _nb_inst_update                    ,
           _size_address                      ,
           _have_bht                       [i],
           _bht_size_shifter               [i],
           _bht_nb_shifter                 [i],
           _have_pht                       [i],
           _pht_size_counter               [i],
           _pht_nb_counter                 [i],
           _pht_size_address_share         [i],
           _predictor_update_on_prediction [i]
           );

        _predictor_size_history [i] = _param_two_level_branch_predictor [i]->_size_history;
      }

    _param_glue = new morpheo::behavioural::core::multi_front_end::front_end::prediction_unit::direction::meta_predictor::meta_predictor_glue::Parameters  
      (
       _nb_inst_predict               ,
       _nb_inst_update                ,
       _nb_predictor                  ,
       _predictor_size_history        ,
       _predictor_update_on_prediction
       );
    _size_history = _param_glue->_size_history;
    
    if (is_toplevel)
      {
        copy();
      }

    log_end(Meta_Predictor,FUNCTION);
  };
  
// #undef  FUNCTION
// #define FUNCTION "Meta_Predictor::Parameters (copy)"
//   Parameters::Parameters (Parameters & param)
//   {
//     log_begin(Meta_Predictor,FUNCTION);
//     test();
//     log_end(Meta_Predictor,FUNCTION);
//   };

#undef  FUNCTION
#define FUNCTION "Meta_Predictor::~Parameters"
  Parameters::~Parameters (void) 
  {
    log_begin(Meta_Predictor,FUNCTION);

    DELETE1(_param_two_level_branch_predictor, _nb_predictor);

    DELETE1(_predictor_size_history          , _nb_predictor);
    DELETE1(_predictor_update_on_prediction  , _nb_predictor);

    log_end(Meta_Predictor,FUNCTION);
  };

#undef  FUNCTION
#define FUNCTION "Meta_Predictor::copy"
  void Parameters::copy (void) 
  {
    log_begin(Meta_Predictor,FUNCTION);

    COPY(_param_glue);
    for (uint32_t i=0; i<_nb_predictor; ++i)
      COPY(_param_two_level_branch_predictor [i]);

    log_end(Meta_Predictor,FUNCTION);
  };

}; // end namespace meta_predictor
}; // 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              
