/*
 * $Id$
 *
 * [ Description ]
 * 
 * Test
 */

#include "Behavioural/Core/Multi_Execute_loop/Execute_loop/Multi_Read_unit/Read_unit/Reservation_station/SelfTest/include/test.h"
#include "Common/include/Test.h"

#define NB_ITERATION  16
#define CYCLE_MAX     (512*NB_ITERATION)

#define LABEL(str)                                                                       \
{                                                                                        \
  cout << "{"+toString(static_cast<uint32_t>(sc_simulation_time()))+"} " << str << endl; \
} while(0)

static uint32_t cycle = 0;

#define SC_START(cycle_offset)                                          \
do                                                                      \
{                                                                       \
/*cout << "SC_START (begin)" << endl;*/                                 \
                                                                        \
  uint32_t cycle_current = static_cast<uint32_t>(sc_simulation_time()); \
  sc_start(cycle_offset);                                               \
  if (cycle_current != cycle)                                           \
    {                                                                   \
      cycle = cycle_current;                                            \
      cout << "##########[ cycle "<< cycle << " ]" << endl;             \
    }                                                                   \
                                                                        \
  if (cycle_current > CYCLE_MAX)                                        \
    {                                                                   \
      TEST_KO("Maximal cycles Reached");                                \
    }                                                                   \
/*cout << "SC_START (end  )" << endl;*/                                 \
} while(0)

void test (string name,
	   morpheo::behavioural::core::multi_execute_loop::execute_loop::multi_read_unit::read_unit::reservation_station::Parameters * _param)
{
  cout << "<" << name << "> : Simulation SystemC" << endl;

#ifdef STATISTICS
  morpheo::behavioural::Parameters_Statistics * _parameters_statistics = new morpheo::behavioural::Parameters_Statistics (5,50);
#endif

  Reservation_station * _Reservation_station = new Reservation_station (name.c_str(),
#ifdef STATISTICS
					     _parameters_statistics,
#endif
					     _param);
  
#ifdef SYSTEMC
  /*********************************************************************
   * Déclarations des signaux
   *********************************************************************/
  string rename = "";

  sc_clock              * in_CLOCK  = new sc_clock ("clock", 1.0, 0.5);
  sc_signal<Tcontrol_t> * in_NRESET = new sc_signal<Tcontrol_t> ("NRESET");

  sc_signal<Tcontrol_t        > *  in_RESERVATION_STATION_IN_VAL            = new sc_signal<Tcontrol_t        >;
  sc_signal<Tcontrol_t        > * out_RESERVATION_STATION_IN_ACK            = new sc_signal<Tcontrol_t        >;
  sc_signal<Tcontext_t        > *  in_RESERVATION_STATION_IN_CONTEXT_ID     = new sc_signal<Tcontext_t        >;
  sc_signal<Tpacket_t         > *  in_RESERVATION_STATION_IN_PACKET_ID      = new sc_signal<Tpacket_t         >;
  sc_signal<Toperation_t      > *  in_RESERVATION_STATION_IN_OPERATION      = new sc_signal<Toperation_t      >;
  sc_signal<Ttype_t           > *  in_RESERVATION_STATION_IN_TYPE           = new sc_signal<Ttype_t           >;
  sc_signal<Tcontrol_t        > *  in_RESERVATION_STATION_IN_HAS_IMMEDIAT   = new sc_signal<Tcontrol_t        >;
  sc_signal<Tgeneral_data_t   > *  in_RESERVATION_STATION_IN_IMMEDIAT       = new sc_signal<Tgeneral_data_t   >;
//sc_signal<Tcontrol_t        > *  in_RESERVATION_STATION_IN_READ_RA        = new sc_signal<Tcontrol_t        >;
  sc_signal<Tgeneral_address_t> *  in_RESERVATION_STATION_IN_NUM_REG_RA     = new sc_signal<Tgeneral_address_t>;
  sc_signal<Tcontrol_t        > *  in_RESERVATION_STATION_IN_DATA_RA_VAL    = new sc_signal<Tcontrol_t        >;
  sc_signal<Tgeneral_data_t   > *  in_RESERVATION_STATION_IN_DATA_RA        = new sc_signal<Tgeneral_data_t   >;
//sc_signal<Tcontrol_t        > *  in_RESERVATION_STATION_IN_READ_RB        = new sc_signal<Tcontrol_t        >;
  sc_signal<Tgeneral_address_t> *  in_RESERVATION_STATION_IN_NUM_REG_RB     = new sc_signal<Tgeneral_address_t>;
  sc_signal<Tcontrol_t        > *  in_RESERVATION_STATION_IN_DATA_RB_VAL    = new sc_signal<Tcontrol_t        >;
  sc_signal<Tgeneral_data_t   > *  in_RESERVATION_STATION_IN_DATA_RB        = new sc_signal<Tgeneral_data_t   >;
//sc_signal<Tcontrol_t        > *  in_RESERVATION_STATION_IN_READ_RC        = new sc_signal<Tcontrol_t        >;
  sc_signal<Tspecial_address_t> *  in_RESERVATION_STATION_IN_NUM_REG_RC     = new sc_signal<Tspecial_address_t>;
  sc_signal<Tcontrol_t        > *  in_RESERVATION_STATION_IN_DATA_RC_VAL    = new sc_signal<Tcontrol_t        >;
  sc_signal<Tspecial_data_t   > *  in_RESERVATION_STATION_IN_DATA_RC        = new sc_signal<Tspecial_data_t   >;
  sc_signal<Tcontrol_t        > *  in_RESERVATION_STATION_IN_WRITE_RD       = new sc_signal<Tcontrol_t        >;
  sc_signal<Tgeneral_address_t> *  in_RESERVATION_STATION_IN_NUM_REG_RD     = new sc_signal<Tgeneral_address_t>;
  sc_signal<Tcontrol_t        > *  in_RESERVATION_STATION_IN_WRITE_RE       = new sc_signal<Tcontrol_t        >;
  sc_signal<Tspecial_address_t> *  in_RESERVATION_STATION_IN_NUM_REG_RE     = new sc_signal<Tspecial_address_t>;

  sc_signal<Tcontrol_t        > ** out_RESERVATION_STATION_OUT_VAL         = new sc_signal<Tcontrol_t        > * [_param->_size_queue];
  sc_signal<Tcontrol_t        > **  in_RESERVATION_STATION_OUT_ACK         = new sc_signal<Tcontrol_t        > * [_param->_size_queue];
  sc_signal<Tcontext_t        > ** out_RESERVATION_STATION_OUT_CONTEXT_ID  = new sc_signal<Tcontext_t        > * [_param->_size_queue];
  sc_signal<Tpacket_t         > ** out_RESERVATION_STATION_OUT_PACKET_ID   = new sc_signal<Tpacket_t         > * [_param->_size_queue];
  sc_signal<Toperation_t      > ** out_RESERVATION_STATION_OUT_OPERATION   = new sc_signal<Toperation_t      > * [_param->_size_queue];
  sc_signal<Ttype_t           > ** out_RESERVATION_STATION_OUT_TYPE        = new sc_signal<Ttype_t           > * [_param->_size_queue];
  sc_signal<Tcontrol_t        > ** out_RESERVATION_STATION_OUT_HAS_IMMEDIAT= new sc_signal<Tcontrol_t        > * [_param->_size_queue];
  sc_signal<Tgeneral_data_t   > ** out_RESERVATION_STATION_OUT_IMMEDIAT    = new sc_signal<Tgeneral_data_t   > * [_param->_size_queue];
  sc_signal<Tgeneral_data_t   > ** out_RESERVATION_STATION_OUT_DATA_RA     = new sc_signal<Tgeneral_data_t   > * [_param->_size_queue];
  sc_signal<Tgeneral_data_t   > ** out_RESERVATION_STATION_OUT_DATA_RB     = new sc_signal<Tgeneral_data_t   > * [_param->_size_queue];
  sc_signal<Tspecial_data_t   > ** out_RESERVATION_STATION_OUT_DATA_RC     = new sc_signal<Tspecial_data_t   > * [_param->_size_queue];
  sc_signal<Tcontrol_t        > ** out_RESERVATION_STATION_OUT_WRITE_RD    = new sc_signal<Tcontrol_t        > * [_param->_size_queue];
  sc_signal<Tgeneral_address_t> ** out_RESERVATION_STATION_OUT_NUM_REG_RD  = new sc_signal<Tgeneral_address_t> * [_param->_size_queue];
  sc_signal<Tcontrol_t        > ** out_RESERVATION_STATION_OUT_WRITE_RE    = new sc_signal<Tcontrol_t        > * [_param->_size_queue];
  sc_signal<Tspecial_address_t> ** out_RESERVATION_STATION_OUT_NUM_REG_RE  = new sc_signal<Tspecial_address_t> * [_param->_size_queue];
    
  for (uint32_t i=0; i<_param->_size_queue; i++)
    {
      out_RESERVATION_STATION_OUT_VAL          [i] = new sc_signal<Tcontrol_t        > (rename.c_str());
       in_RESERVATION_STATION_OUT_ACK          [i] = new sc_signal<Tcontrol_t        > (rename.c_str());
      out_RESERVATION_STATION_OUT_CONTEXT_ID   [i] = new sc_signal<Tcontext_t        > (rename.c_str());
      out_RESERVATION_STATION_OUT_PACKET_ID    [i] = new sc_signal<Tpacket_t         > (rename.c_str());
      out_RESERVATION_STATION_OUT_OPERATION    [i] = new sc_signal<Toperation_t      > (rename.c_str());
      out_RESERVATION_STATION_OUT_TYPE         [i] = new sc_signal<Ttype_t           > (rename.c_str());
      out_RESERVATION_STATION_OUT_HAS_IMMEDIAT [i] = new sc_signal<Tcontrol_t        > (rename.c_str());
      out_RESERVATION_STATION_OUT_IMMEDIAT     [i] = new sc_signal<Tgeneral_data_t   > (rename.c_str());
      out_RESERVATION_STATION_OUT_DATA_RA      [i] = new sc_signal<Tgeneral_data_t   > (rename.c_str());
      out_RESERVATION_STATION_OUT_DATA_RB      [i] = new sc_signal<Tgeneral_data_t   > (rename.c_str());
      out_RESERVATION_STATION_OUT_DATA_RC      [i] = new sc_signal<Tspecial_data_t   > (rename.c_str());
      out_RESERVATION_STATION_OUT_WRITE_RD     [i] = new sc_signal<Tcontrol_t        > (rename.c_str());
      out_RESERVATION_STATION_OUT_NUM_REG_RD   [i] = new sc_signal<Tgeneral_address_t> (rename.c_str());
      out_RESERVATION_STATION_OUT_WRITE_RE     [i] = new sc_signal<Tcontrol_t        > (rename.c_str());
      out_RESERVATION_STATION_OUT_NUM_REG_RE   [i] = new sc_signal<Tspecial_address_t> (rename.c_str());
    }

  sc_signal<Tcontrol_t        > ** in_GPR_WRITE_VAL        = new sc_signal<Tcontrol_t        > * [_param->_nb_gpr_write];
  sc_signal<Tcontext_t        > ** in_GPR_WRITE_CONTEXT_ID = new sc_signal<Tcontext_t        > * [_param->_nb_gpr_write];
  sc_signal<Tgeneral_address_t> ** in_GPR_WRITE_NUM_REG    = new sc_signal<Tgeneral_address_t> * [_param->_nb_gpr_write];
  sc_signal<Tgeneral_data_t   > ** in_GPR_WRITE_DATA       = new sc_signal<Tgeneral_data_t   > * [_param->_nb_gpr_write];
   
  for (uint32_t i=0; i<_param->_nb_gpr_write; i++)
    {
      in_GPR_WRITE_VAL        [i] = new sc_signal<Tcontrol_t        > (rename.c_str());
      in_GPR_WRITE_CONTEXT_ID [i] = new sc_signal<Tcontext_t        > (rename.c_str());
      in_GPR_WRITE_NUM_REG    [i] = new sc_signal<Tgeneral_address_t> (rename.c_str());
      in_GPR_WRITE_DATA       [i] = new sc_signal<Tgeneral_data_t   > (rename.c_str());
    }
  
  sc_signal<Tcontrol_t        > ** in_SPR_WRITE_VAL       = new sc_signal<Tcontrol_t        > * [_param->_nb_spr_write];
  sc_signal<Tcontext_t        > ** in_SPR_WRITE_CONTEXT_ID= new sc_signal<Tcontext_t        > * [_param->_nb_spr_write];
  sc_signal<Tspecial_address_t> ** in_SPR_WRITE_NUM_REG   = new sc_signal<Tspecial_address_t> * [_param->_nb_spr_write];
  sc_signal<Tspecial_data_t   > ** in_SPR_WRITE_DATA      = new sc_signal<Tspecial_data_t   > * [_param->_nb_spr_write];
   
  for (uint32_t i=0; i<_param->_nb_spr_write; i++)
    {
      in_SPR_WRITE_VAL        [i] = new sc_signal<Tcontrol_t        > (rename.c_str());
      in_SPR_WRITE_CONTEXT_ID [i] = new sc_signal<Tcontext_t        > (rename.c_str());
      in_SPR_WRITE_NUM_REG    [i] = new sc_signal<Tspecial_address_t> (rename.c_str());
      in_SPR_WRITE_DATA       [i] = new sc_signal<Tspecial_data_t   > (rename.c_str());
    }

  sc_signal<Tcontext_t        > ** in_BYPASS_WRITE_CONTEXT_ID  = new sc_signal<Tcontext_t        > * [_param->_nb_bypass_write];
  sc_signal<Tcontrol_t        > ** in_BYPASS_WRITE_GPR_VAL     = new sc_signal<Tcontrol_t        > * [_param->_nb_bypass_write];
  sc_signal<Tgeneral_address_t> ** in_BYPASS_WRITE_GPR_NUM_REG = new sc_signal<Tgeneral_address_t> * [_param->_nb_bypass_write];
  sc_signal<Tgeneral_data_t   > ** in_BYPASS_WRITE_GPR_DATA    = new sc_signal<Tgeneral_data_t   > * [_param->_nb_bypass_write];
  sc_signal<Tcontrol_t        > ** in_BYPASS_WRITE_SPR_VAL     = new sc_signal<Tcontrol_t        > * [_param->_nb_bypass_write];
  sc_signal<Tspecial_address_t> ** in_BYPASS_WRITE_SPR_NUM_REG = new sc_signal<Tspecial_address_t> * [_param->_nb_bypass_write];
  sc_signal<Tspecial_data_t   > ** in_BYPASS_WRITE_SPR_DATA    = new sc_signal<Tspecial_data_t   > * [_param->_nb_bypass_write];

  for (uint32_t i=0; i<_param->_nb_bypass_write; i++)
    {
      in_BYPASS_WRITE_CONTEXT_ID [i] = new sc_signal<Tcontext_t        > (rename.c_str());
      in_BYPASS_WRITE_GPR_VAL    [i] = new sc_signal<Tcontrol_t        > (rename.c_str());
      in_BYPASS_WRITE_GPR_NUM_REG[i] = new sc_signal<Tgeneral_address_t> (rename.c_str());
      in_BYPASS_WRITE_GPR_DATA   [i] = new sc_signal<Tgeneral_data_t   > (rename.c_str());
      in_BYPASS_WRITE_SPR_VAL    [i] = new sc_signal<Tcontrol_t        > (rename.c_str());
      in_BYPASS_WRITE_SPR_NUM_REG[i] = new sc_signal<Tspecial_address_t> (rename.c_str());
      in_BYPASS_WRITE_SPR_DATA   [i] = new sc_signal<Tspecial_data_t   > (rename.c_str());
    }
  sc_signal<Tcontrol_t        > ** in_BYPASS_MEMORY_VAL         = new sc_signal<Tcontrol_t        > * [_param->_nb_bypass_memory];
  sc_signal<Tcontext_t        > ** in_BYPASS_MEMORY_CONTEXT_ID  = new sc_signal<Tcontext_t        > * [_param->_nb_bypass_memory];
  sc_signal<Tgeneral_address_t> ** in_BYPASS_MEMORY_NUM_REG     = new sc_signal<Tgeneral_address_t> * [_param->_nb_bypass_memory];
  sc_signal<Tgeneral_data_t   > ** in_BYPASS_MEMORY_DATA        = new sc_signal<Tgeneral_data_t   > * [_param->_nb_bypass_memory];

  for (uint32_t i=0; i<_param->_nb_bypass_memory; i++)
    {
      in_BYPASS_MEMORY_VAL        [i] = new sc_signal<Tcontrol_t        > (rename.c_str());
      in_BYPASS_MEMORY_CONTEXT_ID [i] = new sc_signal<Tcontext_t        > (rename.c_str());
      in_BYPASS_MEMORY_NUM_REG    [i] = new sc_signal<Tgeneral_address_t> (rename.c_str());
      in_BYPASS_MEMORY_DATA       [i] = new sc_signal<Tgeneral_data_t   > (rename.c_str());
    }
    
  /********************************************************
   * Instanciation
   ********************************************************/
  
  cout << "<" << name << "> Instanciation of _Reservation_station" << endl;
  
  (*(_Reservation_station->in_CLOCK))        (*(in_CLOCK));
  (*(_Reservation_station->in_NRESET))       (*(in_NRESET));

  (*(_Reservation_station-> in_RESERVATION_STATION_IN_VAL              )) (*( in_RESERVATION_STATION_IN_VAL              ));
  (*(_Reservation_station->out_RESERVATION_STATION_IN_ACK              )) (*(out_RESERVATION_STATION_IN_ACK              ));
  (*(_Reservation_station-> in_RESERVATION_STATION_IN_CONTEXT_ID       )) (*( in_RESERVATION_STATION_IN_CONTEXT_ID       ));
  (*(_Reservation_station-> in_RESERVATION_STATION_IN_PACKET_ID        )) (*( in_RESERVATION_STATION_IN_PACKET_ID        ));
  (*(_Reservation_station-> in_RESERVATION_STATION_IN_OPERATION        )) (*( in_RESERVATION_STATION_IN_OPERATION        ));
  (*(_Reservation_station-> in_RESERVATION_STATION_IN_TYPE             )) (*( in_RESERVATION_STATION_IN_TYPE             ));
  (*(_Reservation_station-> in_RESERVATION_STATION_IN_HAS_IMMEDIAT     )) (*( in_RESERVATION_STATION_IN_HAS_IMMEDIAT     ));
  (*(_Reservation_station-> in_RESERVATION_STATION_IN_IMMEDIAT         )) (*( in_RESERVATION_STATION_IN_IMMEDIAT         ));
//   (*(_Reservation_station-> in_RESERVATION_STATION_IN_READ_RA          )) (*( in_RESERVATION_STATION_IN_READ_RA          ));
  (*(_Reservation_station-> in_RESERVATION_STATION_IN_NUM_REG_RA       )) (*( in_RESERVATION_STATION_IN_NUM_REG_RA       ));
  (*(_Reservation_station-> in_RESERVATION_STATION_IN_DATA_RA_VAL      )) (*( in_RESERVATION_STATION_IN_DATA_RA_VAL      ));
  (*(_Reservation_station-> in_RESERVATION_STATION_IN_DATA_RA          )) (*( in_RESERVATION_STATION_IN_DATA_RA          ));
//   (*(_Reservation_station-> in_RESERVATION_STATION_IN_READ_RB          )) (*( in_RESERVATION_STATION_IN_READ_RB          ));
  (*(_Reservation_station-> in_RESERVATION_STATION_IN_NUM_REG_RB       )) (*( in_RESERVATION_STATION_IN_NUM_REG_RB       ));
  (*(_Reservation_station-> in_RESERVATION_STATION_IN_DATA_RB_VAL      )) (*( in_RESERVATION_STATION_IN_DATA_RB_VAL      ));
  (*(_Reservation_station-> in_RESERVATION_STATION_IN_DATA_RB          )) (*( in_RESERVATION_STATION_IN_DATA_RB          ));
//   (*(_Reservation_station-> in_RESERVATION_STATION_IN_READ_RC          )) (*( in_RESERVATION_STATION_IN_READ_RC          ));
  (*(_Reservation_station-> in_RESERVATION_STATION_IN_NUM_REG_RC       )) (*( in_RESERVATION_STATION_IN_NUM_REG_RC       ));
  (*(_Reservation_station-> in_RESERVATION_STATION_IN_DATA_RC_VAL      )) (*( in_RESERVATION_STATION_IN_DATA_RC_VAL      ));
  (*(_Reservation_station-> in_RESERVATION_STATION_IN_DATA_RC          )) (*( in_RESERVATION_STATION_IN_DATA_RC          ));
  (*(_Reservation_station-> in_RESERVATION_STATION_IN_WRITE_RD         )) (*( in_RESERVATION_STATION_IN_WRITE_RD         ));
  (*(_Reservation_station-> in_RESERVATION_STATION_IN_NUM_REG_RD       )) (*( in_RESERVATION_STATION_IN_NUM_REG_RD       ));
  (*(_Reservation_station-> in_RESERVATION_STATION_IN_WRITE_RE         )) (*( in_RESERVATION_STATION_IN_WRITE_RE         ));
  (*(_Reservation_station-> in_RESERVATION_STATION_IN_NUM_REG_RE       )) (*( in_RESERVATION_STATION_IN_NUM_REG_RE       ));

    for (uint32_t i=0; i<_param->_size_queue; i++)
      {
  (*(_Reservation_station->out_RESERVATION_STATION_OUT_VAL          [i])) (*(out_RESERVATION_STATION_OUT_VAL          [i]));
  (*(_Reservation_station-> in_RESERVATION_STATION_OUT_ACK          [i])) (*( in_RESERVATION_STATION_OUT_ACK          [i]));
  (*(_Reservation_station->out_RESERVATION_STATION_OUT_CONTEXT_ID   [i])) (*(out_RESERVATION_STATION_OUT_CONTEXT_ID   [i]));
  (*(_Reservation_station->out_RESERVATION_STATION_OUT_PACKET_ID    [i])) (*(out_RESERVATION_STATION_OUT_PACKET_ID    [i]));
  (*(_Reservation_station->out_RESERVATION_STATION_OUT_OPERATION    [i])) (*(out_RESERVATION_STATION_OUT_OPERATION    [i]));
  (*(_Reservation_station->out_RESERVATION_STATION_OUT_TYPE         [i])) (*(out_RESERVATION_STATION_OUT_TYPE         [i]));
  (*(_Reservation_station->out_RESERVATION_STATION_OUT_HAS_IMMEDIAT [i])) (*(out_RESERVATION_STATION_OUT_HAS_IMMEDIAT [i]));
  (*(_Reservation_station->out_RESERVATION_STATION_OUT_IMMEDIAT     [i])) (*(out_RESERVATION_STATION_OUT_IMMEDIAT     [i]));
  (*(_Reservation_station->out_RESERVATION_STATION_OUT_DATA_RA      [i])) (*(out_RESERVATION_STATION_OUT_DATA_RA      [i]));
  (*(_Reservation_station->out_RESERVATION_STATION_OUT_DATA_RB      [i])) (*(out_RESERVATION_STATION_OUT_DATA_RB      [i]));
  (*(_Reservation_station->out_RESERVATION_STATION_OUT_DATA_RC      [i])) (*(out_RESERVATION_STATION_OUT_DATA_RC      [i]));
  (*(_Reservation_station->out_RESERVATION_STATION_OUT_WRITE_RD     [i])) (*(out_RESERVATION_STATION_OUT_WRITE_RD     [i]));
  (*(_Reservation_station->out_RESERVATION_STATION_OUT_NUM_REG_RD   [i])) (*(out_RESERVATION_STATION_OUT_NUM_REG_RD   [i]));
  (*(_Reservation_station->out_RESERVATION_STATION_OUT_WRITE_RE     [i])) (*(out_RESERVATION_STATION_OUT_WRITE_RE     [i]));
  (*(_Reservation_station->out_RESERVATION_STATION_OUT_NUM_REG_RE   [i])) (*(out_RESERVATION_STATION_OUT_NUM_REG_RE   [i]));
      }
    for (uint32_t i=0; i<_param->_nb_gpr_write; i++)
      {
  (*(_Reservation_station-> in_GPR_WRITE_VAL                        [i])) (*( in_GPR_WRITE_VAL                        [i]));
  (*(_Reservation_station-> in_GPR_WRITE_CONTEXT_ID                 [i])) (*( in_GPR_WRITE_CONTEXT_ID                 [i]));
  (*(_Reservation_station-> in_GPR_WRITE_NUM_REG                    [i])) (*( in_GPR_WRITE_NUM_REG                    [i]));
  (*(_Reservation_station-> in_GPR_WRITE_DATA                       [i])) (*( in_GPR_WRITE_DATA                       [i]));
      }
    for (uint32_t i=0; i<_param->_nb_spr_write; i++)
      {
  (*(_Reservation_station-> in_SPR_WRITE_VAL                        [i])) (*( in_SPR_WRITE_VAL                        [i]));
  (*(_Reservation_station-> in_SPR_WRITE_CONTEXT_ID                 [i])) (*( in_SPR_WRITE_CONTEXT_ID                 [i]));
  (*(_Reservation_station-> in_SPR_WRITE_NUM_REG                    [i])) (*( in_SPR_WRITE_NUM_REG                    [i]));
  (*(_Reservation_station-> in_SPR_WRITE_DATA                       [i])) (*( in_SPR_WRITE_DATA                       [i]));
      }
    for (uint32_t i=0; i<_param->_nb_bypass_write; i++)
      {
  (*(_Reservation_station-> in_BYPASS_WRITE_CONTEXT_ID              [i])) (*( in_BYPASS_WRITE_CONTEXT_ID              [i]));
  (*(_Reservation_station-> in_BYPASS_WRITE_GPR_VAL                 [i])) (*( in_BYPASS_WRITE_GPR_VAL                 [i]));
  (*(_Reservation_station-> in_BYPASS_WRITE_GPR_NUM_REG             [i])) (*( in_BYPASS_WRITE_GPR_NUM_REG             [i]));
  (*(_Reservation_station-> in_BYPASS_WRITE_GPR_DATA                [i])) (*( in_BYPASS_WRITE_GPR_DATA                [i]));
  (*(_Reservation_station-> in_BYPASS_WRITE_SPR_VAL                 [i])) (*( in_BYPASS_WRITE_SPR_VAL                 [i]));
  (*(_Reservation_station-> in_BYPASS_WRITE_SPR_NUM_REG             [i])) (*( in_BYPASS_WRITE_SPR_NUM_REG             [i]));
  (*(_Reservation_station-> in_BYPASS_WRITE_SPR_DATA                [i])) (*( in_BYPASS_WRITE_SPR_DATA                [i]));
      }
    for (uint32_t i=0; i<_param->_nb_bypass_memory; i++)
      {
  (*(_Reservation_station-> in_BYPASS_MEMORY_VAL                    [i])) (*( in_BYPASS_MEMORY_VAL                    [i]));
  (*(_Reservation_station-> in_BYPASS_MEMORY_CONTEXT_ID             [i])) (*( in_BYPASS_MEMORY_CONTEXT_ID             [i]));
  (*(_Reservation_station-> in_BYPASS_MEMORY_NUM_REG                [i])) (*( in_BYPASS_MEMORY_NUM_REG                [i]));
  (*(_Reservation_station-> in_BYPASS_MEMORY_DATA                   [i])) (*( in_BYPASS_MEMORY_DATA                   [i]));
      }

  cout << "<" << name << "> Start Simulation ............" << endl;
  Time * _time = new Time();

  /********************************************************
   * Simulation - Begin
   ********************************************************/

  // Initialisation

  const uint32_t nb_request = _param->_nb_packet;
//const uint32_t seed = 0;
  const uint32_t seed = static_cast<uint32_t>(time(NULL));
  srand(seed);

  Tcontext_t         _context_id [nb_request];
  Tcontrol_t         _read_ra    [nb_request];
  Tgeneral_address_t _num_reg_ra [nb_request];
  Tcontrol_t         _read_rb    [nb_request];
  Tgeneral_address_t _num_reg_rb [nb_request];
  Tcontrol_t         _read_rc    [nb_request];
  Tspecial_address_t _num_reg_rc [nb_request];

  // emulation of registerFile
  Tcontrol_t         _gpr_val    [_param->_nb_general_register][_param->_nb_context];
  Tgeneral_data_t    _gpr        [_param->_nb_general_register][_param->_nb_context];
  Tcontrol_t         _spr_val    [_param->_nb_special_register][_param->_nb_context];
  Tspecial_data_t    _spr        [_param->_nb_special_register][_param->_nb_context];

  SC_START(0);

  LABEL("Initialisation");
  in_RESERVATION_STATION_IN_VAL ->write(0);
  for (uint32_t i=0; i<_param->_size_queue      ; i++)
    in_RESERVATION_STATION_OUT_ACK [i]->write(0);
  for (uint32_t i=0; i<_param->_nb_gpr_write    ; i++)
    in_GPR_WRITE_VAL               [i]->write(0);
  for (uint32_t i=0; i<_param->_nb_spr_write    ; i++)
    in_SPR_WRITE_VAL               [i]->write(0);
  for (uint32_t i=0; i<_param->_nb_bypass_write ; i++)
    {
      in_BYPASS_WRITE_GPR_VAL      [i]->write(0);
      in_BYPASS_WRITE_SPR_VAL      [i]->write(0);
    }
  for (uint32_t i=0; i<_param->_nb_bypass_memory; i++)
    in_BYPASS_MEMORY_VAL           [i]->write(0);

  in_NRESET->write(0);
  SC_START(5);
  in_NRESET->write(1);

  LABEL("Loop of Test");

  for (uint32_t iteration=0; iteration<NB_ITERATION; iteration ++)
    {
      LABEL("Iteration "+toString(iteration));

      int32_t percent_transaction_queue_in     = (rand()%50)+25;
      int32_t percent_transaction_queue_out    = (rand()%50)+25;
      int32_t percent_registerfile_valid       = (rand()%50)+25;
      int32_t percent_transaction_registerfile = (rand()%50)+25;
      int32_t percent_transaction_bypass       = (rand()%50)+25;
      
      LABEL("Initialisation");

      for (uint32_t i=0; i<nb_request; i++)
	{
	  _context_id   [i] = rand()% _param->_nb_context            ;
	  _read_ra      [i] = rand()% 2                              ;
	  _num_reg_ra   [i] = rand()% _param->_nb_general_register   ;
	  _read_rb      [i] = rand()% 2                              ;
	  _num_reg_rb   [i] = rand()% _param->_nb_general_register   ;
	  _read_rc      [i] = rand()% 2                              ;
	  _num_reg_rc   [i] = rand()% _param->_nb_special_register   ;
	}
      
      // emulation of registerFile
      for (uint32_t j=0; j<_param->_nb_context; j++)
	{
	  for (uint32_t i=0; i<_param->_nb_general_register; i++)
	    {
	      _gpr_val      [i][j] = ((rand()%100) < percent_registerfile_valid);
	      _gpr          [i][j] = rand()%(1<<_param->_size_general_data);
	    }
	  for (uint32_t i=0; i<_param->_nb_special_register; i++)
	    {
	      _spr_val      [i][j] = ((rand()%100) < percent_registerfile_valid);
	      _spr          [i][j] = rand()%(1<<_param->_size_special_data);
	    }
	}
      // End initialisation .......

      uint32_t request_in  = 0;
      uint32_t request_out = 0;
      bool     request_out_wait [nb_request];

      for (uint32_t i=0; i<nb_request; i++)
	request_out_wait [i] = true;

      while (request_out < nb_request)
	{
	  if ((request_in < nb_request) and
	      ((rand()%100) < percent_transaction_queue_in))
	    {
	      bool               data_val;
	      Tgeneral_address_t gpr_addr;
	      Tspecial_address_t spr_addr;
	      Tcontext_t         ctxt    = _context_id [request_in];
   	      in_RESERVATION_STATION_IN_VAL         ->write(1);
   	      in_RESERVATION_STATION_IN_CONTEXT_ID  ->write(ctxt);
   	      in_RESERVATION_STATION_IN_PACKET_ID   ->write(request_in);
   	      in_RESERVATION_STATION_IN_OPERATION   ->write(0);
   	      in_RESERVATION_STATION_IN_TYPE        ->write(0);
   	      in_RESERVATION_STATION_IN_HAS_IMMEDIAT->write(0);
   	      in_RESERVATION_STATION_IN_IMMEDIAT    ->write(0);
// 	      in_RESERVATION_STATION_IN_READ_RA     ->write(_read_ra[request_in]);
	      gpr_addr = _num_reg_ra [request_in];
	      data_val = not(_read_ra[request_in]) or _gpr_val[gpr_addr][ctxt];
	      in_RESERVATION_STATION_IN_NUM_REG_RA  ->write(gpr_addr);
   	      in_RESERVATION_STATION_IN_DATA_RA_VAL ->write(data_val);
   	      in_RESERVATION_STATION_IN_DATA_RA     ->write((data_val)?_gpr[gpr_addr][ctxt]:0);
// 	      in_RESERVATION_STATION_IN_READ_RB     ->write(_read_rb[request_in]);
	      gpr_addr = _num_reg_rb [request_in];
	      data_val = not(_read_rb[request_in]) or _gpr_val[gpr_addr][ctxt];
   	      in_RESERVATION_STATION_IN_NUM_REG_RB  ->write(gpr_addr);			       
   	      in_RESERVATION_STATION_IN_DATA_RB_VAL ->write(data_val);			       
   	      in_RESERVATION_STATION_IN_DATA_RB     ->write((data_val)?_gpr[gpr_addr][ctxt]:0);
// 	      in_RESERVATION_STATION_IN_READ_RC     ->write(_read_rc[request_in]);
	      spr_addr = _num_reg_rc [request_in];
	      data_val = not(_read_rc[request_in]) or _spr_val[spr_addr][ctxt];
   	      in_RESERVATION_STATION_IN_NUM_REG_RC  ->write(spr_addr);			       
   	      in_RESERVATION_STATION_IN_DATA_RC_VAL ->write(data_val);			       
   	      in_RESERVATION_STATION_IN_DATA_RC     ->write((data_val)?_spr[spr_addr][ctxt]:0);
   	      in_RESERVATION_STATION_IN_WRITE_RD    ->write(0);
   	      in_RESERVATION_STATION_IN_NUM_REG_RD  ->write(0);
   	      in_RESERVATION_STATION_IN_WRITE_RE    ->write(0);
   	      in_RESERVATION_STATION_IN_NUM_REG_RE  ->write(0);
	    }
	  else
	    {
	      in_RESERVATION_STATION_IN_VAL         ->write(0);
	    }

	  for (uint32_t i=0; i<_param->_size_queue      ; i++)
	    in_RESERVATION_STATION_OUT_ACK[i]->write((rand()%100)<percent_transaction_queue_out);


	  LABEL("Bypass Network :");
	  for (uint32_t i=0; i<_param->_nb_gpr_write; i++)
	    {
	      Tgeneral_address_t num_reg = rand()% _param->_nb_general_register;
	      Tcontext_t         context = rand()% _param->_nb_context;
	      Tcontrol_t         val     = (_gpr_val [num_reg][context]== 0)?((rand()%100) < percent_transaction_registerfile):0;
	      Tgeneral_data_t    data    = rand()%(1<<_param->_size_general_data);
	      
	      in_GPR_WRITE_VAL        [i]->write(val);	      
	      in_GPR_WRITE_CONTEXT_ID [i]->write(context);
	      in_GPR_WRITE_NUM_REG    [i]->write(num_reg);
	      in_GPR_WRITE_DATA       [i]->write(data);

	      if (val)
		{
		  LABEL(" * GPR_WRITE     ["+toString(i)+"] - gpr["+toString(num_reg)+"]["+toString(context)+"] <- "+toString(data));
		  _gpr     [num_reg][context] = data;
		  _gpr_val [num_reg][context] = 1;
		}
	    }
	  for (uint32_t i=0; i<_param->_nb_spr_write; i++)
	    {
	      Tspecial_address_t num_reg = rand()% _param->_nb_special_register;
	      Tcontext_t         context = rand()% _param->_nb_context;
	      Tcontrol_t         val     = (_spr_val [num_reg][context]== 0)?((rand()%100) < percent_transaction_registerfile):0;
	      Tspecial_data_t    data    = rand()%(1<<_param->_size_special_data);
	      
	      in_SPR_WRITE_VAL        [i]->write(val);	      
	      in_SPR_WRITE_CONTEXT_ID [i]->write(context);
	      in_SPR_WRITE_NUM_REG    [i]->write(num_reg);
	      in_SPR_WRITE_DATA       [i]->write(data);

	      if (val == 1)
		{
		  LABEL(" * SPR_WRITE     ["+toString(i)+"] - spr["+toString(num_reg)+"]["+toString(context)+"] <- "+toString(data));
		  _spr     [num_reg][context] = data;
		  _spr_val [num_reg][context] = 1;
		}
	    }

	  for (uint32_t i=0; i<_param->_nb_bypass_write; i++)
	    {
	      Tcontext_t         context     = rand()% _param->_nb_context;
	      in_BYPASS_WRITE_CONTEXT_ID [i]->write(context);

	      Tgeneral_address_t gpr_num_reg = rand()% _param->_nb_general_register;
	      Tcontrol_t         gpr_val     = (_gpr_val [gpr_num_reg][context]== 0)?((rand()%100) < percent_transaction_bypass):0;
	      Tgeneral_data_t    gpr_data    = rand()%(1<<_param->_size_general_data);
	      
	      in_BYPASS_WRITE_GPR_VAL    [i]->write(gpr_val);	      
	      in_BYPASS_WRITE_GPR_NUM_REG[i]->write(gpr_num_reg);
	      in_BYPASS_WRITE_GPR_DATA   [i]->write(gpr_data);

	      if (gpr_val)
		{
		  LABEL(" * BYPASS_WRITE  ["+toString(i)+"] - gpr["+toString(gpr_num_reg)+"]["+toString(context)+"] <- "+toString(gpr_data));
		  _gpr     [gpr_num_reg][context] = gpr_data;
		  _gpr_val [gpr_num_reg][context] = 1;
		}

	      Tspecial_address_t spr_num_reg = rand()% _param->_nb_special_register;
	      Tcontrol_t         spr_val     = (_spr_val [spr_num_reg][context]== 0)?((rand()%100) < percent_transaction_bypass):0;
	      Tspecial_data_t    spr_data    = rand()%(1<<_param->_size_special_data);
	      
	      in_BYPASS_WRITE_SPR_VAL    [i]->write(spr_val);	      
	      in_BYPASS_WRITE_SPR_NUM_REG[i]->write(spr_num_reg);
	      in_BYPASS_WRITE_SPR_DATA   [i]->write(spr_data);

	      if (spr_val)
		{
		  LABEL(" * BYPASS_WRITE  ["+toString(i)+"] - spr["+toString(spr_num_reg)+"]["+toString(context)+"] <- "+toString(spr_data));
		  _spr     [spr_num_reg][context] = spr_data;
		  _spr_val [spr_num_reg][context] = 1;
		}

	    }

	  for (uint32_t i=0; i<_param->_nb_bypass_memory; i++)
	    {
	      Tcontext_t         context     = rand()% _param->_nb_context;
	      in_BYPASS_MEMORY_CONTEXT_ID [i]->write(context);

	      Tgeneral_address_t gpr_num_reg = rand()% _param->_nb_general_register;
	      Tcontrol_t         gpr_val     = (_gpr_val [gpr_num_reg][context]== 0)?((rand()%100) < percent_transaction_bypass):0;
	      Tgeneral_data_t    gpr_data    = rand()%(1<<_param->_size_general_data);
	      
	      in_BYPASS_MEMORY_VAL    [i]->write(gpr_val);	      
	      in_BYPASS_MEMORY_NUM_REG[i]->write(gpr_num_reg);
	      in_BYPASS_MEMORY_DATA   [i]->write(gpr_data);

	      if (gpr_val)
		{
		  LABEL(" * BYPASS_MEMORY ["+toString(i)+"] - gpr["+toString(gpr_num_reg)+"]["+toString(context)+"] <- "+toString(gpr_data));
		  _gpr     [gpr_num_reg][context] = gpr_data;
		  _gpr_val [gpr_num_reg][context] = 1;
		}
	    }
	  SC_START(0); // to mealy function
	  
// 	  LABEL("Test     RESERVATION_STATION_IN  : "+toString(in_RESERVATION_STATION_IN_VAL->read())+","+toString(out_RESERVATION_STATION_IN_ACK->read()));
	  if (( in_RESERVATION_STATION_IN_VAL->read() == 1) and
	      (out_RESERVATION_STATION_IN_ACK->read() == 1))
	    {
	      LABEL("Accepted RESERVATION_STATION_IN  n°"+toString(request_in));
	      request_in  ++;
	    }

	  for (uint32_t i=0; i<_param->_size_queue      ; i++)
	    {
 	      LABEL("Test     RESERVATION_STATION_OUT "+toString(i)+" : "+toString(out_RESERVATION_STATION_OUT_VAL[i]->read())+","+toString(in_RESERVATION_STATION_OUT_ACK[i]->read()));
	      if ((out_RESERVATION_STATION_OUT_VAL [i]->read() == 1) and
		  ( in_RESERVATION_STATION_OUT_ACK [i]->read() == 1))
		{
		  Tpacket_t  packet_id  = out_RESERVATION_STATION_OUT_PACKET_ID [i]->read();

		  LABEL("Accepted RESERVATION_STATION_OUT ["+toString(i)+"] n°"+toString(packet_id)+", request n°"+toString(request_out));
		  TEST(bool, request_out_wait [packet_id] , true);

		  request_out ++;
		  request_out_wait [packet_id] = false;

		  Tcontext_t context_id = _context_id [packet_id];
		  
		  TEST(Tcontext_t        ,out_RESERVATION_STATION_OUT_CONTEXT_ID[i]->read(),context_id);
		  if (_read_ra [packet_id])
		  TEST(Tgeneral_data_t   ,out_RESERVATION_STATION_OUT_DATA_RA   [i]->read(),_gpr[_num_reg_ra[packet_id]][context_id]);
		  
		  if (_read_rb [packet_id])
		  TEST(Tgeneral_data_t   ,out_RESERVATION_STATION_OUT_DATA_RB   [i]->read(),_gpr[_num_reg_rb[packet_id]][context_id]);
		  
		  if (_read_rc [packet_id])
		  TEST(Tspecial_data_t   ,out_RESERVATION_STATION_OUT_DATA_RC   [i]->read(),_spr[_num_reg_rc[packet_id]][context_id]);
		}
	    }
	  
	  SC_START(1);	  
	}
    }

  /********************************************************
   * Simulation - End
   ********************************************************/

  TEST_OK ("End of Simulation");
  delete _time;
  cout << "<" << name << "> ............ Stop Simulation" << endl;

  delete     in_CLOCK ;
  delete     in_NRESET;

  delete     in_RESERVATION_STATION_IN_VAL         ;
  delete    out_RESERVATION_STATION_IN_ACK         ;
  delete     in_RESERVATION_STATION_IN_CONTEXT_ID  ;
  delete     in_RESERVATION_STATION_IN_PACKET_ID   ;
  delete     in_RESERVATION_STATION_IN_OPERATION   ;
  delete     in_RESERVATION_STATION_IN_TYPE        ;
  delete     in_RESERVATION_STATION_IN_HAS_IMMEDIAT;
  delete     in_RESERVATION_STATION_IN_IMMEDIAT    ;
//delete     in_RESERVATION_STATION_IN_READ_RA     ;
  delete     in_RESERVATION_STATION_IN_NUM_REG_RA  ;
  delete     in_RESERVATION_STATION_IN_DATA_RA_VAL ;
  delete     in_RESERVATION_STATION_IN_DATA_RA     ;
//delete     in_RESERVATION_STATION_IN_READ_RB     ;
  delete     in_RESERVATION_STATION_IN_NUM_REG_RB  ;
  delete     in_RESERVATION_STATION_IN_DATA_RB_VAL ;
  delete     in_RESERVATION_STATION_IN_DATA_RB     ;
//delete     in_RESERVATION_STATION_IN_READ_RC     ;
  delete     in_RESERVATION_STATION_IN_NUM_REG_RC  ;
  delete     in_RESERVATION_STATION_IN_DATA_RC_VAL ;
  delete     in_RESERVATION_STATION_IN_DATA_RC     ;
  delete     in_RESERVATION_STATION_IN_WRITE_RD    ;
  delete     in_RESERVATION_STATION_IN_NUM_REG_RD  ;
  delete     in_RESERVATION_STATION_IN_WRITE_RE    ;
  delete     in_RESERVATION_STATION_IN_NUM_REG_RE  ;
  
  delete [] out_RESERVATION_STATION_OUT_VAL         ;
  delete []  in_RESERVATION_STATION_OUT_ACK         ;
  delete [] out_RESERVATION_STATION_OUT_CONTEXT_ID  ;
  delete [] out_RESERVATION_STATION_OUT_PACKET_ID   ;
  delete [] out_RESERVATION_STATION_OUT_OPERATION   ;
  delete [] out_RESERVATION_STATION_OUT_TYPE        ;
  delete [] out_RESERVATION_STATION_OUT_HAS_IMMEDIAT;
  delete [] out_RESERVATION_STATION_OUT_IMMEDIAT    ;
  delete [] out_RESERVATION_STATION_OUT_DATA_RA     ;
  delete [] out_RESERVATION_STATION_OUT_DATA_RB     ;
  delete [] out_RESERVATION_STATION_OUT_DATA_RC     ;
  delete [] out_RESERVATION_STATION_OUT_WRITE_RD    ;
  delete [] out_RESERVATION_STATION_OUT_NUM_REG_RD  ;
  delete [] out_RESERVATION_STATION_OUT_WRITE_RE    ;
  delete [] out_RESERVATION_STATION_OUT_NUM_REG_RE  ;
  
  delete []  in_GPR_WRITE_VAL       ;
  delete []  in_GPR_WRITE_CONTEXT_ID;
  delete []  in_GPR_WRITE_NUM_REG   ;
  delete []  in_GPR_WRITE_DATA      ;
  
  delete []  in_SPR_WRITE_VAL       ;
  delete []  in_SPR_WRITE_CONTEXT_ID;
  delete []  in_SPR_WRITE_NUM_REG   ;
  delete []  in_SPR_WRITE_DATA      ;
  
  delete []  in_BYPASS_WRITE_CONTEXT_ID ;
  delete []  in_BYPASS_WRITE_GPR_VAL    ;
  delete []  in_BYPASS_WRITE_GPR_NUM_REG;
  delete []  in_BYPASS_WRITE_GPR_DATA   ;
  delete []  in_BYPASS_WRITE_SPR_VAL    ;
  delete []  in_BYPASS_WRITE_SPR_NUM_REG;
  delete []  in_BYPASS_WRITE_SPR_DATA   ;
  
  delete []  in_BYPASS_MEMORY_VAL       ;
  delete []  in_BYPASS_MEMORY_CONTEXT_ID;
  delete []  in_BYPASS_MEMORY_NUM_REG   ;
  delete []  in_BYPASS_MEMORY_DATA      ;
#endif

  delete _Reservation_station;
#ifdef STATISTICS
  delete _parameters_statistics;
#endif
}
