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

#include "Behavioural/Core/Multi_Execute_loop/Execute_loop/Network/Read_unit_to_Execution_unit/SelfTest/include/test.h"
#include "Common/include/Test.h"
#include "Common/include/BitManipulation.h"
#include "Behavioural/include/Allocation.h"
#include <list>
#include <set>

#define NB_ITERATION  1
#define CYCLE_MAX     (128*NB_ITERATION)

#define LABEL(str...)							\
  {									\
    msg (_("{%d} "),static_cast<uint32_t>(sc_simulation_time()));	\
    msg (str);								\
    msg (_("\n"));							\
  } while(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_offset != 0)						             \
	{								             \
	  cout << "##########[ cycle "<< cycle_current+cycle_offset << " ]" << endl; \
	}								             \
									             \
      if (cycle_current > CYCLE_MAX)					             \
	{								             \
	  TEST_KO("Maximal cycles Reached");				             \
	}								             \
									             \
      sc_start(cycle_offset);						             \
									             \
      /*cout << "SC_START (end  )" << endl;*/				             \
    } while(0)


class entry_t 
{
public : Tcontext_t         _context_id           ;
public : Tcontext_t         _front_end_id         ;
public : Tcontext_t         _ooo_engine_id        ;
public : Tpacket_t          _packet_id            ;
public : Toperation_t       _operation            ;
public : Ttype_t            _type                 ;
public : Tlsq_ptr_t         _store_queue_ptr_write;
public : Tlsq_ptr_t         _load_queue_ptr_write ;
public : Tcontrol_t         _has_immediat         ;
public : Tgeneral_data_t    _immediat             ;
public : Tgeneral_data_t    _data_ra              ;
public : Tgeneral_data_t    _data_rb              ;
public : Tspecial_data_t    _data_rc              ;
public : Tcontrol_t         _write_rd             ;
public : Tgeneral_address_t _num_reg_rd           ;
public : Tcontrol_t         _write_re             ;
public : Tspecial_address_t _num_reg_re           ;

public : entry_t (Tcontext_t         context_id           ,
		  Tcontext_t         front_end_id         ,
		  Tcontext_t         ooo_engine_id        ,
		  Tpacket_t          packet_id            ,
		  Toperation_t       operation            ,
		  Ttype_t            type                 ,
		  Tlsq_ptr_t         store_queue_ptr_write,
		  Tlsq_ptr_t         load_queue_ptr_write ,
		  Tcontrol_t         has_immediat         ,
		  Tgeneral_data_t    immediat             ,
		  Tgeneral_data_t    data_ra              ,
		  Tgeneral_data_t    data_rb              ,
		  Tspecial_data_t    data_rc              ,
		  Tcontrol_t         write_rd             ,
		  Tgeneral_address_t num_reg_rd           ,
		  Tcontrol_t         write_re             ,
		  Tspecial_address_t num_reg_re           )
  {
    _context_id            = context_id           ;
    _front_end_id          = front_end_id         ;
    _ooo_engine_id         = ooo_engine_id        ;
    _packet_id             = packet_id            ;
    _operation             = operation            ;
    _type                  = type                 ;
    _store_queue_ptr_write = store_queue_ptr_write;
    _load_queue_ptr_write  = load_queue_ptr_write ;
    _has_immediat          = has_immediat         ;
    _immediat              = immediat             ;
    _data_ra               = data_ra              ;
    _data_rb               = data_rb              ;
    _data_rc               = data_rc              ;
    _write_rd              = write_rd             ;
    _num_reg_rd            = num_reg_rd           ;
    _write_re              = write_re             ;
    _num_reg_re            = num_reg_re           ;
  }
};

void test (string name,
	   morpheo::behavioural::core::multi_execute_loop::execute_loop::network::read_unit_to_execution_unit::Parameters * _param)
{
  msg(_("<%s> : Simulation SystemC.\n"),name.c_str());

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

  Read_unit_to_Execution_unit * _Read_unit_to_Execution_unit = new Read_unit_to_Execution_unit (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");

  ALLOC1_SC_SIGNAL( in_READ_UNIT_OUT_VAL                  ," in_READ_UNIT_OUT_VAL"                  ,Tcontrol_t        ,_param->_nb_read_unit);
  ALLOC1_SC_SIGNAL(out_READ_UNIT_OUT_ACK                  ,"out_READ_UNIT_OUT_ACK"                  ,Tcontrol_t        ,_param->_nb_read_unit);
  ALLOC1_SC_SIGNAL( in_READ_UNIT_OUT_CONTEXT_ID           ," in_READ_UNIT_OUT_CONTEXT_ID"           ,Tcontext_t        ,_param->_nb_read_unit);
  ALLOC1_SC_SIGNAL( in_READ_UNIT_OUT_FRONT_END_ID         ," in_READ_UNIT_OUT_FRONT_END_ID"         ,Tcontext_t        ,_param->_nb_read_unit);
  ALLOC1_SC_SIGNAL( in_READ_UNIT_OUT_OOO_ENGINE_ID        ," in_READ_UNIT_OUT_OOO_ENGINE_ID"        ,Tcontext_t        ,_param->_nb_read_unit);
  ALLOC1_SC_SIGNAL( in_READ_UNIT_OUT_PACKET_ID            ," in_READ_UNIT_OUT_PACKET_ID"            ,Tpacket_t         ,_param->_nb_read_unit);
  ALLOC1_SC_SIGNAL( in_READ_UNIT_OUT_OPERATION            ," in_READ_UNIT_OUT_OPERATION"            ,Toperation_t      ,_param->_nb_read_unit);
  ALLOC1_SC_SIGNAL( in_READ_UNIT_OUT_TYPE                 ," in_READ_UNIT_OUT_TYPE"                 ,Ttype_t           ,_param->_nb_read_unit);
  ALLOC1_SC_SIGNAL( in_READ_UNIT_OUT_STORE_QUEUE_PTR_WRITE," in_READ_UNIT_OUT_STORE_QUEUE_PTR_WRITE",Tlsq_ptr_t        ,_param->_nb_read_unit);
  ALLOC1_SC_SIGNAL( in_READ_UNIT_OUT_LOAD_QUEUE_PTR_WRITE ," in_READ_UNIT_OUT_LOAD_QUEUE_PTR_WRITE" ,Tlsq_ptr_t        ,_param->_nb_read_unit);
  ALLOC1_SC_SIGNAL( in_READ_UNIT_OUT_HAS_IMMEDIAT         ," in_READ_UNIT_OUT_HAS_IMMEDIAT"         ,Tcontrol_t        ,_param->_nb_read_unit);
  ALLOC1_SC_SIGNAL( in_READ_UNIT_OUT_IMMEDIAT             ," in_READ_UNIT_OUT_IMMEDIAT"             ,Tgeneral_data_t   ,_param->_nb_read_unit);
  ALLOC1_SC_SIGNAL( in_READ_UNIT_OUT_DATA_RA              ," in_READ_UNIT_OUT_DATA_RA"              ,Tgeneral_data_t   ,_param->_nb_read_unit);
  ALLOC1_SC_SIGNAL( in_READ_UNIT_OUT_DATA_RB              ," in_READ_UNIT_OUT_DATA_RB"              ,Tgeneral_data_t   ,_param->_nb_read_unit);
  ALLOC1_SC_SIGNAL( in_READ_UNIT_OUT_DATA_RC              ," in_READ_UNIT_OUT_DATA_RC"              ,Tspecial_data_t   ,_param->_nb_read_unit);
  ALLOC1_SC_SIGNAL( in_READ_UNIT_OUT_WRITE_RD             ," in_READ_UNIT_OUT_WRITE_RD"             ,Tcontrol_t        ,_param->_nb_read_unit);
  ALLOC1_SC_SIGNAL( in_READ_UNIT_OUT_NUM_REG_RD           ," in_READ_UNIT_OUT_NUM_REG_RD"           ,Tgeneral_address_t,_param->_nb_read_unit);
  ALLOC1_SC_SIGNAL( in_READ_UNIT_OUT_WRITE_RE             ," in_READ_UNIT_OUT_WRITE_RE"             ,Tcontrol_t        ,_param->_nb_read_unit);
  ALLOC1_SC_SIGNAL( in_READ_UNIT_OUT_NUM_REG_RE           ," in_READ_UNIT_OUT_NUM_REG_RE"           ,Tspecial_address_t,_param->_nb_read_unit);
  ALLOC1_SC_SIGNAL(out_EXECUTE_UNIT_IN_VAL                  ,"out_EXECUTE_UNIT_IN_VAL"                  ,Tcontrol_t        ,_param->_nb_execute_unit);
  ALLOC1_SC_SIGNAL( in_EXECUTE_UNIT_IN_ACK                  ," in_EXECUTE_UNIT_IN_ACK"                  ,Tcontrol_t        ,_param->_nb_execute_unit);
  ALLOC1_SC_SIGNAL(out_EXECUTE_UNIT_IN_CONTEXT_ID           ,"out_EXECUTE_UNIT_IN_CONTEXT_ID"           ,Tcontext_t        ,_param->_nb_execute_unit);
  ALLOC1_SC_SIGNAL(out_EXECUTE_UNIT_IN_FRONT_END_ID         ,"out_EXECUTE_UNIT_IN_FRONT_END_ID"         ,Tcontext_t        ,_param->_nb_execute_unit);
  ALLOC1_SC_SIGNAL(out_EXECUTE_UNIT_IN_OOO_ENGINE_ID        ,"out_EXECUTE_UNIT_IN_OOO_ENGINE_ID"        ,Tcontext_t        ,_param->_nb_execute_unit);
  ALLOC1_SC_SIGNAL(out_EXECUTE_UNIT_IN_PACKET_ID            ,"out_EXECUTE_UNIT_IN_PACKET_ID"            ,Tpacket_t         ,_param->_nb_execute_unit);
  ALLOC1_SC_SIGNAL(out_EXECUTE_UNIT_IN_OPERATION            ,"out_EXECUTE_UNIT_IN_OPERATION"            ,Toperation_t      ,_param->_nb_execute_unit);
  ALLOC1_SC_SIGNAL(out_EXECUTE_UNIT_IN_TYPE                 ,"out_EXECUTE_UNIT_IN_TYPE"                 ,Ttype_t           ,_param->_nb_execute_unit);
  ALLOC1_SC_SIGNAL(out_EXECUTE_UNIT_IN_STORE_QUEUE_PTR_WRITE,"out_EXECUTE_UNIT_IN_STORE_QUEUE_PTR_WRITE",Tlsq_ptr_t        ,_param->_nb_execute_unit);
  ALLOC1_SC_SIGNAL(out_EXECUTE_UNIT_IN_LOAD_QUEUE_PTR_WRITE ,"out_EXECUTE_UNIT_IN_LOAD_QUEUE_PTR_WRITE" ,Tlsq_ptr_t        ,_param->_nb_execute_unit);
  ALLOC1_SC_SIGNAL(out_EXECUTE_UNIT_IN_HAS_IMMEDIAT         ,"out_EXECUTE_UNIT_IN_HAS_IMMEDIAT"         ,Tcontrol_t        ,_param->_nb_execute_unit);
  ALLOC1_SC_SIGNAL(out_EXECUTE_UNIT_IN_IMMEDIAT             ,"out_EXECUTE_UNIT_IN_IMMEDIAT"             ,Tgeneral_data_t   ,_param->_nb_execute_unit);
  ALLOC1_SC_SIGNAL(out_EXECUTE_UNIT_IN_DATA_RA              ,"out_EXECUTE_UNIT_IN_DATA_RA"              ,Tgeneral_data_t   ,_param->_nb_execute_unit);
  ALLOC1_SC_SIGNAL(out_EXECUTE_UNIT_IN_DATA_RB              ,"out_EXECUTE_UNIT_IN_DATA_RB"              ,Tgeneral_data_t   ,_param->_nb_execute_unit);
  ALLOC1_SC_SIGNAL(out_EXECUTE_UNIT_IN_DATA_RC              ,"out_EXECUTE_UNIT_IN_DATA_RC"              ,Tspecial_data_t   ,_param->_nb_execute_unit);
  ALLOC1_SC_SIGNAL(out_EXECUTE_UNIT_IN_WRITE_RD             ,"out_EXECUTE_UNIT_IN_WRITE_RD"             ,Tcontrol_t        ,_param->_nb_execute_unit);
  ALLOC1_SC_SIGNAL(out_EXECUTE_UNIT_IN_NUM_REG_RD           ,"out_EXECUTE_UNIT_IN_NUM_REG_RD"           ,Tgeneral_address_t,_param->_nb_execute_unit);
  ALLOC1_SC_SIGNAL(out_EXECUTE_UNIT_IN_WRITE_RE             ,"out_EXECUTE_UNIT_IN_WRITE_RE"             ,Tcontrol_t        ,_param->_nb_execute_unit);
  ALLOC1_SC_SIGNAL(out_EXECUTE_UNIT_IN_NUM_REG_RE           ,"out_EXECUTE_UNIT_IN_NUM_REG_RE"           ,Tspecial_address_t,_param->_nb_execute_unit);
  
  
  /********************************************************
   * Instanciation
   ********************************************************/
  
  msg(_("<%s> : Instanciation of _Read_unit_to_Execution_unit.\n"),name.c_str());

  (*(_Read_unit_to_Execution_unit->in_CLOCK))        (*(in_CLOCK));
  (*(_Read_unit_to_Execution_unit->in_NRESET))       (*(in_NRESET));

  INSTANCE1_SC_SIGNAL(_Read_unit_to_Execution_unit, in_READ_UNIT_OUT_VAL                  ,_param->_nb_read_unit);
  INSTANCE1_SC_SIGNAL(_Read_unit_to_Execution_unit,out_READ_UNIT_OUT_ACK                  ,_param->_nb_read_unit);
  if (_param->_have_port_context_id)
  INSTANCE1_SC_SIGNAL(_Read_unit_to_Execution_unit, in_READ_UNIT_OUT_CONTEXT_ID           ,_param->_nb_read_unit);
  if (_param->_have_port_front_end_id)
  INSTANCE1_SC_SIGNAL(_Read_unit_to_Execution_unit, in_READ_UNIT_OUT_FRONT_END_ID         ,_param->_nb_read_unit);
  if (_param->_have_port_ooo_engine_id)
  INSTANCE1_SC_SIGNAL(_Read_unit_to_Execution_unit, in_READ_UNIT_OUT_OOO_ENGINE_ID        ,_param->_nb_read_unit);
  if (_param->_have_port_packet_id)
  INSTANCE1_SC_SIGNAL(_Read_unit_to_Execution_unit, in_READ_UNIT_OUT_PACKET_ID            ,_param->_nb_read_unit);
  INSTANCE1_SC_SIGNAL(_Read_unit_to_Execution_unit, in_READ_UNIT_OUT_OPERATION            ,_param->_nb_read_unit);
  INSTANCE1_SC_SIGNAL(_Read_unit_to_Execution_unit, in_READ_UNIT_OUT_TYPE                 ,_param->_nb_read_unit);
  INSTANCE1_SC_SIGNAL(_Read_unit_to_Execution_unit, in_READ_UNIT_OUT_STORE_QUEUE_PTR_WRITE,_param->_nb_read_unit);
  if (_param->_have_port_load_queue_ptr)
  INSTANCE1_SC_SIGNAL(_Read_unit_to_Execution_unit, in_READ_UNIT_OUT_LOAD_QUEUE_PTR_WRITE ,_param->_nb_read_unit);
  INSTANCE1_SC_SIGNAL(_Read_unit_to_Execution_unit, in_READ_UNIT_OUT_HAS_IMMEDIAT         ,_param->_nb_read_unit);
  INSTANCE1_SC_SIGNAL(_Read_unit_to_Execution_unit, in_READ_UNIT_OUT_IMMEDIAT             ,_param->_nb_read_unit);
  INSTANCE1_SC_SIGNAL(_Read_unit_to_Execution_unit, in_READ_UNIT_OUT_DATA_RA              ,_param->_nb_read_unit);
  INSTANCE1_SC_SIGNAL(_Read_unit_to_Execution_unit, in_READ_UNIT_OUT_DATA_RB              ,_param->_nb_read_unit);
  INSTANCE1_SC_SIGNAL(_Read_unit_to_Execution_unit, in_READ_UNIT_OUT_DATA_RC              ,_param->_nb_read_unit);
  INSTANCE1_SC_SIGNAL(_Read_unit_to_Execution_unit, in_READ_UNIT_OUT_WRITE_RD             ,_param->_nb_read_unit);
  INSTANCE1_SC_SIGNAL(_Read_unit_to_Execution_unit, in_READ_UNIT_OUT_NUM_REG_RD           ,_param->_nb_read_unit);
  INSTANCE1_SC_SIGNAL(_Read_unit_to_Execution_unit, in_READ_UNIT_OUT_WRITE_RE             ,_param->_nb_read_unit);
  INSTANCE1_SC_SIGNAL(_Read_unit_to_Execution_unit, in_READ_UNIT_OUT_NUM_REG_RE           ,_param->_nb_read_unit);

  INSTANCE1_SC_SIGNAL(_Read_unit_to_Execution_unit,out_EXECUTE_UNIT_IN_VAL                  ,_param->_nb_execute_unit);
  INSTANCE1_SC_SIGNAL(_Read_unit_to_Execution_unit, in_EXECUTE_UNIT_IN_ACK                  ,_param->_nb_execute_unit);
  if (_param->_have_port_context_id)
  INSTANCE1_SC_SIGNAL(_Read_unit_to_Execution_unit,out_EXECUTE_UNIT_IN_CONTEXT_ID           ,_param->_nb_execute_unit);
  if (_param->_have_port_front_end_id)
  INSTANCE1_SC_SIGNAL(_Read_unit_to_Execution_unit,out_EXECUTE_UNIT_IN_FRONT_END_ID         ,_param->_nb_execute_unit);
  if (_param->_have_port_ooo_engine_id)
  INSTANCE1_SC_SIGNAL(_Read_unit_to_Execution_unit,out_EXECUTE_UNIT_IN_OOO_ENGINE_ID        ,_param->_nb_execute_unit);
  if (_param->_have_port_packet_id)
  INSTANCE1_SC_SIGNAL(_Read_unit_to_Execution_unit,out_EXECUTE_UNIT_IN_PACKET_ID            ,_param->_nb_execute_unit);
  INSTANCE1_SC_SIGNAL(_Read_unit_to_Execution_unit,out_EXECUTE_UNIT_IN_OPERATION            ,_param->_nb_execute_unit);
  INSTANCE1_SC_SIGNAL(_Read_unit_to_Execution_unit,out_EXECUTE_UNIT_IN_TYPE                 ,_param->_nb_execute_unit);
  INSTANCE1_SC_SIGNAL(_Read_unit_to_Execution_unit,out_EXECUTE_UNIT_IN_STORE_QUEUE_PTR_WRITE,_param->_nb_execute_unit);
  if (_param->_have_port_load_queue_ptr)
  INSTANCE1_SC_SIGNAL(_Read_unit_to_Execution_unit,out_EXECUTE_UNIT_IN_LOAD_QUEUE_PTR_WRITE ,_param->_nb_execute_unit);
  INSTANCE1_SC_SIGNAL(_Read_unit_to_Execution_unit,out_EXECUTE_UNIT_IN_HAS_IMMEDIAT         ,_param->_nb_execute_unit);
  INSTANCE1_SC_SIGNAL(_Read_unit_to_Execution_unit,out_EXECUTE_UNIT_IN_IMMEDIAT             ,_param->_nb_execute_unit);
  INSTANCE1_SC_SIGNAL(_Read_unit_to_Execution_unit,out_EXECUTE_UNIT_IN_DATA_RA              ,_param->_nb_execute_unit);
  INSTANCE1_SC_SIGNAL(_Read_unit_to_Execution_unit,out_EXECUTE_UNIT_IN_DATA_RB              ,_param->_nb_execute_unit);
  INSTANCE1_SC_SIGNAL(_Read_unit_to_Execution_unit,out_EXECUTE_UNIT_IN_DATA_RC              ,_param->_nb_execute_unit);
  INSTANCE1_SC_SIGNAL(_Read_unit_to_Execution_unit,out_EXECUTE_UNIT_IN_WRITE_RD             ,_param->_nb_execute_unit);
  INSTANCE1_SC_SIGNAL(_Read_unit_to_Execution_unit,out_EXECUTE_UNIT_IN_NUM_REG_RD           ,_param->_nb_execute_unit);
  INSTANCE1_SC_SIGNAL(_Read_unit_to_Execution_unit,out_EXECUTE_UNIT_IN_WRITE_RE             ,_param->_nb_execute_unit);
  INSTANCE1_SC_SIGNAL(_Read_unit_to_Execution_unit,out_EXECUTE_UNIT_IN_NUM_REG_RE           ,_param->_nb_execute_unit);

  msg(_("<%s> : Start Simulation ............\n"),name.c_str());
    
  Time * _time = new Time();

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

  // Initialisation

  const uint32_t seed = 0;
// const uint32_t seed = static_cast<uint32_t>(time(NULL));

  srand(seed);

  const  int32_t percent_transaction_in  = 75;
  const  int32_t percent_transaction_out = 75;

  set<Tcontext_t> read_unit_thread [_param->_nb_read_unit];
  set<Ttype_t   > read_unit_type   [_param->_nb_read_unit][_param->_nb_thread];
 
  for (uint32_t i=0; i<_param->_nb_read_unit; i++)
    for (uint32_t j=0; j<_param->_nb_execute_unit; j++)
      if (_param->_table_routing[i][j])
	for (uint32_t k=0; k<_param->_nb_thread; k++)
	  if (_param->_table_execute_thread[j][k])
	    {
	      read_unit_thread [i].insert(k);
	      
	      for (uint32_t l=0; l<_param->_nb_type; l++)
		if (_param->_table_execute_type[j][l])
		  read_unit_type [i][k].insert(l);
	    }
  //bool ** _table_routing       ; //array [nb_read_unit][nb_execute_unit]
  //bool ** _table_execute_type  ; //array [nb_execute_unit][nb_type]
  //bool ** _table_execute_thread; //array [nb_execute_unit][nb_thread]
  
  SC_START(0);
  LABEL("Initialisation");

  LABEL("Reset");
  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 %d",iteration);

      list<entry_t> request [_param->_nb_read_unit];

      uint32_t nb_request_in;
      for (nb_request_in=0; nb_request_in < _param->_nb_packet; )
	for (uint32_t i=0; i<_param->_nb_read_unit; i++)
	  {
	    if (nb_request_in >= _param->_nb_packet)
	      break;

	    Tcontext_t context_id   ;
	    Tcontext_t front_end_id ;
	    Tcontext_t ooo_engine_id;
	    Tcontext_t num_thread   ;

	    // Find compatible thread
	    do
	      {
		context_id    = range<Tcontext_t> (rand(), _param->_size_context_id   );
		front_end_id  = range<Tcontext_t> (rand(), _param->_size_front_end_id );
		ooo_engine_id = range<Tcontext_t> (rand(), _param->_size_ooo_engine_id);
		num_thread    = get_num_thread (context_id   , _param->_size_context_id   ,
						front_end_id , _param->_size_front_end_id ,
						ooo_engine_id, _param->_size_ooo_engine_id);
	      }
	    while (read_unit_thread[i].find(num_thread) == read_unit_thread[i].end());

	    Ttype_t    type;
	    
	    // Find a compatible type
	    do
	      {
		type = range<Ttype_t> (rand(), _param->_size_type);
	      }
	    while (read_unit_type[i][num_thread].find(type) == read_unit_type[i][num_thread].end());

	    request[i].push_back(entry_t (context_id   ,
					  front_end_id ,
					  ooo_engine_id,
					  nb_request_in,
					  range<Toperation_t      > (rand(), _param->_size_operation       ),
					  type,
					  range<Tlsq_ptr_t        > (rand(), _param->_size_store_queue     ),
					  range<Tlsq_ptr_t        > (rand(), _param->_size_load_queue      ),
					  range<Tcontrol_t        > (rand(), 2                             ),
					  range<Tgeneral_data_t   > (rand(), _param->_size_general_data    ),
					  range<Tgeneral_data_t   > (rand(), _param->_size_general_data    ),
					  range<Tgeneral_data_t   > (rand(), _param->_size_general_data    ),
					  range<Tspecial_data_t   > (rand(), _param->_size_special_data    ),
					  range<Tcontrol_t        > (rand(), 2                             ),
					  range<Tgeneral_address_t> (rand(), _param->_size_general_register),
					  range<Tcontrol_t        > (rand(), 2                             ),
					  range<Tspecial_address_t> (rand(), _param->_size_special_register)
					  ));

	    nb_request_in++;
	  }

      uint32_t   nb_request_out = 0;

      while (nb_request_out < nb_request_in)
	{
	  for (uint32_t i=0; i<_param->_nb_read_unit; i++)
	    {
	      bool val = not request[i].empty() and ((rand()%100) < percent_transaction_in);
		
	      in_READ_UNIT_OUT_VAL [i]->write(val);

	      if (val)
		{
		  in_READ_UNIT_OUT_CONTEXT_ID           [i] ->write(request[i].front()._context_id           );
		  in_READ_UNIT_OUT_FRONT_END_ID         [i] ->write(request[i].front()._front_end_id         );
		  in_READ_UNIT_OUT_OOO_ENGINE_ID        [i] ->write(request[i].front()._ooo_engine_id        );
		  in_READ_UNIT_OUT_PACKET_ID            [i] ->write(request[i].front()._packet_id            );
		  in_READ_UNIT_OUT_OPERATION            [i] ->write(request[i].front()._operation            );
		  in_READ_UNIT_OUT_TYPE                 [i] ->write(request[i].front()._type                 );
		  in_READ_UNIT_OUT_STORE_QUEUE_PTR_WRITE[i] ->write(request[i].front()._store_queue_ptr_write);
		  if (_param->_have_port_load_queue_ptr)
		  in_READ_UNIT_OUT_LOAD_QUEUE_PTR_WRITE [i] ->write(request[i].front()._load_queue_ptr_write );
		  in_READ_UNIT_OUT_HAS_IMMEDIAT         [i] ->write(request[i].front()._has_immediat         );
		  in_READ_UNIT_OUT_IMMEDIAT             [i] ->write(request[i].front()._immediat             );
		  in_READ_UNIT_OUT_DATA_RA              [i] ->write(request[i].front()._data_ra              );
		  in_READ_UNIT_OUT_DATA_RB              [i] ->write(request[i].front()._data_rb              );
		  in_READ_UNIT_OUT_DATA_RC              [i] ->write(request[i].front()._data_rc              );
		  in_READ_UNIT_OUT_WRITE_RD             [i] ->write(request[i].front()._write_rd             );
		  in_READ_UNIT_OUT_NUM_REG_RD           [i] ->write(request[i].front()._num_reg_rd           );
		  in_READ_UNIT_OUT_WRITE_RE             [i] ->write(request[i].front()._write_re             );
		  in_READ_UNIT_OUT_NUM_REG_RE           [i] ->write(request[i].front()._num_reg_re           );
		}
	    }

	  for (uint32_t i=0; i<_param->_nb_execute_unit; i++)
	    in_EXECUTE_UNIT_IN_ACK [i]->write((rand()%100) < percent_transaction_out);

	  SC_START(0);

	  for (uint32_t i=0; i<_param->_nb_read_unit; i++)
	    if (in_READ_UNIT_OUT_VAL [i]->read() and out_READ_UNIT_OUT_ACK [i]->read())
	      {
		LABEL("READ_UNIT_OUT   [%d] - Transaction accepted",i);
	      }

	  for (uint32_t i=0; i<_param->_nb_execute_unit; i++)
	    if (out_EXECUTE_UNIT_IN_VAL [i]->read() and in_EXECUTE_UNIT_IN_ACK [i]->read())
	      {
		LABEL("EXECUTE_UNIT_IN [%d] - Transaction accepted (%d)",i,nb_request_out);
		nb_request_out ++;
		
		Tpacket_t packet = (_param->_have_port_packet_id)?out_EXECUTE_UNIT_IN_PACKET_ID[i]->read():0;
		LABEL("  * packet           : %d",packet);		
		uint32_t read_unit;

		// find read_unit
		for (read_unit=0; read_unit<_param->_nb_read_unit; read_unit++)
		  if (packet == ((_param->_have_port_packet_id)?request[read_unit].front()._packet_id:0))
		    break;

		LABEL("  * read_unit source : %d",read_unit);

		if (_param->_have_port_packet_id)
		TEST(Tcontext_t        ,out_EXECUTE_UNIT_IN_PACKET_ID            [i]->read(), request[read_unit].front()._packet_id            );

		// Authorised link ? read_unit -> execute_unit
		TEST(bool, _param->_table_routing[read_unit][i], true);

		if (_param->_have_port_context_id)
		TEST(Tcontext_t        ,out_EXECUTE_UNIT_IN_CONTEXT_ID           [i]->read(), request[read_unit].front()._context_id           );
		if (_param->_have_port_front_end_id)
		TEST(Tcontext_t        ,out_EXECUTE_UNIT_IN_FRONT_END_ID         [i]->read(), request[read_unit].front()._front_end_id         );
		if (_param->_have_port_ooo_engine_id)
		TEST(Tcontext_t        ,out_EXECUTE_UNIT_IN_OOO_ENGINE_ID        [i]->read(), request[read_unit].front()._ooo_engine_id        );
		TEST(Toperation_t      ,out_EXECUTE_UNIT_IN_OPERATION            [i]->read(), request[read_unit].front()._operation            );
		TEST(Ttype_t           ,out_EXECUTE_UNIT_IN_TYPE                 [i]->read(), request[read_unit].front()._type                 );
		TEST(Tlsq_ptr_t        ,out_EXECUTE_UNIT_IN_STORE_QUEUE_PTR_WRITE[i]->read(), request[read_unit].front()._store_queue_ptr_write);
		if (_param->_have_port_load_queue_ptr)
		TEST(Tlsq_ptr_t        ,out_EXECUTE_UNIT_IN_LOAD_QUEUE_PTR_WRITE [i]->read(), request[read_unit].front()._load_queue_ptr_write );
		TEST(Tcontrol_t        ,out_EXECUTE_UNIT_IN_HAS_IMMEDIAT         [i]->read(), request[read_unit].front()._has_immediat         );
		TEST(Tgeneral_data_t   ,out_EXECUTE_UNIT_IN_IMMEDIAT             [i]->read(), request[read_unit].front()._immediat             );
		TEST(Tgeneral_data_t   ,out_EXECUTE_UNIT_IN_DATA_RA              [i]->read(), request[read_unit].front()._data_ra              );
		TEST(Tgeneral_data_t   ,out_EXECUTE_UNIT_IN_DATA_RB              [i]->read(), request[read_unit].front()._data_rb              );
		TEST(Tspecial_data_t   ,out_EXECUTE_UNIT_IN_DATA_RC              [i]->read(), request[read_unit].front()._data_rc              );
		TEST(Tcontrol_t        ,out_EXECUTE_UNIT_IN_WRITE_RD             [i]->read(), request[read_unit].front()._write_rd             );
		TEST(Tgeneral_address_t,out_EXECUTE_UNIT_IN_NUM_REG_RD           [i]->read(), request[read_unit].front()._num_reg_rd           );
		TEST(Tcontrol_t        ,out_EXECUTE_UNIT_IN_WRITE_RE             [i]->read(), request[read_unit].front()._write_re             );
		TEST(Tspecial_address_t,out_EXECUTE_UNIT_IN_NUM_REG_RE           [i]->read(), request[read_unit].front()._num_reg_re           );
		
		request[read_unit].pop_front();
	      }
	  SC_START(1);
	}

    }

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

  TEST_OK ("End of Simulation");
  delete _time;

  msg(_("<%s> : ............ Stop Simulation\n"),name.c_str());

  delete in_CLOCK;
  delete in_NRESET;
  
  delete []  in_READ_UNIT_OUT_VAL                  ;
  delete [] out_READ_UNIT_OUT_ACK                  ;
  delete []  in_READ_UNIT_OUT_CONTEXT_ID           ;
  delete []  in_READ_UNIT_OUT_FRONT_END_ID         ;
  delete []  in_READ_UNIT_OUT_OOO_ENGINE_ID        ;
  delete []  in_READ_UNIT_OUT_PACKET_ID            ;
  delete []  in_READ_UNIT_OUT_OPERATION            ;
  delete []  in_READ_UNIT_OUT_TYPE                 ;
  delete []  in_READ_UNIT_OUT_STORE_QUEUE_PTR_WRITE;
  delete []  in_READ_UNIT_OUT_LOAD_QUEUE_PTR_WRITE ;
  delete []  in_READ_UNIT_OUT_HAS_IMMEDIAT         ;
  delete []  in_READ_UNIT_OUT_IMMEDIAT             ;
  delete []  in_READ_UNIT_OUT_DATA_RA              ;
  delete []  in_READ_UNIT_OUT_DATA_RB              ;
  delete []  in_READ_UNIT_OUT_DATA_RC              ;
  delete []  in_READ_UNIT_OUT_WRITE_RD             ;
  delete []  in_READ_UNIT_OUT_NUM_REG_RD           ;
  delete []  in_READ_UNIT_OUT_WRITE_RE             ;
  delete []  in_READ_UNIT_OUT_NUM_REG_RE           ;

  delete [] out_EXECUTE_UNIT_IN_VAL                  ;
  delete []  in_EXECUTE_UNIT_IN_ACK                  ;
  delete [] out_EXECUTE_UNIT_IN_CONTEXT_ID           ;
  delete [] out_EXECUTE_UNIT_IN_FRONT_END_ID         ;
  delete [] out_EXECUTE_UNIT_IN_OOO_ENGINE_ID        ;
  delete [] out_EXECUTE_UNIT_IN_PACKET_ID            ;
  delete [] out_EXECUTE_UNIT_IN_OPERATION            ;
  delete [] out_EXECUTE_UNIT_IN_TYPE                 ;
  delete [] out_EXECUTE_UNIT_IN_STORE_QUEUE_PTR_WRITE;
  delete [] out_EXECUTE_UNIT_IN_LOAD_QUEUE_PTR_WRITE ;
  delete [] out_EXECUTE_UNIT_IN_HAS_IMMEDIAT         ;
  delete [] out_EXECUTE_UNIT_IN_IMMEDIAT             ;
  delete [] out_EXECUTE_UNIT_IN_DATA_RA              ;
  delete [] out_EXECUTE_UNIT_IN_DATA_RB              ;
  delete [] out_EXECUTE_UNIT_IN_DATA_RC              ;
  delete [] out_EXECUTE_UNIT_IN_WRITE_RD             ;
  delete [] out_EXECUTE_UNIT_IN_NUM_REG_RD           ;
  delete [] out_EXECUTE_UNIT_IN_WRITE_RE             ;
  delete [] out_EXECUTE_UNIT_IN_NUM_REG_RE           ;

#endif

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