/*
 * $Id: test.cpp 97 2008-12-19 15:34:00Z rosiere $
 *
 * [ Description ]
 * 
 * Test
 */

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


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 : Tcontrol_t         _write_rd       ;
  public : Tgeneral_address_t _num_reg_rd     ;
  public : Tgeneral_data_t    _data_rd        ;
  public : Tcontrol_t         _write_re       ;
  public : Tspecial_address_t _num_reg_re     ;
  public : Tspecial_data_t    _data_re        ;
  public : Texception_t       _exception      ;
  public : Tcontrol_t         _no_sequence    ;
  public : Tgeneral_data_t    _address        ;
  
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           ,
  		  Tcontrol_t         write_rd       ,
  		  Tgeneral_address_t num_reg_rd     ,
  		  Tgeneral_data_t    data_rd        ,
  		  Tcontrol_t         write_re       ,
  		  Tspecial_address_t num_reg_re     ,
  		  Tspecial_data_t    data_re        ,
  		  Texception_t       exception      ,
  		  Tcontrol_t         no_sequence    ,
  		  Tgeneral_data_t    address        )
  {
    _context_id     = context_id   ;
    _front_end_id   = front_end_id ;
    _ooo_engine_id  = ooo_engine_id;
    _packet_id      = packet_id    ;
//  _operation      = operation    ;
//  _type           = type         ;
    _write_rd       = write_rd     ;
    _num_reg_rd     = num_reg_rd   ;
    _data_rd        = data_rd      ;
    _write_re       = write_re     ;
    _num_reg_re     = num_reg_re   ;
    _data_re        = data_re      ;
    _exception      = exception    ;
    _no_sequence    = no_sequence  ;
    _address        = address      ;
  }
};

void test (string name,
	   morpheo::behavioural::core::multi_execute_loop::execute_loop::network::execution_unit_to_write_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

  Tusage_t _usage = USE_ALL;

//   _usage = usage_unset(_usage,USE_SYSTEMC              );
//   _usage = usage_unset(_usage,USE_VHDL                 );
//   _usage = usage_unset(_usage,USE_VHDL_TESTBENCH       );
//   _usage = usage_unset(_usage,USE_VHDL_TESTBENCH_ASSERT);
//   _usage = usage_unset(_usage,USE_POSITION             );
   _usage = usage_unset(_usage,USE_STATISTICS           );
//   _usage = usage_unset(_usage,USE_INFORMATION          );

  Execution_unit_to_Write_unit * _Execution_unit_to_Write_unit = new Execution_unit_to_Write_unit 
    (name.c_str(),
#ifdef STATISTICS
     _parameters_statistics,
#endif
     _param,
     _usage);
  
#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");

  ALLOC2_SC_SIGNAL( in_EXECUTE_UNIT_OUT_VAL          ," in_EXECUTE_UNIT_OUT_VAL          ",Tcontrol_t        ,_param->_nb_execute_unit,_param->_nb_execute_unit_port[it1]);
  ALLOC2_SC_SIGNAL(out_EXECUTE_UNIT_OUT_ACK          ,"out_EXECUTE_UNIT_OUT_ACK          ",Tcontrol_t        ,_param->_nb_execute_unit,_param->_nb_execute_unit_port[it1]);
  ALLOC2_SC_SIGNAL( in_EXECUTE_UNIT_OUT_CONTEXT_ID   ," in_EXECUTE_UNIT_OUT_CONTEXT_ID   ",Tcontext_t        ,_param->_nb_execute_unit,_param->_nb_execute_unit_port[it1]);
  ALLOC2_SC_SIGNAL( in_EXECUTE_UNIT_OUT_FRONT_END_ID ," in_EXECUTE_UNIT_OUT_FRONT_END_ID ",Tcontext_t        ,_param->_nb_execute_unit,_param->_nb_execute_unit_port[it1]);
  ALLOC2_SC_SIGNAL( in_EXECUTE_UNIT_OUT_OOO_ENGINE_ID," in_EXECUTE_UNIT_OUT_OOO_ENGINE_ID",Tcontext_t        ,_param->_nb_execute_unit,_param->_nb_execute_unit_port[it1]);
  ALLOC2_SC_SIGNAL( in_EXECUTE_UNIT_OUT_PACKET_ID    ," in_EXECUTE_UNIT_OUT_PACKET_ID    ",Tpacket_t         ,_param->_nb_execute_unit,_param->_nb_execute_unit_port[it1]);
//ALLOC2_SC_SIGNAL( in_EXECUTE_UNIT_OUT_OPERATION    ," in_EXECUTE_UNIT_OUT_OPERATION    ",Toperation_t      ,_param->_nb_execute_unit,_param->_nb_execute_unit_port[it1]);
//ALLOC2_SC_SIGNAL( in_EXECUTE_UNIT_OUT_TYPE         ," in_EXECUTE_UNIT_OUT_TYPE         ",Ttype_t           ,_param->_nb_execute_unit,_param->_nb_execute_unit_port[it1]);
  ALLOC2_SC_SIGNAL( in_EXECUTE_UNIT_OUT_WRITE_RD     ," in_EXECUTE_UNIT_OUT_WRITE_RD     ",Tcontrol_t        ,_param->_nb_execute_unit,_param->_nb_execute_unit_port[it1]);
  ALLOC2_SC_SIGNAL( in_EXECUTE_UNIT_OUT_NUM_REG_RD   ," in_EXECUTE_UNIT_OUT_NUM_REG_RD   ",Tgeneral_address_t,_param->_nb_execute_unit,_param->_nb_execute_unit_port[it1]);
  ALLOC2_SC_SIGNAL( in_EXECUTE_UNIT_OUT_DATA_RD      ," in_EXECUTE_UNIT_OUT_DATA_RD      ",Tgeneral_data_t   ,_param->_nb_execute_unit,_param->_nb_execute_unit_port[it1]);
  ALLOC2_SC_SIGNAL( in_EXECUTE_UNIT_OUT_WRITE_RE     ," in_EXECUTE_UNIT_OUT_WRITE_RE     ",Tcontrol_t        ,_param->_nb_execute_unit,_param->_nb_execute_unit_port[it1]);
  ALLOC2_SC_SIGNAL( in_EXECUTE_UNIT_OUT_NUM_REG_RE   ," in_EXECUTE_UNIT_OUT_NUM_REG_RE   ",Tspecial_address_t,_param->_nb_execute_unit,_param->_nb_execute_unit_port[it1]);
  ALLOC2_SC_SIGNAL( in_EXECUTE_UNIT_OUT_DATA_RE      ," in_EXECUTE_UNIT_OUT_DATA_RE      ",Tspecial_data_t   ,_param->_nb_execute_unit,_param->_nb_execute_unit_port[it1]);
  ALLOC2_SC_SIGNAL( in_EXECUTE_UNIT_OUT_EXCEPTION    ," in_EXECUTE_UNIT_OUT_EXCEPTION    ",Texception_t      ,_param->_nb_execute_unit,_param->_nb_execute_unit_port[it1]);
  ALLOC2_SC_SIGNAL( in_EXECUTE_UNIT_OUT_NO_SEQUENCE  ," in_EXECUTE_UNIT_OUT_NO_SEQUENCE  ",Tcontrol_t        ,_param->_nb_execute_unit,_param->_nb_execute_unit_port[it1]);
  ALLOC2_SC_SIGNAL( in_EXECUTE_UNIT_OUT_ADDRESS      ," in_EXECUTE_UNIT_OUT_ADDRESS      ",Taddress_t        ,_param->_nb_execute_unit,_param->_nb_execute_unit_port[it1]);

  ALLOC1_SC_SIGNAL(out_WRITE_UNIT_IN_VAL             ,"out_WRITE_UNIT_IN_VAL             ",Tcontrol_t        ,_param->_nb_write_unit  );
  ALLOC1_SC_SIGNAL( in_WRITE_UNIT_IN_ACK             ," in_WRITE_UNIT_IN_ACK             ",Tcontrol_t        ,_param->_nb_write_unit  );
  ALLOC1_SC_SIGNAL(out_WRITE_UNIT_IN_CONTEXT_ID      ,"out_WRITE_UNIT_IN_CONTEXT_ID      ",Tcontext_t        ,_param->_nb_write_unit  );
  ALLOC1_SC_SIGNAL(out_WRITE_UNIT_IN_FRONT_END_ID    ,"out_WRITE_UNIT_IN_FRONT_END_ID    ",Tcontext_t        ,_param->_nb_write_unit  );
  ALLOC1_SC_SIGNAL(out_WRITE_UNIT_IN_OOO_ENGINE_ID   ,"out_WRITE_UNIT_IN_OOO_ENGINE_ID   ",Tcontext_t        ,_param->_nb_write_unit  );
  ALLOC1_SC_SIGNAL(out_WRITE_UNIT_IN_PACKET_ID       ,"out_WRITE_UNIT_IN_PACKET_ID       ",Tpacket_t         ,_param->_nb_write_unit  );
//ALLOC1_SC_SIGNAL(out_WRITE_UNIT_IN_OPERATION       ,"out_WRITE_UNIT_IN_OPERATION       ",Toperation_t      ,_param->_nb_write_unit  );
//ALLOC1_SC_SIGNAL(out_WRITE_UNIT_IN_TYPE            ,"out_WRITE_UNIT_IN_TYPE            ",Ttype_t           ,_param->_nb_write_unit  );
  ALLOC1_SC_SIGNAL(out_WRITE_UNIT_IN_WRITE_RD        ,"out_WRITE_UNIT_IN_WRITE_RD        ",Tcontrol_t        ,_param->_nb_write_unit  );
  ALLOC1_SC_SIGNAL(out_WRITE_UNIT_IN_NUM_REG_RD      ,"out_WRITE_UNIT_IN_NUM_REG_RD      ",Tgeneral_address_t,_param->_nb_write_unit  );
  ALLOC1_SC_SIGNAL(out_WRITE_UNIT_IN_DATA_RD         ,"out_WRITE_UNIT_IN_DATA_RD         ",Tgeneral_data_t   ,_param->_nb_write_unit  );
  ALLOC1_SC_SIGNAL(out_WRITE_UNIT_IN_WRITE_RE        ,"out_WRITE_UNIT_IN_WRITE_RE        ",Tcontrol_t        ,_param->_nb_write_unit  );
  ALLOC1_SC_SIGNAL(out_WRITE_UNIT_IN_NUM_REG_RE      ,"out_WRITE_UNIT_IN_NUM_REG_RE      ",Tspecial_address_t,_param->_nb_write_unit  );
  ALLOC1_SC_SIGNAL(out_WRITE_UNIT_IN_DATA_RE         ,"out_WRITE_UNIT_IN_DATA_RE         ",Tspecial_data_t   ,_param->_nb_write_unit  );
  ALLOC1_SC_SIGNAL(out_WRITE_UNIT_IN_EXCEPTION       ,"out_WRITE_UNIT_IN_EXCEPTION       ",Texception_t      ,_param->_nb_write_unit  );
  ALLOC1_SC_SIGNAL(out_WRITE_UNIT_IN_NO_SEQUENCE     ,"out_WRITE_UNIT_IN_NO_SEQUENCE     ",Tcontrol_t        ,_param->_nb_write_unit  );
  ALLOC1_SC_SIGNAL(out_WRITE_UNIT_IN_ADDRESS         ,"out_WRITE_UNIT_IN_ADDRESS         ",Taddress_t        ,_param->_nb_write_unit  );
    
  /********************************************************
   * Instanciation
   ********************************************************/
  
  msg(_("<%s> : Instanciation of _Execution_unit_to_Write_unit.\n"),name.c_str());

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

  INSTANCE2_SC_SIGNAL(_Execution_unit_to_Write_unit, in_EXECUTE_UNIT_OUT_VAL          ,_param->_nb_execute_unit,_param->_nb_execute_unit_port[it1]);
  INSTANCE2_SC_SIGNAL(_Execution_unit_to_Write_unit,out_EXECUTE_UNIT_OUT_ACK          ,_param->_nb_execute_unit,_param->_nb_execute_unit_port[it1]);
  if (_param->_have_port_context_id)
  INSTANCE2_SC_SIGNAL(_Execution_unit_to_Write_unit, in_EXECUTE_UNIT_OUT_CONTEXT_ID   ,_param->_nb_execute_unit,_param->_nb_execute_unit_port[it1]);
  if (_param->_have_port_front_end_id)
  INSTANCE2_SC_SIGNAL(_Execution_unit_to_Write_unit, in_EXECUTE_UNIT_OUT_FRONT_END_ID ,_param->_nb_execute_unit,_param->_nb_execute_unit_port[it1]);
  if (_param->_have_port_ooo_engine_id)
  INSTANCE2_SC_SIGNAL(_Execution_unit_to_Write_unit, in_EXECUTE_UNIT_OUT_OOO_ENGINE_ID,_param->_nb_execute_unit,_param->_nb_execute_unit_port[it1]);
  if (_param->_have_port_rob_ptr  )
  INSTANCE2_SC_SIGNAL(_Execution_unit_to_Write_unit, in_EXECUTE_UNIT_OUT_PACKET_ID    ,_param->_nb_execute_unit,_param->_nb_execute_unit_port[it1]);
//INSTANCE2_SC_SIGNAL(_Execution_unit_to_Write_unit, in_EXECUTE_UNIT_OUT_OPERATION    ,_param->_nb_execute_unit,_param->_nb_execute_unit_port[it1]);
//INSTANCE2_SC_SIGNAL(_Execution_unit_to_Write_unit, in_EXECUTE_UNIT_OUT_TYPE         ,_param->_nb_execute_unit,_param->_nb_execute_unit_port[it1]);
  INSTANCE2_SC_SIGNAL(_Execution_unit_to_Write_unit, in_EXECUTE_UNIT_OUT_WRITE_RD     ,_param->_nb_execute_unit,_param->_nb_execute_unit_port[it1]);
  INSTANCE2_SC_SIGNAL(_Execution_unit_to_Write_unit, in_EXECUTE_UNIT_OUT_NUM_REG_RD   ,_param->_nb_execute_unit,_param->_nb_execute_unit_port[it1]);
  INSTANCE2_SC_SIGNAL(_Execution_unit_to_Write_unit, in_EXECUTE_UNIT_OUT_DATA_RD      ,_param->_nb_execute_unit,_param->_nb_execute_unit_port[it1]);
  INSTANCE2_SC_SIGNAL(_Execution_unit_to_Write_unit, in_EXECUTE_UNIT_OUT_WRITE_RE     ,_param->_nb_execute_unit,_param->_nb_execute_unit_port[it1]);
  INSTANCE2_SC_SIGNAL(_Execution_unit_to_Write_unit, in_EXECUTE_UNIT_OUT_NUM_REG_RE   ,_param->_nb_execute_unit,_param->_nb_execute_unit_port[it1]);
  INSTANCE2_SC_SIGNAL(_Execution_unit_to_Write_unit, in_EXECUTE_UNIT_OUT_DATA_RE      ,_param->_nb_execute_unit,_param->_nb_execute_unit_port[it1]);
  INSTANCE2_SC_SIGNAL(_Execution_unit_to_Write_unit, in_EXECUTE_UNIT_OUT_EXCEPTION    ,_param->_nb_execute_unit,_param->_nb_execute_unit_port[it1]);
  INSTANCE2_SC_SIGNAL(_Execution_unit_to_Write_unit, in_EXECUTE_UNIT_OUT_NO_SEQUENCE  ,_param->_nb_execute_unit,_param->_nb_execute_unit_port[it1]);
  INSTANCE2_SC_SIGNAL(_Execution_unit_to_Write_unit, in_EXECUTE_UNIT_OUT_ADDRESS      ,_param->_nb_execute_unit,_param->_nb_execute_unit_port[it1]);

  INSTANCE1_SC_SIGNAL(_Execution_unit_to_Write_unit,out_WRITE_UNIT_IN_VAL             ,_param->_nb_write_unit  );
  INSTANCE1_SC_SIGNAL(_Execution_unit_to_Write_unit, in_WRITE_UNIT_IN_ACK             ,_param->_nb_write_unit  );
  if (_param->_have_port_context_id)
  INSTANCE1_SC_SIGNAL(_Execution_unit_to_Write_unit,out_WRITE_UNIT_IN_CONTEXT_ID      ,_param->_nb_write_unit  );
  if (_param->_have_port_front_end_id)
  INSTANCE1_SC_SIGNAL(_Execution_unit_to_Write_unit,out_WRITE_UNIT_IN_FRONT_END_ID    ,_param->_nb_write_unit  );
  if (_param->_have_port_ooo_engine_id)
  INSTANCE1_SC_SIGNAL(_Execution_unit_to_Write_unit,out_WRITE_UNIT_IN_OOO_ENGINE_ID   ,_param->_nb_write_unit  );
  if (_param->_have_port_rob_ptr  )
  INSTANCE1_SC_SIGNAL(_Execution_unit_to_Write_unit,out_WRITE_UNIT_IN_PACKET_ID       ,_param->_nb_write_unit  );
//INSTANCE1_SC_SIGNAL(_Execution_unit_to_Write_unit,out_WRITE_UNIT_IN_OPERATION       ,_param->_nb_write_unit  );
//INSTANCE1_SC_SIGNAL(_Execution_unit_to_Write_unit,out_WRITE_UNIT_IN_TYPE            ,_param->_nb_write_unit  );
  INSTANCE1_SC_SIGNAL(_Execution_unit_to_Write_unit,out_WRITE_UNIT_IN_WRITE_RD        ,_param->_nb_write_unit  );
  INSTANCE1_SC_SIGNAL(_Execution_unit_to_Write_unit,out_WRITE_UNIT_IN_NUM_REG_RD      ,_param->_nb_write_unit  );
  INSTANCE1_SC_SIGNAL(_Execution_unit_to_Write_unit,out_WRITE_UNIT_IN_DATA_RD         ,_param->_nb_write_unit  );
  INSTANCE1_SC_SIGNAL(_Execution_unit_to_Write_unit,out_WRITE_UNIT_IN_WRITE_RE        ,_param->_nb_write_unit  );
  INSTANCE1_SC_SIGNAL(_Execution_unit_to_Write_unit,out_WRITE_UNIT_IN_NUM_REG_RE      ,_param->_nb_write_unit  );
  INSTANCE1_SC_SIGNAL(_Execution_unit_to_Write_unit,out_WRITE_UNIT_IN_DATA_RE         ,_param->_nb_write_unit  );
  INSTANCE1_SC_SIGNAL(_Execution_unit_to_Write_unit,out_WRITE_UNIT_IN_EXCEPTION       ,_param->_nb_write_unit  );
  INSTANCE1_SC_SIGNAL(_Execution_unit_to_Write_unit,out_WRITE_UNIT_IN_NO_SEQUENCE     ,_param->_nb_write_unit  );
  INSTANCE1_SC_SIGNAL(_Execution_unit_to_Write_unit,out_WRITE_UNIT_IN_ADDRESS         ,_param->_nb_write_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> execute_unit_thread [_param->_nb_execute_unit][_param->_max_nb_execute_unit_port];
 
  for (uint32_t i=0; i<_param->_nb_execute_unit; i++)
    for (uint32_t ii=0; ii<_param->_nb_execute_unit_port[i]; ii++)
      for (uint32_t j=0; j<_param->_nb_write_unit; j++)
	if (_param->_table_routing[i][ii][j])
	  for (uint32_t k=0; k<_param->_nb_thread; k++)
	    if (_param->_table_thread[j][k])
	      {
		execute_unit_thread [i][ii].insert(k);
	      }

  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_execute_unit][_param->_max_nb_execute_unit_port];

      uint32_t nb_request_in;
      for (nb_request_in=0; nb_request_in < _param->_nb_packet; )
	for (uint32_t i=0; i<_param->_nb_execute_unit; i++)
	  for (uint32_t j=0; j<_param->_nb_execute_unit_port[i]; j++)
	    {
	      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 (execute_unit_thread[i][j].find(num_thread) == execute_unit_thread[i][j].end());
	      
	      request[i][j].push_back(entry_t (context_id   ,
					       front_end_id ,
					       ooo_engine_id,
					       nb_request_in,
// 					       range<Toperation_t      > (rand(), _param->_size_operation       ),
// 					       range<Ttype_t           > (rand(), _param->_size_type            ),
					       range<Tcontrol_t        > (rand(), 2                             ),
					       range<Tgeneral_address_t> (rand(), _param->_size_general_register),
					       range<Tgeneral_data_t   > (rand(), _param->_size_general_data    ),
					       range<Tcontrol_t        > (rand(), 2                             ),
					       range<Tspecial_address_t> (rand(), _param->_size_special_register),
					       range<Tspecial_data_t   > (rand(), _param->_size_special_data    ),
					       range<Texception_t      > (rand(), _param->_size_exception       ),
					       range<Tcontrol_t        > (rand(), 2                             ),
					       range<Tgeneral_data_t   > (rand(), _param->_size_general_data    )
					       ));
	      
	      nb_request_in++;
	    }

      uint32_t   nb_request_out = 0;

      while (nb_request_out < nb_request_in)
	{
	  for (uint32_t i=0; i<_param->_nb_execute_unit; i++)
	    for (uint32_t j=0; j<_param->_nb_execute_unit_port[i]; j++)
	      {
		bool val = not request[i][j].empty() and ((rand()%100) < percent_transaction_in);
		
		in_EXECUTE_UNIT_OUT_VAL [i][j]->write(val);
		
		if (val)
		  {
		    in_EXECUTE_UNIT_OUT_CONTEXT_ID           [i][j] ->write(request[i][j].front()._context_id           );
		    in_EXECUTE_UNIT_OUT_FRONT_END_ID         [i][j] ->write(request[i][j].front()._front_end_id         );
		    in_EXECUTE_UNIT_OUT_OOO_ENGINE_ID        [i][j] ->write(request[i][j].front()._ooo_engine_id        );
		    in_EXECUTE_UNIT_OUT_PACKET_ID            [i][j] ->write(request[i][j].front()._packet_id            );
// 		    in_EXECUTE_UNIT_OUT_OPERATION            [i][j] ->write(request[i][j].front()._operation            );
// 		    in_EXECUTE_UNIT_OUT_TYPE                 [i][j] ->write(request[i][j].front()._type                 );
		    in_EXECUTE_UNIT_OUT_WRITE_RD             [i][j] ->write(request[i][j].front()._write_rd             );
		    in_EXECUTE_UNIT_OUT_NUM_REG_RD           [i][j] ->write(request[i][j].front()._num_reg_rd           );
		    in_EXECUTE_UNIT_OUT_DATA_RD              [i][j] ->write(request[i][j].front()._data_rd              );
		    in_EXECUTE_UNIT_OUT_WRITE_RE             [i][j] ->write(request[i][j].front()._write_re             );
		    in_EXECUTE_UNIT_OUT_NUM_REG_RE           [i][j] ->write(request[i][j].front()._num_reg_re           );
		    in_EXECUTE_UNIT_OUT_DATA_RE              [i][j] ->write(request[i][j].front()._data_re              );
		    in_EXECUTE_UNIT_OUT_EXCEPTION            [i][j] ->write(request[i][j].front()._exception            );
		    in_EXECUTE_UNIT_OUT_NO_SEQUENCE          [i][j] ->write(request[i][j].front()._no_sequence          );
		    in_EXECUTE_UNIT_OUT_ADDRESS              [i][j] ->write(request[i][j].front()._address              );
		  }
	      }

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

	  SC_START(0);

	  for (uint32_t i=0; i<_param->_nb_execute_unit; i++)
	    for (uint32_t j=0; j<_param->_nb_execute_unit_port[i]; j++)
	      if (in_EXECUTE_UNIT_OUT_VAL [i][j]->read() and out_EXECUTE_UNIT_OUT_ACK [i][j]->read())
		{
		  LABEL("EXECUTE_UNIT_OUT   [%d][%d] - Transaction accepted",i,j);
		}
	  
	  for (uint32_t i=0; i<_param->_nb_write_unit; i++)
	    if (out_WRITE_UNIT_IN_VAL [i]->read() and in_WRITE_UNIT_IN_ACK [i]->read())
	      {
		LABEL("WRITE_UNIT_IN [%d] - Transaction accepted (%d)",i,nb_request_out);
		nb_request_out ++;
		
		Tpacket_t packet = (_param->_have_port_rob_ptr  )?out_WRITE_UNIT_IN_PACKET_ID[i]->read():0;
		LABEL("  * packet              : %d",packet);		

		// find execute_unit
		uint32_t x = 0;
		uint32_t y = 0;
		bool     find = false;
		for (x=0; x<_param->_nb_execute_unit; x++)
		  {
		    for (y=0; y<_param->_nb_execute_unit_port[x]; y++)
		      if (packet == ((_param->_have_port_rob_ptr  )?request[x][y].front()._packet_id:0))
			{
			  find = true;
			  break;
			}
		    if (find)
		      break;
		  }

		LABEL("  * execute_unit source : %d",x);
		LABEL("  * execute_unit port   : %d",y);
		TEST(bool,x<_param->_nb_execute_unit, true);
		TEST(bool,y<_param->_nb_execute_unit_port[x],true);
		
		if (_param->_have_port_rob_ptr  )
		TEST(Tpacket_t         ,packet                                            , request[x][y].front()._packet_id            );

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

		if (_param->_have_port_context_id)
		TEST(Tcontext_t        ,out_WRITE_UNIT_IN_CONTEXT_ID           [i]->read(), request[x][y].front()._context_id           );
		if (_param->_have_port_front_end_id)
		TEST(Tcontext_t        ,out_WRITE_UNIT_IN_FRONT_END_ID         [i]->read(), request[x][y].front()._front_end_id         );
		if (_param->_have_port_ooo_engine_id)
		TEST(Tcontext_t        ,out_WRITE_UNIT_IN_OOO_ENGINE_ID        [i]->read(), request[x][y].front()._ooo_engine_id        );
// 		TEST(Toperation_t      ,out_WRITE_UNIT_IN_OPERATION            [i]->read(), request[x][y].front()._operation            );
// 		TEST(Ttype_t           ,out_WRITE_UNIT_IN_TYPE                 [i]->read(), request[x][y].front()._type                 );
		TEST(Tcontrol_t        ,out_WRITE_UNIT_IN_WRITE_RD             [i]->read(), request[x][y].front()._write_rd             );
		TEST(Tgeneral_address_t,out_WRITE_UNIT_IN_NUM_REG_RD           [i]->read(), request[x][y].front()._num_reg_rd           );
		TEST(Tgeneral_data_t   ,out_WRITE_UNIT_IN_DATA_RD              [i]->read(), request[x][y].front()._data_rd              );
		TEST(Tcontrol_t        ,out_WRITE_UNIT_IN_WRITE_RE             [i]->read(), request[x][y].front()._write_re             );
		TEST(Tspecial_address_t,out_WRITE_UNIT_IN_NUM_REG_RE           [i]->read(), request[x][y].front()._num_reg_re           );
		TEST(Tspecial_data_t   ,out_WRITE_UNIT_IN_DATA_RE              [i]->read(), request[x][y].front()._data_re              );
		TEST(Texception_t      ,out_WRITE_UNIT_IN_EXCEPTION            [i]->read(), request[x][y].front()._exception            );
		TEST(Tcontrol_t        ,out_WRITE_UNIT_IN_NO_SEQUENCE          [i]->read(), request[x][y].front()._no_sequence          );
		TEST(Tgeneral_data_t   ,out_WRITE_UNIT_IN_ADDRESS              [i]->read(), request[x][y].front()._address              );
		
		request[x][y].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;

  DELETE2_SC_SIGNAL( in_EXECUTE_UNIT_OUT_VAL          ,_param->_nb_execute_unit,_param->_nb_execute_unit_port[it1]);
  DELETE2_SC_SIGNAL(out_EXECUTE_UNIT_OUT_ACK          ,_param->_nb_execute_unit,_param->_nb_execute_unit_port[it1]);
  DELETE2_SC_SIGNAL( in_EXECUTE_UNIT_OUT_CONTEXT_ID   ,_param->_nb_execute_unit,_param->_nb_execute_unit_port[it1]);
  DELETE2_SC_SIGNAL( in_EXECUTE_UNIT_OUT_FRONT_END_ID ,_param->_nb_execute_unit,_param->_nb_execute_unit_port[it1]);
  DELETE2_SC_SIGNAL( in_EXECUTE_UNIT_OUT_OOO_ENGINE_ID,_param->_nb_execute_unit,_param->_nb_execute_unit_port[it1]);
  DELETE2_SC_SIGNAL( in_EXECUTE_UNIT_OUT_PACKET_ID    ,_param->_nb_execute_unit,_param->_nb_execute_unit_port[it1]);
//DELETE2_SC_SIGNAL( in_EXECUTE_UNIT_OUT_OPERATION    ,_param->_nb_execute_unit,_param->_nb_execute_unit_port[it1]);
//DELETE2_SC_SIGNAL( in_EXECUTE_UNIT_OUT_TYPE         ,_param->_nb_execute_unit,_param->_nb_execute_unit_port[it1]);
  DELETE2_SC_SIGNAL( in_EXECUTE_UNIT_OUT_WRITE_RD     ,_param->_nb_execute_unit,_param->_nb_execute_unit_port[it1]);
  DELETE2_SC_SIGNAL( in_EXECUTE_UNIT_OUT_NUM_REG_RD   ,_param->_nb_execute_unit,_param->_nb_execute_unit_port[it1]);
  DELETE2_SC_SIGNAL( in_EXECUTE_UNIT_OUT_DATA_RD      ,_param->_nb_execute_unit,_param->_nb_execute_unit_port[it1]);
  DELETE2_SC_SIGNAL( in_EXECUTE_UNIT_OUT_WRITE_RE     ,_param->_nb_execute_unit,_param->_nb_execute_unit_port[it1]);
  DELETE2_SC_SIGNAL( in_EXECUTE_UNIT_OUT_NUM_REG_RE   ,_param->_nb_execute_unit,_param->_nb_execute_unit_port[it1]);
  DELETE2_SC_SIGNAL( in_EXECUTE_UNIT_OUT_DATA_RE      ,_param->_nb_execute_unit,_param->_nb_execute_unit_port[it1]);
  DELETE2_SC_SIGNAL( in_EXECUTE_UNIT_OUT_EXCEPTION    ,_param->_nb_execute_unit,_param->_nb_execute_unit_port[it1]);
  DELETE2_SC_SIGNAL( in_EXECUTE_UNIT_OUT_NO_SEQUENCE  ,_param->_nb_execute_unit,_param->_nb_execute_unit_port[it1]);
  DELETE2_SC_SIGNAL( in_EXECUTE_UNIT_OUT_ADDRESS      ,_param->_nb_execute_unit,_param->_nb_execute_unit_port[it1]);

  DELETE1_SC_SIGNAL(out_WRITE_UNIT_IN_VAL             ,_param->_nb_write_unit  );
  DELETE1_SC_SIGNAL( in_WRITE_UNIT_IN_ACK             ,_param->_nb_write_unit  );
  DELETE1_SC_SIGNAL(out_WRITE_UNIT_IN_CONTEXT_ID      ,_param->_nb_write_unit  );
  DELETE1_SC_SIGNAL(out_WRITE_UNIT_IN_FRONT_END_ID    ,_param->_nb_write_unit  );
  DELETE1_SC_SIGNAL(out_WRITE_UNIT_IN_OOO_ENGINE_ID   ,_param->_nb_write_unit  );
  DELETE1_SC_SIGNAL(out_WRITE_UNIT_IN_PACKET_ID       ,_param->_nb_write_unit  );
//DELETE1_SC_SIGNAL(out_WRITE_UNIT_IN_OPERATION       ,_param->_nb_write_unit  );
//DELETE1_SC_SIGNAL(out_WRITE_UNIT_IN_TYPE            ,_param->_nb_write_unit  );
  DELETE1_SC_SIGNAL(out_WRITE_UNIT_IN_WRITE_RD        ,_param->_nb_write_unit  );
  DELETE1_SC_SIGNAL(out_WRITE_UNIT_IN_NUM_REG_RD      ,_param->_nb_write_unit  );
  DELETE1_SC_SIGNAL(out_WRITE_UNIT_IN_DATA_RD         ,_param->_nb_write_unit  );
  DELETE1_SC_SIGNAL(out_WRITE_UNIT_IN_WRITE_RE        ,_param->_nb_write_unit  );
  DELETE1_SC_SIGNAL(out_WRITE_UNIT_IN_NUM_REG_RE      ,_param->_nb_write_unit  );
  DELETE1_SC_SIGNAL(out_WRITE_UNIT_IN_DATA_RE         ,_param->_nb_write_unit  );
  DELETE1_SC_SIGNAL(out_WRITE_UNIT_IN_EXCEPTION       ,_param->_nb_write_unit  );
  DELETE1_SC_SIGNAL(out_WRITE_UNIT_IN_NO_SEQUENCE     ,_param->_nb_write_unit  );
  DELETE1_SC_SIGNAL(out_WRITE_UNIT_IN_ADDRESS         ,_param->_nb_write_unit  );
#endif

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