/*
 * $Id: Parameters_msg_error.cpp 117 2009-05-16 14:42:39Z rosiere $
 *
 * [ Description ]
 * 
 */

#include "Behavioural/include/Types.h"
#include "Behavioural/Core/include/Parameters.h"
#include "Common/include/Max.h"
#include <sstream>

namespace morpheo                    {
namespace behavioural {
namespace core {


#undef  FUNCTION
#define FUNCTION "Core::msg_error"
  Parameters_test Parameters::msg_error(void)
  {
    log_begin(Core,FUNCTION);

    Parameters_test test ("Core");

    // TESTER SI LES VALEURS NE DEPASSE PAS DE L'INTERVALLE AUTORISE

    {
      // initialisation
      uint32_t nb_link_context [_nb_front_end][max<uint32_t>(_nb_context,_nb_front_end)];
      
      for (uint32_t i=0; i<_nb_front_end; ++i)
        for (uint32_t j=0; j<_nb_context[i];++j)
          nb_link_context [i][j] = 0;
      
      // set link
      for (uint32_t i=0; i<_nb_thread; ++i)
        nb_link_context[_link_context_with_thread[i].first][_link_context_with_thread[i].second] ++;

      // test
      for (uint32_t i=0; i<_nb_front_end; ++i)
        for (uint32_t j=0; j<_nb_context[i];++j)
          {
            if (nb_link_context[i][j] == 0)
              test.error(toString(_("Context [%d][%d] is not link with a thread.\n"),i,j));
            if (nb_link_context[i][j]  > 1)
              test.error(toString(_("Context [%d][%d] is linked with 2 or more threads.\n"),i,j));
          }
    }

    {
      // initialisation
      uint32_t nb_link_decod_unit [_nb_front_end][max<uint32_t>(_nb_decod_unit,_nb_front_end)];
      
      for (uint32_t i=0; i<_nb_front_end; ++i)
        for (uint32_t j=0; j<_nb_decod_unit[i];++j)
          nb_link_decod_unit [i][j] = 0;
      
      // set link
      for (uint32_t i=0; i<_nb_decod_bloc; ++i)
        nb_link_decod_unit[_link_decod_unit_with_decod_bloc[i].first][_link_decod_unit_with_decod_bloc[i].second] ++;

      // test
      for (uint32_t i=0; i<_nb_front_end; ++i)
        for (uint32_t j=0; j<_nb_decod_unit[i];++j)
          {
            if (nb_link_decod_unit[i][j] == 0)
              test.error(toString(_("Decod_Unit [%d][%d] is not link with a decod_bloc.\n"),i,j));
            if (nb_link_decod_unit[i][j]  > 1)
              test.error(toString(_("Decod_Unit [%d][%d] is linked with 2 or more decod_bloc.\n"),i,j));
          }
    }

    {
      // initialisation
      uint32_t nb_link_rename_unit [_nb_ooo_engine][max<uint32_t>(_nb_rename_unit,_nb_ooo_engine)];
      
      for (uint32_t i=0; i<_nb_ooo_engine; ++i)
        for (uint32_t j=0; j<_nb_rename_unit[i];++j)
          nb_link_rename_unit [i][j] = 0;
      
      // set link
      for (uint32_t i=0; i<_nb_rename_bloc; ++i)
        nb_link_rename_unit[_link_rename_unit_with_rename_bloc[i].first][_link_rename_unit_with_rename_bloc[i].second] ++;

      // test
      for (uint32_t i=0; i<_nb_ooo_engine; ++i)
        for (uint32_t j=0; j<_nb_rename_unit[i];++j)
          {
            if (nb_link_rename_unit[i][j] == 0)
              test.error(toString(_("Rename_Unit [%d][%d] is not link with a rename_bloc.\n"),i,j));
            if (nb_link_rename_unit[i][j]  > 1)
              test.error(toString(_("Rename_Unit [%d][%d] is linked with 2 or more rename_bloc.\n"),i,j));
          }
    }

    {
      // initialisation
      uint32_t nb_link_read_unit [_nb_execute_loop][max<uint32_t>(_nb_read_unit,_nb_execute_loop)];
      
      for (uint32_t i=0; i<_nb_execute_loop; ++i)
        for (uint32_t j=0; j<_nb_read_unit[i];++j)
          nb_link_read_unit [i][j] = 0;
      
      // set link
      for (uint32_t i=0; i<_nb_read_bloc; ++i)
        nb_link_read_unit[_link_read_unit_with_read_bloc[i].first][_link_read_unit_with_read_bloc[i].second] ++;

      // test
      for (uint32_t i=0; i<_nb_execute_loop; ++i)
        for (uint32_t j=0; j<_nb_read_unit[i];++j)
          {
            if (nb_link_read_unit[i][j] == 0)
              test.error(toString(_("Read_Unit [%d][%d] is not link with a read_bloc.\n"),i,j));
            if (nb_link_read_unit[i][j]  > 1)
              test.error(toString(_("Read_Unit [%d][%d] is linked with 2 or more read_bloc.\n"),i,j));
          }
    }

    {
      // initialisation
      uint32_t nb_link_write_unit [_nb_execute_loop][max<uint32_t>(_nb_write_unit,_nb_execute_loop)];
      
      for (uint32_t i=0; i<_nb_execute_loop; ++i)
        for (uint32_t j=0; j<_nb_write_unit[i];++j)
          nb_link_write_unit [i][j] = 0;
      
      // set link
      for (uint32_t i=0; i<_nb_write_bloc; ++i)
        nb_link_write_unit[_link_write_unit_with_write_bloc[i].first][_link_write_unit_with_write_bloc[i].second] ++;

      // test
      for (uint32_t i=0; i<_nb_execute_loop; ++i)
        for (uint32_t j=0; j<_nb_write_unit[i];++j)
          {
            if (nb_link_write_unit[i][j] == 0)
              test.error(toString(_("Write_Unit [%d][%d] is not link with a write_bloc.\n"),i,j));
            if (nb_link_write_unit[i][j]  > 1)
              test.error(toString(_("Write_Unit [%d][%d] is linked with 2 or more write_bloc.\n"),i,j));
          }
    }

    {
      // initialisation
      uint32_t nb_link_execute_unit [_nb_execute_loop][max<uint32_t>(_nb_execute_unit,_nb_execute_loop)];
//       uint32_t nb_functionnal_unit  [_nb_functionnal_unit];
//       uint32_t nb_load_store_unit   [_nb_load_store_unit];

//       for (uint32_t i=0; i<_nb_functionnal_unit; ++i)
//         nb_functionnal_unit [i] = 0;
      
//       for (uint32_t i=0; i<_nb_load_store_unit; ++i)
//         nb_load_store_unit  [i] = 0;
      
      for (uint32_t i=0; i<_nb_execute_loop; ++i)
        for (uint32_t j=0; j<_nb_execute_unit[i];++j)
          nb_link_execute_unit [i][j] = 0;

      // set link
      for (uint32_t i=0; i<_nb_functionnal_unit; ++i)
        {
          uint32_t num_execute_loop = _link_execute_unit_with_functionnal_unit [i].first;
          uint32_t num_execute_unit = _link_execute_unit_with_functionnal_unit [i].second;

          log_printf(TRACE,Core,FUNCTION,"  * _link_execute_unit_with_functionnal_unit [%d] = %d.%d",i,num_execute_loop,num_execute_unit);

          nb_link_execute_unit [num_execute_loop][num_execute_unit] ++;
//           nb_functionnal_unit  [i] ++;
        }
      for (uint32_t i=0; i<_nb_load_store_unit; ++i)
        {
          uint32_t num_execute_loop = _link_execute_unit_with_load_store_unit [i].first;
          uint32_t num_execute_unit = _link_execute_unit_with_load_store_unit [i].second;

          nb_link_execute_unit [num_execute_loop][num_execute_unit] ++;
//           nb_load_store_unit   [i] ++;
        }

      // test
      for (uint32_t i=0; i<_nb_execute_loop; ++i)
        for (uint32_t j=0; j<_nb_execute_unit[i];++j)
          {
            if (nb_link_execute_unit[i][j] == 0)
              test.error(toString(_("Execute_Unit [%d][%d] is not link with a load_store_unit or functionnal_unit.\n"),i,j));
            if (nb_link_execute_unit[i][j]  > 1)
              test.error(toString(_("Execute_Unit [%d][%d] is linked with 2 or more time.\n"),i,j));
          }

//       for (uint32_t i=0; i<_nb_functionnal_unit; ++i)
//         {
//           if (nb_functionnal_unit[i] == 0)
//             test.error(toString(_("Functionnal_Unit [%d] is not instanced.\n"),i));
//           if (nb_functionnal_unit[i]  > 1)
//             test.error(toString(_("Functionnal_Unit [%d] is linked with 2 or more time.\n"),i));
//         }

//       for (uint32_t i=0; i<_nb_load_store_unit; ++i)
//         {
//           if (nb_load_store_unit[i] == 0)
//             test.error(toString(_("Load_Store_Unit [%d] is not instanced.\n"),i));
//           if (nb_load_store_unit[i]  > 1)
//             test.error(toString(_("Load_Store_Unit [%d] is linked with 2 or more time.\n"),i));
//         }
    }
    
    {
      // initialisation
      uint32_t nb_link_slot      [_nb_ooo_engine][max<uint32_t>(_nb_inst_issue_slot,_nb_ooo_engine)];
      uint32_t nb_link_read_bloc [_nb_read_bloc];
  
      // initialisation
      for (uint32_t i=0; i<_nb_ooo_engine; ++i)
        for (uint32_t j=0; j<_nb_inst_issue_slot[i]; ++j)
          nb_link_slot [i][j] = 0;
      for (uint32_t i=0; i<_nb_read_bloc; ++i)
        nb_link_read_bloc [i] = 0;

      // set link
      for (uint32_t i=0; i<_nb_ooo_engine; ++i)
        for (uint32_t j=0; j<_nb_inst_issue_slot[i]; ++j)
          for (uint32_t k=0; k<_nb_read_bloc; ++k)
            if (_table_dispatch [i][j][k])
              {
                nb_link_slot      [i][j] ++;
                nb_link_read_bloc [k] ++;
              }
      
      // test
      for (uint32_t i=0; i<_nb_ooo_engine; ++i)
        for (uint32_t j=0; j<_nb_inst_issue_slot[i]; ++j)
          if (nb_link_slot [i][j] == 0)
            test.error(toString(_("In Out Of Order Engine [%d], the slot issue [%d] is not link with a read_bloc.\n"),i,j));
      for (uint32_t i=0; i<_nb_read_bloc; ++i)
        if (nb_link_read_bloc [i] == 0)
          test.error(toString(_("Read_bloc [%d] is not link with a issue's slot.\n"),i));
    }

    {
      uint32_t nb_link_read_bloc        [_nb_read_bloc];
      uint32_t nb_link_load_store_unit  [_nb_load_store_unit];
      uint32_t nb_link_functionnal_unit [_nb_functionnal_unit];

      for (uint32_t i=0; i<_nb_read_bloc; ++i)
        nb_link_read_bloc [i] = 0;
      for (uint32_t i=0; i<_nb_load_store_unit; ++i)
        nb_link_load_store_unit [i] = 0;
      for (uint32_t i=0; i<_nb_functionnal_unit; ++i)
        nb_link_functionnal_unit [i] = 0;

      for (uint32_t i=0; i<_nb_read_bloc; ++i)
        {
          for (uint32_t j=0; j<_nb_load_store_unit; ++j)
            if (_link_read_bloc_and_load_store_unit [i][j])
              {
                nb_link_read_bloc        [i] ++;
                nb_link_load_store_unit  [j] ++;
              }
          for (uint32_t j=0; j<_nb_functionnal_unit; ++j)
            if (_link_read_bloc_and_functionnal_unit [i][j])
              {
                nb_link_read_bloc        [i] ++;
                nb_link_functionnal_unit [j] ++;
              }
        }

      for (uint32_t i=0; i<_nb_read_bloc; ++i)
        if (nb_link_read_bloc [i] == 0)
          test.error(toString(_("Read_bloc [%d] is not link with an execute_unit.\n"),i));
      for (uint32_t i=0; i<_nb_load_store_unit; ++i)
        if (nb_link_load_store_unit [i] == 0)
          test.error(toString(_("load_store_unit [%d] is not link with a read_bloc.\n"),i));
      for (uint32_t i=0; i<_nb_functionnal_unit; ++i)
        if (nb_link_functionnal_unit [i] == 0)
          test.error(toString(_("functionnal_unit [%d] is not link with a read_bloc.\n"),i));
    }

    {
      uint32_t nb_link_write_bloc       [_nb_write_bloc];
      uint32_t nb_link_load_store_unit  [_nb_load_store_unit];
      uint32_t nb_link_functionnal_unit [_nb_functionnal_unit];

      for (uint32_t i=0; i<_nb_write_bloc; ++i)
        nb_link_write_bloc [i] = 0;
      for (uint32_t i=0; i<_nb_load_store_unit; ++i)
        nb_link_load_store_unit [i] = 0;
      for (uint32_t i=0; i<_nb_functionnal_unit; ++i)
        nb_link_functionnal_unit [i] = 0;

      for (uint32_t i=0; i<_nb_write_bloc; ++i)
        {
          for (uint32_t j=0; j<_nb_load_store_unit; ++j)
            if (_link_write_bloc_and_load_store_unit [i][j])
              {
                nb_link_write_bloc       [i] ++;
                nb_link_load_store_unit  [j] ++;
              }
          for (uint32_t j=0; j<_nb_functionnal_unit; ++j)
            if (_link_write_bloc_and_functionnal_unit [i][j])
              {
                nb_link_write_bloc       [i] ++;
                nb_link_functionnal_unit [j] ++;
              }
        }

      for (uint32_t i=0; i<_nb_write_bloc; ++i)
        if (nb_link_write_bloc [i] == 0)
          test.error(toString(_("Write_bloc [%d] is not link with an execute_unit.\n"),i));
      for (uint32_t i=0; i<_nb_load_store_unit; ++i)
        if (nb_link_load_store_unit [i] == 0)
          test.error(toString(_("load_store_unit [%d] is not link with a write_bloc.\n"),i));
      for (uint32_t i=0; i<_nb_functionnal_unit; ++i)
        if (nb_link_functionnal_unit [i] == 0)
          test.error(toString(_("functionnal_unit [%d] is not link with a write_bloc.\n"),i));
    }

    {
      uint32_t nb_link_thread           [_nb_thread];
      uint32_t nb_link_load_store_unit  [_nb_load_store_unit];
      uint32_t nb_link_functionnal_unit [_nb_functionnal_unit];

      for (uint32_t i=0; i<_nb_thread; ++i)
        nb_link_thread [i] = 0;
      for (uint32_t i=0; i<_nb_load_store_unit; ++i)
        nb_link_load_store_unit [i] = 0;
      for (uint32_t i=0; i<_nb_functionnal_unit; ++i)
        nb_link_functionnal_unit [i] = 0;
      
      for (uint32_t i=0; i<_nb_thread; ++i)
        {
          {
            uint32_t num_load_store_unit = _link_load_store_unit_with_thread [i];
            
            nb_link_thread           [i] ++;
            nb_link_load_store_unit  [num_load_store_unit] ++;
          }

          for (uint32_t j=0; j<_nb_functionnal_unit; ++j)
            if (_link_thread_and_functionnal_unit [i][j])
              {
                nb_link_thread           [i] ++;
                nb_link_functionnal_unit [j] ++;
              }
        }

      for (uint32_t i=0; i<_nb_thread; ++i)
        if (nb_link_thread [i] < 2)
          test.error(toString(_("Thread [%d] is not link with a load_store_unit and a functionnal_unit.\n"),i));
      for (uint32_t i=0; i<_nb_load_store_unit; ++i)
        if (nb_link_load_store_unit [i] == 0)
          test.error(toString(_("Load_store_unit [%d] is not link with a thread.\n"),i));
      for (uint32_t i=0; i<_nb_functionnal_unit; ++i)
        if (nb_link_functionnal_unit [i] == 0)
          test.error(toString(_("Functionnal_unit [%d] is not link with a thread.\n"),i));
    }
    
    {
      uint32_t nb_link_icache_port [_nb_icache_port];

      for (uint32_t i=0; i<_nb_icache_port; ++i)
        nb_link_icache_port [i] = 0;

      for (uint32_t i=0; i<_nb_thread; ++i)
        nb_link_icache_port [_link_icache_port_with_thread [i]] ++;
      
      for (uint32_t i=0; i<_nb_icache_port; ++i)
        if (nb_link_icache_port [i] == 0)
          test.error(toString(_("Icache port [%d] is not link with a thread.\n"),i));
    }

    {
      uint32_t nb_link_dcache_port [_nb_dcache_port];

      for (uint32_t i=0; i<_nb_dcache_port; ++i)
        nb_link_dcache_port [i] = 0;
          
      for (uint32_t i=0; i<_nb_load_store_unit; ++i)
        for (uint32_t j=0; j<_nb_cache_port[i]; ++j)
        nb_link_dcache_port [_link_dcache_port_with_load_store_unit[i][j]] ++;
      
      for (uint32_t i=0; i<_nb_dcache_port; ++i)
        if (nb_link_dcache_port [i] == 0)
          test.error(toString(_("Dcache port [%d] is not link with a port of load store unit.\n"),i));
    }


//   public : pair_dual             * _link_context_with_thread                      ;//[nb_thread]
//   public : pair_dual             * _link_decod_unit_with_decod_bloc               ;//[nb_decod_bloc]
//   public : pair_dual             * _link_rename_unit_with_rename_bloc             ;//[nb_rename_bloc]
//   public : pair_dual             * _link_read_unit_with_read_bloc                 ;//[nb_read_bloc]
//   public : pair_dual             * _link_write_unit_with_write_bloc               ;//[nb_write_bloc]
//   public : pair_dual             * _link_execute_unit_with_functionnal_unit       ;//[nb_functionnal_unit]
//   public : pair_dual             * _link_execute_unit_with_load_store_unit        ;//[nb_load_store_unit]
//   public : uint32_t              * _link_decod_bloc_with_thread                   ;//[nb_thread]
//   public : uint32_t              * _link_rename_bloc_with_front_end               ;//[nb_front_end]
//   public : bool                *** _table_dispatch                                ;//[nb_ooo_engine][nb_inst_issue][nb_read_bloc]
//   public : bool                 ** _link_read_bloc_and_load_store_unit            ;//[nb_read_bloc][nb_load_store_unit]
//   public : bool                 ** _link_read_bloc_and_functionnal_unit           ;//[nb_read_bloc][nb_functionnal_unit]
//   public : bool                 ** _link_write_bloc_and_load_store_unit           ;//[nb_write_bloc][nb_load_store_unit]
//   public : bool                 ** _link_write_bloc_and_functionnal_unit          ;//[nb_write_bloc][nb_functionnal_unit]
//   public : uint32_t              * _link_load_store_unit_with_thread              ;//[nb_thread]
//   public : bool                 ** _link_thread_and_functionnal_unit              ;//[nb_thread][nb_functionnal_unit]
//   public : uint32_t              * _link_icache_port_with_thread                  ;//[nb_thread]
//   public : uint32_t             ** _link_dcache_port_with_load_store_unit         ;//[nb_load_store_unit][nb_cache_port]

    log_end(Core,FUNCTION);

    return test;
  };

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