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

#include "Behavioural/Core/Core_Glue/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_ooo_engine                                                                                    (uint32_t         )\n"));
  err (_(" * nb_execute_loop                                                                                  (uint32_t         )\n"));
  err (_(" * ooo_engine_nb_front_end               [nb_ooo_engine]                                            (uint32_t         )\n"));
  err (_(" * ooo_engine_nb_execute_loop            [nb_ooo_engine]                                            (uint32_t         )\n"));
  err (_(" * execute_loop_nb_ooo_engine            [nb_execute_loop]                                          (uint32_t         )\n"));
  err (_(" * nb_inst_decod                         [nb_front_end]                                             (uint32_t         )\n"));
  err (_(" * front_end_nb_inst_branch_complete     [nb_front_end]                                             (uint32_t         )\n"));
  err (_(" * ooo_engine_nb_inst_branch_complete    [nb_ooo_engine]                                            (uint32_t         )\n"));
  err (_(" * nb_inst_insert                        [nb_ooo_engine]                                            (uint32_t         )\n"));
//err (_(" * nb_inst_issue_queue                   [nb_ooo_engine]                                            (uint32_t         )\n"));
  err (_(" * nb_inst_issue_slot                    [nb_ooo_engine]                                            (uint32_t         )\n"));
  err (_(" * nb_inst_execute                       [nb_ooo_engine][ooo_engine_nb_execute_loop]                (uint32_t         )\n"));
  err (_(" * nb_read_unit                          [nb_execute_loop]                                          (uint32_t         )\n"));
  err (_(" * nb_write_unit                         [nb_execute_loop]                                          (uint32_t         )\n"));
  err (_(" * size_depth                                                                                       (uint32_t         )\n"));
  err (_(" * size_rob_ptr                                                                                     (uint32_t         )\n"));
  err (_(" * size_load_queue_ptr                                                                              (uint32_t         )\n"));
  err (_(" * size_store_queue_ptr                                                                             (uint32_t         )\n"));
  err (_(" * size_general_data                                                                                (uint32_t         )\n"));
  err (_(" * size_special_data                                                                                (uint32_t         )\n"));
  err (_(" * size_general_register                                                                            (uint32_t         )\n"));
  err (_(" * size_special_register                                                                            (uint32_t         )\n"));
  err (_(" * dispatch_priority                                                                                (Tpriority_t      )\n"));
  err (_(" * dispatch_load_balancing                                                                          (Tload_balancing_t)\n"));
  err (_(" * table_dispatch                        [nb_ooo_engine][nb_inst_issue][execute_loop][nb_read_unit] (bool             )\n"));
//   err (_(" * table_issue_type                      [execute_loop][nb_read_unit][MAX_TYPE]                      (bool             )\n"));
//   err (_("   * TYPE_ALU    \n"));
//   err (_("   * TYPE_SHIFT  \n"));
//   err (_("   * TYPE_MOVE   \n"));
//   err (_("   * TYPE_TEST   \n"));
//   err (_("   * TYPE_MUL    \n"));
//   err (_("   * TYPE_DIV    \n"));
//   err (_("   * TYPE_EXTEND \n"));
//   err (_("   * TYPE_FIND   \n"));
//   err (_("   * TYPE_SPECIAL\n"));
//   err (_("   * TYPE_CUSTOM \n"));
//   err (_("   * TYPE_BRANCH \n"));
//   err (_("   * TYPE_MEMORY \n"));
  err (_(" * translate_ooo_engine_num_front_end    [nb_ooo_engine][ooo_engine_nb_front_end]                   (uint32_t         )\n"));
  err (_(" * translate_ooo_engine_num_execute_loop [nb_ooo_engine][ooo_engine_nb_execute_loop]                (uint32_t         )\n"));
  err (_(" * translate_execute_loop_num_ooo_engine [nb_execute_loop][execute_loop_nb_ooo_engine]              (uint32_t         )\n"));

  exit (1);
}

#ifndef SYSTEMC
int main    (int argc, char * argv[])
#else
int sc_main (int argc, char * argv[])
#endif
{
  int nb_params;

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

  uint32_t x = 1;

  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_issue_slot                   ;//[nb_ooo_engine]
  uint32_t             ** nb_inst_execute                      ;//[nb_ooo_engine][ooo_engine_nb_execute_loop]
  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][MAX_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]

  string name = argv[x++];

  SELFTEST0(nb_front_end                         ,uint32_t         ,argv,x);

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

  SELFTEST1(nb_context                           ,uint32_t         ,argv,x,nb_front_end);
  SELFTEST0(nb_ooo_engine                        ,uint32_t         ,argv,x);
  SELFTEST0(nb_execute_loop                      ,uint32_t         ,argv,x);

  nb_params = static_cast<int> (2+NB_PARAMS+
                                3*nb_front_end+
                                5*nb_ooo_engine+
                                3*nb_execute_loop
                                );
  if (argc < nb_params)
    usage (argc, argv);

  SELFTEST1(ooo_engine_nb_front_end              ,uint32_t         ,argv,x,nb_ooo_engine);
  SELFTEST1(ooo_engine_nb_execute_loop           ,uint32_t         ,argv,x,nb_ooo_engine);
  SELFTEST1(execute_loop_nb_ooo_engine           ,uint32_t         ,argv,x,nb_execute_loop);
  SELFTEST1(nb_inst_decod                        ,uint32_t         ,argv,x,nb_front_end);
  SELFTEST1(front_end_nb_inst_branch_complete    ,uint32_t         ,argv,x,nb_front_end);
  SELFTEST1(ooo_engine_nb_inst_branch_complete   ,uint32_t         ,argv,x,nb_ooo_engine);
  SELFTEST1(nb_inst_insert                       ,uint32_t         ,argv,x,nb_ooo_engine);
  SELFTEST1(nb_inst_issue_slot                   ,uint32_t         ,argv,x,nb_ooo_engine);

  uint32_t sum_ooo_engine_nb_front_end    = 0;
  uint32_t sum_ooo_engine_nb_execute_loop = 0;
  uint32_t sum_nb_inst_issue              = 0;

  for (uint32_t i=0; i<nb_ooo_engine; ++i)
    {
      sum_ooo_engine_nb_front_end    += ooo_engine_nb_front_end    [i];
      sum_ooo_engine_nb_execute_loop += ooo_engine_nb_execute_loop [i];
      sum_nb_inst_issue              += nb_inst_issue_slot         [i];
    }

  nb_params = static_cast<int> (2+NB_PARAMS+
                                3*nb_front_end+
                                5*nb_ooo_engine+
                                3*nb_execute_loop+
                                1*sum_ooo_engine_nb_execute_loop
                                );
  if (argc < nb_params)
    usage (argc, argv);

  SELFTEST2(nb_inst_execute                      ,uint32_t         ,argv,x,nb_ooo_engine,ooo_engine_nb_execute_loop[it1]);
  SELFTEST1(nb_read_unit                         ,uint32_t         ,argv,x,nb_execute_loop);
  SELFTEST1(nb_write_unit                        ,uint32_t         ,argv,x,nb_execute_loop);
  SELFTEST0(size_depth                           ,uint32_t         ,argv,x);
  SELFTEST0(size_rob_ptr                         ,uint32_t         ,argv,x);
  SELFTEST0(size_load_queue_ptr                  ,uint32_t         ,argv,x);
  SELFTEST0(size_store_queue_ptr                 ,uint32_t         ,argv,x);
  SELFTEST0(size_general_data                    ,uint32_t         ,argv,x);
  SELFTEST0(size_special_data                    ,uint32_t         ,argv,x);
  SELFTEST0(size_general_register                ,uint32_t         ,argv,x);
  SELFTEST0(size_special_register                ,uint32_t         ,argv,x);

  uint32_t sum_execute_loop_nb_ooo_engine = 0;
  uint32_t sum_nb_read_unit               = 0;

  for (uint32_t i=0; i<nb_execute_loop; ++i)
    {
      sum_execute_loop_nb_ooo_engine += execute_loop_nb_ooo_engine [i];
      sum_nb_read_unit               += nb_read_unit               [i];
    }

  nb_params = static_cast<int> (2+NB_PARAMS+
                                3*nb_front_end+
                                5*nb_ooo_engine+
                                3*nb_execute_loop+
                                sum_nb_inst_issue*sum_nb_read_unit+
                                sum_ooo_engine_nb_front_end+
                                2*sum_ooo_engine_nb_execute_loop+
                                sum_execute_loop_nb_ooo_engine
                                );
  if (argc != nb_params)
    usage (argc, argv);

  SELFTEST0(dispatch_priority                    ,Tpriority_t      ,argv,x);
  SELFTEST0(dispatch_load_balancing              ,Tload_balancing_t,argv,x);

  SELFTEST4(table_dispatch                       ,bool             ,argv,x,nb_ooo_engine,nb_inst_issue_slot[it1],nb_execute_loop,nb_read_unit[it3]);

  ALLOC3   (table_issue_type                     ,bool                                                     ,nb_execute_loop,nb_read_unit[it1],MAX_TYPE);

  for (uint32_t i=0; i<nb_execute_loop; ++i)
    for (uint32_t j=0; j<nb_read_unit[i]; ++j)
      for (uint32_t k=0; k<MAX_TYPE; ++k)
//         table_issue_type [i][j][k] = false;
        table_issue_type [i][j][k] = true;

//   for (uint32_t i=0; i<nb_execute_loop; ++i)
//     for (uint32_t j=0; j<nb_read_unit[i]; ++j)
//       {
//         table_issue_type [i][j][TYPE_ALU    ] = fromString<bool>(argv[x++]);
//         table_issue_type [i][j][TYPE_SHIFT  ] = fromString<bool>(argv[x++]);
//         table_issue_type [i][j][TYPE_MOVE   ] = fromString<bool>(argv[x++]);
//         table_issue_type [i][j][TYPE_TEST   ] = fromString<bool>(argv[x++]);
//         table_issue_type [i][j][TYPE_MUL    ] = fromString<bool>(argv[x++]);
//         table_issue_type [i][j][TYPE_DIV    ] = fromString<bool>(argv[x++]);
//         table_issue_type [i][j][TYPE_EXTEND ] = fromString<bool>(argv[x++]);
//         table_issue_type [i][j][TYPE_FIND   ] = fromString<bool>(argv[x++]);
//         table_issue_type [i][j][TYPE_SPECIAL] = fromString<bool>(argv[x++]);
//         table_issue_type [i][j][TYPE_CUSTOM ] = fromString<bool>(argv[x++]);
//         table_issue_type [i][j][TYPE_BRANCH ] = fromString<bool>(argv[x++]);
//         table_issue_type [i][j][TYPE_MEMORY ] = fromString<bool>(argv[x++]);
//       }

  SELFTEST2(translate_ooo_engine_num_front_end   ,uint32_t         ,argv,x,nb_ooo_engine,ooo_engine_nb_front_end[it1]);
  SELFTEST2(translate_ooo_engine_num_execute_loop,uint32_t         ,argv,x,nb_ooo_engine,ooo_engine_nb_execute_loop[it1]);
  SELFTEST2(translate_execute_loop_num_ooo_engine,uint32_t         ,argv,x,nb_execute_loop,execute_loop_nb_ooo_engine[it1]);

  int _return = EXIT_SUCCESS;
  try 
    {
      morpheo::behavioural::core::core_glue::Parameters * param = new morpheo::behavioural::core::core_glue::Parameters
	(
         nb_front_end                         ,
         nb_context                           ,//[nb_front_end]
         nb_ooo_engine                        ,
         nb_execute_loop                      ,
         ooo_engine_nb_front_end              ,//[nb_ooo_engine]
         ooo_engine_nb_execute_loop           ,//[nb_ooo_engine]
         execute_loop_nb_ooo_engine           ,//[nb_execute_loop]
         nb_inst_decod                        ,//[nb_front_end]
         front_end_nb_inst_branch_complete    ,//[nb_front_end]
         ooo_engine_nb_inst_branch_complete   ,//[nb_ooo_engine]
         nb_inst_insert                       ,//[nb_ooo_engine]
         nb_inst_issue_slot                   ,//[nb_ooo_engine]
         nb_inst_issue_slot                   ,//[nb_ooo_engine]
         nb_inst_execute                      ,//[nb_ooo_engine][ooo_engine_nb_execute_loop]
         nb_read_unit                         ,//[nb_execute_loop]
         nb_write_unit                        ,//[nb_execute_loop]
         size_depth                           ,
         size_rob_ptr                         ,
         size_load_queue_ptr                  ,
         size_store_queue_ptr                 ,
         size_general_data                    ,
         size_special_data                    ,
         size_general_register                ,
         size_special_register                ,
         dispatch_priority                    ,
         dispatch_load_balancing              ,
         table_dispatch                       ,//[nb_ooo_engine][nb_inst_issue_slot][execute_loop][nb_read_unit]
         table_issue_type                     ,//                                   [execute_loop][nb_read_unit][MAX_TYPE]
         translate_ooo_engine_num_front_end   ,//[nb_ooo_engine][ooo_engine_nb_front_end]
         translate_ooo_engine_num_execute_loop,//[nb_ooo_engine][ooo_engine_nb_execute_loop]
         translate_execute_loop_num_ooo_engine,//[nb_execute_loop][execute_loop_nb_ooo_engine]
         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("Core_Glue : no error");
      else
	TEST_KO("Core_Glue : a lot of error");
    }
  catch (morpheo::ErrorMorpheo & error)
    {
//       msg (_("<%s> :\n%s"),name.c_str(), error.what ());
      _return = EXIT_FAILURE;
    }

  DELETE2(translate_execute_loop_num_ooo_engine,nb_execute_loop,execute_loop_nb_ooo_engine[it1]);
  DELETE2(translate_ooo_engine_num_execute_loop,nb_ooo_engine,ooo_engine_nb_execute_loop[it1]);
  DELETE2(translate_ooo_engine_num_front_end   ,nb_ooo_engine,ooo_engine_nb_front_end[it1]);
  DELETE3(table_issue_type                                                           ,nb_execute_loop,nb_read_unit[it1],MAX_TYPE);
  DELETE4(table_dispatch                       ,nb_ooo_engine,nb_inst_issue_slot[it1],nb_execute_loop,nb_read_unit[it2]);
  DELETE1(nb_write_unit                        ,nb_execute_loop);
  DELETE1(nb_read_unit                         ,nb_execute_loop);
  DELETE2(nb_inst_execute                      ,nb_ooo_engine,ooo_engine_nb_execute_loop[it1]);
  DELETE1(nb_inst_issue_slot                   ,nb_ooo_engine);
  DELETE1(ooo_engine_nb_inst_branch_complete   ,nb_ooo_engine);
  DELETE1(front_end_nb_inst_branch_complete    ,nb_front_end);
  DELETE1(nb_inst_decod                        ,nb_front_end);
  DELETE1(execute_loop_nb_ooo_engine           ,nb_execute_loop);
  DELETE1(ooo_engine_nb_execute_loop           ,nb_ooo_engine);
  DELETE1(ooo_engine_nb_front_end              ,nb_ooo_engine);
  DELETE1(nb_context                           ,nb_front_end);

  return (_return);
}
