/*
 * $Id: Parameters.cpp 120 2009-05-26 19:01:47Z rosiere $
 *
 * [ Description ]
 * 
 */

#include "Behavioural/Core/Core_Glue/include/Parameters.h"
#include "Behavioural/include/Allocation.h"
#include "Common/include/Max.h"

namespace morpheo {
namespace behavioural {
namespace core {
namespace core_glue {


#undef  FUNCTION
#define FUNCTION "Core_Glue::Parameters"
  Parameters::Parameters
  (uint32_t                nb_front_end                         ,
   uint32_t              * nb_context                           ,//[nb_front_end]
   uint32_t                nb_ooo_engine                        ,
   uint32_t                nb_execute_loop                      ,
   uint32_t              * ooo_engine_nb_front_end              ,//[nb_ooo_engine]
   uint32_t              * ooo_engine_nb_execute_loop           ,//[nb_ooo_engine]
   uint32_t              * execute_loop_nb_ooo_engine           ,//[nb_execute_loop]
   uint32_t              * nb_inst_decod                        ,//[nb_front_end] -> [sum_inst_decod]
   uint32_t              * front_end_nb_inst_branch_complete    ,//[nb_front_end]
   uint32_t              * ooo_engine_nb_inst_branch_complete   ,//[nb_ooo_engine]
   uint32_t              * nb_inst_insert                       ,//[nb_ooo_engine]
   uint32_t              * nb_inst_reexecute                    ,//[nb_ooo_engine]
   uint32_t              * nb_inst_issue_queue                  ,//[nb_ooo_engine]
   uint32_t              * nb_inst_issue_slot                   ,//[nb_ooo_engine]
   uint32_t             ** nb_inst_execute                      ,//[nb_ooo_engine][ooo_engine_nb_execute_loop]
   bool                  * issue_queue_in_order                 ,//[nb_ooo_engine]
   uint32_t              * nb_read_unit                         ,//[nb_execute_loop]
   uint32_t              * nb_write_unit                        ,//[nb_execute_loop]
   uint32_t                size_depth                           ,
   uint32_t                size_rob_ptr                         ,
   uint32_t                size_load_queue_ptr                  ,
   uint32_t                size_store_queue_ptr                 ,
   uint32_t                size_general_data                    ,
   uint32_t                size_special_data                    ,
   uint32_t                size_general_register                ,
   uint32_t                size_special_register                ,
   Tpriority_t             dispatch_priority                    ,
   Tload_balancing_t       dispatch_load_balancing              ,
   bool               **** table_dispatch                       ,//[nb_ooo_engine][nb_inst_issue_slot][execute_loop][nb_read_unit]
   bool                *** table_issue_type                     ,//                                   [execute_loop][nb_read_unit][nb_type]
   uint32_t             ** translate_ooo_engine_num_front_end   ,//[nb_ooo_engine][ooo_engine_nb_front_end]
   uint32_t             ** translate_ooo_engine_num_execute_loop,//[nb_ooo_engine][ooo_engine_nb_execute_loop]
   uint32_t             ** translate_execute_loop_num_ooo_engine,//[nb_execute_loop][execute_loop_nb_ooo_engine]
   bool                    is_toplevel)
  {
    log_begin(Core_Glue,FUNCTION);

    _nb_front_end                          = nb_front_end                         ;
    _nb_context                            = nb_context                           ;
    _nb_ooo_engine                         = nb_ooo_engine                        ;
    _nb_execute_loop                       = nb_execute_loop                      ;
    _ooo_engine_nb_front_end               = ooo_engine_nb_front_end              ;
    _ooo_engine_nb_execute_loop            = ooo_engine_nb_execute_loop           ;
    _execute_loop_nb_ooo_engine            = execute_loop_nb_ooo_engine           ;
    _nb_inst_decod                         = nb_inst_decod                        ;
    _front_end_nb_inst_branch_complete     = front_end_nb_inst_branch_complete    ;
    _ooo_engine_nb_inst_branch_complete    = ooo_engine_nb_inst_branch_complete   ;
    _nb_inst_insert                        = nb_inst_insert                       ;
    _nb_inst_reexecute                     = nb_inst_reexecute                    ;
    _nb_inst_issue_queue                   = nb_inst_issue_queue                  ;
    _nb_inst_issue_slot                    = nb_inst_issue_slot                   ;
    _nb_inst_execute                       = nb_inst_execute                      ;
    _issue_queue_in_order                  = issue_queue_in_order                 ;
    _nb_read_unit                          = nb_read_unit                         ;
    _nb_write_unit                         = nb_write_unit                        ;
    _dispatch_priority                     = dispatch_priority                    ;
    _dispatch_load_balancing               = dispatch_load_balancing              ;
    _table_dispatch                        = table_dispatch                       ;
    _table_issue_type                      = table_issue_type                     ;
    _translate_ooo_engine_num_front_end    = translate_ooo_engine_num_front_end   ;
    _translate_ooo_engine_num_execute_loop = translate_ooo_engine_num_execute_loop;
    _translate_execute_loop_num_ooo_engine = translate_execute_loop_num_ooo_engine;

    test();

    ALLOC1(_link_ooo_engine_with_front_end,uint32_t,_nb_front_end);
    ALLOC1(_translate_num_front_end_to_ooo_engine_front_end_id,uint32_t,_nb_front_end);
    for (uint32_t i=0; i<_nb_ooo_engine; ++i)
      for (uint32_t j=0; j<_ooo_engine_nb_front_end[i]; ++j)
        {
          uint32_t num_front_end = _translate_ooo_engine_num_front_end [i][j];
          
          _link_ooo_engine_with_front_end                     [num_front_end] = i;
          _translate_num_front_end_to_ooo_engine_front_end_id [num_front_end] = j;
        }

    ALLOC2(_translate_num_execute_loop_to_ooo_engine_execute_loop_id,uint32_t  ,_nb_execute_loop,_execute_loop_nb_ooo_engine[it1]);
    ALLOC2(_translate_num_ooo_engine_to_execute_loop_ooo_engine_id  ,Tcontext_t,_nb_ooo_engine,_nb_execute_loop);

    for (uint32_t i=0; i<_nb_ooo_engine; ++i)
      for (uint32_t j=0; j<_nb_execute_loop; ++j)
        _translate_num_ooo_engine_to_execute_loop_ooo_engine_id [i][j] = _nb_ooo_engine;

    for (uint32_t i=0; i<_nb_execute_loop; ++i)
      for (uint32_t j=0; j<_execute_loop_nb_ooo_engine[i]; ++j)
        {
          uint32_t num_ooo_engine  = _translate_execute_loop_num_ooo_engine [i][j];

          _translate_num_ooo_engine_to_execute_loop_ooo_engine_id [num_ooo_engine][i] = j;

          uint32_t execute_loop_id;
          for (execute_loop_id = 0; execute_loop_id<_ooo_engine_nb_execute_loop[num_ooo_engine]; ++execute_loop_id)
            if (_translate_ooo_engine_num_execute_loop [num_ooo_engine][execute_loop_id] == i)
              break;
          
          _translate_num_execute_loop_to_ooo_engine_execute_loop_id [i][j] = execute_loop_id;
        }

    ALLOC2(_execute_loop_nb_inst_insert,uint32_t,_nb_execute_loop,_execute_loop_nb_ooo_engine[it1]);
    ALLOC2(_execute_loop_nb_inst_issue_slot ,uint32_t,_nb_execute_loop,_execute_loop_nb_ooo_engine[it1]);

    for (uint32_t i=0; i<_nb_execute_loop; ++i)
      for (uint32_t j=0; j<_execute_loop_nb_ooo_engine[i]; ++j)
        {
          uint32_t num_ooo_engine = _translate_execute_loop_num_ooo_engine [i][j];
          _execute_loop_nb_inst_issue_slot [i][j] = _nb_inst_issue_slot [num_ooo_engine];
          _execute_loop_nb_inst_insert     [i][j] = _nb_inst_insert     [num_ooo_engine];
        }

    _max_ooo_engine_nb_inst_branch_complete = max<uint32_t>(_ooo_engine_nb_inst_branch_complete,_nb_ooo_engine);
    _max_front_end_nb_inst_branch_complete  = max<uint32_t>(_front_end_nb_inst_branch_complete,_nb_front_end);
    _max_ooo_engine_nb_execute_loop         = max<uint32_t>(_ooo_engine_nb_execute_loop,_nb_ooo_engine);
    _max_nb_inst_execute                    = max<uint32_t>(_nb_inst_execute           ,_nb_ooo_engine, _ooo_engine_nb_execute_loop);
    _max_nb_write_unit                      = max<uint32_t>(_nb_write_unit             ,_nb_execute_loop);
    _max_nb_inst_insert                     = max<uint32_t>(_nb_inst_insert            ,_nb_ooo_engine);
    _max_nb_inst_issue_queue                = max<uint32_t>(_nb_inst_issue_queue       ,_nb_ooo_engine);
    _max_nb_inst_issue_slot                 = max<uint32_t>(_nb_inst_issue_slot        ,_nb_ooo_engine);
    _max_nb_read_unit                       = max<uint32_t>(_nb_read_unit              ,_nb_execute_loop);

    if (is_toplevel)
      {
    _size_context_id                       = log2(max<uint32_t>(nb_context,nb_front_end));
    _size_front_end_id                     = log2(nb_front_end );
    _size_ooo_engine_id                    = log2(nb_ooo_engine);
    _size_instruction_address              = size_general_data-2  ;
    _size_data_address                     = size_general_data    ;
    _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_depth                            = size_depth           ;
    _size_rob_ptr                          = size_rob_ptr         ;
    _size_load_queue_ptr                   = size_load_queue_ptr  ;
    _size_store_queue_ptr                  = size_store_queue_ptr ;
//  _size_nb_inst_decod                    = size_nb_inst_decod   ;
//  _size_nb_inst_commit                   = size_nb_inst_commit  ;
//  _size_ifetch_queue_ptr                 = size_ifetch_queue_ptr;
//  _size_inst_ifetch_ptr                  = size_inst_ifetch_ptr ;
                                           
    _have_port_context_id                  = _size_context_id       > 0;
    _have_port_front_end_id                = _size_front_end_id     > 0;
    _have_port_ooo_engine_id               = _size_ooo_engine_id    > 0;
    _have_port_depth                       = _size_depth            > 0;
    _have_port_rob_ptr                     = _size_rob_ptr          > 0;
    _have_port_load_queue_ptr              = _size_load_queue_ptr   > 0;
//  _have_port_ifetch_queue_ptr            = _size_ifetch_queue_ptr > 0;
//  _have_port_inst_ifetch_ptr             = _size_inst_ifetch_ptr  > 0;

        copy();
      }

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

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

    DELETE2(_execute_loop_nb_inst_issue_slot                         ,_nb_execute_loop,_execute_loop_nb_ooo_engine[it1]);
    DELETE2(_execute_loop_nb_inst_insert                             ,_nb_execute_loop,_execute_loop_nb_ooo_engine[it1]);
    DELETE2(_translate_num_ooo_engine_to_execute_loop_ooo_engine_id  ,_nb_ooo_engine,_nb_execute_loop);
    DELETE2(_translate_num_execute_loop_to_ooo_engine_execute_loop_id,_nb_execute_loop,_execute_loop_nb_ooo_engine[it1]);
    DELETE1(_translate_num_front_end_to_ooo_engine_front_end_id      ,_nb_front_end);
    DELETE1(_link_ooo_engine_with_front_end                          ,_nb_front_end);

    log_end(Core_Glue,FUNCTION);
  };

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

}; // end namespace core_glue
}; // end namespace core

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