/*
 * $Id: Parameters_msg_error.cpp 109 2009-02-16 20:28:31Z rosiere $
 *
 * [ Description ]
 * 
 */

#include "Behavioural/include/Types.h"
#include "Behavioural/Core/Multi_Execute_loop/Execute_loop/Network/Read_unit_to_Execution_unit/include/Parameters.h"
#include <sstream>

namespace morpheo                    {
namespace behavioural {
namespace core {
namespace multi_execute_loop {
namespace execute_loop {
namespace network {
namespace read_unit_to_execution_unit {


#undef  FUNCTION
#define FUNCTION "Read_unit_to_Execution_unit::msg_error"
  Parameters_test Parameters::msg_error(void)
  {
    log_printf(FUNC,Read_unit_to_Execution_unit,FUNCTION,"Begin");

    Parameters_test test ("Read_unit_to_Execution_unit");

    // TYPE         | multiple? | Optionnal? | Exclusive? | Comment
    //--------------+-----------+------------+------------+---------
    // TYPE_ALU     |     X     |            |            |
    // TYPE_SHIFT   |     X     |            |            | ror is optionnal
    // TYPE_MOVE    |     X     |            |            | cmov is optionnal
    // TYPE_TEST    |     X     |            |            |
    // TYPE_MUL     |     X     |            |            |
    // TYPE_DIV     |     X     |     X      |            |
    // TYPE_EXTEND  |     X     |     X      |            |
    // TYPE_FIND    |     X     |     X      |            |
    // TYPE_SPECIAL |           |            |            | mac unit is optionnal
    // TYPE_CUSTOM  |           |     X      |            |
    // TYPE_BRANCH  |     X     |            |            |
    // TYPE_MEMORY  |           |            |     X      |
    
    bool type_present [_nb_thread][_nb_type];
    for (uint32_t i=0; i<_nb_thread; i++)
      for (Ttype_t j=0; j<_nb_type; j++)
	type_present [i][j] = false;
    
    for (uint32_t i=0; i<_nb_execute_unit; i++)
      for (uint32_t j=0; j<_nb_thread; j++)
	if (_table_execute_thread [i][j] == true)
	  // this execute_unit execute this thread !
	  for (Ttype_t k=0; k<_nb_type; k++)
            if (_table_execute_type[i][k] == true)
              {
//                 test.information(toString(_("Execute_unit [%d], Thread [%d], Type [%d], type_valid %d, type_present %d, type_uniq %d\n"),i,j,k,type_valid[k],type_present[j][k],type_uniq[k]));
                
                // Test uniq type
                if (type_present [j][k] and is_type_uniq(k))
                  test.error(toString(_("The execute_unit '%d' can execute operation of type '%s' at the thread '%d'. But an another execute_unit can be execute the same type for the same thread. And the type must be single !.\n"),i,toString(k).c_str(),j));
                
                type_present [j][k] = true;
              }

    for (Ttype_t j=0; j<_nb_type; j++)
      if (not is_type_valid(j))
	for (uint32_t i=0; i<_nb_thread; i++)
	  if (type_present [i][j])
	    test.error(toString(_("The thread '%d' can execute the type's operation '%s' but this type is invalid.\n"),i,toString(j).c_str()));

    for (Ttype_t j=0; j<_nb_type; j++)
      if (is_type_valid(j) and not is_type_optionnal(j))
	for (uint32_t i=0; i<_nb_thread; i++)
	  if (not type_present [i][j])
	    test.error(toString(_("The thread '%d' can't access at the execute_unit to execute the type's operation '%s' (and this type is not optional !).\n"),i,toString(j).c_str()));
	    
    // Test all excluve type
    for (uint32_t i=0; i<_nb_execute_unit; i++)
      for (Ttype_t j=0; j<_nb_type; j++)
	if (is_type_exclusive(j) and _table_execute_type[i][j])
	  for (Ttype_t k=0; k<_nb_type; k++)
	    if ((j != k) and (_table_execute_type[i][k] == true))
	      {
		test.error(toString(_("The execute_unit [%d] implement the type '%s', and this type is exclusive with all others type.\n"),i,toString(j).c_str()));
		break;
	      }

    for (uint32_t i=0; i<_nb_execute_unit; i++)
      {
	uint32_t j;
	for (j=0; j<_nb_thread; j++)
	  if (_table_execute_thread [i][j] == true)
	    break;

	if (j == _nb_thread)
	  test.error(toString(_("The execute_unit [%d] have none source's thread.\n"),i));
      }	  

    if ( (_priority != PRIORITY_STATIC     ) and
	 (_priority != PRIORITY_ROUND_ROBIN))
      test.error(_("Unsupported priority scheme. It must be Static or Round Robin.\n"));
        
    log_printf(FUNC,Read_unit_to_Execution_unit,FUNCTION,"End");

    return test;
  };

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

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