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

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

#define NB_ITERATION  64
#define CYCLE_MAX     (1024*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()); \
  if (cycle_current != cycle)                                           \
    {                                                                   \
      cycle = cycle_current;                                            \
      cout << "##########[ cycle "<< cycle << " ]" << endl;             \
    }                                                                   \
                                                                        \
  if (cycle_current > CYCLE_MAX)                                        \
    {                                                                   \
      TEST_KO("Maximal cycles Reached");                                \
    }                                                                   \
  sc_start(cycle_offset);                                               \
/*cout << "SC_START (end  )" << endl;*/                                 \
} while(0)

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

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

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

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

    // ~~~~~[ Interface "read_queue_in" ]~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

  sc_signal<Tcontrol_t         >         * READ_QUEUE_IN_VAL          = new sc_signal<Tcontrol_t         >         ("READ_QUEUE_IN_VAL         ");
  sc_signal<Tcontrol_t         >         * READ_QUEUE_IN_ACK          = new sc_signal<Tcontrol_t         >         ("READ_QUEUE_IN_ACK         ");
  sc_signal<Tcontext_t         >         * READ_QUEUE_IN_CONTEXT_ID   = new sc_signal<Tcontext_t         >         ("READ_QUEUE_IN_CONTEXT_ID  ");
  sc_signal<Tpacket_t          >         * READ_QUEUE_IN_PACKET_ID    = new sc_signal<Tpacket_t          >         ("READ_QUEUE_IN_PACKET_ID   ");
  sc_signal<Toperation_t       >         * READ_QUEUE_IN_OPERATION    = new sc_signal<Toperation_t       >         ("READ_QUEUE_IN_OPERATION   ");
  sc_signal<Ttype_t            >         * READ_QUEUE_IN_TYPE         = new sc_signal<Ttype_t            >         ("READ_QUEUE_IN_TYPE        ");
  sc_signal<Tcontrol_t         >         * READ_QUEUE_IN_HAS_IMMEDIAT = new sc_signal<Tcontrol_t         >         ("READ_QUEUE_IN_HAS_IMMEDIAT");
  sc_signal<Tgeneral_data_t    >         * READ_QUEUE_IN_IMMEDIAT     = new sc_signal<Tgeneral_data_t    >         ("READ_QUEUE_IN_IMMEDIAT    ");
  sc_signal<Tcontrol_t         >         * READ_QUEUE_IN_READ_RA      = new sc_signal<Tcontrol_t         >         ("READ_QUEUE_IN_READ_RA     ");
  sc_signal<Tgeneral_address_t >         * READ_QUEUE_IN_NUM_REG_RA   = new sc_signal<Tgeneral_address_t >         ("READ_QUEUE_IN_NUM_REG_RA  ");
  sc_signal<Tcontrol_t         >         * READ_QUEUE_IN_READ_RB      = new sc_signal<Tcontrol_t         >         ("READ_QUEUE_IN_READ_RB     ");
  sc_signal<Tgeneral_address_t >         * READ_QUEUE_IN_NUM_REG_RB   = new sc_signal<Tgeneral_address_t >         ("READ_QUEUE_IN_NUM_REG_RB  ");
  sc_signal<Tcontrol_t         >         * READ_QUEUE_IN_READ_RC      = new sc_signal<Tcontrol_t         >         ("READ_QUEUE_IN_READ_RC     ");
  sc_signal<Tspecial_address_t >         * READ_QUEUE_IN_NUM_REG_RC   = new sc_signal<Tspecial_address_t >         ("READ_QUEUE_IN_NUM_REG_RC  ");
  sc_signal<Tcontrol_t         >         * READ_QUEUE_IN_WRITE_RD     = new sc_signal<Tcontrol_t         >         ("READ_QUEUE_IN_WRITE_RD    ");
  sc_signal<Tgeneral_address_t >         * READ_QUEUE_IN_NUM_REG_RD   = new sc_signal<Tgeneral_address_t >         ("READ_QUEUE_IN_NUM_REG_RD  ");
  sc_signal<Tcontrol_t         >         * READ_QUEUE_IN_WRITE_RE     = new sc_signal<Tcontrol_t         >         ("READ_QUEUE_IN_WRITE_RE    ");
  sc_signal<Tspecial_address_t >         * READ_QUEUE_IN_NUM_REG_RE   = new sc_signal<Tspecial_address_t >         ("READ_QUEUE_IN_NUM_REG_RE  ");

    // ~~~~~[ Interface "read_queue_out" ]~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

  sc_signal<Tcontrol_t         >         * READ_QUEUE_OUT_VAL         = new sc_signal<Tcontrol_t         >         ("READ_QUEUE_OUT_VAL         ");
  sc_signal<Tcontrol_t         >         * READ_QUEUE_OUT_ACK         = new sc_signal<Tcontrol_t         >         ("READ_QUEUE_OUT_ACK         ");
  sc_signal<Tcontext_t         >         * READ_QUEUE_OUT_CONTEXT_ID  = new sc_signal<Tcontext_t         >         ("READ_QUEUE_OUT_CONTEXT_ID  ");
  sc_signal<Tpacket_t          >         * READ_QUEUE_OUT_PACKET_ID   = new sc_signal<Tpacket_t          >         ("READ_QUEUE_OUT_PACKET_ID   ");
  sc_signal<Toperation_t       >         * READ_QUEUE_OUT_OPERATION   = new sc_signal<Toperation_t       >         ("READ_QUEUE_OUT_OPERATION   ");
  sc_signal<Ttype_t            >         * READ_QUEUE_OUT_TYPE        = new sc_signal<Ttype_t            >         ("READ_QUEUE_OUT_TYPE        ");
  sc_signal<Tcontrol_t         >         * READ_QUEUE_OUT_HAS_IMMEDIAT= new sc_signal<Tcontrol_t         >         ("READ_QUEUE_OUT_HAS_IMMEDIAT");
  sc_signal<Tgeneral_data_t    >         * READ_QUEUE_OUT_IMMEDIAT    = new sc_signal<Tgeneral_data_t    >         ("READ_QUEUE_OUT_IMMEDIAT    ");
  sc_signal<Tcontrol_t         >         * READ_QUEUE_OUT_READ_RA     = new sc_signal<Tcontrol_t         >         ("READ_QUEUE_OUT_READ_RA     ");
  sc_signal<Tgeneral_address_t >         * READ_QUEUE_OUT_NUM_REG_RA  = new sc_signal<Tgeneral_address_t >         ("READ_QUEUE_OUT_NUM_REG_RA  ");
  sc_signal<Tcontrol_t         >         * READ_QUEUE_OUT_DATA_RA_VAL = new sc_signal<Tcontrol_t         >         ("READ_QUEUE_OUT_DATA_RA_VAL ");
  sc_signal<Tgeneral_data_t    >         * READ_QUEUE_OUT_DATA_RA     = new sc_signal<Tgeneral_data_t    >         ("READ_QUEUE_OUT_DATA_RA     ");
  sc_signal<Tcontrol_t         >         * READ_QUEUE_OUT_READ_RB     = new sc_signal<Tcontrol_t         >         ("READ_QUEUE_OUT_READ_RB     ");
  sc_signal<Tgeneral_address_t >         * READ_QUEUE_OUT_NUM_REG_RB  = new sc_signal<Tgeneral_address_t >         ("READ_QUEUE_OUT_NUM_REG_RB  ");
  sc_signal<Tcontrol_t         >         * READ_QUEUE_OUT_DATA_RB_VAL = new sc_signal<Tcontrol_t         >         ("READ_QUEUE_OUT_DATA_RB_VAL ");
  sc_signal<Tgeneral_data_t    >         * READ_QUEUE_OUT_DATA_RB     = new sc_signal<Tgeneral_data_t    >         ("READ_QUEUE_OUT_DATA_RB     ");
  sc_signal<Tcontrol_t         >         * READ_QUEUE_OUT_READ_RC     = new sc_signal<Tcontrol_t         >         ("READ_QUEUE_OUT_READ_RC     ");
  sc_signal<Tspecial_address_t >         * READ_QUEUE_OUT_NUM_REG_RC  = new sc_signal<Tspecial_address_t >         ("READ_QUEUE_OUT_NUM_REG_RC  ");
  sc_signal<Tcontrol_t         >         * READ_QUEUE_OUT_DATA_RC_VAL = new sc_signal<Tcontrol_t         >         ("READ_QUEUE_OUT_DATA_RC_VAL ");
  sc_signal<Tspecial_data_t    >         * READ_QUEUE_OUT_DATA_RC     = new sc_signal<Tspecial_data_t    >         ("READ_QUEUE_OUT_DATA_RC     ");
  sc_signal<Tcontrol_t         >         * READ_QUEUE_OUT_WRITE_RD    = new sc_signal<Tcontrol_t         >         ("READ_QUEUE_OUT_WRITE_RD    ");
  sc_signal<Tgeneral_address_t >         * READ_QUEUE_OUT_NUM_REG_RD  = new sc_signal<Tgeneral_address_t >         ("READ_QUEUE_OUT_NUM_REG_RD  ");
  sc_signal<Tcontrol_t         >         * READ_QUEUE_OUT_WRITE_RE    = new sc_signal<Tcontrol_t         >         ("READ_QUEUE_OUT_WRITE_RE    ");
  sc_signal<Tspecial_address_t >         * READ_QUEUE_OUT_NUM_REG_RE  = new sc_signal<Tspecial_address_t >         ("READ_QUEUE_OUT_NUM_REG_RE  ");

    // ~~~~~[ Interface "gpr_read" ]~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

  sc_signal<Tcontrol_t         > ** GPR_READ_VAL        = new sc_signal<Tcontrol_t         > * [_param->_nb_gpr_read];
  sc_signal<Tcontrol_t         > ** GPR_READ_ACK        = new sc_signal<Tcontrol_t         > * [_param->_nb_gpr_read];
  sc_signal<Tcontext_t         > ** GPR_READ_CONTEXT_ID = new sc_signal<Tcontext_t         > * [_param->_nb_gpr_read];
  sc_signal<Tgeneral_address_t > ** GPR_READ_NUM_REG    = new sc_signal<Tgeneral_address_t > * [_param->_nb_gpr_read];
  sc_signal<Tgeneral_data_t    > ** GPR_READ_DATA       = new sc_signal<Tgeneral_data_t    > * [_param->_nb_gpr_read];
  sc_signal<Tcontrol_t         > ** GPR_READ_DATA_VAL   = new sc_signal<Tcontrol_t         > * [_param->_nb_gpr_read];

  for (uint32_t i=0; i<_param->_nb_gpr_read; i++)
    {
      rename = "GPR_READ_"+toString(i)+"_VAL";   
      GPR_READ_VAL        [i] = new sc_signal<Tcontrol_t         > (rename.c_str());
      rename = "GPR_READ_"+toString(i)+"_ACK";     
      GPR_READ_ACK        [i] = new sc_signal<Tcontrol_t         > (rename.c_str());
      rename = "GPR_READ_"+toString(i)+"_CONTEXT_ID";
      GPR_READ_CONTEXT_ID [i] = new sc_signal<Tcontext_t         > (rename.c_str());
      rename = "GPR_READ_"+toString(i)+"_NUM_REG"; 
      GPR_READ_NUM_REG    [i] = new sc_signal<Tgeneral_address_t > (rename.c_str());
      rename = "GPR_READ_"+toString(i)+"_DATA";    
      GPR_READ_DATA       [i] = new sc_signal<Tgeneral_data_t    > (rename.c_str());
      rename = "GPR_READ_"+toString(i)+"_DATA_VAL";
      GPR_READ_DATA_VAL   [i] = new sc_signal<Tcontrol_t         > (rename.c_str());
    }

    // ~~~~~[ Interface "spr_read" ]~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

  sc_signal<Tcontrol_t         > ** SPR_READ_VAL        = new sc_signal<Tcontrol_t         > * [_param->_nb_spr_read];
  sc_signal<Tcontrol_t         > ** SPR_READ_ACK        = new sc_signal<Tcontrol_t         > * [_param->_nb_spr_read];
  sc_signal<Tcontext_t         > ** SPR_READ_CONTEXT_ID = new sc_signal<Tcontext_t         > * [_param->_nb_spr_read];
  sc_signal<Tspecial_address_t > ** SPR_READ_NUM_REG    = new sc_signal<Tspecial_address_t > * [_param->_nb_spr_read];
  sc_signal<Tspecial_data_t    > ** SPR_READ_DATA       = new sc_signal<Tspecial_data_t    > * [_param->_nb_spr_read];
  sc_signal<Tcontrol_t         > ** SPR_READ_DATA_VAL   = new sc_signal<Tcontrol_t         > * [_param->_nb_spr_read];

  for (uint32_t i=0; i<_param->_nb_spr_read; i++)
    {
      rename = "SPR_READ_"+toString(i)+"_VAL";   
      SPR_READ_VAL         [i] = new sc_signal<Tcontrol_t         > (rename.c_str());
      rename = "SPR_READ_"+toString(i)+"_ACK";     
      SPR_READ_ACK         [i] = new sc_signal<Tcontrol_t         > (rename.c_str());
      rename = "SPR_READ_"+toString(i)+"_CONTEXT_ID"; 
      SPR_READ_CONTEXT_ID  [i] = new sc_signal<Tcontext_t         > (rename.c_str());
      rename = "SPR_READ_"+toString(i)+"_NUM_REG"; 
      SPR_READ_NUM_REG     [i] = new sc_signal<Tspecial_address_t > (rename.c_str());
      rename = "SPR_READ_"+toString(i)+"_DATA";    
      SPR_READ_DATA        [i] = new sc_signal<Tspecial_data_t    > (rename.c_str());
      rename = "SPR_READ_"+toString(i)+"_DATA_VAL";
      SPR_READ_DATA_VAL    [i] = new sc_signal<Tcontrol_t         > (rename.c_str());
    }

    // ~~~~~[ Interface "gpr_write" ]~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

  sc_signal<Tcontrol_t         > ** GPR_WRITE_VAL        = new sc_signal<Tcontrol_t         > * [_param->_nb_gpr_write];
  sc_signal<Tcontext_t         > ** GPR_WRITE_CONTEXT_ID = new sc_signal<Tcontext_t         > * [_param->_nb_gpr_write];
  sc_signal<Tgeneral_address_t > ** GPR_WRITE_NUM_REG    = new sc_signal<Tgeneral_address_t > * [_param->_nb_gpr_write];
  sc_signal<Tgeneral_data_t    > ** GPR_WRITE_DATA       = new sc_signal<Tgeneral_data_t    > * [_param->_nb_gpr_write];

  for (uint32_t i=0; i<_param->_nb_gpr_write; i++)
    {
      rename = "GPR_WRITE_"+toString(i)+"_VAL"       ;
      GPR_WRITE_VAL        [i] = new sc_signal<Tcontrol_t         > (rename.c_str());
      rename = "GPR_WRITE_"+toString(i)+"_CONTEXT_ID";
      GPR_WRITE_CONTEXT_ID [i] = new sc_signal<Tcontext_t         > (rename.c_str());
      rename = "GPR_WRITE_"+toString(i)+"_NUM_REG"   ;
      GPR_WRITE_NUM_REG    [i] = new sc_signal<Tgeneral_address_t > (rename.c_str());
      rename = "GPR_WRITE_"+toString(i)+"_DATA"      ;
      GPR_WRITE_DATA       [i] = new sc_signal<Tgeneral_data_t    > (rename.c_str());
    }

    // ~~~~~[ Interface "spr_write" ]~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

  sc_signal<Tcontrol_t         > ** SPR_WRITE_VAL        = new sc_signal<Tcontrol_t         > * [_param->_nb_spr_write];
  sc_signal<Tcontext_t         > ** SPR_WRITE_CONTEXT_ID = new sc_signal<Tcontext_t         > * [_param->_nb_spr_write];
  sc_signal<Tspecial_address_t > ** SPR_WRITE_NUM_REG    = new sc_signal<Tspecial_address_t > * [_param->_nb_spr_write];
  sc_signal<Tspecial_data_t    > ** SPR_WRITE_DATA       = new sc_signal<Tspecial_data_t    > * [_param->_nb_spr_write];

  for (uint32_t i=0; i<_param->_nb_spr_write; i++)
    {
      rename = "SPR_WRITE_"+toString(i)+"_VAL"       ;
      SPR_WRITE_VAL        [i] = new sc_signal<Tcontrol_t         > (rename.c_str());
      rename = "SPR_WRITE_"+toString(i)+"_CONTEXT_ID";
      SPR_WRITE_CONTEXT_ID [i] = new sc_signal<Tcontext_t         > (rename.c_str());
      rename = "SPR_WRITE_"+toString(i)+"_NUM_REG"   ;
      SPR_WRITE_NUM_REG    [i] = new sc_signal<Tspecial_address_t > (rename.c_str());
      rename = "SPR_WRITE_"+toString(i)+"_DATA"      ;
      SPR_WRITE_DATA       [i] = new sc_signal<Tspecial_data_t    > (rename.c_str());
    }

  /********************************************************
   * Instanciation
   ********************************************************/
  
  cout << "<" << name << "> Instanciation of _Read_queue" << endl;
  
  (*(_Read_queue->in_CLOCK ))        (*(CLOCK));
  (*(_Read_queue->in_NRESET))        (*(NRESET));

  
  (*(_Read_queue-> in_READ_QUEUE_IN_VAL            )) (*(READ_QUEUE_IN_VAL            ));
  (*(_Read_queue->out_READ_QUEUE_IN_ACK            )) (*(READ_QUEUE_IN_ACK            ));
  (*(_Read_queue-> in_READ_QUEUE_IN_CONTEXT_ID     )) (*(READ_QUEUE_IN_CONTEXT_ID     ));
  (*(_Read_queue-> in_READ_QUEUE_IN_PACKET_ID      )) (*(READ_QUEUE_IN_PACKET_ID      ));
  (*(_Read_queue-> in_READ_QUEUE_IN_OPERATION      )) (*(READ_QUEUE_IN_OPERATION      ));
  (*(_Read_queue-> in_READ_QUEUE_IN_TYPE           )) (*(READ_QUEUE_IN_TYPE           ));
  (*(_Read_queue-> in_READ_QUEUE_IN_HAS_IMMEDIAT   )) (*(READ_QUEUE_IN_HAS_IMMEDIAT   ));
  (*(_Read_queue-> in_READ_QUEUE_IN_IMMEDIAT       )) (*(READ_QUEUE_IN_IMMEDIAT       ));
  (*(_Read_queue-> in_READ_QUEUE_IN_READ_RA        )) (*(READ_QUEUE_IN_READ_RA        ));
  (*(_Read_queue-> in_READ_QUEUE_IN_NUM_REG_RA     )) (*(READ_QUEUE_IN_NUM_REG_RA     ));
  (*(_Read_queue-> in_READ_QUEUE_IN_READ_RB        )) (*(READ_QUEUE_IN_READ_RB        ));
  (*(_Read_queue-> in_READ_QUEUE_IN_NUM_REG_RB     )) (*(READ_QUEUE_IN_NUM_REG_RB     ));
  (*(_Read_queue-> in_READ_QUEUE_IN_READ_RC        )) (*(READ_QUEUE_IN_READ_RC        ));
  (*(_Read_queue-> in_READ_QUEUE_IN_NUM_REG_RC     )) (*(READ_QUEUE_IN_NUM_REG_RC     ));
  (*(_Read_queue-> in_READ_QUEUE_IN_WRITE_RD       )) (*(READ_QUEUE_IN_WRITE_RD       ));
  (*(_Read_queue-> in_READ_QUEUE_IN_NUM_REG_RD     )) (*(READ_QUEUE_IN_NUM_REG_RD     ));
  (*(_Read_queue-> in_READ_QUEUE_IN_WRITE_RE       )) (*(READ_QUEUE_IN_WRITE_RE       ));
  (*(_Read_queue-> in_READ_QUEUE_IN_NUM_REG_RE     )) (*(READ_QUEUE_IN_NUM_REG_RE     ));

  (*(_Read_queue->out_READ_QUEUE_OUT_VAL           )) (*(READ_QUEUE_OUT_VAL           )); 
  (*(_Read_queue-> in_READ_QUEUE_OUT_ACK           )) (*(READ_QUEUE_OUT_ACK           )); 
  (*(_Read_queue->out_READ_QUEUE_OUT_CONTEXT_ID    )) (*(READ_QUEUE_OUT_CONTEXT_ID    )); 
  (*(_Read_queue->out_READ_QUEUE_OUT_PACKET_ID     )) (*(READ_QUEUE_OUT_PACKET_ID     )); 
  (*(_Read_queue->out_READ_QUEUE_OUT_OPERATION     )) (*(READ_QUEUE_OUT_OPERATION     )); 
  (*(_Read_queue->out_READ_QUEUE_OUT_TYPE          )) (*(READ_QUEUE_OUT_TYPE          )); 
  (*(_Read_queue->out_READ_QUEUE_OUT_HAS_IMMEDIAT  )) (*(READ_QUEUE_OUT_HAS_IMMEDIAT  )); 
  (*(_Read_queue->out_READ_QUEUE_OUT_IMMEDIAT      )) (*(READ_QUEUE_OUT_IMMEDIAT      )); 
  (*(_Read_queue->out_READ_QUEUE_OUT_READ_RA       )) (*(READ_QUEUE_OUT_READ_RA       )); 
  (*(_Read_queue->out_READ_QUEUE_OUT_NUM_REG_RA    )) (*(READ_QUEUE_OUT_NUM_REG_RA    )); 
  (*(_Read_queue->out_READ_QUEUE_OUT_DATA_RA_VAL   )) (*(READ_QUEUE_OUT_DATA_RA_VAL   )); 
  (*(_Read_queue->out_READ_QUEUE_OUT_DATA_RA       )) (*(READ_QUEUE_OUT_DATA_RA       )); 
  (*(_Read_queue->out_READ_QUEUE_OUT_READ_RB       )) (*(READ_QUEUE_OUT_READ_RB       )); 
  (*(_Read_queue->out_READ_QUEUE_OUT_NUM_REG_RB    )) (*(READ_QUEUE_OUT_NUM_REG_RB    )); 
  (*(_Read_queue->out_READ_QUEUE_OUT_DATA_RB_VAL   )) (*(READ_QUEUE_OUT_DATA_RB_VAL   )); 
  (*(_Read_queue->out_READ_QUEUE_OUT_DATA_RB       )) (*(READ_QUEUE_OUT_DATA_RB       )); 
  (*(_Read_queue->out_READ_QUEUE_OUT_READ_RC       )) (*(READ_QUEUE_OUT_READ_RC       )); 
  (*(_Read_queue->out_READ_QUEUE_OUT_NUM_REG_RC    )) (*(READ_QUEUE_OUT_NUM_REG_RC    )); 
  (*(_Read_queue->out_READ_QUEUE_OUT_DATA_RC_VAL   )) (*(READ_QUEUE_OUT_DATA_RC_VAL   )); 
  (*(_Read_queue->out_READ_QUEUE_OUT_DATA_RC       )) (*(READ_QUEUE_OUT_DATA_RC       )); 
  (*(_Read_queue->out_READ_QUEUE_OUT_WRITE_RD      )) (*(READ_QUEUE_OUT_WRITE_RD      )); 
  (*(_Read_queue->out_READ_QUEUE_OUT_NUM_REG_RD    )) (*(READ_QUEUE_OUT_NUM_REG_RD    )); 
  (*(_Read_queue->out_READ_QUEUE_OUT_WRITE_RE      )) (*(READ_QUEUE_OUT_WRITE_RE      )); 
  (*(_Read_queue->out_READ_QUEUE_OUT_NUM_REG_RE    )) (*(READ_QUEUE_OUT_NUM_REG_RE    )); 

  for (uint32_t i=0; i<_param->_nb_gpr_read; i++)
    {
      (*(_Read_queue->out_GPR_READ_VAL         [i])) (*(GPR_READ_VAL         [i]));
      (*(_Read_queue-> in_GPR_READ_ACK         [i])) (*(GPR_READ_ACK         [i]));
      (*(_Read_queue->out_GPR_READ_CONTEXT_ID  [i])) (*(GPR_READ_CONTEXT_ID  [i]));
      (*(_Read_queue->out_GPR_READ_NUM_REG     [i])) (*(GPR_READ_NUM_REG     [i]));
      (*(_Read_queue-> in_GPR_READ_DATA        [i])) (*(GPR_READ_DATA        [i]));
      (*(_Read_queue-> in_GPR_READ_DATA_VAL    [i])) (*(GPR_READ_DATA_VAL    [i]));
    }
  
  for (uint32_t i=0; i<_param->_nb_spr_read; i++)
    {
      (*(_Read_queue->out_SPR_READ_VAL         [i])) (*(SPR_READ_VAL         [i]));
      (*(_Read_queue-> in_SPR_READ_ACK         [i])) (*(SPR_READ_ACK         [i]));
      (*(_Read_queue->out_SPR_READ_CONTEXT_ID  [i])) (*(SPR_READ_CONTEXT_ID  [i]));
      (*(_Read_queue->out_SPR_READ_NUM_REG     [i])) (*(SPR_READ_NUM_REG     [i]));
      (*(_Read_queue-> in_SPR_READ_DATA        [i])) (*(SPR_READ_DATA        [i]));
      (*(_Read_queue-> in_SPR_READ_DATA_VAL    [i])) (*(SPR_READ_DATA_VAL    [i]));
    }
  
  for (uint32_t i=0; i<_param->_nb_gpr_write; i++)
    {
      (*(_Read_queue-> in_GPR_WRITE_VAL        [i])) (*(GPR_WRITE_VAL        [i]));
      (*(_Read_queue-> in_GPR_WRITE_CONTEXT_ID [i])) (*(GPR_WRITE_CONTEXT_ID [i]));
      (*(_Read_queue-> in_GPR_WRITE_NUM_REG    [i])) (*(GPR_WRITE_NUM_REG    [i]));
      (*(_Read_queue-> in_GPR_WRITE_DATA       [i])) (*(GPR_WRITE_DATA       [i]));
    }
  
  for (uint32_t i=0; i<_param->_nb_spr_write; i++)
    {
      (*(_Read_queue-> in_SPR_WRITE_VAL        [i])) (*(SPR_WRITE_VAL        [i]));
      (*(_Read_queue-> in_SPR_WRITE_CONTEXT_ID [i])) (*(SPR_WRITE_CONTEXT_ID [i]));
      (*(_Read_queue-> in_SPR_WRITE_NUM_REG    [i])) (*(SPR_WRITE_NUM_REG    [i]));
      (*(_Read_queue-> in_SPR_WRITE_DATA       [i])) (*(SPR_WRITE_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);

//   for (uint32_t i=0; i<_param->_nb_gpr_write; i++)
//     GPR_WRITE_VAL    [i]->write (0);
//   for (uint32_t i=0; i<_param->_nb_spr_write; i++)
//     SPR_WRITE_VAL    [i]->write (0);

  NRESET->write(0);
  SC_START(5);
  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()%74)+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;

      while (request_out < nb_request)
	{
	  if ((request_in < nb_request) and
	      ((rand()%100) < percent_transaction_queue_in))
	    {
	      READ_QUEUE_IN_VAL         ->write(1);
	      READ_QUEUE_IN_CONTEXT_ID  ->write(_context_id [request_in]);
	      READ_QUEUE_IN_PACKET_ID   ->write(request_in);
	      READ_QUEUE_IN_OPERATION   ->write(0);
	      READ_QUEUE_IN_TYPE        ->write(0);
	      READ_QUEUE_IN_HAS_IMMEDIAT->write(0);
	      READ_QUEUE_IN_IMMEDIAT    ->write(0);
	      READ_QUEUE_IN_READ_RA     ->write(_read_ra    [request_in]);
	      READ_QUEUE_IN_NUM_REG_RA  ->write(_num_reg_ra [request_in]);
	      READ_QUEUE_IN_READ_RB     ->write(_read_rb    [request_in]);
	      READ_QUEUE_IN_NUM_REG_RB  ->write(_num_reg_rb [request_in]);
	      READ_QUEUE_IN_READ_RC     ->write(_read_rc    [request_in]);
	      READ_QUEUE_IN_NUM_REG_RC  ->write(_num_reg_rc [request_in]);
	      READ_QUEUE_IN_WRITE_RD    ->write(0);
	      READ_QUEUE_IN_NUM_REG_RD  ->write(0);
	      READ_QUEUE_IN_WRITE_RE    ->write(0);
	      READ_QUEUE_IN_NUM_REG_RE  ->write(0);
	    }
	  else
	    {
	      READ_QUEUE_IN_VAL         ->write(0);
	    }

	  READ_QUEUE_OUT_ACK         ->write((rand()%100) < percent_transaction_queue_out);
	    	  
	  // RegisterFile access
	  for (uint32_t i=0; i<_param->_nb_gpr_read ; i++)
	    {
	      GPR_READ_ACK      [i]->write((rand()%100) < percent_transaction_registerfile);
	      if (GPR_READ_VAL [i]->read())
		{
		  Tgeneral_address_t num_reg = GPR_READ_NUM_REG    [i]->read();
		  Tcontext_t         context = GPR_READ_CONTEXT_ID [i]->read();

		  GPR_READ_DATA     [i]->write(_gpr    [num_reg][context]);
		  GPR_READ_DATA_VAL [i]->write(_gpr_val[num_reg][context]);
		}
	    }
	  for (uint32_t i=0; i<_param->_nb_spr_read ; i++)
	    {
	      SPR_READ_ACK      [i]->write((rand()%100) < percent_transaction_registerfile);

	      if (SPR_READ_VAL [i]->read())
		{
		  Tspecial_address_t num_reg = SPR_READ_NUM_REG    [i]->read();
		  Tcontext_t         context = SPR_READ_CONTEXT_ID [i]->read();

		  SPR_READ_DATA     [i]->write(_spr    [num_reg][context]);
		  SPR_READ_DATA_VAL [i]->write(_spr_val[num_reg][context]);
		}
	    }

	  // BYPASS 
	  for (uint32_t i=0; i<_param->_nb_gpr_write; i++)
	    {
	      Tcontrol_t         val     = (rand()%100) < percent_transaction_bypass;
	      Tcontext_t         context = rand()% _param->_nb_context;
	      Tgeneral_address_t num_reg = rand()% _param->_nb_general_register;
	      Tgeneral_data_t    data    = rand()%(1<<_param->_size_general_data);
	      
	      GPR_WRITE_VAL        [i]->write(val);	      
	      GPR_WRITE_CONTEXT_ID [i]->write(context);
	      GPR_WRITE_NUM_REG    [i]->write(num_reg);
	      GPR_WRITE_DATA       [i]->write(data);

	      if (val)
		{
		  _gpr     [num_reg][context] = data;
		  _gpr_val [num_reg][context] = 1;
		}
	    }
	  for (uint32_t i=0; i<_param->_nb_spr_write; i++)
	    {
	      Tcontrol_t         val     = (rand()%100) < percent_transaction_bypass;
	      Tcontext_t         context = rand()% _param->_nb_context;
	      Tspecial_address_t num_reg = rand()% _param->_nb_special_register;
	      Tspecial_data_t    data    = rand()%(1<<_param->_size_special_data);
	      
	      SPR_WRITE_VAL        [i]->write(val);	      
	      SPR_WRITE_CONTEXT_ID [i]->write(context);
	      SPR_WRITE_NUM_REG    [i]->write(num_reg);
	      SPR_WRITE_DATA       [i]->write(data);

	      if (val)
		{
		  _spr     [num_reg][context] = data;
		  _spr_val [num_reg][context] = 1;
		}
	    }

	  SC_START(0);
	  
	  LABEL("Test     READ_QUEUE_IN  : "+toString(READ_QUEUE_IN_VAL->read())+","+toString(READ_QUEUE_IN_ACK->read()));
	  if ((READ_QUEUE_IN_VAL->read() == 1) and
	      (READ_QUEUE_IN_ACK->read() == 1))
	    {
	      LABEL("Accepted READ_QUEUE_IN  ["+toString(request_in)+"]");
	      request_in  ++;
	    }
	  LABEL("Test     READ_QUEUE_OUT : "+toString(READ_QUEUE_OUT_VAL->read())+","+toString(READ_QUEUE_OUT_ACK->read()));
	  if ((READ_QUEUE_OUT_VAL->read() == 1) and
	      (READ_QUEUE_OUT_ACK->read() == 1))
	    {
	      Tpacket_t packet_id = READ_QUEUE_OUT_PACKET_ID->read();

	      LABEL("Accepted READ_QUEUE_OUT ["+toString(packet_id)+"]");
	      
	      TEST(uint32_t          , packet_id ,request_out);
	      
	      request_out ++;

	      TEST(Tcontext_t        ,READ_QUEUE_OUT_CONTEXT_ID ->read(),_context_id   [packet_id]);
	      TEST(Tcontrol_t        ,READ_QUEUE_OUT_READ_RA    ->read(),_read_ra      [packet_id]);
	      TEST(Tgeneral_address_t,READ_QUEUE_OUT_NUM_REG_RA ->read(),_num_reg_ra   [packet_id]);
	      TEST(Tcontrol_t        ,READ_QUEUE_OUT_DATA_RA_VAL->read(),not READ_QUEUE_OUT_READ_RA->read() or _gpr_val [_num_reg_ra[packet_id]][_context_id [packet_id]]);
	      if (READ_QUEUE_OUT_READ_RA    ->read() and
		  READ_QUEUE_OUT_DATA_RA_VAL->read())
	      TEST(Tgeneral_data_t   ,READ_QUEUE_OUT_DATA_RA    ->read(),_gpr          [_num_reg_ra[packet_id]][_context_id [packet_id]]);
	      TEST(Tcontrol_t        ,READ_QUEUE_OUT_READ_RB    ->read(),_read_rb      [packet_id]);
	      TEST(Tgeneral_address_t,READ_QUEUE_OUT_NUM_REG_RB ->read(),_num_reg_rb   [packet_id]);
	      TEST(Tcontrol_t        ,READ_QUEUE_OUT_DATA_RB_VAL->read(),not READ_QUEUE_OUT_READ_RB->read() or _gpr_val [_num_reg_rb[packet_id]][_context_id [packet_id]]);
	      if (READ_QUEUE_OUT_READ_RB    ->read() and
		  READ_QUEUE_OUT_DATA_RB_VAL->read())
	      TEST(Tgeneral_data_t   ,READ_QUEUE_OUT_DATA_RB    ->read(),_gpr          [_num_reg_rb[packet_id]][_context_id [packet_id]]);
	      TEST(Tcontrol_t        ,READ_QUEUE_OUT_READ_RC    ->read(),_read_rc      [packet_id]);
	      TEST(Tspecial_address_t,READ_QUEUE_OUT_NUM_REG_RC ->read(),_num_reg_rc   [packet_id]);
      	      TEST(Tcontrol_t        ,READ_QUEUE_OUT_DATA_RC_VAL->read(),not READ_QUEUE_OUT_READ_RC->read() or _spr_val [_num_reg_rc[packet_id]][_context_id [packet_id]]);
	      if (READ_QUEUE_OUT_READ_RC    ->read() and
		  READ_QUEUE_OUT_DATA_RC_VAL->read())
	      TEST(Tspecial_data_t   ,READ_QUEUE_OUT_DATA_RC    ->read(),_spr     [_num_reg_rc[packet_id]][_context_id [packet_id]]);
	    }
	  SC_START(1);
	}
    }

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

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

  delete    CLOCK;
  delete    NRESET;

  delete    READ_QUEUE_IN_VAL          ;
  delete    READ_QUEUE_IN_ACK          ;
  delete    READ_QUEUE_IN_CONTEXT_ID   ;
  delete    READ_QUEUE_IN_PACKET_ID    ;
  delete    READ_QUEUE_IN_OPERATION    ;
  delete    READ_QUEUE_IN_TYPE         ;
  delete    READ_QUEUE_IN_HAS_IMMEDIAT ;
  delete    READ_QUEUE_IN_IMMEDIAT     ;
  delete    READ_QUEUE_IN_READ_RA      ;
  delete    READ_QUEUE_IN_NUM_REG_RA   ;
  delete    READ_QUEUE_IN_READ_RB      ;
  delete    READ_QUEUE_IN_NUM_REG_RB   ;
  delete    READ_QUEUE_IN_READ_RC      ;
  delete    READ_QUEUE_IN_NUM_REG_RC   ;
  delete    READ_QUEUE_IN_WRITE_RD     ;
  delete    READ_QUEUE_IN_NUM_REG_RD   ;
  delete    READ_QUEUE_IN_WRITE_RE     ;
  delete    READ_QUEUE_IN_NUM_REG_RE   ;

  delete    READ_QUEUE_OUT_VAL         ;
  delete    READ_QUEUE_OUT_ACK         ;
  delete    READ_QUEUE_OUT_CONTEXT_ID  ;
  delete    READ_QUEUE_OUT_PACKET_ID   ;
  delete    READ_QUEUE_OUT_OPERATION   ;
  delete    READ_QUEUE_OUT_TYPE        ;
  delete    READ_QUEUE_OUT_HAS_IMMEDIAT;
  delete    READ_QUEUE_OUT_IMMEDIAT    ;
  delete    READ_QUEUE_OUT_READ_RA     ;
  delete    READ_QUEUE_OUT_NUM_REG_RA  ;
  delete    READ_QUEUE_OUT_DATA_RA_VAL ;
  delete    READ_QUEUE_OUT_DATA_RA     ;
  delete    READ_QUEUE_OUT_READ_RB     ;
  delete    READ_QUEUE_OUT_NUM_REG_RB  ;
  delete    READ_QUEUE_OUT_DATA_RB_VAL ;
  delete    READ_QUEUE_OUT_DATA_RB     ;
  delete    READ_QUEUE_OUT_READ_RC     ;
  delete    READ_QUEUE_OUT_NUM_REG_RC  ;
  delete    READ_QUEUE_OUT_DATA_RC_VAL ;
  delete    READ_QUEUE_OUT_DATA_RC     ;
  delete    READ_QUEUE_OUT_WRITE_RD    ;
  delete    READ_QUEUE_OUT_NUM_REG_RD  ;
  delete    READ_QUEUE_OUT_WRITE_RE    ;
  delete    READ_QUEUE_OUT_NUM_REG_RE  ;

  delete [] GPR_READ_VAL     ;
  delete [] GPR_READ_ACK     ;
  delete [] GPR_READ_NUM_REG ;
  delete [] GPR_READ_DATA    ;
  delete [] GPR_READ_DATA_VAL;

  delete [] SPR_READ_VAL     ;
  delete [] SPR_READ_ACK     ;
  delete [] SPR_READ_NUM_REG ;
  delete [] SPR_READ_DATA    ;
  delete [] SPR_READ_DATA_VAL;

  delete [] GPR_WRITE_VAL        ;
  delete [] GPR_WRITE_CONTEXT_ID ;
  delete [] GPR_WRITE_NUM_REG    ;
  delete [] GPR_WRITE_DATA       ;

  delete [] SPR_WRITE_VAL        ;
  delete [] SPR_WRITE_CONTEXT_ID ;
  delete [] SPR_WRITE_NUM_REG    ;
  delete [] SPR_WRITE_DATA       ;
#endif

  delete _Read_queue;

#ifdef STATISTICS
  delete _parameters_statistics;
#endif
}
