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

#include "Behavioural/Core/Multi_Front_end/Front_end/Prediction_unit/Branch_Target_Buffer/include/Parameters.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 {


#undef  FUNCTION
#define FUNCTION "Branch_Target_Buffer::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 ,
			  Tvictim_t  victim_scheme  )
  {
    log_printf(FUNC,Branch_Target_Buffer,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 ;
    _victim_scheme   = victim_scheme  ;

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

    _have_port_context_id   = (_size_context_id > 0);
    _have_component_victim  = (_size_victim     > 0);
    _is_full_associative    = _size_bank == 1;
    uint32_t nb_access = nb_inst_predict + nb_inst_decod + nb_inst_update;

    if (_have_component_victim)
      {
	_param_sort = new morpheo::behavioural::generic::sort::Parameters
	  (_associativity, // nb_input
	   1             , // nb_output
	   true          , // ascending
	   _size_victim  , // size_data
	   true          , // have_port_index_out
	   false           // have_port_data_out 
	   );

	_param_victim = new morpheo::behavioural::generic::victim::Parameters
	  (_victim_scheme, //victim_scheme
	   _associativity, //nb_entity    
	   _size_bank    , //nb_entry     
	   nb_access     , //nb_access    
	   false           //table_global 
	   );
      }

    _param_branch_target_buffer_glue = new morpheo::behavioural::core::multi_front_end::front_end::prediction_unit::branch_target_buffer::branch_target_buffer_glue::Parameters
      (
       max<uint32_t>(_nb_instruction, _nb_context),
       _size_buffer       ,
       _associativity     ,
       _size_address      ,
       _nb_inst_predict   ,
       _nb_inst_decod     ,
       _nb_inst_update    );
    
    _param_branch_target_buffer_register = new morpheo::behavioural::core::multi_front_end::front_end::prediction_unit::branch_target_buffer::branch_target_buffer_register::Parameters
      (_nb_context     ,
       _nb_instruction ,
       _size_buffer    ,
       _associativity  ,
       _size_address   ,
       _size_counter   ,
       _nb_inst_predict,
       _nb_inst_decod  ,
       _nb_inst_update );

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

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

    if (_have_component_victim)
      {
	delete _param_sort;
	delete _param_victim;
      }

    delete _param_branch_target_buffer_glue;
    delete _param_branch_target_buffer_register;

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

}; // 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              
