/*
 * $Id: Parameters.cpp 88 2008-12-10 18:31:39Z rosiere $
 *
 * [ Description ]
 * 
 */

#include "Behavioural/Core/Multi_OOO_Engine/OOO_Engine/OOO_Engine_Glue/include/Parameters.h"
#include "Common/include/Max.h"
#include "Common/include/BitManipulation.h"

namespace morpheo {
namespace behavioural {
namespace core {
namespace multi_ooo_engine {
namespace ooo_engine {
namespace ooo_engine_glue {

#undef  FUNCTION
#define FUNCTION "OOO_Engine_Glue::Parameters"
  Parameters::Parameters (uint32_t                nb_front_end                           ,
                          uint32_t              * nb_context                             ,
                          uint32_t                nb_rename_unit                         ,
                          uint32_t              * nb_inst_decod                          ,
                          uint32_t              * nb_inst_insert                         ,
                          uint32_t              * nb_inst_retire                         ,
                          uint32_t                size_general_data                      ,
                          uint32_t                size_special_data                      ,
                          uint32_t              * link_rename_unit_with_front_end        ,
                          std::vector<uint32_t> * translate_front_end_id_from_rename_unit,
                          uint32_t                size_packet_id                         ,
                          uint32_t                size_general_register                  ,
                          uint32_t                size_special_register                  ,
                          uint32_t                size_store_queue_ptr                   ,
                          uint32_t                size_load_queue_ptr                    ,
                          bool                    is_toplevel                            )
  {
    log_begin(OOO_Engine_Glue,FUNCTION);

    _nb_front_end                           = nb_front_end                    ;
    _nb_context                             = nb_context                      ;
    _nb_rename_unit                         = nb_rename_unit                  ;
    _nb_inst_decod                          = nb_inst_decod                   ;
    _nb_inst_insert                         = nb_inst_insert                  ;
    _nb_inst_retire                         = nb_inst_retire                  ;
    _link_rename_unit_with_front_end        = link_rename_unit_with_front_end ;
    _translate_front_end_id_from_rename_unit= translate_front_end_id_from_rename_unit ;
                                            
//  _rename_unit_nb_front_end               = rename_unit_nb_front_end        ;
//  _rename_unit_nb_context                 = rename_unit_nb_context          ;
//  _rename_unit_size_front_end_id          = rename_unit_size_front_end_id   ;
//  _rename_unit_size_context_id            = rename_unit_size_context_id     ;
    _size_rename_id                         = log2(_nb_rename_unit)           ;
    _sum_inst_insert                        = 0;
//     _sum_inst_retire                        = 0;

    for (uint32_t i=0; i<_nb_rename_unit; ++i)
      {
        _sum_inst_insert += _nb_inst_insert[i];
//         _sum_inst_retire += _nb_inst_retire[i];
      }

    _translate_front_end_id_to_rename_unit  = new uint32_t [_nb_front_end];
    
    for (uint32_t i=0; i<_nb_front_end; i++)
      {
        _translate_front_end_id_to_rename_unit [i]=0;
        
        uint32_t x = _link_rename_unit_with_front_end [i];

        for (uint32_t j=0; j<_translate_front_end_id_from_rename_unit [x].size(); ++j)
          {
            if (_translate_front_end_id_from_rename_unit [x][j] == i)
              break;
            _translate_front_end_id_to_rename_unit [i]++;
          }
      }
    
    _mask_num_general_register              = gen_mask<Tgeneral_address_t>(size_general_register);
    _mask_num_special_register              = gen_mask<Tspecial_address_t>(size_special_register);

    test();

    if (is_toplevel)
      {
        _size_context_id                        = log2(max<uint32_t>(_nb_context,_nb_front_end));
        _size_front_end_id                      = log2(_nb_front_end)  ;
        _size_rob_ptr                           = size_packet_id       ;
        _size_general_data                      = size_general_data    ;
        _size_special_data                      = size_special_data    ;
        _size_general_register                  = size_general_register;
        _size_special_register                  = size_special_register;
        _size_store_queue_ptr                   = size_store_queue_ptr ;
        _size_load_queue_ptr                    = size_load_queue_ptr  ;
        
        _have_port_context_id                   = _size_context_id     > 0;
        _have_port_front_end_id                 = _size_front_end_id   > 0;
        _have_port_rob_ptr                      = _size_rob_ptr        > 0;
        _have_port_load_queue_ptr               = _size_load_queue_ptr > 0;
        
        copy();
      }

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

#undef  FUNCTION
#define FUNCTION "OOO_Engine_Glue::~Parameters"
  Parameters::~Parameters (void) 
  {
    log_begin(OOO_Engine_Glue,FUNCTION);
    delete _translate_front_end_id_to_rename_unit;
    log_end(OOO_Engine_Glue,FUNCTION);
  };

#undef  FUNCTION
#define FUNCTION "OOO_Engine_Glue::copy"
  void Parameters::copy (void) 
  {
    log_begin(OOO_Engine_Glue,FUNCTION);
    log_end(OOO_Engine_Glue,FUNCTION);
  };

}; // end namespace ooo_engine_glue
}; // end namespace ooo_engine
}; // end namespace multi_ooo_engine
}; // end namespace core

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