/*
 * $Id: main.cpp 112 2009-03-18 22:36:26Z rosiere $
 *
 * [ Description ]
 * 
 */

#include "Behavioural/Core/Multi_OOO_Engine/OOO_Engine/Rename_unit/SelfTest/include/test.h"

#define NB_PARAMS 13

void usage (int argc, char * argv[])
{
  err (_("<Usage> %s name_instance list_params.\n"),argv[0]);
  err (_("list_params is :\n"));
  err (_(" * nb_front_end                                                 (uint32_t         )\n"));
  err (_(" * nb_context                        [nb_front_end]             (uint32_t         )\n"));
  err (_(" * nb_inst_decod                     [nb_front_end]             (uint32_t         )\n"));
  err (_(" * nb_inst_insert                                               (uint32_t         )\n"));
  err (_(" * nb_inst_retire                                               (uint32_t         )\n"));
  err (_(" * nb_load_store_queue                                          (uint32_t         )\n"));
  err (_(" * size_store_queue                  [nb_load_store_queue]      (uint32_t         )\n"));
  err (_(" * size_load_queue                   [nb_load_store_queue]      (uint32_t         )\n"));
  err (_(" * nb_inst_memory                    [nb_load_store_queue]      (uint32_t         )\n"));
  err (_(" * link_load_store_unit_with_thread  [nb_front_end][nb_context] (uint32_t         )\n"));
  err (_(" * rename_select_priority                                       (Tpriority_t      )\n"));
  err (_(" * rename_select_load_balancing                                 (Tload_balancing_t)\n"));
  err (_(" * rename_select_nb_front_end_select                            (uint32_t         )\n"));
  err (_(" * max_branch_speculated                                        (uint32_t         )\n"));
  err (_(" * size_general_data                                            (uint32_t         )\n"));
  err (_(" * nb_general_register                                          (uint32_t         )\n"));
  err (_(" * nb_special_register                                          (uint32_t         )\n"));
  err (_(" * nb_reg_free                                                  (uint32_t         )\n"));
  err (_(" * nb_bank                                                      (uint32_t         )\n"));
//   err (_(" * size_read_counter                                            (uint32_t         )\n"));

  exit (1);
}

#ifndef SYSTEMC
int main    (int argc, char * argv[])
#else
int sc_main (int argc, char * argv[])
#endif
{
  if (argc <= static_cast<int>(2+NB_PARAMS))
    usage (argc, argv);

  uint32_t x = 1;

  string name = argv[x++];

  uint32_t             _nb_front_end                      = fromString<uint32_t         >(argv[x++]);

  if (argc <= static_cast<int>(2+NB_PARAMS+2*_nb_front_end))
    usage (argc, argv);

  uint32_t             _sum_nb_context = 0;

  uint32_t           * _nb_context    = new uint32_t [_nb_front_end];
  uint32_t           * _nb_inst_decod = new uint32_t [_nb_front_end];
  
  for (uint32_t i=0; i<_nb_front_end; i++)
    {
      _nb_context [i] = fromString<uint32_t>(argv[x++]);
      _sum_nb_context += _nb_context [i];
    }
  for (uint32_t i=0; i<_nb_front_end; i++)
    _nb_inst_decod [i] = fromString<uint32_t>(argv[x++]);
  uint32_t             _nb_inst_insert                    = fromString<uint32_t         >(argv[x++]);
  uint32_t             _nb_inst_retire                    = fromString<uint32_t         >(argv[x++]);
  uint32_t             _nb_load_store_queue               = fromString<uint32_t         >(argv[x++]);

  if (argc != static_cast<int>(2+NB_PARAMS+2*_nb_front_end+3*_nb_load_store_queue+_sum_nb_context))
    usage (argc, argv);

  uint32_t           * _size_store_queue                  = new uint32_t [_nb_load_store_queue];
  uint32_t           * _size_load_queue                   = new uint32_t [_nb_load_store_queue];
  uint32_t           * _nb_inst_memory                    = new uint32_t [_nb_load_store_queue];

  for (uint32_t i=0; i<_nb_load_store_queue; i++)
    _size_store_queue [i] = fromString<uint32_t>(argv[x++]);
  for (uint32_t i=0; i<_nb_load_store_queue; i++)
    _size_load_queue  [i] = fromString<uint32_t>(argv[x++]);
  for (uint32_t i=0; i<_nb_load_store_queue; i++)
    _nb_inst_memory   [i] = fromString<uint32_t>(argv[x++]);

  uint32_t          ** _link_load_store_unit_with_thread  = new uint32_t * [_nb_front_end];
  for (uint32_t i=0; i<_nb_front_end; i++)
    {
      _link_load_store_unit_with_thread [i] = new uint32_t [_nb_context[i]];
      for (uint32_t j=0; j<_nb_context[i]; j++)
	_link_load_store_unit_with_thread  [i][j] = fromString<uint32_t>(argv[x++]);
    }

  Tpriority_t          _rename_select_priority            = fromString<Tpriority_t      >(argv[x++]);
  Tload_balancing_t    _rename_select_load_balancing      = fromString<Tload_balancing_t>(argv[x++]);
  uint32_t             _rename_select_nb_front_end_select = fromString<uint32_t         >(argv[x++]);
  uint32_t             _max_branch_speculated             = fromString<uint32_t         >(argv[x++]);
  uint32_t             _size_general_data                 = fromString<uint32_t         >(argv[x++]);
  uint32_t             _nb_general_register               = fromString<uint32_t         >(argv[x++]);
  uint32_t             _nb_special_register               = fromString<uint32_t         >(argv[x++]);
  uint32_t             _nb_reg_free                       = fromString<uint32_t         >(argv[x++]);
  uint32_t             _nb_bank                           = fromString<uint32_t         >(argv[x++]);
//   uint32_t             _size_read_counter                 = fromString<uint32_t         >(argv[x++]);

  int _return = EXIT_SUCCESS;
  try 
    {
      morpheo::behavioural::core::multi_ooo_engine::ooo_engine::rename_unit::Parameters * param = new morpheo::behavioural::core::multi_ooo_engine::ooo_engine::rename_unit::Parameters
	(_nb_front_end                     ,
	 _nb_context                       ,
	 _nb_inst_decod                    ,
	 _nb_inst_insert                   ,
	 _nb_inst_retire                   ,
	 _nb_load_store_queue              ,
	 _size_store_queue                 ,
	 _size_load_queue                  ,
	 _nb_inst_memory                   ,
	 _link_load_store_unit_with_thread ,
	 _rename_select_priority           ,
	 _rename_select_load_balancing     ,
	 _rename_select_nb_front_end_select,
	 _max_branch_speculated            ,
	 _size_general_data                ,
	 _nb_general_register              ,
	 _nb_special_register              ,
	 _nb_reg_free                      ,
	 _nb_bank                          ,
// 	 _size_read_counter                ,
         true //is_toplevel
         );
      
      msg(_("%s"),param->print(0).c_str());
      
      test (name,param);
    }
  catch (morpheo::ErrorMorpheo & error)
    {
      msg (_("<%s> :\n%s"),name.c_str(), error.what ());
      _return = EXIT_FAILURE;
    }

  try 
    {
      if (_return == EXIT_SUCCESS)
	TEST_OK("Rename_unit : no error");
      else
	TEST_KO("Rename_unit : a lot of error");
    }
  catch (morpheo::ErrorMorpheo & error)
    {
//       msg (_("<%s> :\n%s"),name.c_str(), error.what ());
      _return = EXIT_FAILURE;
    }

  for (uint32_t i=0; i<_nb_front_end; i++)
    delete [] _link_load_store_unit_with_thread [i];
  delete [] _link_load_store_unit_with_thread;

  delete [] _nb_inst_decod   ;
  delete [] _size_store_queue;
  delete [] _size_load_queue ;
  delete [] _nb_inst_memory  ;
  delete [] _nb_context      ;

  return (_return);
}
