/*
 * $Id$
 *
 * [ Description ]
 * 
 */

#include "Behavioural/Stage_1_Ifetch/Predictor/Meta_Predictor/Two_Level_Branch_Predictor/include/Parameters.h"

namespace morpheo {
namespace behavioural {
namespace stage_1_ifetch {
namespace predictor {
namespace meta_predictor {
namespace two_level_branch_predictor {


  Parameters::Parameters (bool     have_bht              ,
			  uint32_t bht_size_shifter      ,
			  uint32_t bht_nb_shifter        ,
			  bool     have_pht              ,
			  uint32_t pht_size_counter      ,
			  uint32_t pht_nb_counter        ,
			  uint32_t pht_size_address_share,
			  uint32_t size_address          ,
			  uint32_t nb_prediction         ,
			  uint32_t nb_branch_complete    ) : 
    _have_bht               (have_bht          ),
    _bht_size_shifter       ((_have_bht == true)?bht_size_shifter:0),
    _bht_nb_shifter         ((_have_bht == true)?bht_nb_shifter  :0),
    _have_pht               (have_pht          ),
    _pht_size_counter       ((_have_pht == true)?pht_size_counter:0),
    _pht_nb_counter         ((_have_pht == true)?pht_nb_counter  :0),
    _pht_size_address_share (((_have_bht and _have_pht) == true)?pht_size_address_share:0),
    _size_address           (size_address      ),
    _nb_prediction          (nb_prediction     ),
    _nb_branch_complete     (nb_branch_complete),
    _bht_size_address       (static_cast<uint32_t>(ceil(log2(bht_nb_shifter)))),
    _pht_size_address       (static_cast<uint32_t>(ceil(log2(pht_nb_counter))))
  {
    log_printf(FUNC,Two_Level_Branch_Predictor,"Parameters","Begin");
    
    if (_have_bht)
    _param_branch_history_table  = new morpheo::behavioural::stage_1_ifetch::predictor::meta_predictor::two_level_branch_predictor::branch_history_table ::Parameters (_bht_size_shifter  ,
																				       _bht_nb_shifter    ,
																				       _nb_prediction     ,
																				       _nb_branch_complete);
    if (_have_pht)
    _param_pattern_history_table = new morpheo::behavioural::stage_1_ifetch::predictor::meta_predictor::two_level_branch_predictor::pattern_history_table::Parameters (_pht_size_counter  ,
																				       _pht_nb_counter    ,
																				       _nb_prediction     ,
																				       _nb_branch_complete);
    
                                                     
    _param_two_level_branch_predictor_glue = new morpheo::behavioural::stage_1_ifetch::predictor::meta_predictor::two_level_branch_predictor::two_level_branch_predictor_glue::Parameters (_have_bht              ,
																							   _bht_size_shifter      ,
																							   _bht_size_address      ,
																							   _have_pht              ,
																							   _pht_size_address      ,
																							   _pht_size_address_share,
																							   _size_address          ,
																							   _nb_prediction         ,
																							   _nb_branch_complete    );

    test();
    log_printf(FUNC,Two_Level_Branch_Predictor,"Parameters","End");
  };
  
  Parameters::Parameters (Parameters & param) :
    _have_bht               (param._have_bht              ),
    _bht_size_shifter       (param._bht_size_shifter      ),
    _bht_nb_shifter         (param._bht_nb_shifter        ),
    _have_pht               (param._have_pht              ),
    _pht_size_counter       (param._pht_size_counter      ),
    _pht_nb_counter         (param._pht_nb_counter        ),
    _pht_size_address_share (param._pht_size_address_share),
    _size_address           (param._size_address          ),
    _nb_prediction          (param._nb_prediction         ),
    _nb_branch_complete     (param._nb_branch_complete    ),
    _bht_size_address       (param._bht_size_address      ),
    _pht_size_address       (param._pht_size_address      )

  {
    log_printf(FUNC,Two_Level_Branch_Predictor,"Parameters","Begin");

    if (_have_bht)
    _param_branch_history_table  = new morpheo::behavioural::stage_1_ifetch::predictor::meta_predictor::two_level_branch_predictor::branch_history_table ::Parameters (_bht_size_shifter  ,
																				       _bht_nb_shifter    ,
																				       _nb_prediction     ,
																				       _nb_branch_complete);
    if (_have_pht)
    _param_pattern_history_table = new morpheo::behavioural::stage_1_ifetch::predictor::meta_predictor::two_level_branch_predictor::pattern_history_table::Parameters (_pht_size_counter  ,
																				       _pht_nb_counter    ,
																				       _nb_prediction     ,
																				       _nb_branch_complete);

    _param_two_level_branch_predictor_glue = new morpheo::behavioural::stage_1_ifetch::predictor::meta_predictor::two_level_branch_predictor::two_level_branch_predictor_glue::Parameters (_have_bht              ,
																							   _bht_size_shifter      ,
																							   _bht_size_address      ,
																							   _have_pht              ,
																							   _pht_size_address      ,
																							   _pht_size_address_share,
																							   _size_address          ,
																							   _nb_prediction         ,
																							   _nb_branch_complete    );

    test();
    log_printf(FUNC,Two_Level_Branch_Predictor,"Parameters","End");
  };

  Parameters::~Parameters () 
  {
    log_printf(FUNC,Two_Level_Branch_Predictor,"~Parameters","Begin");

    if (_have_bht)
    delete _param_branch_history_table;
    if (_have_pht)
    delete _param_pattern_history_table;
    delete _param_two_level_branch_predictor_glue;
    log_printf(FUNC,Two_Level_Branch_Predictor,"~Parameters","End");
  };

}; // end namespace two_level_branch_predictor
}; // end namespace meta_predictor
}; // end namespace predictor
}; // end namespace stage_1_ifetch

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