/*
 * $Id: Parameters.cpp 124 2009-06-17 12:11:25Z rosiere $
 *
 * [ Description ]
 * 
 */

#include "Behavioural/Core/Multi_Execute_loop/Execute_loop/include/Parameters.h"
#include "Common/include/Max.h"

namespace morpheo {
namespace behavioural {
namespace core {
namespace multi_execute_loop {
namespace execute_loop {


#undef  FUNCTION
#define FUNCTION "Execute_loop::Parameters"
  Parameters::Parameters (uint32_t              nb_read_unit                              ,
			  uint32_t              nb_functionnal_unit                       ,
			  uint32_t              nb_load_store_unit                        ,
			  uint32_t              nb_write_unit                             ,
			  
			  uint32_t              nb_context                                ,
			  uint32_t              nb_front_end                              ,
			  uint32_t              nb_ooo_engine                             ,
			  uint32_t              nb_packet                                 ,
			  uint32_t              size_general_data                         ,
			  uint32_t              size_special_data                         ,
			  
			  uint32_t            * size_read_queue                           ,//[nb_read_unit]
			  uint32_t            * size_reservation_station                  ,//[nb_read_unit]
			  uint32_t            * nb_inst_retire                            ,//[nb_read_unit]

			  uint32_t            * nb_inst_functionnal_unit                  ,//[nb_functionnal_unit]
			  execute_timing_t  *** timing                                    ,//[nb_functionnal_unit][nb_type][nb_operation]
			  morpheo::behavioural::custom::custom_information_t (*get_custom_information) (void),
			  
			  uint32_t            * size_store_queue                          ,//[nb_load_store_unit]
			  uint32_t            * size_load_queue                           ,//[nb_load_store_unit]
			  uint32_t            * size_speculative_access_queue             ,//[nb_load_store_unit]
			  uint32_t            * nb_port_check                             ,//[nb_load_store_unit]
			  Tspeculative_load_t * speculative_load                          ,//[nb_load_store_unit]
			  uint32_t            * nb_bypass_memory                          ,//[nb_load_store_unit]
			  uint32_t            * nb_cache_port                             ,//[nb_load_store_unit]
			  uint32_t            * nb_inst_memory                            ,//[nb_load_store_unit]

			  uint32_t            * size_write_queue                          ,//[nb_write_unit]
			  uint32_t            * size_execute_queue                        ,//[nb_write_unit]
			  uint32_t            * nb_bypass_write                           ,//[nb_write_unit]
			  multi_write_unit::write_unit::write_queue::Twrite_queue_scheme_t * write_queue_scheme,//[nb_write_unit]
			  
			  uint32_t              nb_gpr_bank                               ,
			  uint32_t              nb_gpr_port_read_by_bank                  ,
			  uint32_t              nb_gpr_port_write_by_bank                 ,
			  uint32_t              nb_spr_bank                               ,
			  uint32_t              nb_spr_port_read_by_bank                  ,
			  uint32_t              nb_spr_port_write_by_bank                 ,
			  uint32_t            * nb_general_register                       ,//[nb_ooo_engine]
			  uint32_t            * nb_special_register                       ,//[nb_ooo_engine]
			  uint32_t            * nb_inst_insert_rob                        ,//[nb_ooo_engine]
			  uint32_t            * nb_inst_retire_rob                        ,//[nb_ooo_engine]
			  
			  Tpriority_t           execution_unit_to_write_unit_priority     ,
                          bool              *** execution_unit_to_write_unit_table_routing,//[nb_execute_unit][nb_execute_unit_port][nb_write_unit]
                          bool               ** execution_unit_to_write_unit_table_thread ,//[nb_write_unit][nb_thread]

                          Tpriority_t           read_unit_to_execution_unit_priority      ,
                          bool              *** read_unit_to_execution_unit_table_routing ,//[nb_read_unit][nb_execute_unit][nb_execute_unit_port]
                          bool               ** read_unit_to_execution_unit_table_thread  ,//[nb_execute_unit][nb_thread]
                          
                          bool                * is_load_store_unit                        ,//[nb_execute_unit]
                          uint32_t            * translate_num_execute_unit                ,//[nb_execute_unit]

                          bool                * num_thread_valid                          ,//[nb_thread]
                          
                          bool                  is_toplevel
                          )
  {
    log_printf(FUNC,Execute_loop,FUNCTION,"Begin");

    _nb_read_unit                               = nb_read_unit                         ;
    _nb_functionnal_unit                        = nb_functionnal_unit                  ;
    _nb_load_store_unit                         = nb_load_store_unit                   ;
    _nb_write_unit                              = nb_write_unit                        ;
                                                
    _nb_context                                 = nb_context                           ;
    _nb_front_end                               = nb_front_end                         ;
    _nb_ooo_engine                              = nb_ooo_engine                        ;
    _nb_packet                                  = nb_packet                            ;
                                                
    _size_read_queue                            = size_read_queue                      ;
    _size_reservation_station                   = size_reservation_station             ;
    _nb_inst_retire                             = nb_inst_retire                       ;
                                                
    _nb_inst_functionnal_unit                   = nb_inst_functionnal_unit             ;
    _timing                                     = timing                               ;
    _get_custom_information                     = get_custom_information               ;
                                                
    _size_store_queue                           = size_store_queue                     ;
    _size_load_queue                            = size_load_queue                      ;
    _size_speculative_access_queue              = size_speculative_access_queue        ;
    _nb_port_check                              = nb_port_check                        ;
    _speculative_load                           = speculative_load                     ;
    _nb_bypass_memory                           = nb_bypass_memory                     ;
    _nb_cache_port                              = nb_cache_port                        ;
    _nb_inst_memory                             = nb_inst_memory                       ;
                                                
    _size_write_queue                           = size_write_queue                     ;
    _size_execute_queue                         = size_execute_queue                   ;
    _nb_bypass_write                            = nb_bypass_write                      ;
    _write_queue_scheme                         = write_queue_scheme                   ;
                                                
    _nb_gpr_bank                                = nb_gpr_bank                          ;
    _nb_gpr_port_read_by_bank                   = nb_gpr_port_read_by_bank             ;
    _nb_gpr_port_write_by_bank                  = nb_gpr_port_write_by_bank            ;
    _nb_spr_bank                                = nb_spr_bank                          ;
    _nb_spr_port_read_by_bank                   = nb_spr_port_read_by_bank             ;
    _nb_spr_port_write_by_bank                  = nb_spr_port_write_by_bank            ;
    _nb_general_register                        = nb_general_register                  ;
    _nb_special_register                        = nb_special_register                  ;
    _nb_inst_insert_rob                         = nb_inst_insert_rob                   ;
    _nb_inst_retire_rob                         = nb_inst_retire_rob                   ;
    
    _execution_unit_to_write_unit_priority      = execution_unit_to_write_unit_priority;
    _execution_unit_to_write_unit_table_routing = execution_unit_to_write_unit_table_routing;
    _execution_unit_to_write_unit_table_thread  = execution_unit_to_write_unit_table_thread ;
    
    _read_unit_to_execution_unit_priority       = read_unit_to_execution_unit_priority      ;
    _read_unit_to_execution_unit_table_routing  = read_unit_to_execution_unit_table_routing ;
    _read_unit_to_execution_unit_table_thread   = read_unit_to_execution_unit_table_thread  ;

    _is_load_store_unit                         = is_load_store_unit        ;
    _translate_num_execute_unit                 = translate_num_execute_unit;

    _num_thread_valid                           = num_thread_valid;

    _nb_execute_unit                            = _nb_functionnal_unit + _nb_load_store_unit;

    _nb_execute_unit_port                       = new uint32_t [_nb_execute_unit];
    
    _read_unit_to_execution_unit_table_execute_type = new bool * [_nb_execute_unit];
    for (uint32_t i=0; i<_nb_execute_unit; i++)
      {
	_read_unit_to_execution_unit_table_execute_type [i] = new bool [_nb_type];
	for (uint32_t j=0; j<_nb_type; j++)
	  _read_unit_to_execution_unit_table_execute_type [i][j] = false;
      }

    // Fill execute_type
    for (uint32_t i=0; i<_nb_execute_unit; i++)
      // is load store 
      if (is_load_store_unit [i])
        _read_unit_to_execution_unit_table_execute_type [i][TYPE_MEMORY] = true;
      else
        for (uint32_t j=0; j<_nb_type; j++)
          if (is_type_valid (j))
            for (uint32_t k=0; k<_nb_operation; k++)
              {
                uint32_t x = translate_num_execute_unit [i];
                if (timing[x][j][k]._latence > 0)
                  {
                    log_printf(TRACE,Execute_loop,FUNCTION,"  * Execute unit '%d' (functional unit '%d') can execute type '%s'.",i,x,toString(j).c_str());
                    _read_unit_to_execution_unit_table_execute_type [i][j] = true;
                    break; // find an operation
                  }
              }

    for (uint32_t i=0; i<_nb_load_store_unit; ++i)
      log_printf(TRACE,Execute_loop,FUNCTION,"  * Load_store_unit  [%d] - nb_inst : %d",i,_nb_inst_memory [i]);
    for (uint32_t i=0; i<_nb_functionnal_unit; ++i)
      log_printf(TRACE,Execute_loop,FUNCTION,"  * Functionnal_unit [%d] - nb_inst : %d",i,_nb_inst_functionnal_unit [i]);


    for (uint32_t i=0; i<_nb_execute_unit; i++)
      {
        uint32_t x = translate_num_execute_unit [i];
        
        if (_is_load_store_unit [i])
          _nb_execute_unit_port [i] = _nb_inst_memory [x];
        else
          _nb_execute_unit_port [i] = _nb_inst_functionnal_unit [x];

        log_printf(TRACE,Execute_loop,FUNCTION,"  * Execute unit [%d] (%d) - nb_inst : %d",i,x,_nb_execute_unit_port [i]);
      }

    _nb_gpr_read  = 2*_nb_read_unit;
    _nb_spr_read  = 1*_nb_read_unit;
    _nb_gpr_write = 1*_nb_write_unit;
    _nb_spr_write = 1*_nb_write_unit;

    _max_nb_general_register = max<uint32_t>(nb_general_register,nb_ooo_engine);
    _max_nb_special_register = max<uint32_t>(nb_special_register,nb_ooo_engine);

    _max_size_store_queue    = max<uint32_t>(size_store_queue,nb_load_store_unit);
    _max_size_load_queue     = max<uint32_t>(size_load_queue ,nb_load_store_unit);

    uint32_t _nb_thread = get_nb_thread(_nb_context,
					_nb_front_end,
					_nb_ooo_engine);

    uint32_t _max_nb_inst_memory = max<uint32_t>(_nb_inst_memory,_nb_load_store_unit);

    _set_read_unit_source_register_write = new std::set<uint32_t> [_nb_read_unit];
    _set_read_unit_source_bypass_write   = new std::set<uint32_t> [_nb_read_unit];
    _set_read_unit_source_bypass_memory  = new std::set<uint32_t> [_nb_read_unit];
    
    _read_unit_nb_register_write          = new uint32_t [_nb_read_unit];
    _read_unit_nb_bypass_write            = new uint32_t [_nb_read_unit];
    _read_unit_nb_bypass_memory           = new uint32_t [_nb_read_unit];

    _link_read_unit_with_load_store_unit  = new bool ** [nb_read_unit];
    _link_read_unit_with_write_unit       = new bool *  [nb_read_unit];
    _link_read_unit_with_thread           = new bool *  [nb_read_unit];

    for (uint32_t i=0; i<_nb_read_unit; i++)
      {
	_read_unit_nb_register_write [i] = 0;
	_read_unit_nb_bypass_write   [i] = 0;
	_read_unit_nb_bypass_memory  [i] = 0;

	_link_read_unit_with_load_store_unit [i] = new bool * [_nb_execute_unit];
	_link_read_unit_with_write_unit      [i] = new bool   [_nb_write_unit];
	_link_read_unit_with_thread          [i] = new bool   [_nb_thread];

	for (uint32_t j=0; j<_nb_execute_unit; j++)
	  {
	    _link_read_unit_with_load_store_unit [i][j] = new bool [_max_nb_inst_memory];

	    for (uint32_t k=0; k<_max_nb_inst_memory; k++)
	      _link_read_unit_with_load_store_unit [i][j][k] = false;
	  }
	for (uint32_t j=0; j<_nb_write_unit; j++)
	  _link_read_unit_with_write_unit [i][j] = false;
	for (uint32_t j=0; j<_nb_thread; j++)
	  _link_read_unit_with_thread [i][j] = false;
	
	// fill link array
	for (uint32_t x=0; x<_nb_execute_unit; x++)
	  for (uint32_t y=0; y<_nb_execute_unit_port[x]; y++)
	    {
	      // Test if this read unit can send operation at this execute_unit
	      if (_read_unit_to_execution_unit_table_routing [i][x][y])
		{
		  if (_is_load_store_unit [x])
		    {
		      _link_read_unit_with_load_store_unit [i][x][y] = true;
		    }
		  
		  for (uint32_t k=0; k<_nb_thread; k++)
		    {
		      if (_read_unit_to_execution_unit_table_thread [x][k])
			{
			  _link_read_unit_with_thread [i][k] = true;
			}
		    }
		  // Scearch associed write_unit
		  for (uint32_t k=0; k<_nb_write_unit; k++)
		    {
                      log_printf(TRACE,Execute_loop,FUNCTION,"  * Execution_unit_to_write_unit_table_routing [%d][%d][%d]",x,y,k);

		      // Test if this execute_unit can send operation at this write_unit
		      // Test if have not a previous link ! (a same read_unit can send operation à two execute_unit and each execute_unit send at the same write_unit)
		      if (_execution_unit_to_write_unit_table_routing [x][y][k] and 
			  not _link_read_unit_with_write_unit [i][k])
			// if yes : this write_unit can have operation sended by this read_unit
			{
			  _link_read_unit_with_write_unit [i][k] = true;
			}
		    }
		}
	    }
      }

    // Compute the gpr_write and spr_write port for the read_unit :
    //   * Max : 2*nb_write_unit gpr_write_port.
    //   * a specific read_unit and a specific write_unit can execute a null intersection of thread operation. Also it's unnecessarry to send the gpr_write at the read_unit.

    
//     std::cout << "_link_......." << std::endl;
//     std::cout << "_link_read_unit_with_load_store_unit" << std::endl;
//     for (uint32_t i=0; i<_nb_read_unit; i++)
//       {
// 	std::cout << "\t" << std::endl;
// 	for (uint32_t j=0; j<_nb_execute_unit; j++)
// 	  for (uint32_t k=0; k<_nb_execute_unit_port[j]; k++)
// 	    std::cout << _link_read_unit_with_load_store_unit [i][j][k] << " ";
// 	std::cout << std::endl;
//       }
//     std::cout << "_link_read_unit_with_write_unit" << std::endl;
//     for (uint32_t i=0; i<_nb_read_unit; i++)
//       {
// 	std::cout << "\t" << std::endl;
// 	for (uint32_t j=0; j<_nb_write_unit; j++)
// 	  std::cout << _link_read_unit_with_write_unit [i][j] << " ";
// 	std::cout << std::endl;
//       }
//     std::cout << "_link_read_unit_with_thread" << std::endl;
//     for (uint32_t i=0; i<_nb_read_unit; i++)
//       {
// 	std::cout << "\t" << std::endl;
// 	for (uint32_t j=0; j<_nb_thread; j++)
// 	  std::cout << _link_read_unit_with_thread [i][j] << " ";
// 	std::cout << std::endl;
//       }

//     std::cout << "_set_......." << std::endl;

    for (uint32_t i=0; i<_nb_read_unit; i++)
      {
// 	std::cout << " * Read_unit[" << i << "]" << std::endl;
	for (uint32_t j=0; j<_nb_write_unit; j++)
	  {
// 	    std::cout << "   * Write_unit[" << j << "]" << std::endl;
	    // Test the thread executed on this write_unit
	    for (uint32_t k=0; k<_nb_thread; k++)
	      {
// 		std::cout << "     * Thread[" << k << "]" << std::endl;
		if ( (_execution_unit_to_write_unit_table_thread [j][k]) and
		     (_link_read_unit_with_thread [i][k]))
		  {
// 		    std::cout << "       * Find !!!!" << std::endl;
// 		    std::cout << "         * Read_unit "+toString(i)+" must take the gpr_write with write_unit "+toString(j)+"." << std::endl;
		    _set_read_unit_source_register_write[i].insert(j);
		    _read_unit_nb_register_write        [i] ++;

// 		    std::cout << "       * bypass_write : " << _nb_bypass_write [j] << std::endl;
// 		    std::cout << "         * Read_unit "+toString(i)+" must take the bypass_write with write_unit "+toString(j)+"." << std::endl;		    
		    _set_read_unit_source_bypass_write  [i].insert(j);
		    _read_unit_nb_bypass_write          [i] += _nb_bypass_write [j];
		    break;
		  }
	      }
	  }
      }

    for (uint32_t i=0; i<_nb_read_unit; i++)
      {
// 	std::cout << " * Read_unit[" << i << "]" << std::endl;
	for (uint32_t j=0; j<_nb_execute_unit; j++)
	  {
            uint32_t x = translate_num_execute_unit [j];

// 	    std::cout << "   * Execute_unit[" << j << "]" << std::endl;
	    // Test the thread executed on this execute_unit
	    for (uint32_t k=0; k<_nb_thread; k++)	
	      {
// 		std::cout << "     * Thread[" << k << "]" << std::endl;
		if ((_read_unit_to_execution_unit_table_thread [j][k]) and
		    (_link_read_unit_with_thread [i][k]) and
		    (_is_load_store_unit [j]))
		  {
// 		    std::cout << "       * Find !!!!" << std::endl;
// 		    std::cout << "       * Bypass_memory !!!!" << std::endl;
// 		    std::cout << "         * Read_unit "+toString(i)+" must take the bypass_memory with load_store_unit "+toString(j)+"." << std::endl;		    
		    
		    _set_read_unit_source_bypass_memory [i].insert(j);
		    _read_unit_nb_bypass_memory         [i] += _nb_bypass_memory [x];
                    
		    break; // loop on thread
		  }
	      }
	  }
      }

    uint32_t size_ooo_engine_id      = log2(nb_ooo_engine        );
    uint32_t size_general_register   = log2(_max_nb_general_register);
    uint32_t size_special_register   = log2(_max_nb_special_register);
    
    test();

    log_printf(TRACE,Execute_loop,FUNCTION,"Parameters : glue");

    _param_glue = new morpheo::behavioural::core::multi_execute_loop::execute_loop::execute_loop_glue::Parameters
	(_nb_gpr_write              ,
	 _nb_spr_write              ,
	  size_ooo_engine_id        ,
	  size_general_register     ,
	  size_special_register     ,
	  size_general_data         ,
	  size_special_data         );

    log_printf(TRACE,Execute_loop,FUNCTION,"Parameters : read_unit");

    _param_read_unit = new morpheo::behavioural::core::multi_execute_loop::execute_loop::multi_read_unit::read_unit::Parameters * [_nb_read_unit];
    for (uint32_t i=0; i<_nb_read_unit; i++)
      _param_read_unit [i] = new morpheo::behavioural::core::multi_execute_loop::execute_loop::multi_read_unit::read_unit::Parameters 
	(_size_read_queue               [i],
	 _size_reservation_station      [i],
	 _nb_context                       ,
	 _nb_front_end                     ,
	 _nb_ooo_engine                    ,
	 _nb_packet                        ,
	  size_general_data                ,
	  size_special_data                ,
	 _max_nb_general_register          ,
	 _max_nb_special_register          ,
	 1*_read_unit_nb_register_write [i],
	 1*_read_unit_nb_register_write [i],
	 _max_size_store_queue             ,
	 _max_size_load_queue              ,
	 _nb_inst_retire                [i],
	 _read_unit_nb_bypass_write     [i],
	 _read_unit_nb_bypass_memory    [i]);
    
    log_printf(TRACE,Execute_loop,FUNCTION,"Parameters : execute_unit");

    _param_functionnal_unit = new morpheo::behavioural::core::multi_execute_loop::execute_loop::multi_execute_unit::execute_unit::functionnal_unit::Parameters * [_nb_functionnal_unit];
    _param_load_store_unit = new morpheo::behavioural::core::multi_execute_loop::execute_loop::multi_execute_unit::execute_unit::load_store_unit::Parameters * [_nb_load_store_unit];

    for (uint32_t i=0; i<_nb_execute_unit; i++)
      {
        uint32_t x = _translate_num_execute_unit [i];
        if (_is_load_store_unit [i] == false)
	  _param_functionnal_unit [x] = new morpheo::behavioural::core::multi_execute_loop::execute_loop::multi_execute_unit::execute_unit::functionnal_unit::Parameters
	    (_nb_context                 ,
	     _nb_front_end               ,
	     _nb_ooo_engine              ,
	     _nb_packet                  ,
	      size_general_data          ,
	     _max_nb_general_register    ,
	      size_special_data          ,
	     _max_nb_special_register    ,
	     _max_size_store_queue       ,
	     _max_size_load_queue        ,
	     _timing                  [x],
	     _get_custom_information     );
        else
	  _param_load_store_unit [x] = new morpheo::behavioural::core::multi_execute_loop::execute_loop::multi_execute_unit::execute_unit::load_store_unit::Parameters
	    (_size_store_queue              [x],
	     _size_load_queue               [x],
	     _size_speculative_access_queue [x],
	     _nb_port_check                 [x],
	     _speculative_load              [x],
	     _nb_bypass_memory              [x],
	     _nb_cache_port                 [x],
	     _nb_inst_memory                [x],
	     _nb_context                       ,
	     _nb_front_end                     ,
	     _nb_ooo_engine                    ,
	     _nb_packet                        ,
	      size_general_data                ,
	      size_special_data                ,
	     _max_nb_special_register          ,
	     _max_nb_general_register          ,
             _nb_thread                        ,
             _num_thread_valid                 );
      }

    log_printf(TRACE,Execute_loop,FUNCTION,"Parameters : write_unit");
    
    _param_write_unit = new morpheo::behavioural::core::multi_execute_loop::execute_loop::multi_write_unit::write_unit::Parameters * [_nb_write_unit];
    for (uint32_t i=0; i<_nb_write_unit; i++)
      _param_write_unit [i] = new morpheo::behavioural::core::multi_execute_loop::execute_loop::multi_write_unit::write_unit::Parameters
	(_size_write_queue        [i],
	 _size_execute_queue      [i],
	 _nb_context                 ,
	 _nb_front_end               ,
	 _nb_ooo_engine              ,
	 _nb_packet                  ,
	  size_general_data          ,
	 _max_nb_general_register    ,
	  size_special_data          ,
	 _max_nb_special_register    ,
	 _nb_bypass_write         [i],
	 _write_queue_scheme      [i]);

    log_printf(TRACE,Execute_loop,FUNCTION,"Parameters : read_unit_to_execution_unit");

    _param_read_unit_to_execution_unit = new morpheo::behavioural::core::multi_execute_loop::execute_loop::network::read_unit_to_execution_unit::Parameters
      (_nb_read_unit                                  ,
       _nb_inst_retire                                ,
       _nb_execute_unit                               ,
       _nb_execute_unit_port                          ,
       _nb_context                                    ,
       _nb_front_end                                  ,
       _nb_ooo_engine                                 ,
       _nb_packet                                     ,
        size_general_data                             ,
        size_special_data                             ,
       _max_nb_general_register                       ,
       _max_nb_special_register                       ,
       _max_size_store_queue                          ,
       _max_size_load_queue                           ,
       _read_unit_to_execution_unit_priority          ,
       _read_unit_to_execution_unit_table_routing     ,
       _read_unit_to_execution_unit_table_execute_type,
       _read_unit_to_execution_unit_table_thread      ,
       _num_thread_valid);
    
    log_printf(TRACE,Execute_loop,FUNCTION,"Parameters : execution_unit_to_write_unit");

    _param_execution_unit_to_write_unit = new morpheo::behavioural::core::multi_execute_loop::execute_loop::network::execution_unit_to_write_unit::Parameters
      (_nb_execute_unit                           ,
       _nb_execute_unit_port                      ,
       _nb_write_unit                             ,
       _nb_context                                ,
       _nb_front_end                              ,
       _nb_ooo_engine                             ,
       _nb_packet                                 ,
        size_general_data                         ,
        size_special_data                         ,
       _max_nb_general_register                   ,
       _max_nb_special_register                   ,
       _execution_unit_to_write_unit_priority     ,
       _execution_unit_to_write_unit_table_routing,
       _execution_unit_to_write_unit_table_thread ,
       _num_thread_valid);
      
    log_printf(TRACE,Execute_loop,FUNCTION,"Parameters : register_unit");

    _param_register_unit = new morpheo::behavioural::core::multi_execute_loop::execute_loop::register_unit::Parameters
	(_nb_ooo_engine             ,
	  size_general_data         ,
	  size_special_data         ,
	 _nb_gpr_read               ,
	 _nb_gpr_write              ,
	 _nb_gpr_bank               ,
	 _nb_gpr_port_read_by_bank  ,
	 _nb_gpr_port_write_by_bank ,
	 _nb_spr_read               ,
	 _nb_spr_write              ,
	 _nb_spr_bank               ,
	 _nb_spr_port_read_by_bank  ,
	 _nb_spr_port_write_by_bank ,
	 _nb_general_register       ,
	 _nb_special_register       ,
	 _nb_inst_insert_rob        ,
	 _nb_inst_retire_rob        );

    _max_size_dcache_context_id = 0;
    _max_size_dcache_packet_id  = 0;
    
    for (uint32_t i=0; i<_nb_load_store_unit; i++)    
      {
	if (_param_load_store_unit [i]->_size_dcache_context_id > _max_size_dcache_context_id) _max_size_dcache_context_id = _param_load_store_unit [i]->_size_dcache_context_id;
	if (_param_load_store_unit [i]->_size_dcache_packet_id  > _max_size_dcache_packet_id)  _max_size_dcache_packet_id  = _param_load_store_unit [i]->_size_dcache_packet_id;
      }

//     log_printf(TRACE,Load_store_unit,FUNCTION,"kane : size_dcache_context_id      : %d",_max_size_dcache_context_id     );
//     log_printf(TRACE,Load_store_unit,FUNCTION,"kane : size_dcache_packet_id       : %d",_max_size_dcache_packet_id      );

    _have_port_dcache_context_id = (_max_size_dcache_context_id>0);

//     log_printf(TRACE,Load_store_unit,FUNCTION,"kane : have_port_dcache_context_id : %d",_have_port_dcache_context_id);

    if (is_toplevel)
      {
        _size_instruction_address= size_general_data-2;
        _size_context_id         = log2(nb_context);
        _size_front_end_id       = log2(nb_front_end);
        _size_ooo_engine_id      = size_ooo_engine_id;
        _size_rob_ptr            = log2(nb_packet);
        _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    = log2(_max_size_store_queue);
        _size_load_queue_ptr     = log2(_max_size_load_queue );
        
        _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_rob_ptr       = _size_rob_ptr        > 0;
        _have_port_load_queue_ptr= _size_load_queue_ptr > 0;

        copy();
      }

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

//     test();

//     log_printf(FUNC,Execute_loop,FUNCTION,"End");
//   };

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

    delete    _param_glue;
    for (uint32_t i=0; i<_nb_read_unit; i++)
    delete    _param_read_unit [i];
    delete [] _param_read_unit;

    for (uint32_t i=0; i<_nb_execute_unit; i++)
      {
        uint32_t x = _translate_num_execute_unit [i];

        if (_is_load_store_unit [i] == false)
          delete _param_functionnal_unit [x];
        else
          delete _param_load_store_unit [x];
      }
    delete [] _param_functionnal_unit;
    delete [] _param_load_store_unit;
    for (uint32_t i=0; i<_nb_write_unit; i++)
    delete    _param_write_unit [i];
    delete [] _param_write_unit;
    delete    _param_read_unit_to_execution_unit;
    delete    _param_execution_unit_to_write_unit;
    delete    _param_register_unit;

    delete [] _read_unit_to_execution_unit_table_execute_type;
    delete [] _read_unit_nb_register_write;
    delete [] _read_unit_nb_bypass_write;
    delete [] _read_unit_nb_bypass_memory;
    delete [] _set_read_unit_source_register_write ;
    delete [] _set_read_unit_source_bypass_write   ;
    delete [] _set_read_unit_source_bypass_memory  ;
    delete [] _link_read_unit_with_load_store_unit;
    delete [] _link_read_unit_with_write_unit;
    delete [] _link_read_unit_with_thread;
    delete [] _is_load_store_unit;
    delete [] _translate_num_execute_unit;
    delete [] _nb_execute_unit_port;
    log_printf(FUNC,Execute_loop,FUNCTION,"End");
  };


#undef  FUNCTION
#define FUNCTION "Execute_loop::copy"
  void Parameters::copy (void) 
  {
    log_printf(FUNC,Execute_loop,FUNCTION,"Begin");

    COPY(_param_glue);
    for (uint32_t i=0; i<_nb_read_unit; i++)
      COPY(_param_read_unit [i]);

    for (uint32_t i=0; i<_nb_execute_unit; i++)
      {
        uint32_t x = _translate_num_execute_unit [i];

        if (_is_load_store_unit [i] == false)
          COPY(_param_functionnal_unit [x]);
        else
          COPY(_param_load_store_unit [x]);
      }
    for (uint32_t i=0; i<_nb_write_unit; i++)
      COPY(_param_write_unit [i]);
    COPY(_param_read_unit_to_execution_unit);
    COPY(_param_execution_unit_to_write_unit);
    COPY(_param_register_unit);

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

}; // end namespace execute_loop
}; // end namespace multi_execute_loop
}; // end namespace core

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