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

#include "Behavioural/Core/Multi_Front_end/Front_end/Prediction_unit/Branch_Target_Buffer/Branch_Target_Buffer_Register/include/Parameters.h"
#include "Common/include/BitManipulation.h"
#include "Common/include/Max.h"

namespace morpheo {
namespace behavioural {
namespace core {
namespace multi_front_end {
namespace front_end {
namespace prediction_unit {
namespace branch_target_buffer {
namespace branch_target_buffer_register {


#undef  FUNCTION
#define FUNCTION "Branch_Target_Buffer_Register::Parameters"
  Parameters::Parameters (uint32_t   nb_context     ,
			  uint32_t * nb_instruction ,
			  uint32_t   size_buffer    ,
			  uint32_t   associativity  ,
			  uint32_t   size_address   ,
			  uint32_t   size_counter   ,
			  uint32_t   nb_inst_predict,
			  uint32_t   nb_inst_decod  ,
			  uint32_t   nb_inst_update )
  {
    log_printf(FUNC,Branch_Target_Buffer_Register,FUNCTION,"Begin");

    _nb_context      = nb_context     ;
    _nb_instruction  = nb_instruction ;
    _size_buffer     = size_buffer    ;
    _associativity   = associativity  ;
    _size_address    = size_address   ;
    _size_counter    = size_counter   ;
    _nb_inst_predict = nb_inst_predict;
    _nb_inst_decod   = nb_inst_decod  ;
    _nb_inst_update  = nb_inst_update ;

    _size_bank       = size_buffer/associativity;
    _size_context_id = log2(nb_context);
    _size_victim     = log2(associativity);

    _have_port_context_id   = (_size_context_id > 0);
    _have_port_victim       = (_size_victim     > 0);

    _accurate_max           = (1<<_size_counter);
    _accurate_limit         = (_accurate_max*PERCENT_ACCURATE_LIMIT)/100;
    _first_accurate_if_hit  = (1<<(_size_counter-1));   //b1000
    _first_accurate_if_miss = _first_accurate_if_hit-1; //b0111

    uint32_t max_inst = max<uint32_t>(nb_instruction, nb_context);
    uint32_t size_offset = log2(max_inst);
    uint32_t size_bank   = log2(_size_bank);

    _mask_offset  = gen_mask<Tgeneral_data_t> (size_offset);
    _mask_bank    = gen_mask<Tgeneral_data_t> (size_bank  );
    _shift_offset = 2;
    _shift_bank   = _shift_offset+size_offset;
    _shift_tag    = _shift_bank  +size_bank  ;

//     std::cout << "max_inst     : " << toString(max_inst   ) << std::endl;
//     std::cout << "size_offset  : " << toString(size_offset) << std::endl;
//     std::cout << "size_bank    : " << toString(size_bank  ) << std::endl;
//     std::cout << "mask_offset  : " << toString(_mask_offset ) << std::endl;
//     std::cout << "mask_bank    : " << toString(_mask_bank   ) << std::endl;
//     std::cout << "shift_offset : " << toString(_shift_offset) << std::endl;
//     std::cout << "shift_bank   : " << toString(_shift_bank  ) << std::endl;
//     std::cout << "shift_tag    : " << toString(_shift_tag   ) << std::endl;
//     std::cout << "accurate_max           : " << toString(_accurate_max          ) << std::endl;
//     std::cout << "first_accurate_if_hit  : " << toString(_first_accurate_if_hit ) << std::endl;
//     std::cout << "first_accurate_if_miss : " << toString(_first_accurate_if_miss) << std::endl;
//     std::cout << "accurate_limit         : " << toString(_accurate_limit        ) << std::endl;

    test();

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

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

}; // end namespace branch_target_buffer_register
}; // end namespace branch_target_buffer
}; // end namespace prediction_unit
}; // end namespace front_end
}; // end namespace multi_front_end
}; // end namespace core

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