/*
 * $Id: test.cpp 107 2009-02-10 23:03:25Z rosiere $
 *
 * [ Description ]
 * 
 * Test
 */

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

#include "Behavioural/Core/Multi_Front_end/Front_end/Prediction_unit/Return_Address_Stack/SelfTest/include/test.h"
#include "Common/include/Test.h"
#include "Behavioural/include/Allocation.h"

void test (string name,
	   morpheo::behavioural::core::multi_front_end::front_end::prediction_unit::return_address_stack::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          );

  Return_Address_Stack * _Return_Address_Stack = new Return_Address_Stack 
    (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");

  ALLOC1_SC_SIGNAL( in_PREDICT_VAL           ," in_PREDICT_VAL           ",Tcontrol_t,_param->_nb_inst_predict);
  ALLOC1_SC_SIGNAL(out_PREDICT_ACK           ,"out_PREDICT_ACK           ",Tcontrol_t,_param->_nb_inst_predict);
  ALLOC1_SC_SIGNAL( in_PREDICT_CONTEXT_ID    ," in_PREDICT_CONTEXT_ID    ",Tcontext_t,_param->_nb_inst_predict);
  ALLOC1_SC_SIGNAL(out_PREDICT_HIT           ,"out_PREDICT_HIT           ",Tcontrol_t,_param->_nb_inst_predict);
  ALLOC1_SC_SIGNAL( in_PREDICT_PUSH          ," in_PREDICT_PUSH          ",Tcontrol_t,_param->_nb_inst_predict);
  ALLOC1_SC_SIGNAL( in_PREDICT_ADDRESS_PUSH  ," in_PREDICT_ADDRESS_PUSH  ",Taddress_t,_param->_nb_inst_predict);
  ALLOC1_SC_SIGNAL(out_PREDICT_ADDRESS_POP   ,"out_PREDICT_ADDRESS_POP   ",Taddress_t,_param->_nb_inst_predict);
  ALLOC1_SC_SIGNAL(out_PREDICT_INDEX         ,"out_PREDICT_INDEX         ",Tptr_t    ,_param->_nb_inst_predict);
  ALLOC1_SC_SIGNAL( in_DECOD_VAL             ," in_DECOD_VAL             ",Tcontrol_t,_param->_nb_inst_decod  );
  ALLOC1_SC_SIGNAL(out_DECOD_ACK             ,"out_DECOD_ACK             ",Tcontrol_t,_param->_nb_inst_decod  );
  ALLOC1_SC_SIGNAL( in_DECOD_PUSH            ," in_DECOD_PUSH            ",Tcontrol_t,_param->_nb_inst_decod  );
  ALLOC1_SC_SIGNAL( in_DECOD_CONTEXT_ID      ," in_DECOD_CONTEXT_ID      ",Tcontext_t,_param->_nb_inst_decod  );
  ALLOC1_SC_SIGNAL(out_DECOD_HIT             ,"out_DECOD_HIT             ",Tcontrol_t,_param->_nb_inst_decod  );
  ALLOC1_SC_SIGNAL( in_DECOD_ADDRESS_PUSH    ," in_DECOD_ADDRESS_PUSH    ",Taddress_t,_param->_nb_inst_decod  );
  ALLOC1_SC_SIGNAL(out_DECOD_ADDRESS_POP     ,"out_DECOD_ADDRESS_POP     ",Taddress_t,_param->_nb_inst_decod  );
  ALLOC1_SC_SIGNAL(out_DECOD_INDEX           ,"out_DECOD_INDEX           ",Tptr_t    ,_param->_nb_inst_decod  );
  ALLOC1_SC_SIGNAL( in_DECOD_MISS_PREDICTION ," in_DECOD_MISS_PREDICTION ",Tcontrol_t,_param->_nb_inst_decod  );
  ALLOC1_SC_SIGNAL( in_UPDATE_VAL            ," in_UPDATE_VAL            ",Tcontrol_t,_param->_nb_inst_update );
  ALLOC1_SC_SIGNAL(out_UPDATE_ACK            ,"out_UPDATE_ACK            ",Tcontrol_t,_param->_nb_inst_update );
  ALLOC1_SC_SIGNAL( in_UPDATE_CONTEXT_ID     ," in_UPDATE_CONTEXT_ID     ",Tcontext_t,_param->_nb_inst_update );
  ALLOC1_SC_SIGNAL( in_UPDATE_PUSH           ," in_UPDATE_PUSH           ",Tcontrol_t,_param->_nb_inst_update );
  ALLOC1_SC_SIGNAL( in_UPDATE_FLUSH          ," in_UPDATE_FLUSH          ",Tcontrol_t,_param->_nb_inst_update );
  ALLOC1_SC_SIGNAL( in_UPDATE_INDEX          ," in_UPDATE_INDEX          ",Tptr_t    ,_param->_nb_inst_update );
  ALLOC1_SC_SIGNAL( in_UPDATE_ADDRESS        ," in_UPDATE_ADDRESS        ",Taddress_t,_param->_nb_inst_update );
  ALLOC1_SC_SIGNAL( in_UPDATE_MISS_PREDICTION," in_UPDATE_MISS_PREDICTION",Tcontrol_t,_param->_nb_inst_update );
  ALLOC1_SC_SIGNAL( in_UPDATE_PREDICTION_IFETCH," in_UPDATE_PREDICTION_IFETCH",Tcontrol_t,_param->_nb_inst_update );
  
  /********************************************************
   * Instanciation
   ********************************************************/
  
  msg(_("<%s> : Instanciation of _Return_Address_Stack.\n"),name.c_str());

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

  INSTANCE1_SC_SIGNAL(_Return_Address_Stack, in_PREDICT_VAL           ,_param->_nb_inst_predict);
  INSTANCE1_SC_SIGNAL(_Return_Address_Stack,out_PREDICT_ACK           ,_param->_nb_inst_predict);
  if (_param->_have_port_context_id)
  INSTANCE1_SC_SIGNAL(_Return_Address_Stack, in_PREDICT_CONTEXT_ID    ,_param->_nb_inst_predict);
  INSTANCE1_SC_SIGNAL(_Return_Address_Stack,out_PREDICT_HIT           ,_param->_nb_inst_predict);
  INSTANCE1_SC_SIGNAL(_Return_Address_Stack, in_PREDICT_PUSH          ,_param->_nb_inst_predict);
  INSTANCE1_SC_SIGNAL(_Return_Address_Stack, in_PREDICT_ADDRESS_PUSH  ,_param->_nb_inst_predict);
  INSTANCE1_SC_SIGNAL(_Return_Address_Stack,out_PREDICT_ADDRESS_POP   ,_param->_nb_inst_predict);
  INSTANCE1_SC_SIGNAL(_Return_Address_Stack,out_PREDICT_INDEX         ,_param->_nb_inst_predict);
  INSTANCE1_SC_SIGNAL(_Return_Address_Stack, in_DECOD_VAL             ,_param->_nb_inst_decod  );
  INSTANCE1_SC_SIGNAL(_Return_Address_Stack,out_DECOD_ACK             ,_param->_nb_inst_decod  );
  INSTANCE1_SC_SIGNAL(_Return_Address_Stack, in_DECOD_PUSH            ,_param->_nb_inst_decod  );
  if (_param->_have_port_context_id)
  INSTANCE1_SC_SIGNAL(_Return_Address_Stack, in_DECOD_CONTEXT_ID      ,_param->_nb_inst_decod  );
  INSTANCE1_SC_SIGNAL(_Return_Address_Stack,out_DECOD_HIT             ,_param->_nb_inst_decod  );
  INSTANCE1_SC_SIGNAL(_Return_Address_Stack, in_DECOD_ADDRESS_PUSH    ,_param->_nb_inst_decod  );
  INSTANCE1_SC_SIGNAL(_Return_Address_Stack,out_DECOD_ADDRESS_POP     ,_param->_nb_inst_decod  );
  INSTANCE1_SC_SIGNAL(_Return_Address_Stack,out_DECOD_INDEX           ,_param->_nb_inst_decod  );
  INSTANCE1_SC_SIGNAL(_Return_Address_Stack, in_DECOD_MISS_PREDICTION ,_param->_nb_inst_decod  );
  INSTANCE1_SC_SIGNAL(_Return_Address_Stack, in_UPDATE_VAL            ,_param->_nb_inst_update );
  INSTANCE1_SC_SIGNAL(_Return_Address_Stack,out_UPDATE_ACK            ,_param->_nb_inst_update );
  if (_param->_have_port_context_id)
  INSTANCE1_SC_SIGNAL(_Return_Address_Stack, in_UPDATE_CONTEXT_ID     ,_param->_nb_inst_update );
  INSTANCE1_SC_SIGNAL(_Return_Address_Stack, in_UPDATE_PUSH           ,_param->_nb_inst_update );
  INSTANCE1_SC_SIGNAL(_Return_Address_Stack, in_UPDATE_FLUSH          ,_param->_nb_inst_update );
  INSTANCE1_SC_SIGNAL(_Return_Address_Stack, in_UPDATE_INDEX          ,_param->_nb_inst_update );
  INSTANCE1_SC_SIGNAL(_Return_Address_Stack, in_UPDATE_ADDRESS        ,_param->_nb_inst_update );
  INSTANCE1_SC_SIGNAL(_Return_Address_Stack, in_UPDATE_MISS_PREDICTION,_param->_nb_inst_update );
  INSTANCE1_SC_SIGNAL(_Return_Address_Stack, in_UPDATE_PREDICTION_IFETCH,_param->_nb_inst_update );

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

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

  // Initialisation
  const bool test1 = true;
  const bool test2 = true;
  const bool test3 = true;
  const bool test4 = true;
  
  const uint32_t seed = 0;
//const uint32_t seed = static_cast<uint32_t>(time(NULL));

  srand(seed);

  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);
      
      if (test1)
	{
          uint32_t port = rand()%_param->_nb_inst_predict;
          
          LABEL("PREDICT - PUSH");
          
          in_PREDICT_VAL  [port]->write(1);
          in_PREDICT_PUSH [port]->write(1);
          
          for (uint32_t i=0; i<_param->_nb_context; i++)
            for (uint32_t j=0; j<_param->_size_queue[i]; j++)
              {
                in_PREDICT_CONTEXT_ID   [port]->write(i);
                in_PREDICT_ADDRESS_PUSH [port]->write(0xdeadbeef+j);
                
                SC_START(0);
                
                TEST(Tcontrol_t, out_PREDICT_ACK  [port]->read(), 1);
                TEST(Tptr_t    , out_PREDICT_INDEX[port]->read(),(j+1)%_param->_size_queue[i]);
                
                SC_START(1);
                
              }
          in_PREDICT_VAL [port]->write(0);
          
          SC_START(1);
          
          in_PREDICT_VAL  [port]->write(1);
          in_PREDICT_PUSH [port]->write(1);
          for (uint32_t i=0; i<_param->_nb_context; i++)
            for (uint32_t j=0; j<_param->_size_queue[i]; j++)
              {
                in_PREDICT_CONTEXT_ID   [port]->write(i);
                in_PREDICT_ADDRESS_PUSH [port]->write(0x21071981+j);
                
                SC_START(0);
                
                TEST(Tcontrol_t, out_PREDICT_ACK        [port]->read(), 1);
                TEST(Tptr_t    , out_PREDICT_INDEX      [port]->read(),(j+1)%_param->_size_queue[i]);
                TEST(Taddress_t, out_PREDICT_ADDRESS_POP[port]->read(),0xdeadbeef+j);
                
                SC_START(1);
              }
          in_PREDICT_VAL [port]->write(0);
          
          LABEL("PREDICT - POP");
          
          in_PREDICT_VAL  [port]->write(1);
          in_PREDICT_PUSH [port]->write(0);
          for (uint32_t i=0; i<_param->_nb_context; i++)
            for (uint32_t j=0; j< _param->_size_queue[i]; j++)
              {
                in_PREDICT_CONTEXT_ID   [port]->write(i);
                in_PREDICT_ADDRESS_PUSH [port]->write(0xbabedead);
                
                SC_START(0);
                
                TEST(Tcontrol_t, out_PREDICT_ACK        [port]->read(), 1);
                TEST(Tcontrol_t, out_PREDICT_HIT        [port]->read(), 1);
                uint32_t k=(_param->_size_queue[i]-j)%_param->_size_queue[i];
                TEST(Tptr_t    , out_PREDICT_INDEX      [port]->read(), k);
                TEST(Taddress_t, out_PREDICT_ADDRESS_POP[port]->read(),(0x21071981+((k==0)?(_param->_size_queue[i]-1):(k-1))));
                
                SC_START(1);
              }
          in_PREDICT_VAL [port]->write(0);

          // Now, the stack is empty
        }

      if (test2)
	{
          uint32_t port = rand()%_param->_nb_inst_decod;
          
          LABEL("DECOD - without predict");
          
          LABEL("DECOD - PUSH");  
          
          in_DECOD_VAL             [port]->write(1);
          in_DECOD_PUSH            [port]->write(1);
          in_DECOD_MISS_PREDICTION [port]->write(0);
          
          for (uint32_t i=0; i<_param->_nb_context; i++)
            for (uint32_t j=0; j<_param->_size_queue[i]; j++)
              {
                in_DECOD_CONTEXT_ID   [port]->write(i);
                in_DECOD_ADDRESS_PUSH [port]->write(0xbeefcaca+j);
                
                SC_START(0);
                
                TEST(Tcontrol_t, out_DECOD_ACK  [port]->read(), 1);
                TEST(Tptr_t    , out_DECOD_INDEX[port]->read(),(j+1)%_param->_size_queue[i]);
                
                SC_START(1);
                
              }
          in_DECOD_VAL [port]->write(0);
	
          SC_START(1);
          
          in_DECOD_VAL  [port]->write(1);
          in_DECOD_PUSH [port]->write(1);
          for (uint32_t i=0; i<_param->_nb_context; i++)
            for (uint32_t j=0; j<_param->_size_queue[i]; j++)
              {
                in_DECOD_CONTEXT_ID   [port]->write(i);
                in_DECOD_ADDRESS_PUSH [port]->write(0x21071981+j);
                
                SC_START(0);
                
                TEST(Tcontrol_t, out_DECOD_ACK        [port]->read(), 1);
                TEST(Tptr_t    , out_DECOD_INDEX      [port]->read(),(j+1)%_param->_size_queue[i]);
                TEST(Taddress_t, out_DECOD_ADDRESS_POP[port]->read(),0xbeefcaca+j);
                
                SC_START(1);
              }
          in_DECOD_VAL [port]->write(0);
          
          LABEL("DECOD - POP");
          
          in_DECOD_VAL  [port]->write(1);
          in_DECOD_PUSH [port]->write(0);
          for (uint32_t i=0; i<_param->_nb_context; i++)
            for (uint32_t j=0; j< _param->_size_queue[i]; j++)
              {
                in_DECOD_CONTEXT_ID   [port]->write(i);
                in_DECOD_ADDRESS_PUSH [port]->write(0xbabedead);
                
                SC_START(0);
                
                TEST(Tcontrol_t, out_DECOD_ACK        [port]->read(), 1);
                TEST(Tcontrol_t, out_DECOD_HIT        [port]->read(), 1);
                uint32_t k=(_param->_size_queue[i]-j)%_param->_size_queue[i];
                TEST(Tptr_t    , out_DECOD_INDEX      [port]->read(), k);
                TEST(Taddress_t, out_DECOD_ADDRESS_POP[port]->read(),(0x21071981+((k==0)?(_param->_size_queue[i]-1):(k-1))));
                
                SC_START(1);
              }
          in_DECOD_VAL [port]->write(0);
          // Now, the stack is empty
        }

      if (test3)
        {
          uint32_t port1 = rand()%_param->_nb_inst_predict;
          uint32_t port2 = rand()%_param->_nb_inst_decod;
          uint32_t port3 = rand()%_param->_nb_inst_update;

          LABEL("Test UPDATE");

          LABEL("Predict");
          in_PREDICT_VAL  [port1]->write(1);
          in_PREDICT_PUSH [port1]->write(1);
          for (uint32_t i=0; i<_param->_nb_context; i++)
            for (uint32_t j=0; j<_param->_size_queue[i]; j++)
              {
                in_PREDICT_CONTEXT_ID   [port1]->write(i);
                in_PREDICT_ADDRESS_PUSH [port1]->write(0x25071959+j);
                
                SC_START(0);
                
                TEST(Tcontrol_t, out_PREDICT_ACK        [port1]->read(), 1);
                TEST(Tptr_t    , out_PREDICT_INDEX      [port1]->read(),(j+1)%_param->_size_queue[i]);
//              TEST(Taddress_t, out_PREDICT_ADDRESS_POP[port1]->read(),0xdeadbeef+j);
                
                SC_START(1);
              }
          in_PREDICT_VAL [port1]->write(0);

          LABEL("Decod");
          in_DECOD_VAL  [port2]->write(1);
          in_DECOD_PUSH [port2]->write(1);
          for (uint32_t i=0; i<_param->_nb_context; i++)
            for (uint32_t j=0; j<_param->_size_queue[i]/2; j++)
              {
                in_DECOD_CONTEXT_ID      [port2]->write(i);
                in_DECOD_ADDRESS_PUSH    [port2]->write(0x25071959+j);
                in_DECOD_MISS_PREDICTION [port2]->write(0);
                
                SC_START(0);
                
                TEST(Tcontrol_t, out_DECOD_ACK        [port2]->read(), 1);
                TEST(Tptr_t    , out_DECOD_INDEX      [port2]->read(),(j+1)%_param->_size_queue[i]);
                TEST(Taddress_t, out_DECOD_ADDRESS_POP[port2]->read(),0x25071959+j);
                
                SC_START(1);
              }
          in_DECOD_VAL [port2]->write(0);

          LABEL("Update Decod OK");
          in_UPDATE_VAL  [port3]->write(1);
          in_UPDATE_PUSH [port3]->write(1);
          in_UPDATE_FLUSH[port3]->write(0);
          for (uint32_t i=0; i<_param->_nb_context; i++)
            for (uint32_t j=0; j<_param->_size_queue[i]/2; j++)
              {
                uint32_t x=(_param->_size_queue[i]/2)-1;
                in_UPDATE_CONTEXT_ID        [port3]->write(i);
                in_UPDATE_MISS_PREDICTION   [port3]->write(0);
                in_UPDATE_PREDICTION_IFETCH [port3]->write(0);
                in_UPDATE_INDEX             [port3]->write((x+1)%_param->_size_queue[i]);
                in_UPDATE_ADDRESS           [port3]->write(0x25071959+x);
                
                SC_START(0);
                
                TEST(Tcontrol_t, out_UPDATE_ACK        [port3]->read(), 1);
                
                SC_START(1);
              }
          in_UPDATE_VAL [port3]->write(0);

          LABEL("Update FLUSH");
          in_UPDATE_VAL  [port3]->write(1);
          in_UPDATE_FLUSH[port3]->write(1);
          in_UPDATE_PUSH [port3]->write(0);
          for (uint32_t i=0; i<_param->_nb_context; i++)
            for (uint32_t j=0; j<_param->_size_queue[i]/2; j++)
              {
                in_UPDATE_CONTEXT_ID        [port3]->write(i);
                SC_START(1);
                TEST(Tcontrol_t, out_UPDATE_ACK        [port3]->read(), 1);
              }
          in_UPDATE_VAL [port3]->write(0);


// Tcontrol_t, in_UPDATE_VAL               
// Tcontrol_t,out_UPDATE_ACK               
// Tcontext_t, in_UPDATE_CONTEXT_ID        
// Tcontrol_t, in_UPDATE_PUSH              
// Tcontrol_t, in_UPDATE_FLUSH             
// Tptr_t    , in_UPDATE_INDEX             
// Taddress_t, in_UPDATE_ADDRESS           
// Tcontrol_t, in_UPDATE_MISS_PREDICTION   
// Tcontrol_t, in_UPDATE_PREDICTION_IFETCH 


        }

      if (test4)
        {
          uint32_t port1 = rand()%_param->_nb_inst_predict;
          uint32_t port2 = rand()%_param->_nb_inst_decod;
          uint32_t port3 = rand()%_param->_nb_inst_update;

          LABEL("Test UPDATE");

          LABEL("Predict");
          in_PREDICT_VAL  [port1]->write(1);
          in_PREDICT_PUSH [port1]->write(1);
          for (uint32_t i=0; i<_param->_nb_context; i++)
            for (uint32_t j=0; j<_param->_size_queue[i]; j++)
              {
                in_PREDICT_CONTEXT_ID   [port1]->write(i);
                in_PREDICT_ADDRESS_PUSH [port1]->write(0x14011959+j);
                
                SC_START(0);
                
                TEST(Tcontrol_t, out_PREDICT_ACK        [port1]->read(), 1);
                TEST(Tptr_t    , out_PREDICT_INDEX      [port1]->read(),(j+1)%_param->_size_queue[i]);
//              TEST(Taddress_t, out_PREDICT_ADDRESS_POP[port1]->read(),0xdeadbeef+j);
                
                SC_START(1);
              }
          in_PREDICT_VAL [port1]->write(0);

          LABEL("Decod");
          in_DECOD_VAL  [port2]->write(1);
          in_DECOD_PUSH [port2]->write(1);
          for (uint32_t i=0; i<_param->_nb_context; i++)
            for (uint32_t j=0; j<_param->_size_queue[i]/2; j++)
              {
                in_DECOD_CONTEXT_ID      [port2]->write(i);
                in_DECOD_ADDRESS_PUSH    [port2]->write(0x14011959+j);
                in_DECOD_MISS_PREDICTION [port2]->write(0);
                
                SC_START(0);
                
                TEST(Tcontrol_t, out_DECOD_ACK        [port2]->read(), 1);
                TEST(Tptr_t    , out_DECOD_INDEX      [port2]->read(),(j+1)%_param->_size_queue[i]);
                TEST(Taddress_t, out_DECOD_ADDRESS_POP[port2]->read(),0x14011959+j);
                
                SC_START(1);
              }
          in_DECOD_VAL [port2]->write(0);

          LABEL("Update Decod KO");
          in_UPDATE_VAL  [port3]->write(1);
          in_UPDATE_PUSH [port3]->write(1);
          in_UPDATE_FLUSH[port3]->write(0);
          for (uint32_t i=0; i<_param->_nb_context; i++)
            for (uint32_t j=0; j<_param->_size_queue[i]/2; j++)
              {
                uint32_t x=(_param->_size_queue[i]/2);
                in_UPDATE_CONTEXT_ID        [port3]->write(i);
                in_UPDATE_MISS_PREDICTION   [port3]->write(1);
                in_UPDATE_PREDICTION_IFETCH [port3]->write(0);
                in_UPDATE_INDEX             [port3]->write((x-j)%_param->_size_queue[i]);
                in_UPDATE_ADDRESS           [port3]->write(0xffffffff+x);
                
                SC_START(0);
                
                TEST(Tcontrol_t, out_UPDATE_ACK        [port3]->read(), 1);
                
                SC_START(1);
              }
          in_UPDATE_VAL [port3]->write(0);

          LABEL("Decod");
          in_DECOD_VAL  [port2]->write(1);
          in_DECOD_PUSH [port2]->write(1);
          for (uint32_t i=0; i<_param->_nb_context; i++)
            for (uint32_t j=0; j<_param->_size_queue[i]/2; j++)
              {
                in_DECOD_CONTEXT_ID      [port2]->write(i);
                in_DECOD_ADDRESS_PUSH    [port2]->write(0x14011959+j);
                in_DECOD_MISS_PREDICTION [port2]->write(0);
                
                SC_START(0);
                
                TEST(Tcontrol_t, out_DECOD_ACK        [port2]->read(), 1);
                TEST(Tptr_t    , out_DECOD_INDEX      [port2]->read(),(j+1)%_param->_size_queue[i]);
                TEST(Taddress_t, out_DECOD_ADDRESS_POP[port2]->read(),0x14011959+j);
                
                SC_START(1);
              }
          in_DECOD_VAL [port2]->write(0);


          LABEL("Update Decod KO");
          in_UPDATE_VAL  [port3]->write(1);
          in_UPDATE_PUSH [port3]->write(1);
          in_UPDATE_FLUSH[port3]->write(0);
          for (uint32_t i=0; i<_param->_nb_context; i++)
            for (uint32_t j=0; j<_param->_size_queue[i]/2; j++)
              {
                uint32_t x=(_param->_size_queue[i]/2);
                in_UPDATE_CONTEXT_ID        [port3]->write(i);
                in_UPDATE_MISS_PREDICTION   [port3]->write(1);
                in_UPDATE_PREDICTION_IFETCH [port3]->write(0);
                in_UPDATE_INDEX             [port3]->write((x-j)%_param->_size_queue[i]);
                in_UPDATE_ADDRESS           [port3]->write(0xffffffff+x);
                
                SC_START(0);
                
                TEST(Tcontrol_t, out_UPDATE_ACK        [port3]->read(), 1);
                
                SC_START(1);
              }
          in_UPDATE_VAL [port3]->write(0);

          LABEL("Update Predict KO");
          in_UPDATE_VAL  [port3]->write(1);
          in_UPDATE_PUSH [port3]->write(1);
          in_UPDATE_FLUSH[port3]->write(0);
          for (uint32_t i=0; i<_param->_nb_context; i++)
            for (uint32_t j=0; j<_param->_size_queue[i]; j++)
              {
                uint32_t x=(_param->_size_queue[i]);
                in_UPDATE_CONTEXT_ID        [port3]->write(i);
                in_UPDATE_MISS_PREDICTION   [port3]->write(1);
                in_UPDATE_PREDICTION_IFETCH [port3]->write(1);
                in_UPDATE_INDEX             [port3]->write((x-j)%_param->_size_queue[i]);
                in_UPDATE_ADDRESS           [port3]->write(0xffffffff+x);
                
                SC_START(0);
                
                TEST(Tcontrol_t, out_UPDATE_ACK        [port3]->read(), 1);
                
                SC_START(1);
              }
          in_UPDATE_VAL [port3]->write(0);

          LABEL("Predict");
          in_PREDICT_VAL  [port1]->write(1);
          in_PREDICT_PUSH [port1]->write(1);
          for (uint32_t i=0; i<_param->_nb_context; i++)
            for (uint32_t j=0; j<_param->_size_queue[i]; j++)
              {
                in_PREDICT_CONTEXT_ID   [port1]->write(i);
                in_PREDICT_ADDRESS_PUSH [port1]->write(0x14011959+j);
                
                SC_START(0);
                
                TEST(Tcontrol_t, out_PREDICT_ACK        [port1]->read(), 1);
                TEST(Tptr_t    , out_PREDICT_INDEX      [port1]->read(),(j+1)%_param->_size_queue[i]);
                TEST(Taddress_t, out_PREDICT_ADDRESS_POP[port1]->read(),0x14011959+j);
                
                SC_START(1);
              }
          in_PREDICT_VAL [port1]->write(0);

          LABEL("Update Predict KO");
          in_UPDATE_VAL  [port3]->write(1);
          in_UPDATE_PUSH [port3]->write(0);
          in_UPDATE_FLUSH[port3]->write(0);
          for (uint32_t i=0; i<_param->_nb_context; i++)
            for (uint32_t j=0; j<_param->_size_queue[i]; j++)
              {
                uint32_t x=(_param->_size_queue[i]);
                in_UPDATE_CONTEXT_ID        [port3]->write(i);
                in_UPDATE_MISS_PREDICTION   [port3]->write(1);
                in_UPDATE_PREDICTION_IFETCH [port3]->write(1);
                in_UPDATE_INDEX             [port3]->write((x+j+1)%_param->_size_queue[i]);
                in_UPDATE_ADDRESS           [port3]->write(0x87654321+j);
                
                SC_START(0);
                
                TEST(Tcontrol_t, out_UPDATE_ACK        [port3]->read(), 1);
                
                SC_START(1);
              }
          in_UPDATE_VAL [port3]->write(0);

          LABEL("Predict");
          in_PREDICT_VAL  [port1]->write(1);
          in_PREDICT_PUSH [port1]->write(1);
          for (uint32_t i=0; i<_param->_nb_context; i++)
            for (uint32_t j=0; j<_param->_size_queue[i]; j++)
              {
                in_PREDICT_CONTEXT_ID   [port1]->write(i);
                in_PREDICT_ADDRESS_PUSH [port1]->write(0x14011959+j);
                
                SC_START(0);
                
                TEST(Tcontrol_t, out_PREDICT_ACK        [port1]->read(), 1);
                TEST(Tptr_t    , out_PREDICT_INDEX      [port1]->read(),(j+1)%_param->_size_queue[i]);
                TEST(Taddress_t, out_PREDICT_ADDRESS_POP[port1]->read(),0x87654321+j);
                
                SC_START(1);
              }
          in_PREDICT_VAL [port1]->write(0);

          LABEL("Update FLUSH");
          in_UPDATE_VAL  [port3]->write(1);
          in_UPDATE_PUSH [port3]->write(0);
          in_UPDATE_FLUSH[port3]->write(1);
          for (uint32_t i=0; i<_param->_nb_context; i++)
            for (uint32_t j=0; j<_param->_size_queue[i]/2; j++)
              {
                in_UPDATE_CONTEXT_ID        [port3]->write(i);
                SC_START(1);
                TEST(Tcontrol_t, out_UPDATE_ACK        [port3]->read(), 1);
              }
          in_UPDATE_VAL [port3]->write(0);
        }
    }

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

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

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

  delete in_CLOCK;
  delete in_NRESET;

  DELETE1_SC_SIGNAL( in_PREDICT_VAL             ,_param->_nb_inst_predict);
  DELETE1_SC_SIGNAL(out_PREDICT_ACK             ,_param->_nb_inst_predict);
  DELETE1_SC_SIGNAL( in_PREDICT_CONTEXT_ID      ,_param->_nb_inst_predict);
  DELETE1_SC_SIGNAL(out_PREDICT_HIT             ,_param->_nb_inst_predict);
  DELETE1_SC_SIGNAL( in_PREDICT_PUSH            ,_param->_nb_inst_predict);
  DELETE1_SC_SIGNAL( in_PREDICT_ADDRESS_PUSH    ,_param->_nb_inst_predict);
  DELETE1_SC_SIGNAL(out_PREDICT_ADDRESS_POP     ,_param->_nb_inst_predict);
  DELETE1_SC_SIGNAL(out_PREDICT_INDEX           ,_param->_nb_inst_predict);

  DELETE1_SC_SIGNAL( in_DECOD_VAL               ,_param->_nb_inst_decod);
  DELETE1_SC_SIGNAL(out_DECOD_ACK               ,_param->_nb_inst_decod);
  DELETE1_SC_SIGNAL( in_DECOD_CONTEXT_ID        ,_param->_nb_inst_decod);
  DELETE1_SC_SIGNAL(out_DECOD_HIT               ,_param->_nb_inst_decod);
  DELETE1_SC_SIGNAL( in_DECOD_PUSH              ,_param->_nb_inst_decod);
  DELETE1_SC_SIGNAL( in_DECOD_ADDRESS_PUSH      ,_param->_nb_inst_decod);
  DELETE1_SC_SIGNAL(out_DECOD_ADDRESS_POP       ,_param->_nb_inst_decod);
  DELETE1_SC_SIGNAL(out_DECOD_INDEX             ,_param->_nb_inst_decod);
  DELETE1_SC_SIGNAL( in_DECOD_MISS_PREDICTION   ,_param->_nb_inst_decod);

  DELETE1_SC_SIGNAL( in_UPDATE_VAL              ,_param->_nb_inst_update);
  DELETE1_SC_SIGNAL(out_UPDATE_ACK              ,_param->_nb_inst_update);
  DELETE1_SC_SIGNAL( in_UPDATE_CONTEXT_ID       ,_param->_nb_inst_update);
  DELETE1_SC_SIGNAL( in_UPDATE_PUSH             ,_param->_nb_inst_update);
  DELETE1_SC_SIGNAL( in_UPDATE_FLUSH            ,_param->_nb_inst_update);
  DELETE1_SC_SIGNAL( in_UPDATE_ADDRESS          ,_param->_nb_inst_update);
  DELETE1_SC_SIGNAL( in_UPDATE_INDEX            ,_param->_nb_inst_update);
  DELETE1_SC_SIGNAL( in_UPDATE_MISS_PREDICTION  ,_param->_nb_inst_update);
  DELETE1_SC_SIGNAL( in_UPDATE_PREDICTION_IFETCH,_param->_nb_inst_update);

#endif

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