/*
 * $id: test.cpp 82 2008-05-01 16:48:45Z rosiere $
 *
 * [ Description ]
 * 
 * Test
 */

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

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

typedef struct
{
  uint32_t            ufpt_ptr    ;
  uint32_t            upt_ptr     ;

  Tcontext_t          context     ;
  Taddress_t          address_src ;
  Taddress_t          address_dest;
  Taddress_t          address_good;
  Tbranch_condition_t condition   ;
  Tcontrol_t          take        ;
  Tcontrol_t          take_good   ;
  Tcontrol_t          flag        ;
  Tcontrol_t          no_sequence ;
  Tcontrol_t          is_accurate ;
  Thistory_t          history     ;
  Taddress_t          ras_address ;
  Tptr_t              ras_index   ;
  Tcontrol_t          miss_ifetch ;
  Tcontrol_t          miss_decod  ;
  Tcontrol_t          miss_commit ;
} request_t;

void test (string name,
	   morpheo::behavioural::core::multi_front_end::front_end::prediction_unit::update_prediction_table::Parameters * _param)
{
  msg(_("<%s> : Simulation SystemC.\n"),name.c_str());

#ifdef STATISTICS
  morpheo::behavioural::Parameters_Statistics * _parameters_statistics = new morpheo::behavioural::Parameters_Statistics (5,CYCLE_MAX);
#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          );
    
  Update_Prediction_Table * _Update_Prediction_Table = new Update_Prediction_Table 
    (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( in_PREDICT_BTB_ADDRESS_SRC        ," in_PREDICT_BTB_ADDRESS_SRC        ",Taddress_t         ,_param->_nb_inst_predict);
  ALLOC1_SC_SIGNAL( in_PREDICT_BTB_ADDRESS_DEST       ," in_PREDICT_BTB_ADDRESS_DEST       ",Taddress_t         ,_param->_nb_inst_predict);
  ALLOC1_SC_SIGNAL( in_PREDICT_BTB_CONDITION          ," in_PREDICT_BTB_CONDITION          ",Tbranch_condition_t,_param->_nb_inst_predict);
  ALLOC1_SC_SIGNAL( in_PREDICT_BTB_LAST_TAKE          ," in_PREDICT_BTB_LAST_TAKE          ",Tcontrol_t         ,_param->_nb_inst_predict);
  ALLOC1_SC_SIGNAL( in_PREDICT_BTB_IS_ACCURATE        ," in_PREDICT_BTB_IS_ACCURATE        ",Tcontrol_t         ,_param->_nb_inst_predict);
  ALLOC1_SC_SIGNAL( in_PREDICT_DIR_HISTORY            ," in_PREDICT_DIR_HISTORY            ",Thistory_t         ,_param->_nb_inst_predict);
  ALLOC1_SC_SIGNAL( in_PREDICT_RAS_ADDRESS            ," in_PREDICT_RAS_ADDRESS            ",Taddress_t         ,_param->_nb_inst_predict);
  ALLOC1_SC_SIGNAL( in_PREDICT_RAS_INDEX              ," in_PREDICT_RAS_INDEX              ",Tptr_t             ,_param->_nb_inst_predict);
  ALLOC1_SC_SIGNAL(out_PREDICT_UPDATE_PREDICTION_ID   ,"out_PREDICT_UPDATE_PREDICTION_ID   ",Tprediction_ptr_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_CONTEXT_ID               ," in_DECOD_CONTEXT_ID               ",Tcontext_t         ,_param->_nb_inst_decod);
  ALLOC1_SC_SIGNAL( in_DECOD_BTB_ADDRESS_SRC          ," in_DECOD_BTB_ADDRESS_SRC          ",Taddress_t         ,_param->_nb_inst_decod);
  ALLOC1_SC_SIGNAL( in_DECOD_BTB_ADDRESS_DEST         ," in_DECOD_BTB_ADDRESS_DEST         ",Taddress_t         ,_param->_nb_inst_decod);
  ALLOC1_SC_SIGNAL( in_DECOD_BTB_CONDITION            ," in_DECOD_BTB_CONDITION            ",Tbranch_condition_t,_param->_nb_inst_decod);
  ALLOC1_SC_SIGNAL( in_DECOD_BTB_LAST_TAKE            ," in_DECOD_BTB_LAST_TAKE            ",Tcontrol_t         ,_param->_nb_inst_decod);
  ALLOC1_SC_SIGNAL( in_DECOD_RAS_ADDRESS              ," in_DECOD_RAS_ADDRESS              ",Taddress_t         ,_param->_nb_inst_decod);
  ALLOC1_SC_SIGNAL( in_DECOD_RAS_INDEX                ," in_DECOD_RAS_INDEX                ",Tptr_t             ,_param->_nb_inst_decod);
  ALLOC1_SC_SIGNAL( in_DECOD_MISS_IFETCH              ," in_DECOD_MISS_IFETCH              ",Tcontrol_t         ,_param->_nb_inst_decod);
  ALLOC1_SC_SIGNAL( in_DECOD_MISS_DECOD               ," in_DECOD_MISS_DECOD               ",Tcontrol_t         ,_param->_nb_inst_decod);
  ALLOC1_SC_SIGNAL( in_DECOD_UPDATE_PREDICTION_ID     ," in_DECOD_UPDATE_PREDICTION_ID     ",Tprediction_ptr_t  ,_param->_nb_inst_decod);
//ALLOC1_SC_SIGNAL(out_DECOD_DEPTH                    ,"out_DECOD_DEPTH                    ",Tdepth_t           ,_param->_nb_inst_decod);
  ALLOC1_SC_SIGNAL( in_DECOD_IS_ACCURATE              ," in_DECOD_IS_ACCURATE              ",Tcontrol_t         ,_param->_nb_inst_decod);

  ALLOC1_SC_SIGNAL( in_BRANCH_COMPLETE_VAL            ," in_BRANCH_COMPLETE_VAL            ",Tcontrol_t         ,_param->_nb_inst_branch_complete);
  ALLOC1_SC_SIGNAL(out_BRANCH_COMPLETE_ACK            ,"out_BRANCH_COMPLETE_ACK            ",Tcontrol_t         ,_param->_nb_inst_branch_complete);
  ALLOC1_SC_SIGNAL( in_BRANCH_COMPLETE_CONTEXT_ID     ," in_BRANCH_COMPLETE_CONTEXT_ID     ",Tcontext_t         ,_param->_nb_inst_branch_complete);
  ALLOC1_SC_SIGNAL( in_BRANCH_COMPLETE_DEPTH          ," in_BRANCH_COMPLETE_DEPTH          ",Tdepth_t           ,_param->_nb_inst_branch_complete);
  ALLOC1_SC_SIGNAL( in_BRANCH_COMPLETE_ADDRESS        ," in_BRANCH_COMPLETE_ADDRESS        ",Taddress_t         ,_param->_nb_inst_branch_complete);
  ALLOC1_SC_SIGNAL( in_BRANCH_COMPLETE_NO_SEQUENCE    ," in_BRANCH_COMPLETE_NO_SEQUENCE    ",Tcontrol_t         ,_param->_nb_inst_branch_complete);
  ALLOC1_SC_SIGNAL(out_BRANCH_COMPLETE_MISS_PREDICTION,"out_BRANCH_COMPLETE_MISS_PREDICTION",Tcontrol_t         ,_param->_nb_inst_branch_complete);
  ALLOC1_SC_SIGNAL(out_BRANCH_COMPLETE_TAKE           ,"out_BRANCH_COMPLETE_TAKE           ",Tcontrol_t         ,_param->_nb_inst_branch_complete);
  ALLOC1_SC_SIGNAL(out_BRANCH_COMPLETE_ADDRESS_SRC    ,"out_BRANCH_COMPLETE_ADDRESS_SRC    ",Taddress_t         ,_param->_nb_inst_branch_complete);
  ALLOC1_SC_SIGNAL(out_BRANCH_COMPLETE_ADDRESS_DEST   ,"out_BRANCH_COMPLETE_ADDRESS_DEST   ",Taddress_t         ,_param->_nb_inst_branch_complete);

  ALLOC1_SC_SIGNAL(out_BRANCH_EVENT_VAL            ,"out_BRANCH_EVENT_VAL            ",Tcontrol_t         ,_param->_nb_context);
  ALLOC1_SC_SIGNAL( in_BRANCH_EVENT_ACK            ," in_BRANCH_EVENT_ACK            ",Tcontrol_t         ,_param->_nb_context);
//   ALLOC1_SC_SIGNAL(out_BRANCH_EVENT_CONTEXT_ID     ,"out_BRANCH_EVENT_CONTEXT_ID     ",Tcontext_t         ,_param->_nb_context);
  ALLOC1_SC_SIGNAL(out_BRANCH_EVENT_DEPTH          ,"out_BRANCH_EVENT_DEPTH          ",Tdepth_t           ,_param->_nb_context);
//   ALLOC1_SC_SIGNAL(out_BRANCH_EVENT_MISS_PREDICTION,"out_BRANCH_EVENT_MISS_PREDICTION",Tcontrol_t         ,_param->_nb_context);
  ALLOC1_SC_SIGNAL(out_BRANCH_EVENT_ADDRESS_SRC    ,"out_BRANCH_EVENT_ADDRESS_SRC    ",Taddress_t         ,_param->_nb_context);
  ALLOC1_SC_SIGNAL(out_BRANCH_EVENT_ADDRESS_DEST_VAL,"out_BRANCH_EVENT_ADDRESS_DEST_VAL",Tcontrol_t         ,_param->_nb_context);
  ALLOC1_SC_SIGNAL(out_BRANCH_EVENT_ADDRESS_DEST   ,"out_BRANCH_EVENT_ADDRESS_DEST   ",Taddress_t         ,_param->_nb_context);

  ALLOC1_SC_SIGNAL(out_UPDATE_VAL                     ,"out_UPDATE_VAL                     ",Tcontrol_t         ,_param->_nb_inst_update);
  ALLOC1_SC_SIGNAL( in_UPDATE_ACK                     ," in_UPDATE_ACK                     ",Tcontrol_t         ,_param->_nb_inst_update);
  ALLOC1_SC_SIGNAL(out_UPDATE_CONTEXT_ID              ,"out_UPDATE_CONTEXT_ID              ",Tcontext_t         ,_param->_nb_inst_update);
  ALLOC1_SC_SIGNAL(out_UPDATE_MISS_PREDICTION         ,"out_UPDATE_MISS_PREDICTION         ",Tcontrol_t         ,_param->_nb_inst_update);
  ALLOC1_SC_SIGNAL(out_UPDATE_DIRECTION_GOOD          ,"out_UPDATE_DIRECTION_GOOD          ",Tcontrol_t         ,_param->_nb_inst_update);
  ALLOC1_SC_SIGNAL(out_UPDATE_BTB_VAL                 ,"out_UPDATE_BTB_VAL                 ",Tcontrol_t         ,_param->_nb_inst_update);
  ALLOC1_SC_SIGNAL(out_UPDATE_BTB_ADDRESS_SRC         ,"out_UPDATE_BTB_ADDRESS_SRC         ",Taddress_t         ,_param->_nb_inst_update);
  ALLOC1_SC_SIGNAL(out_UPDATE_BTB_ADDRESS_DEST        ,"out_UPDATE_BTB_ADDRESS_DEST        ",Taddress_t         ,_param->_nb_inst_update);
  ALLOC1_SC_SIGNAL(out_UPDATE_BTB_CONDITION           ,"out_UPDATE_BTB_CONDITION           ",Tbranch_condition_t,_param->_nb_inst_update);
  ALLOC1_SC_SIGNAL(out_UPDATE_DIR_VAL                 ,"out_UPDATE_DIR_VAL                 ",Tcontrol_t         ,_param->_nb_inst_update);
  ALLOC1_SC_SIGNAL(out_UPDATE_DIR_HISTORY             ,"out_UPDATE_DIR_HISTORY             ",Thistory_t         ,_param->_nb_inst_update);
  ALLOC1_SC_SIGNAL(out_UPDATE_RAS_VAL                 ,"out_UPDATE_RAS_VAL                 ",Tcontrol_t         ,_param->_nb_inst_update);
  ALLOC1_SC_SIGNAL(out_UPDATE_RAS_FLUSH               ,"out_UPDATE_RAS_FLUSH               ",Tcontrol_t         ,_param->_nb_inst_update);
  ALLOC1_SC_SIGNAL(out_UPDATE_RAS_PUSH                ,"out_UPDATE_RAS_PUSH                ",Tcontrol_t         ,_param->_nb_inst_update);
  ALLOC1_SC_SIGNAL(out_UPDATE_RAS_ADDRESS             ,"out_UPDATE_RAS_ADDRESS             ",Taddress_t         ,_param->_nb_inst_update);
  ALLOC1_SC_SIGNAL(out_UPDATE_RAS_INDEX               ,"out_UPDATE_RAS_INDEX               ",Tptr_t             ,_param->_nb_inst_update);
  ALLOC1_SC_SIGNAL(out_UPDATE_RAS_PREDICTION_IFETCH   ,"out_UPDATE_RAS_PREDICTION_IFETCH   ",Tcontrol_t         ,_param->_nb_inst_update);

  ALLOC1_SC_SIGNAL( in_EVENT_VAL                      ," in_EVENT_VAL                      ",Tcontrol_t         ,_param->_nb_context);
  ALLOC1_SC_SIGNAL(out_EVENT_ACK                      ,"out_EVENT_ACK                      ",Tcontrol_t         ,_param->_nb_context);
  ALLOC1_SC_SIGNAL( in_EVENT_TYPE                     ," in_EVENT_TYPE                     ",Tevent_type_t      ,_param->_nb_context);
  ALLOC1_SC_SIGNAL( in_EVENT_DEPTH                    ," in_EVENT_DEPTH                    ",Tdepth_t           ,_param->_nb_context);

  ALLOC1_SC_SIGNAL(out_DEPTH_CURRENT                  ,"out_DEPTH_CURRENT                  ",Tdepth_t           ,_param->_nb_context);
  ALLOC1_SC_SIGNAL(out_DEPTH_MIN                      ,"out_DEPTH_MIN                      ",Tdepth_t           ,_param->_nb_context);
  ALLOC1_SC_SIGNAL(out_DEPTH_MAX                      ,"out_DEPTH_MAX                      ",Tdepth_t           ,_param->_nb_context);
  
  /********************************************************
   * Instanciation
   ********************************************************/
  
  msg(_("<%s> : Instanciation of _Update_Prediction_Table.\n"),name.c_str());

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

  INSTANCE1_SC_SIGNAL(_Update_Prediction_Table, in_PREDICT_VAL                    ,_param->_nb_inst_predict);
  INSTANCE1_SC_SIGNAL(_Update_Prediction_Table,out_PREDICT_ACK                    ,_param->_nb_inst_predict);
  if (_param->_have_port_context_id)
  INSTANCE1_SC_SIGNAL(_Update_Prediction_Table, in_PREDICT_CONTEXT_ID             ,_param->_nb_inst_predict);
  INSTANCE1_SC_SIGNAL(_Update_Prediction_Table, in_PREDICT_BTB_ADDRESS_SRC        ,_param->_nb_inst_predict);
  INSTANCE1_SC_SIGNAL(_Update_Prediction_Table, in_PREDICT_BTB_ADDRESS_DEST       ,_param->_nb_inst_predict);
  INSTANCE1_SC_SIGNAL(_Update_Prediction_Table, in_PREDICT_BTB_CONDITION          ,_param->_nb_inst_predict);
  INSTANCE1_SC_SIGNAL(_Update_Prediction_Table, in_PREDICT_BTB_LAST_TAKE          ,_param->_nb_inst_predict);
  INSTANCE1_SC_SIGNAL(_Update_Prediction_Table, in_PREDICT_BTB_IS_ACCURATE        ,_param->_nb_inst_predict);
  if (_param->_have_port_history)
  INSTANCE1_SC_SIGNAL(_Update_Prediction_Table, in_PREDICT_DIR_HISTORY            ,_param->_nb_inst_predict);
  INSTANCE1_SC_SIGNAL(_Update_Prediction_Table, in_PREDICT_RAS_ADDRESS            ,_param->_nb_inst_predict);
  INSTANCE1_SC_SIGNAL(_Update_Prediction_Table, in_PREDICT_RAS_INDEX              ,_param->_nb_inst_predict);
  if (_param->_have_port_depth)
  INSTANCE1_SC_SIGNAL(_Update_Prediction_Table,out_PREDICT_UPDATE_PREDICTION_ID   ,_param->_nb_inst_predict);
  INSTANCE1_SC_SIGNAL(_Update_Prediction_Table, in_DECOD_VAL                      ,_param->_nb_inst_decod);
  INSTANCE1_SC_SIGNAL(_Update_Prediction_Table,out_DECOD_ACK                      ,_param->_nb_inst_decod);
  if (_param->_have_port_context_id)
  INSTANCE1_SC_SIGNAL(_Update_Prediction_Table, in_DECOD_CONTEXT_ID               ,_param->_nb_inst_decod);
  INSTANCE1_SC_SIGNAL(_Update_Prediction_Table, in_DECOD_BTB_ADDRESS_SRC          ,_param->_nb_inst_decod);
  INSTANCE1_SC_SIGNAL(_Update_Prediction_Table, in_DECOD_BTB_ADDRESS_DEST         ,_param->_nb_inst_decod);
  INSTANCE1_SC_SIGNAL(_Update_Prediction_Table, in_DECOD_BTB_CONDITION            ,_param->_nb_inst_decod);
  INSTANCE1_SC_SIGNAL(_Update_Prediction_Table, in_DECOD_BTB_LAST_TAKE            ,_param->_nb_inst_decod);
  INSTANCE1_SC_SIGNAL(_Update_Prediction_Table, in_DECOD_RAS_ADDRESS              ,_param->_nb_inst_decod);
  INSTANCE1_SC_SIGNAL(_Update_Prediction_Table, in_DECOD_RAS_INDEX                ,_param->_nb_inst_decod);
  INSTANCE1_SC_SIGNAL(_Update_Prediction_Table, in_DECOD_MISS_IFETCH              ,_param->_nb_inst_decod);
  INSTANCE1_SC_SIGNAL(_Update_Prediction_Table, in_DECOD_MISS_DECOD               ,_param->_nb_inst_decod);
  if (_param->_have_port_depth)
  INSTANCE1_SC_SIGNAL(_Update_Prediction_Table, in_DECOD_UPDATE_PREDICTION_ID     ,_param->_nb_inst_decod);
//if (_param->_have_port_depth)
//INSTANCE1_SC_SIGNAL(_Update_Prediction_Table,out_DECOD_DEPTH                    ,_param->_nb_inst_decod);
  INSTANCE1_SC_SIGNAL(_Update_Prediction_Table, in_DECOD_IS_ACCURATE              ,_param->_nb_inst_decod);
  INSTANCE1_SC_SIGNAL(_Update_Prediction_Table, in_BRANCH_COMPLETE_VAL            ,_param->_nb_inst_branch_complete);
  INSTANCE1_SC_SIGNAL(_Update_Prediction_Table,out_BRANCH_COMPLETE_ACK            ,_param->_nb_inst_branch_complete);
  if (_param->_have_port_context_id)
  INSTANCE1_SC_SIGNAL(_Update_Prediction_Table, in_BRANCH_COMPLETE_CONTEXT_ID     ,_param->_nb_inst_branch_complete);
  if (_param->_have_port_depth)
  INSTANCE1_SC_SIGNAL(_Update_Prediction_Table, in_BRANCH_COMPLETE_DEPTH          ,_param->_nb_inst_branch_complete);
  INSTANCE1_SC_SIGNAL(_Update_Prediction_Table, in_BRANCH_COMPLETE_ADDRESS        ,_param->_nb_inst_branch_complete);
  INSTANCE1_SC_SIGNAL(_Update_Prediction_Table, in_BRANCH_COMPLETE_NO_SEQUENCE    ,_param->_nb_inst_branch_complete);
  INSTANCE1_SC_SIGNAL(_Update_Prediction_Table,out_BRANCH_COMPLETE_MISS_PREDICTION,_param->_nb_inst_branch_complete);
  INSTANCE1_SC_SIGNAL(_Update_Prediction_Table,out_BRANCH_COMPLETE_TAKE           ,_param->_nb_inst_branch_complete);
  INSTANCE1_SC_SIGNAL(_Update_Prediction_Table,out_BRANCH_COMPLETE_ADDRESS_SRC    ,_param->_nb_inst_branch_complete);
  INSTANCE1_SC_SIGNAL(_Update_Prediction_Table,out_BRANCH_COMPLETE_ADDRESS_DEST   ,_param->_nb_inst_branch_complete);

  INSTANCE1_SC_SIGNAL(_Update_Prediction_Table,out_BRANCH_EVENT_VAL            ,_param->_nb_context);
  INSTANCE1_SC_SIGNAL(_Update_Prediction_Table, in_BRANCH_EVENT_ACK            ,_param->_nb_context);
//if (_param->_have_port_context_id)
//INSTANCE1_SC_SIGNAL(_Update_Prediction_Table,out_BRANCH_EVENT_CONTEXT_ID     ,_param->_nb_context);
  if (_param->_have_port_depth)
  INSTANCE1_SC_SIGNAL(_Update_Prediction_Table,out_BRANCH_EVENT_DEPTH          ,_param->_nb_context);
//INSTANCE1_SC_SIGNAL(_Update_Prediction_Table,out_BRANCH_EVENT_MISS_PREDICTION,_param->_nb_context);
  INSTANCE1_SC_SIGNAL(_Update_Prediction_Table,out_BRANCH_EVENT_ADDRESS_SRC    ,_param->_nb_context);
  INSTANCE1_SC_SIGNAL(_Update_Prediction_Table,out_BRANCH_EVENT_ADDRESS_DEST_VAL,_param->_nb_context);
  INSTANCE1_SC_SIGNAL(_Update_Prediction_Table,out_BRANCH_EVENT_ADDRESS_DEST   ,_param->_nb_context);

  INSTANCE1_SC_SIGNAL(_Update_Prediction_Table,out_UPDATE_VAL                     ,_param->_nb_inst_update);
  INSTANCE1_SC_SIGNAL(_Update_Prediction_Table, in_UPDATE_ACK                     ,_param->_nb_inst_update);
  if (_param->_have_port_context_id)
  INSTANCE1_SC_SIGNAL(_Update_Prediction_Table,out_UPDATE_CONTEXT_ID              ,_param->_nb_inst_update);
  INSTANCE1_SC_SIGNAL(_Update_Prediction_Table,out_UPDATE_MISS_PREDICTION         ,_param->_nb_inst_update);
  INSTANCE1_SC_SIGNAL(_Update_Prediction_Table,out_UPDATE_DIRECTION_GOOD          ,_param->_nb_inst_update);
  INSTANCE1_SC_SIGNAL(_Update_Prediction_Table,out_UPDATE_BTB_VAL                 ,_param->_nb_inst_update);
  INSTANCE1_SC_SIGNAL(_Update_Prediction_Table,out_UPDATE_BTB_ADDRESS_SRC         ,_param->_nb_inst_update);
  INSTANCE1_SC_SIGNAL(_Update_Prediction_Table,out_UPDATE_BTB_ADDRESS_DEST        ,_param->_nb_inst_update);
  INSTANCE1_SC_SIGNAL(_Update_Prediction_Table,out_UPDATE_BTB_CONDITION           ,_param->_nb_inst_update);
  INSTANCE1_SC_SIGNAL(_Update_Prediction_Table,out_UPDATE_DIR_VAL                 ,_param->_nb_inst_update);
  if (_param->_have_port_history)
  INSTANCE1_SC_SIGNAL(_Update_Prediction_Table,out_UPDATE_DIR_HISTORY             ,_param->_nb_inst_update);
  INSTANCE1_SC_SIGNAL(_Update_Prediction_Table,out_UPDATE_RAS_VAL                 ,_param->_nb_inst_update);
  INSTANCE1_SC_SIGNAL(_Update_Prediction_Table,out_UPDATE_RAS_FLUSH               ,_param->_nb_inst_update);
  INSTANCE1_SC_SIGNAL(_Update_Prediction_Table,out_UPDATE_RAS_PUSH                ,_param->_nb_inst_update);
  INSTANCE1_SC_SIGNAL(_Update_Prediction_Table,out_UPDATE_RAS_ADDRESS             ,_param->_nb_inst_update);
  INSTANCE1_SC_SIGNAL(_Update_Prediction_Table,out_UPDATE_RAS_INDEX               ,_param->_nb_inst_update);
  INSTANCE1_SC_SIGNAL(_Update_Prediction_Table,out_UPDATE_RAS_PREDICTION_IFETCH   ,_param->_nb_inst_update);
  INSTANCE1_SC_SIGNAL(_Update_Prediction_Table, in_EVENT_VAL                      ,_param->_nb_context);
  INSTANCE1_SC_SIGNAL(_Update_Prediction_Table,out_EVENT_ACK                      ,_param->_nb_context);
  INSTANCE1_SC_SIGNAL(_Update_Prediction_Table, in_EVENT_TYPE                     ,_param->_nb_context);
  if (_param->_have_port_depth)
    {
  INSTANCE1_SC_SIGNAL(_Update_Prediction_Table, in_EVENT_DEPTH                    ,_param->_nb_context);
  INSTANCE1_SC_SIGNAL(_Update_Prediction_Table,out_DEPTH_CURRENT                  ,_param->_nb_context);
  INSTANCE1_SC_SIGNAL(_Update_Prediction_Table,out_DEPTH_MIN                      ,_param->_nb_context);
    }
  INSTANCE1_SC_SIGNAL(_Update_Prediction_Table,out_DEPTH_MAX                      ,_param->_nb_context);

  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_predict         = 75;
  const  int32_t percent_transaction_decod           = 75;
  const  int32_t percent_transaction_branch_complete = 75;
  const  int32_t percent_transaction_update          = 75;
  const  int32_t percent_transaction_branch_event    = 75;

  const bool     test1 = true;
  const bool     test2 = true;
  const bool     test3 = true;
  const bool     test4 = true;

  std::list<request_t> ufpt;
  std::list<request_t> upt;
  request_t            event;

  SC_START(0);
  LABEL("Initialisation");

  LABEL("Reset");
  in_NRESET->write(0);
  SC_START(5);
  in_NRESET->write(1);  

  Tdepth_t ufpt_bottom  [_param->_nb_context];
  Tdepth_t ufpt_top     [_param->_nb_context];
                       
  Tdepth_t upt_bottom   [_param->_nb_context];
  Tdepth_t upt_top      [_param->_nb_context];
  Tdepth_t upt_top_event[_param->_nb_context];

  for (uint32_t i=0; i<_param->_nb_context; ++i)
    {
      ufpt_bottom  [i] = 0;
      ufpt_top     [i] = 0;
      upt_bottom   [i] = 0;
      upt_top      [i] = 0;
      upt_top_event[i] = 0;
    }

  for (uint32_t i=0; i<_param->_nb_context; ++i)
    {
      TEST(Tdepth_t,out_DEPTH_CURRENT [i]->read(),upt_top    [i]);
      TEST(Tdepth_t,out_DEPTH_MIN     [i]->read(),upt_bottom [i]);
      TEST(Tdepth_t,out_DEPTH_MAX     [i]->read(),upt_top    [i]);
    }

  for (uint32_t iteration=0; iteration<NB_ITERATION; iteration ++)
    {
      LABEL("Iteration %d",iteration);

      for (uint32_t i=0; i<_param->_nb_inst_predict; ++i)
        in_PREDICT_VAL         [i]->write(0);
      for (uint32_t i=0; i<_param->_nb_inst_decod; ++i)
        in_DECOD_VAL           [i]->write(0);
      for (uint32_t i=0; i<_param->_nb_inst_branch_complete; ++i)
        in_BRANCH_COMPLETE_VAL [i]->write(0);
      for (uint32_t i=0; i<_param->_nb_context; ++i)
        in_BRANCH_EVENT_ACK    [i]->write(0);
      for (uint32_t i=0; i<_param->_nb_inst_update; ++i)
        in_UPDATE_ACK          [i]->write(0);
      for (uint32_t i=0; i<_param->_nb_context; ++i)
        in_EVENT_VAL   [i]->write(0);

      //---------------------------------------------------------------------
      //---------------------------------------------------------------------
      // COMMON CASE
      //---------------------------------------------------------------------
      //---------------------------------------------------------------------
      if (test1)
        {
	uint32_t context = rand() % _param->_nb_context;

	{
          LABEL("PREDICT - fill the queue");
	  uint32_t port = rand() % _param->_nb_inst_predict;

          LABEL("  * context : %d",context);
          LABEL("  * port    : %d",port);
	  
	  for (uint32_t i=0; i<_param->_size_ufpt_queue[context]; i++)
	    {
              request_t request;
              request.context          = context;
              request.address_src      = 0xdeadbeef+i;
              request.address_dest     = 0x21071981+i;                                   
              request.address_good     = request.address_dest;
              request.condition        = BRANCH_CONDITION_FLAG_SET;                      
              request.take             = 1;                                              
              request.take_good        = 1;                                              
              request.flag             = (request.condition == BRANCH_CONDITION_FLAG_SET)?request.take_good:(not request.take_good);
              request.no_sequence      = (request.condition == BRANCH_CONDITION_FLAG_SET)?request.flag:not request.flag;
              request.is_accurate      = true;
              request.miss_ifetch      = false;
              request.miss_decod       = false;
              request.miss_commit      = false;
              request.history          = i;                                              
              request.ras_address      = 0xdeaddead+i;                                   
              request.ras_index        = (0x12345678+i)%_param->_size_ras_index[context];
              request.ufpt_ptr         = ufpt_top [context];
//            request.upt_ptr;

	      bool have_transaction = false;
	      do
		{
		  in_PREDICT_VAL              [port]->write((rand()%100)<percent_transaction_predict);
		  in_PREDICT_CONTEXT_ID       [port]->write(request.context     );
		  in_PREDICT_BTB_ADDRESS_SRC  [port]->write(request.address_src );
		  in_PREDICT_BTB_ADDRESS_DEST [port]->write(request.address_dest);
		  in_PREDICT_BTB_CONDITION    [port]->write(request.condition   );
		  in_PREDICT_BTB_LAST_TAKE    [port]->write(request.take        );
		  in_PREDICT_BTB_IS_ACCURATE  [port]->write(request.is_accurate );
		  in_PREDICT_DIR_HISTORY      [port]->write(request.history     );
		  in_PREDICT_RAS_ADDRESS      [port]->write(request.ras_address );
		  in_PREDICT_RAS_INDEX        [port]->write(request.ras_index   );
		  
		  if (_param->_have_port_depth)
		  TEST(Tdepth_t,out_DEPTH_MIN [context]->read(), upt_bottom [context]);
                  TEST(Tdepth_t,out_DEPTH_MAX [context]->read(), upt_top [context]);
		      
		  SC_START(0); // fct melay
		  
		  LABEL("PREDICT         [%d] %d - %d (accurate : %d).",
                        port,
                         in_PREDICT_VAL [port]->read(),
                        out_PREDICT_ACK [port]->read(),
                         in_PREDICT_BTB_IS_ACCURATE [port]->read());
		  
		  if (in_PREDICT_VAL [port]->read() and out_PREDICT_ACK [port]->read())
		    {
		      LABEL("PREDICT         [%d] - Transaction accepted",port);
		      have_transaction = true;

                      if (_param->_have_port_depth)
                      TEST(Tprediction_ptr_t,out_PREDICT_UPDATE_PREDICTION_ID [port]->read(),ufpt_top [context]);
                      
                      ufpt_top [context] = (ufpt_top [context]+1)%_param->_size_ufpt_queue[context];
		    }
		  
		  SC_START(1); // transition
		  
		} while (not have_transaction);

              ufpt.push_back(request);

	      in_PREDICT_VAL [port]->write(0);
	    
              if (_param->_have_port_depth)
	      TEST(Tdepth_t,out_DEPTH_MIN [context]->read(), upt_bottom [context]);
              TEST(Tdepth_t,out_DEPTH_MAX [context]->read(), upt_top [context]);
	    }
	}
	
        {
          LABEL("DECOD");
	  uint32_t port = rand() % _param->_nb_inst_decod;

          LABEL("  * context : %d",context);
          LABEL("  * port    : %d",port);
          
	  for (uint32_t i=0; i<_param->_size_ufpt_queue[context]; i++)
	    {
              request_t request = ufpt.front();

	      bool have_transaction = false;
	      do
		{
		  in_DECOD_VAL                  [port]->write((rand()%100)<percent_transaction_decod);
		  in_DECOD_CONTEXT_ID           [port]->write(request.context     );
		  in_DECOD_BTB_ADDRESS_SRC      [port]->write(request.address_src );
		  in_DECOD_BTB_ADDRESS_DEST     [port]->write(request.address_dest);
		  in_DECOD_BTB_CONDITION        [port]->write(request.condition   );
		  in_DECOD_BTB_LAST_TAKE        [port]->write(request.take        );
		  in_DECOD_RAS_ADDRESS          [port]->write(request.ras_address );
		  in_DECOD_RAS_INDEX            [port]->write(request.ras_index   );
		  in_DECOD_UPDATE_PREDICTION_ID [port]->write(request.ufpt_ptr    );
		  in_DECOD_MISS_IFETCH          [port]->write(request.miss_ifetch );
		  in_DECOD_MISS_DECOD           [port]->write(request.miss_decod  );
		  in_DECOD_IS_ACCURATE          [port]->write(request.is_accurate );

		  SC_START(0); // fct melay
		  
		  LABEL("DECOD           [%d] %d - %d",
                        port,
                         in_PREDICT_VAL [port]->read(),
                        out_PREDICT_ACK [port]->read());
		  
		  if (in_DECOD_VAL [port]->read() and out_DECOD_ACK [port]->read())
		    {
		      LABEL("DECOD          [%d] - Transaction accepted",port);
		      have_transaction = true;

                      request.upt_ptr = upt_top [context];
                      upt.push_back(request);
                      ufpt.pop_front();

                      upt_top [context] = (upt_top [context]+1)%_param->_size_upt_queue[context];
		    }

		  SC_START(1); // transition

                } while (not have_transaction);

	      in_DECOD_VAL              [port]->write(0);
	      
              if (_param->_have_port_depth)
	      TEST(Tdepth_t,out_DEPTH_MIN [context]->read(), upt_bottom [context]);
              TEST(Tdepth_t,out_DEPTH_MAX [context]->read(), upt_top [context]);
            }
        }

	{
          LABEL("BRANCH_COMPLETE - hit ifetch");
	
	  uint32_t port = rand() % _param->_nb_inst_branch_complete;
	
          LABEL("  * port    : %d",port);
  
          std::list<request_t>::iterator it_upt = upt.begin();

// 	  for (uint32_t i=0; i<_param->_size_ufpt_queue[context]; i++)
	  for (uint32_t i=0; i<upt.size(); i++)
	    {
	      bool have_transaction = false;

	      do
		{
		  in_BRANCH_COMPLETE_VAL        [port]->write((rand()%100)<percent_transaction_branch_complete);
		  in_BRANCH_COMPLETE_CONTEXT_ID [port]->write(it_upt->context     );
		  in_BRANCH_COMPLETE_DEPTH      [port]->write(it_upt->upt_ptr     );
		  in_BRANCH_COMPLETE_ADDRESS    [port]->write(it_upt->address_good);
		  in_BRANCH_COMPLETE_NO_SEQUENCE[port]->write(it_upt->no_sequence );

                  if (_param->_have_port_depth)
                  TEST(Tdepth_t,out_DEPTH_MIN [context]->read(), upt_bottom [context]);
                  TEST(Tdepth_t,out_DEPTH_MAX [context]->read(), upt_top [context]);
		  
		  SC_START(0);
		  
		  LABEL("BRANCH_COMPLETE [%d] %d - %d.",port,in_BRANCH_COMPLETE_VAL [port]->read(),out_BRANCH_COMPLETE_ACK [port]->read());
		  
		  if (in_BRANCH_COMPLETE_VAL [port]->read() and out_BRANCH_COMPLETE_ACK [port]->read())
		    {
		      LABEL("BRANCH_COMPLETE [%d] - Transaction accepted",port);
		      have_transaction = true;
		      
		      TEST(Tcontrol_t,out_BRANCH_COMPLETE_MISS_PREDICTION[port]->read(),it_upt->miss_commit );
		      TEST(Tcontrol_t,out_BRANCH_COMPLETE_TAKE           [port]->read(),it_upt->take_good   );
		      TEST(Taddress_t,out_BRANCH_COMPLETE_ADDRESS_SRC    [port]->read(),it_upt->address_src );
		      TEST(Taddress_t,out_BRANCH_COMPLETE_ADDRESS_DEST   [port]->read(),it_upt->address_good);

                      it_upt ++;
		    }
		  
		  SC_START(1);
		} while (not have_transaction);

	      in_BRANCH_COMPLETE_VAL [port]->write(0);
	      
              if (_param->_have_port_depth)
              TEST(Tdepth_t,out_DEPTH_MIN [context]->read(), upt_bottom [context]);
              TEST(Tdepth_t,out_DEPTH_MAX [context]->read(), upt_top [context]);
	    }
	}

	{
          LABEL("UPDATE - hit ifetch");
	
	  uint32_t port = 0;
	
          LABEL("  * port    : %d",port);
          std::list<request_t>::iterator it_upt = upt.begin();
  
// 	  for (uint32_t i=0; i<_param->_size_ufpt_queue[context]; i++)
	  for (uint32_t i=0; i<upt.size(); i++)
	    {
	      bool have_transaction = false;

	      do
		{
		  in_UPDATE_ACK [port]->write((rand()%100)<percent_transaction_update);

//                   if (_param->_have_port_depth)
//                   TEST(Tdepth_t,out_DEPTH_MIN [context]->read(), upt_bottom [context]);
//                   TEST(Tdepth_t,out_DEPTH_MAX [context]->read(), upt_top [context]);
		  
		  SC_START(0);

		  LABEL("UPDATE [%d] %d - %d.",port,out_UPDATE_VAL [port]->read(),in_UPDATE_ACK [port]->read());
		  
		  if (out_UPDATE_VAL [port]->read() and in_UPDATE_ACK [port]->read())
		    {
		      LABEL("UPDATE [%d] - Transaction accepted",port);
		      have_transaction = true;
		  
                      if (_param->_have_port_context_id)
                      TEST(Tcontext_t         ,out_UPDATE_CONTEXT_ID            [port]->read(),it_upt->context);
                      TEST(Tcontrol_t         ,out_UPDATE_MISS_PREDICTION       [port]->read(),it_upt->miss_commit);
                      TEST(Tcontrol_t         ,out_UPDATE_DIRECTION_GOOD        [port]->read(),it_upt->take_good);
                      TEST(Tcontrol_t         ,out_UPDATE_BTB_VAL               [port]->read(),update_btb(it_upt->condition));
                      if (update_btb(it_upt->condition))
                        {
                      TEST(Taddress_t         ,out_UPDATE_BTB_ADDRESS_SRC       [port]->read(),it_upt->address_src);
                      TEST(Taddress_t         ,out_UPDATE_BTB_ADDRESS_DEST      [port]->read(),it_upt->address_dest);
                      TEST(Tbranch_condition_t,out_UPDATE_BTB_CONDITION         [port]->read(),it_upt->condition);
                        }
                      TEST(Tcontrol_t         ,out_UPDATE_DIR_VAL               [port]->read(),update_dir(it_upt->condition) and not (it_upt->miss_ifetch or it_upt->miss_decod));
                      if (update_dir(it_upt->condition))
                      if (_param->_have_port_history)
                      TEST(Thistory_t         ,out_UPDATE_DIR_HISTORY           [port]->read(),it_upt->history);
                      TEST(Tcontrol_t         ,out_UPDATE_RAS_VAL               [port]->read(),update_ras(it_upt->condition));
                      if (update_ras(it_upt->condition))
                        {
//                    TEST(Tcontrol_t         ,out_UPDATE_RAS_FLUSH             [port]->read(),0);
                      TEST(Tcontrol_t         ,out_UPDATE_RAS_PUSH              [port]->read(),push_ras  (it_upt->condition));
                      TEST(Taddress_t         ,out_UPDATE_RAS_ADDRESS           [port]->read(),it_upt->ras_address);
                      TEST(Tptr_t             ,out_UPDATE_RAS_INDEX             [port]->read(),it_upt->ras_index);
                      TEST(Tcontrol_t         ,out_UPDATE_RAS_PREDICTION_IFETCH [port]->read(),not it_upt->miss_ifetch);
                        }
                      ++ it_upt;
		    }

		  SC_START(1);
		} while (not have_transaction);

	      in_UPDATE_ACK [port]->write(0);
//               if (_param->_have_port_depth)
//               TEST(Tdepth_t,out_DEPTH_MIN [context]->read(), upt_bottom [context]);
//               TEST(Tdepth_t,out_DEPTH_MAX [context]->read(), upt_top [context]);
	    }
          upt.clear();
	}

        // Wait Garbage Collector
        {
          upt_bottom [context] = (upt_bottom [context]+_param->_size_ufpt_queue[context])%_param->_size_upt_queue[context];
//        upt_top    [context] = (upt_top    [context]);

          while ((upt_bottom [context] != out_DEPTH_MIN [context]->read()) or
                 (upt_top    [context] != out_DEPTH_MAX [context]->read()))
            SC_START(1);

        }
      }

      //---------------------------------------------------------------------
      //---------------------------------------------------------------------
      // DECOD MISS : no RAS in ifetch
      //---------------------------------------------------------------------
      //---------------------------------------------------------------------
      if (test2)
        {
	uint32_t context = rand() % _param->_nb_context;

	{
          LABEL("PREDICT - fill the queue");
	  uint32_t port = rand() % _param->_nb_inst_predict;

          LABEL("  * context : %d",context);
          LABEL("  * port    : %d",port);
	  
	  for (uint32_t i=0; i<_param->_size_ufpt_queue[context]; i++)
	    {
              request_t request;
              request.context          = context;
              request.address_src      = 0xdeadbeef+i;
              request.address_dest     = 0x21071981+i;                                   
              request.address_good     = request.address_dest;
              request.condition        = BRANCH_CONDITION_FLAG_SET;                      
              request.take             = 1;                                              
              request.take_good        = 1;                                              
              request.flag             = (request.condition == BRANCH_CONDITION_FLAG_SET)?request.take_good:(not request.take_good);
              request.no_sequence      = (request.condition == BRANCH_CONDITION_FLAG_SET)?request.flag:not request.flag;
              request.is_accurate      = true;
              request.miss_ifetch      = false;
              request.miss_decod       = false;
              request.miss_commit      = false;
              request.history          = i;                                              
              request.ras_address      = 0xdeaddead+i;                                   
              request.ras_index        = (0x12345678+i)%_param->_size_ras_index[context];
              request.ufpt_ptr         = ufpt_top [context];
//            request.upt_ptr;

	      bool have_transaction = false;
	      do
		{
		  in_PREDICT_VAL              [port]->write((rand()%100)<percent_transaction_predict);
		  in_PREDICT_CONTEXT_ID       [port]->write(request.context     );
		  in_PREDICT_BTB_ADDRESS_SRC  [port]->write(request.address_src );
		  in_PREDICT_BTB_ADDRESS_DEST [port]->write(request.address_dest);
		  in_PREDICT_BTB_CONDITION    [port]->write(request.condition   );
		  in_PREDICT_BTB_LAST_TAKE    [port]->write(request.take        );
		  in_PREDICT_BTB_IS_ACCURATE  [port]->write(request.is_accurate );
		  in_PREDICT_DIR_HISTORY      [port]->write(request.history     );
		  in_PREDICT_RAS_ADDRESS      [port]->write(request.ras_address );
		  in_PREDICT_RAS_INDEX        [port]->write(request.ras_index   );
		  
		  if (_param->_have_port_depth)
		  TEST(Tdepth_t,out_DEPTH_MIN [context]->read(), upt_bottom [context]);
                  TEST(Tdepth_t,out_DEPTH_MAX [context]->read(), upt_top [context]);
		      
		  SC_START(0); // fct melay
		  
		  LABEL("PREDICT         [%d] %d - %d (accurate : %d).",
                        port,
                         in_PREDICT_VAL [port]->read(),
                        out_PREDICT_ACK [port]->read(),
                         in_PREDICT_BTB_IS_ACCURATE [port]->read());
		  
		  if (in_PREDICT_VAL [port]->read() and out_PREDICT_ACK [port]->read())
		    {
		      LABEL("PREDICT         [%d] - Transaction accepted",port);
		      have_transaction = true;

                      if (_param->_have_port_depth)
                      TEST(Tprediction_ptr_t,out_PREDICT_UPDATE_PREDICTION_ID [port]->read(),ufpt_top [context]);
                      
                      ufpt_top [context] = (ufpt_top [context]+1)%_param->_size_ufpt_queue[context];
		    }
		  
		  SC_START(1); // transition
		  
		} while (not have_transaction);

//            ufpt.push_back(request);

	      in_PREDICT_VAL [port]->write(0);
	    
              if (_param->_have_port_depth)
	      TEST(Tdepth_t,out_DEPTH_MIN [context]->read(), upt_bottom [context]);
              TEST(Tdepth_t,out_DEPTH_MAX [context]->read(), upt_top [context]);
	    }
	}
	
        {
          LABEL("DECOD - Miss");
	  uint32_t port = rand() % _param->_nb_inst_decod;

          LABEL("  * context : %d",context);
          LABEL("  * port    : %d",port);
          
          request_t request;
          request.context          = context;
          request.address_src      = 0x14011959;
          request.address_dest     = 0x25071959; // after = not take               
          request.address_good     = request.address_dest;
          request.condition        = BRANCH_CONDITION_FLAG_SET;
          request.take             = 0;                                              
          request.take_good        = 0;                                              
          request.flag             = (request.condition == BRANCH_CONDITION_FLAG_SET)?request.take_good:(not request.take_good);
          request.no_sequence      = (request.condition == BRANCH_CONDITION_FLAG_SET)?request.flag:not request.flag;
          request.is_accurate      = true;
          request.miss_ifetch      = false;
          request.miss_decod       = true ;
          request.miss_commit      = false;
          request.history          = 1; 
          request.ras_address      = 0xbabababa;                                   
          request.ras_index        = (0x87654321)%_param->_size_ras_index[context];
          request.ufpt_ptr         = ufpt_top [context];
          request.upt_ptr          = upt_top  [context];
        
          event = request;

//           for (uint32_t i=0; i<upt.size(); i++)
          // just one
            {
	      bool have_transaction = false;
	      do
		{
		  in_DECOD_VAL                  [port]->write((rand()%100)<percent_transaction_decod);
		  in_DECOD_CONTEXT_ID           [port]->write(request.context     );
		  in_DECOD_BTB_ADDRESS_SRC      [port]->write(request.address_src );
		  in_DECOD_BTB_ADDRESS_DEST     [port]->write(request.address_dest);
		  in_DECOD_BTB_CONDITION        [port]->write(request.condition   );
		  in_DECOD_BTB_LAST_TAKE        [port]->write(request.take        );
		  in_DECOD_RAS_ADDRESS          [port]->write(request.ras_address );
		  in_DECOD_RAS_INDEX            [port]->write(request.ras_index   );
		  in_DECOD_UPDATE_PREDICTION_ID [port]->write(request.ufpt_ptr    );
		  in_DECOD_MISS_IFETCH          [port]->write(request.miss_ifetch );
		  in_DECOD_MISS_DECOD           [port]->write(request.miss_decod  );
		  in_DECOD_IS_ACCURATE          [port]->write(request.is_accurate );

		  SC_START(0); // fct melay
		  
		  LABEL("DECOD           [%d] %d - %d",
                        port,
                         in_PREDICT_VAL [port]->read(),
                        out_PREDICT_ACK [port]->read());
		  
		  if (in_DECOD_VAL [port]->read() and out_DECOD_ACK [port]->read())
		    {
		      LABEL("DECOD          [%d] - Transaction accepted",port);
		      have_transaction = true;

                      request.upt_ptr = upt_top [context];
                      upt.push_back(request);
//                    ufpt.pop_front();

                      upt_top [context] = (upt_top [context]+1)%_param->_size_upt_queue[context];
		    }

		  SC_START(1); // transition

                } while (not have_transaction);

	      in_DECOD_VAL              [port]->write(0);
	      
              if (_param->_have_port_depth)
	      TEST(Tdepth_t,out_DEPTH_MIN [context]->read(), upt_bottom [context]);
              TEST(Tdepth_t,out_DEPTH_MAX [context]->read(), upt_top [context]);
            }
        }

	{
          LABEL("BRANCH_COMPLETE - hit ifetch");
	
	  uint32_t port = rand() % _param->_nb_inst_branch_complete;
	
          LABEL("  * port    : %d",port);
  
          std::list<request_t>::iterator it_upt = upt.begin();

// 	  for (uint32_t i=0; i<_param->_size_ufpt_queue[context]; i++)
// 	  for (uint32_t i=0; i<upt.size(); i++)
          // just one
          {
	      bool have_transaction = false;

	      do
		{
		  in_BRANCH_COMPLETE_VAL        [port]->write((rand()%100)<percent_transaction_branch_complete);
		  in_BRANCH_COMPLETE_CONTEXT_ID [port]->write(it_upt->context     );
		  in_BRANCH_COMPLETE_DEPTH      [port]->write(it_upt->upt_ptr     );
		  in_BRANCH_COMPLETE_ADDRESS    [port]->write(it_upt->address_good);
		  in_BRANCH_COMPLETE_NO_SEQUENCE[port]->write(it_upt->no_sequence );

                  if (_param->_have_port_depth)
                  TEST(Tdepth_t,out_DEPTH_MIN [context]->read(), upt_bottom [context]);
                  TEST(Tdepth_t,out_DEPTH_MAX [context]->read(), upt_top [context]);
		  
		  SC_START(0);
		  
		  LABEL("BRANCH_COMPLETE [%d] %d - %d.",port,in_BRANCH_COMPLETE_VAL [port]->read(),out_BRANCH_COMPLETE_ACK [port]->read());
		  
		  if (in_BRANCH_COMPLETE_VAL [port]->read() and out_BRANCH_COMPLETE_ACK [port]->read())
		    {
		      LABEL("BRANCH_COMPLETE [%d] - Transaction accepted",port);
		      have_transaction = true;
		      
		      TEST(Tcontrol_t,out_BRANCH_COMPLETE_MISS_PREDICTION[port]->read(),it_upt->miss_commit );
		      TEST(Tcontrol_t,out_BRANCH_COMPLETE_TAKE           [port]->read(),it_upt->take_good   );
		      TEST(Taddress_t,out_BRANCH_COMPLETE_ADDRESS_SRC    [port]->read(),it_upt->address_src );
		      TEST(Taddress_t,out_BRANCH_COMPLETE_ADDRESS_DEST   [port]->read(),it_upt->address_good);

                      it_upt ++;
		    }
		  
		  SC_START(1);
		} while (not have_transaction);

	      in_BRANCH_COMPLETE_VAL [port]->write(0);
	      
              if (_param->_have_port_depth)
              TEST(Tdepth_t,out_DEPTH_MIN [context]->read(), upt_bottom [context]);
              TEST(Tdepth_t,out_DEPTH_MAX [context]->read(), upt_top [context]);
	    }
	}

	{
          LABEL("UPDATE - hit ifetch");
	
	  uint32_t port = 0;
	
          LABEL("  * port    : %d",port);
          std::list<request_t>::iterator it_upt = upt.begin();
  
// 	  for (uint32_t i=0; i<_param->_size_ufpt_queue[context]; i++)
// 	  for (uint32_t i=0; i<upt.size(); i++)
          // just one
	    {
	      bool have_transaction = false;

	      do
		{
		  in_UPDATE_ACK [port]->write((rand()%100)<percent_transaction_update);

//                   if (_param->_have_port_depth)
//                   TEST(Tdepth_t,out_DEPTH_MIN [context]->read(), upt_bottom [context]);
//                   TEST(Tdepth_t,out_DEPTH_MAX [context]->read(), upt_top [context]);
		  
		  SC_START(0);

		  LABEL("UPDATE [%d] %d - %d.",port,out_UPDATE_VAL [port]->read(),in_UPDATE_ACK [port]->read());
		  
		  if (out_UPDATE_VAL [port]->read() and in_UPDATE_ACK [port]->read())
		    {
		      LABEL("UPDATE [%d] - Transaction accepted",port);
		      have_transaction = true;
		  
                      if (_param->_have_port_context_id)
                      TEST(Tcontext_t         ,out_UPDATE_CONTEXT_ID            [port]->read(),it_upt->context);
                      TEST(Tcontrol_t         ,out_UPDATE_MISS_PREDICTION       [port]->read(),it_upt->miss_commit);
                      TEST(Tcontrol_t         ,out_UPDATE_DIRECTION_GOOD        [port]->read(),it_upt->take_good);
                      TEST(Tcontrol_t         ,out_UPDATE_BTB_VAL               [port]->read(),update_btb(it_upt->condition));
                      if (update_btb(it_upt->condition))
                        {
                      TEST(Taddress_t         ,out_UPDATE_BTB_ADDRESS_SRC       [port]->read(),it_upt->address_src);
                      TEST(Taddress_t         ,out_UPDATE_BTB_ADDRESS_DEST      [port]->read(),it_upt->address_dest);
                      TEST(Tbranch_condition_t,out_UPDATE_BTB_CONDITION         [port]->read(),it_upt->condition);
                        }
                      TEST(Tcontrol_t         ,out_UPDATE_DIR_VAL               [port]->read(),update_dir(it_upt->condition) and not (it_upt->miss_ifetch or it_upt->miss_decod));

                      if (update_dir(it_upt->condition))
                      if (_param->_have_port_history)
                      TEST(Thistory_t         ,out_UPDATE_DIR_HISTORY           [port]->read(),it_upt->history);
                      TEST(Tcontrol_t         ,out_UPDATE_RAS_VAL               [port]->read(),update_ras(it_upt->condition));
                      if (update_ras(it_upt->condition))
                        {
//                    TEST(Tcontrol_t         ,out_UPDATE_RAS_FLUSH             [port]->read(),0);
                      TEST(Tcontrol_t         ,out_UPDATE_RAS_PUSH              [port]->read(),push_ras  (it_upt->condition));
                      TEST(Taddress_t         ,out_UPDATE_RAS_ADDRESS           [port]->read(),it_upt->ras_address);
                      TEST(Tptr_t             ,out_UPDATE_RAS_INDEX             [port]->read(),it_upt->ras_index);
                      TEST(Tcontrol_t         ,out_UPDATE_RAS_PREDICTION_IFETCH [port]->read(),not it_upt->miss_ifetch);
                        }
                      ++ it_upt;
		    }

		  SC_START(1);
		} while (not have_transaction);

	      in_UPDATE_ACK [port]->write(0);
//               if (_param->_have_port_depth)
//               TEST(Tdepth_t,out_DEPTH_MIN [context]->read(), upt_bottom [context]);
//               TEST(Tdepth_t,out_DEPTH_MAX [context]->read(), upt_top [context]);
	    }
          upt.clear();
	}

        {
          LABEL("BRANCH_EVENT - have miss decod");
          
	  uint32_t port = context;

          {
            bool have_transaction = false;
            
            do
              {
                in_BRANCH_EVENT_ACK [port]->write((rand()%100)<percent_transaction_branch_event);
                
                SC_START(0);
                
                LABEL("BRANCH_EVENT [%d] %d - %d.",port,out_BRANCH_EVENT_VAL [port]->read(),in_BRANCH_EVENT_ACK [port]->read());
		
                if (out_BRANCH_EVENT_VAL [port]->read() and in_BRANCH_EVENT_ACK [port]->read())
                  {
                    LABEL("BRANCH_EVENT [%d] - Transaction accepted",port);
                    have_transaction = true;

                    TEST(Tdepth_t  ,out_BRANCH_EVENT_DEPTH            [port]->read(),event.upt_ptr);
                    TEST(Taddress_t,out_BRANCH_EVENT_ADDRESS_SRC      [port]->read(),event.address_src);
                    TEST(Tcontrol_t,out_BRANCH_EVENT_ADDRESS_DEST_VAL [port]->read(),event.take);
                    if (event.take)
                    TEST(Taddress_t,out_BRANCH_EVENT_ADDRESS_DEST     [port]->read(),event.address_good);

                    event.address_src  = 0;
                    event.take         = 0;
                    event.address_dest = 0;
                  }
                
                SC_START(1);
              } while (not have_transaction);

	      in_BRANCH_EVENT_ACK [port]->write(0);
          }
        }
 
        {
          LABEL("EVENT_STATE");
         
          SC_START(1);
          in_EVENT_VAL   [context]->write(1);
          in_EVENT_TYPE  [context]->write(EVENT_TYPE_MISS_SPECULATION);

          SC_START(1);
          in_EVENT_VAL   [context]->write(0);
          in_EVENT_TYPE  [context]->write(EVENT_TYPE_NONE            );
        }

        // Wait Garbage Collector
        {
          upt_bottom [context] = (upt_bottom [context]+1)%_param->_size_upt_queue[context];
//        upt_top    [context] = (upt_top    [context]);

          while ((upt_bottom [context] != out_DEPTH_MIN [context]->read()) or
                 (upt_top    [context] != out_DEPTH_MAX [context]->read()))
            SC_START(1);

        }
        }

      //---------------------------------------------------------------------
      //---------------------------------------------------------------------
      // DECOD MISS : with RAS in ifetch
      //---------------------------------------------------------------------
      //---------------------------------------------------------------------
      if (test3)
        {
	uint32_t context = rand() % _param->_nb_context;
        uint32_t have_ras = false;
	{
          LABEL("PREDICT - fill the queue");
	  uint32_t port = rand() % _param->_nb_inst_predict;

          LABEL("  * context : %d",context);
          LABEL("  * port    : %d",port);
	  
	  for (uint32_t i=0; i<_param->_size_ufpt_queue[context]; i++)
	    {
              request_t request;
              request.context          = context;
              request.address_src      = 0xdeadbeef+i;
              request.address_dest     = 0x21071981+i;                                   
              request.address_good     = request.address_dest;
              request.condition        = (rand()%2)?BRANCH_CONDITION_NONE_WITH_WRITE_STACK:BRANCH_CONDITION_FLAG_SET;

              have_ras |= (update_ras(request.condition));

              request.take             = 1;                                              
              request.take_good        = 1;                                              
              request.flag             = (request.condition == BRANCH_CONDITION_FLAG_SET)?request.take_good:(not request.take_good);
              request.no_sequence      = (request.condition == BRANCH_CONDITION_FLAG_SET)?request.flag:not request.flag;
              request.is_accurate      = true;
              request.miss_ifetch      = false;
              request.miss_decod       = true ;
              request.miss_commit      = false;
              request.history          = i;                                              
              request.ras_address      = 0x12344321+i;                                   
              request.ras_index        = (043211234+i)%_param->_size_ras_index[context];
              request.ufpt_ptr         = ufpt_top [context];
//            request.upt_ptr;
              
	      bool have_transaction = false;
	      do
		{
		  in_PREDICT_VAL              [port]->write((rand()%100)<percent_transaction_predict);
		  in_PREDICT_CONTEXT_ID       [port]->write(request.context     );
		  in_PREDICT_BTB_ADDRESS_SRC  [port]->write(request.address_src );
		  in_PREDICT_BTB_ADDRESS_DEST [port]->write(request.address_dest);
		  in_PREDICT_BTB_CONDITION    [port]->write(request.condition   );
		  in_PREDICT_BTB_LAST_TAKE    [port]->write(request.take        );
		  in_PREDICT_BTB_IS_ACCURATE  [port]->write(request.is_accurate );
		  in_PREDICT_DIR_HISTORY      [port]->write(request.history     );
		  in_PREDICT_RAS_ADDRESS      [port]->write(request.ras_address );
		  in_PREDICT_RAS_INDEX        [port]->write(request.ras_index   );
		  
		  if (_param->_have_port_depth)
		  TEST(Tdepth_t,out_DEPTH_MIN [context]->read(), upt_bottom [context]);
                  TEST(Tdepth_t,out_DEPTH_MAX [context]->read(), upt_top [context]);
		      
		  SC_START(0); // fct melay
		  
		  LABEL("PREDICT         [%d] %d - %d (accurate : %d).",
                        port,
                         in_PREDICT_VAL [port]->read(),
                        out_PREDICT_ACK [port]->read(),
                         in_PREDICT_BTB_IS_ACCURATE [port]->read());
		  
		  if (in_PREDICT_VAL [port]->read() and out_PREDICT_ACK [port]->read())
		    {
		      LABEL("PREDICT         [%d] - Transaction accepted",port);
		      have_transaction = true;

                      if (_param->_have_port_depth)
                      TEST(Tprediction_ptr_t,out_PREDICT_UPDATE_PREDICTION_ID [port]->read(),ufpt_top [context]);
                      
                      ufpt_top [context] = (ufpt_top [context]+1)%_param->_size_ufpt_queue[context];
		    }
		  
		  SC_START(1); // transition
		  
		} while (not have_transaction);

              ufpt.push_back(request); // to update

	      in_PREDICT_VAL [port]->write(0);
	    
              if (_param->_have_port_depth)
	      TEST(Tdepth_t,out_DEPTH_MIN [context]->read(), upt_bottom [context]);
              TEST(Tdepth_t,out_DEPTH_MAX [context]->read(), upt_top [context]);
	    }
	}
	
        {
          LABEL("DECOD - Miss");
	  uint32_t port = rand() % _param->_nb_inst_decod;

          LABEL("  * context : %d",context);
          LABEL("  * port    : %d",port);
          
          request_t request;
          request.context          = context;
          request.address_src      = 0x14011959;
          request.address_dest     = 0x25071959; // after = not take               
          request.address_good     = request.address_dest;
          request.condition        = BRANCH_CONDITION_FLAG_SET;
          request.take             = 0;                                              
          request.take_good        = 0;                                              
          request.flag             = (request.condition == BRANCH_CONDITION_FLAG_SET)?request.take_good:(not request.take_good);
          request.no_sequence      = (request.condition == BRANCH_CONDITION_FLAG_SET)?request.flag:not request.flag;
          request.is_accurate      = true;
          request.miss_ifetch      = false;
          request.miss_decod       = true ;
          request.miss_commit      = false;
          request.history          = 1; 
          request.ras_address      = 0xbabababa;                                   
          request.ras_index        = (0x87654321)%_param->_size_ras_index[context];
          request.ufpt_ptr         = ufpt_top [context];
          request.upt_ptr          = upt_top  [context];

          event = request;
          
//           for (uint32_t i=0; i<upt.size(); i++)
          // just one
            {
	      bool have_transaction = false;
	      do
		{
		  in_DECOD_VAL                  [port]->write((rand()%100)<percent_transaction_decod);
		  in_DECOD_CONTEXT_ID           [port]->write(request.context     );
		  in_DECOD_BTB_ADDRESS_SRC      [port]->write(request.address_src );
		  in_DECOD_BTB_ADDRESS_DEST     [port]->write(request.address_dest);
		  in_DECOD_BTB_CONDITION        [port]->write(request.condition   );
		  in_DECOD_BTB_LAST_TAKE        [port]->write(request.take        );
		  in_DECOD_RAS_ADDRESS          [port]->write(request.ras_address );
		  in_DECOD_RAS_INDEX            [port]->write(request.ras_index   );
		  in_DECOD_UPDATE_PREDICTION_ID [port]->write(request.ufpt_ptr    );
		  in_DECOD_MISS_IFETCH          [port]->write(request.miss_ifetch );
		  in_DECOD_MISS_DECOD           [port]->write(request.miss_decod  );
		  in_DECOD_IS_ACCURATE          [port]->write(request.is_accurate );

		  SC_START(0); // fct melay
		  
		  LABEL("DECOD           [%d] %d - %d",
                        port,
                         in_PREDICT_VAL [port]->read(),
                        out_PREDICT_ACK [port]->read());
		  
		  if (in_DECOD_VAL [port]->read() and out_DECOD_ACK [port]->read())
		    {
		      LABEL("DECOD          [%d] - Transaction accepted",port);
		      have_transaction = true;

                      request.upt_ptr = upt_top [context];
                      upt.push_back(request);
//                    ufpt.pop_front();

                      upt_top [context] = (upt_top [context]+1)%_param->_size_upt_queue[context];
		    }

		  SC_START(1); // transition

                } while (not have_transaction);

	      in_DECOD_VAL              [port]->write(0);
	      
              if (_param->_have_port_depth)
	      TEST(Tdepth_t,out_DEPTH_MIN [context]->read(), upt_bottom [context]);
              TEST(Tdepth_t,out_DEPTH_MAX [context]->read(), upt_top [context]);
            }
        }

	{
          LABEL("BRANCH_COMPLETE - hit ifetch");
	
	  uint32_t port = rand() % _param->_nb_inst_branch_complete;
	
          LABEL("  * port    : %d",port);
  
          std::list<request_t>::iterator it_upt = upt.begin();

// 	  for (uint32_t i=0; i<_param->_size_ufpt_queue[context]; i++)
// 	  for (uint32_t i=0; i<upt.size(); i++)
          // just one
          {
	      bool have_transaction = false;

	      do
		{
		  in_BRANCH_COMPLETE_VAL        [port]->write((rand()%100)<percent_transaction_branch_complete);
		  in_BRANCH_COMPLETE_CONTEXT_ID [port]->write(it_upt->context     );
		  in_BRANCH_COMPLETE_DEPTH      [port]->write(it_upt->upt_ptr     );
		  in_BRANCH_COMPLETE_ADDRESS    [port]->write(it_upt->address_good);
		  in_BRANCH_COMPLETE_NO_SEQUENCE[port]->write(it_upt->no_sequence );

                  if (_param->_have_port_depth)
                  TEST(Tdepth_t,out_DEPTH_MIN [context]->read(), upt_bottom [context]);
                  TEST(Tdepth_t,out_DEPTH_MAX [context]->read(), upt_top [context]);
		  
		  SC_START(0);
		  
		  LABEL("BRANCH_COMPLETE [%d] %d - %d.",port,in_BRANCH_COMPLETE_VAL [port]->read(),out_BRANCH_COMPLETE_ACK [port]->read());
		  
		  if (in_BRANCH_COMPLETE_VAL [port]->read() and out_BRANCH_COMPLETE_ACK [port]->read())
		    {
		      LABEL("BRANCH_COMPLETE [%d] - Transaction accepted",port);
		      have_transaction = true;
		      
		      TEST(Tcontrol_t,out_BRANCH_COMPLETE_MISS_PREDICTION[port]->read(),it_upt->miss_commit );
		      TEST(Tcontrol_t,out_BRANCH_COMPLETE_TAKE           [port]->read(),it_upt->take_good   );
		      TEST(Taddress_t,out_BRANCH_COMPLETE_ADDRESS_SRC    [port]->read(),it_upt->address_src );
		      TEST(Taddress_t,out_BRANCH_COMPLETE_ADDRESS_DEST   [port]->read(),it_upt->address_good);

                      it_upt ++;
		    }
		  
		  SC_START(1);
		} while (not have_transaction);

	      in_BRANCH_COMPLETE_VAL [port]->write(0);
	      
              if (_param->_have_port_depth)
              TEST(Tdepth_t,out_DEPTH_MIN [context]->read(), upt_bottom [context]);
              TEST(Tdepth_t,out_DEPTH_MAX [context]->read(), upt_top [context]);
	    }
	}

        if (have_ras)
	{
          LABEL("UPDATE - Update UPFT");
	
	  uint32_t port = 0;
	
          LABEL("  * port    : %d",port);
          std::list<request_t>::iterator it_ufpt = ufpt.end();
          -- it_ufpt;
  
 	  for (uint32_t i=0; i<_param->_size_ufpt_queue[context]; i++)
	    {
	      bool have_transaction = false;

	      do
		{
		  in_UPDATE_ACK [port]->write((rand()%100)<percent_transaction_update);

//                   if (_param->_have_port_depth)
//                   TEST(Tdepth_t,out_DEPTH_MIN [context]->read(), ufpt_bottom [context]);
//                   TEST(Tdepth_t,out_DEPTH_MAX [context]->read(), ufpt_top [context]);
		  
		  SC_START(0);

		  LABEL("UPDATE [%d] %d - %d.",port,out_UPDATE_VAL [port]->read(),in_UPDATE_ACK [port]->read());
		  
		  if (out_UPDATE_VAL [port]->read() and in_UPDATE_ACK [port]->read())
		    {
		      LABEL("UPDATE [%d] - Transaction accepted",port);
		      have_transaction = true;
		  
                      if (_param->_have_port_context_id)
                      TEST(Tcontext_t         ,out_UPDATE_CONTEXT_ID            [port]->read(),it_ufpt->context);
                      TEST(Tcontrol_t         ,out_UPDATE_MISS_PREDICTION       [port]->read(),(it_ufpt->miss_ifetch or
                                                                                                it_ufpt->miss_decod  or
                                                                                                it_ufpt->miss_commit ));
//                       if (update_btb(it_ufpt->condition) or
//                           update_dir(it_ufpt->condition))
//                       TEST(Tcontrol_t         ,out_UPDATE_DIRECTION_GOOD        [port]->read(),it_ufpt->take_good);
                      TEST(Tcontrol_t         ,out_UPDATE_BTB_VAL               [port]->read(),0);
//                       if (update_btb(it_ufpt->condition))
//                         {
//                       TEST(Taddress_t         ,out_UPDATE_BTB_ADDRESS_SRC       [port]->read(),it_ufpt->address_src);
//                       TEST(Taddress_t         ,out_UPDATE_BTB_ADDRESS_DEST      [port]->read(),it_ufpt->address_dest);
//                       TEST(Tbranch_condition_t,out_UPDATE_BTB_CONDITION         [port]->read(),it_ufpt->condition);
//                         }
                      TEST(Tcontrol_t         ,out_UPDATE_DIR_VAL               [port]->read(),0);

//                       if (update_dir(it_ufpt->condition))
//                       if (_param->_have_port_history)
//                       TEST(Thistory_t         ,out_UPDATE_DIR_HISTORY           [port]->read(),it_ufpt->history);
//                       TEST(Tcontrol_t         ,out_UPDATE_RAS_VAL               [port]->read(),update_ras(it_ufpt->condition));
                      if (update_ras(it_ufpt->condition))
                        {
//                    TEST(Tcontrol_t         ,out_UPDATE_RAS_FLUSH             [port]->read(),0);
                      TEST(Tcontrol_t         ,out_UPDATE_RAS_PUSH              [port]->read(),push_ras  (it_ufpt->condition));
                      LABEL("KANE : out_UPDATE_RAS_ADDRESS [port]->read() : %.8x",out_UPDATE_RAS_ADDRESS [port]->read());
                      LABEL("KANE : it_ufpt->ras_address                  : %.8x",it_ufpt->ras_address);

                      TEST(Taddress_t         ,out_UPDATE_RAS_ADDRESS           [port]->read(),it_ufpt->ras_address);
                      TEST(Tptr_t             ,out_UPDATE_RAS_INDEX             [port]->read(),it_ufpt->ras_index);
                      TEST(Tcontrol_t         ,out_UPDATE_RAS_PREDICTION_IFETCH [port]->read(),not it_ufpt->miss_ifetch);
                        }
		    }

		  SC_START(1);
		} while (not have_transaction);

              -- it_ufpt;
                

	      in_UPDATE_ACK [port]->write(0);
//               if (_param->_have_port_depth)
//               TEST(Tdepth_t,out_DEPTH_MIN [context]->read(), ufpt_bottom [context]);
//               TEST(Tdepth_t,out_DEPTH_MAX [context]->read(), ufpt_top [context]);
	    }
	}
        ufpt.clear();

	{
          LABEL("UPDATE - hit ifetch");
	
	  uint32_t port = 0;
	
          LABEL("  * port    : %d",port);
          std::list<request_t>::iterator it_upt = upt.begin();
  
// 	  for (uint32_t i=0; i<_param->_size_ufpt_queue[context]; i++)
// 	  for (uint32_t i=0; i<upt.size(); i++)
          // just one
	    {
	      bool have_transaction = false;

	      do
		{
		  in_UPDATE_ACK [port]->write((rand()%100)<percent_transaction_update);

//                   if (_param->_have_port_depth)
//                   TEST(Tdepth_t,out_DEPTH_MIN [context]->read(), upt_bottom [context]);
//                   TEST(Tdepth_t,out_DEPTH_MAX [context]->read(), upt_top [context]);
		  
		  SC_START(0);

		  LABEL("UPDATE [%d] %d - %d.",port,out_UPDATE_VAL [port]->read(),in_UPDATE_ACK [port]->read());
		  
		  if (out_UPDATE_VAL [port]->read() and in_UPDATE_ACK [port]->read())
		    {
		      LABEL("UPDATE [%d] - Transaction accepted",port);
		      have_transaction = true;
		  
                      if (_param->_have_port_context_id)
                      TEST(Tcontext_t         ,out_UPDATE_CONTEXT_ID            [port]->read(),it_upt->context);
                      TEST(Tcontrol_t         ,out_UPDATE_MISS_PREDICTION       [port]->read(),it_upt->miss_commit);
                      TEST(Tcontrol_t         ,out_UPDATE_DIRECTION_GOOD        [port]->read(),it_upt->take_good);
                      TEST(Tcontrol_t         ,out_UPDATE_BTB_VAL               [port]->read(),update_btb(it_upt->condition));
                      if (update_btb(it_upt->condition))
                        {
                      TEST(Taddress_t         ,out_UPDATE_BTB_ADDRESS_SRC       [port]->read(),it_upt->address_src);
                      TEST(Taddress_t         ,out_UPDATE_BTB_ADDRESS_DEST      [port]->read(),it_upt->address_dest);
                      TEST(Tbranch_condition_t,out_UPDATE_BTB_CONDITION         [port]->read(),it_upt->condition);
                        }
                      TEST(Tcontrol_t         ,out_UPDATE_DIR_VAL               [port]->read(),update_dir(it_upt->condition) and not (it_upt->miss_ifetch or it_upt->miss_decod));

                      if (update_dir(it_upt->condition))
                      if (_param->_have_port_history)
                      TEST(Thistory_t         ,out_UPDATE_DIR_HISTORY           [port]->read(),it_upt->history);
                      TEST(Tcontrol_t         ,out_UPDATE_RAS_VAL               [port]->read(),update_ras(it_upt->condition));
                      if (update_ras(it_upt->condition))
                        {
//                    TEST(Tcontrol_t         ,out_UPDATE_RAS_FLUSH             [port]->read(),0);
                      TEST(Tcontrol_t         ,out_UPDATE_RAS_PUSH              [port]->read(),push_ras  (it_upt->condition));
                      TEST(Taddress_t         ,out_UPDATE_RAS_ADDRESS           [port]->read(),it_upt->ras_address);
                      TEST(Tptr_t             ,out_UPDATE_RAS_INDEX             [port]->read(),it_upt->ras_index);
                      TEST(Tcontrol_t         ,out_UPDATE_RAS_PREDICTION_IFETCH [port]->read(),not it_upt->miss_ifetch);
                        }
                      ++ it_upt;
		    }

		  SC_START(1);
		} while (not have_transaction);

	      in_UPDATE_ACK [port]->write(0);
//               if (_param->_have_port_depth)
//               TEST(Tdepth_t,out_DEPTH_MIN [context]->read(), upt_bottom [context]);
//               TEST(Tdepth_t,out_DEPTH_MAX [context]->read(), upt_top [context]);
	    }
	}
        upt.clear();

        {
          LABEL("BRANCH_EVENT - have miss decod");
          
	  uint32_t port = context;

          {
            bool have_transaction = false;
            
            do
              {
                in_BRANCH_EVENT_ACK [port]->write((rand()%100)<percent_transaction_branch_event);
                
                SC_START(0);
                
                LABEL("BRANCH_EVENT [%d] %d - %d.",port,out_BRANCH_EVENT_VAL [port]->read(),in_BRANCH_EVENT_ACK [port]->read());
		
                if (out_BRANCH_EVENT_VAL [port]->read() and in_BRANCH_EVENT_ACK [port]->read())
                  {
                    LABEL("BRANCH_EVENT [%d] - Transaction accepted",port);
                    have_transaction = true;
              
                    TEST(Tdepth_t  ,out_BRANCH_EVENT_DEPTH            [port]->read(),event.upt_ptr);
                    TEST(Taddress_t,out_BRANCH_EVENT_ADDRESS_SRC      [port]->read(),event.address_src);
                    TEST(Tcontrol_t,out_BRANCH_EVENT_ADDRESS_DEST_VAL [port]->read(),event.take);
                    if (event.take)
                    TEST(Taddress_t,out_BRANCH_EVENT_ADDRESS_DEST     [port]->read(),event.address_good);

                    event.address_src  = 0;
                    event.take         = 0;
                    event.address_dest = 0;
                  }
                
                SC_START(1);
              } while (not have_transaction);

	      in_BRANCH_EVENT_ACK [port]->write(0);
          }
        }

        {
          LABEL("EVENT_STATE");
         
          SC_START(1);
          in_EVENT_VAL   [context]->write(1);
          in_EVENT_TYPE  [context]->write(EVENT_TYPE_MISS_SPECULATION);

          SC_START(1);
          in_EVENT_VAL   [context]->write(0);
          in_EVENT_TYPE  [context]->write(EVENT_TYPE_NONE            );
        }

        // Wait Garbage Collector
        {
          upt_bottom [context] = (upt_bottom [context]+1)%_param->_size_upt_queue[context];
//        upt_top    [context] = (upt_top    [context]);

          while ((upt_bottom [context] != out_DEPTH_MIN [context]->read()) or
                 (upt_top    [context] != out_DEPTH_MAX [context]->read()))
            SC_START(1);

        }
      }
     
      //---------------------------------------------------------------------
      //---------------------------------------------------------------------
      // COMMIT MISS : with RAS in UPFT and UPT
      //---------------------------------------------------------------------
      //---------------------------------------------------------------------
      if (test4)
        {
          uint32_t context = rand() % _param->_nb_context;
          uint32_t have_ufpt_ras = false;
          uint32_t have_upt_ras  = false;
          {
            LABEL("PREDICT - fill the queue");
            uint32_t port = rand() % _param->_nb_inst_predict;
            
            LABEL("  * context : %d",context);
            LABEL("  * port    : %d",port);
            
            for (uint32_t i=0; i<_param->_size_ufpt_queue[context]; i++)
              {
                request_t request;
                request.context          = context;
                request.address_src      = rand();
                request.address_dest     = rand();                                   
                
                request.condition        = (rand()%2)?BRANCH_CONDITION_READ_STACK:BRANCH_CONDITION_FLAG_SET;

                request.take             = 1;                                              
                request.take_good        = 1;                                              
                request.flag             = (request.condition == BRANCH_CONDITION_FLAG_SET)?request.take_good:(not request.take_good);
                request.no_sequence      = (request.condition == BRANCH_CONDITION_FLAG_SET)?request.flag:not request.flag;
                request.is_accurate      = true ;
                request.miss_ifetch      = false;
                request.miss_decod       = false;
                request.miss_commit      = false;
                request.history          = i;                                              
                request.ras_address      = rand();                                   
                request.ras_index        = rand()%_param->_size_ras_index[context];
                request.ufpt_ptr         = ufpt_top [context];
//              request.upt_ptr;
                
                bool have_transaction = false;
                do
                  {
                    in_PREDICT_VAL              [port]->write((rand()%100)<percent_transaction_predict);
                    in_PREDICT_CONTEXT_ID       [port]->write(request.context     );
                    in_PREDICT_BTB_ADDRESS_SRC  [port]->write(request.address_src );
                    in_PREDICT_BTB_ADDRESS_DEST [port]->write(request.address_dest);
                    in_PREDICT_BTB_CONDITION    [port]->write(request.condition   );
                    in_PREDICT_BTB_LAST_TAKE    [port]->write(request.take        );
                    in_PREDICT_BTB_IS_ACCURATE  [port]->write(request.is_accurate );
                    in_PREDICT_DIR_HISTORY      [port]->write(request.history     );
                    in_PREDICT_RAS_ADDRESS      [port]->write(request.ras_address );
                    in_PREDICT_RAS_INDEX        [port]->write(request.ras_index   );
                    
                    if (_param->_have_port_depth)
                    TEST(Tdepth_t,out_DEPTH_MIN [context]->read(), upt_bottom [context]);
                    TEST(Tdepth_t,out_DEPTH_MAX [context]->read(), upt_top [context]);
                    
                    SC_START(0); // fct melay
                    
                    LABEL("PREDICT         [%d] %d - %d (accurate : %d).",
                          port,
                          in_PREDICT_VAL [port]->read(),
                          out_PREDICT_ACK [port]->read(),
                          in_PREDICT_BTB_IS_ACCURATE [port]->read());
                    
                    if (in_PREDICT_VAL [port]->read() and out_PREDICT_ACK [port]->read())
                      {
                        LABEL("PREDICT         [%d] - Transaction accepted",port);
                        have_transaction = true;
                        
                        if (_param->_have_port_depth)
                          TEST(Tprediction_ptr_t,out_PREDICT_UPDATE_PREDICTION_ID [port]->read(),ufpt_top [context]);
                        
                        ufpt_top [context] = (ufpt_top [context]+1)%_param->_size_ufpt_queue[context];
                      }
                    
                    SC_START(1); // transition
                    
                  } while (not have_transaction);
                
                ufpt.push_back(request); // to update
                
                in_PREDICT_VAL [port]->write(0);
                
                if (_param->_have_port_depth)
                  TEST(Tdepth_t,out_DEPTH_MIN [context]->read(), upt_bottom [context]);
                TEST(Tdepth_t,out_DEPTH_MAX [context]->read(), upt_top [context]);
              }
          }
	
          {
            LABEL("DECOD");
            uint32_t port = rand() % _param->_nb_inst_decod;
            
            LABEL("  * context : %d",context);
            LABEL("  * port    : %d",port);
            
            for (uint32_t i=0; i<_param->_size_ufpt_queue[context]; i++)
              {
                request_t request = ufpt.front();
                
                bool have_transaction = false;
                do
                  {
                    in_DECOD_VAL                  [port]->write((rand()%100)<percent_transaction_decod);
                    in_DECOD_CONTEXT_ID           [port]->write(request.context     );
                    in_DECOD_BTB_ADDRESS_SRC      [port]->write(request.address_src );
                    in_DECOD_BTB_ADDRESS_DEST     [port]->write(request.address_dest);
                    in_DECOD_BTB_CONDITION        [port]->write(request.condition   );
                    in_DECOD_BTB_LAST_TAKE        [port]->write(request.take        );
                    in_DECOD_RAS_ADDRESS          [port]->write(request.ras_address );
                    in_DECOD_RAS_INDEX            [port]->write(request.ras_index   );
                    in_DECOD_UPDATE_PREDICTION_ID [port]->write(request.ufpt_ptr    );
                    in_DECOD_MISS_IFETCH          [port]->write(request.miss_ifetch );
                    in_DECOD_MISS_DECOD           [port]->write(request.miss_decod  );
                    in_DECOD_IS_ACCURATE          [port]->write(request.is_accurate );
          
                    have_upt_ras |= (update_ras(request.condition));
          
                    SC_START(0); // fct melay
                    
                    LABEL("DECOD           [%d] %d - %d",
                          port,
                          in_DECOD_VAL [port]->read(),
                          out_DECOD_ACK [port]->read());
                    
                    if (in_DECOD_VAL [port]->read() and out_DECOD_ACK [port]->read())
                      {
                        LABEL("DECOD          [%d] - Transaction accepted",port);
                        have_transaction = true;
                        
                        request.upt_ptr = upt_top [context];
                        upt.push_back(request);
                        ufpt.pop_front();
                        
                        upt_top [context] = (upt_top [context]+1)%_param->_size_upt_queue[context];
                      }
                    
                    SC_START(1); // transition
                    
                  } while (not have_transaction);
                
                in_DECOD_VAL              [port]->write(0);
                
                if (_param->_have_port_depth)
                  TEST(Tdepth_t,out_DEPTH_MIN [context]->read(), upt_bottom [context]);
                TEST(Tdepth_t,out_DEPTH_MAX [context]->read(), upt_top [context]);
              }
          }

          {
            LABEL("PREDICT - fill the queue");
            uint32_t port = rand() % _param->_nb_inst_predict;
            
            LABEL("  * context : %d",context);
            LABEL("  * port    : %d",port);
            
            for (uint32_t i=0; i<_param->_size_ufpt_queue[context]; i++)
              {
                request_t request;
                request.context          = context;
                request.address_src      = rand();
                request.address_dest     = rand();                                   
                request.address_good     = request.address_dest;
                request.condition        = (rand()%2)?BRANCH_CONDITION_NONE_WITH_WRITE_STACK:BRANCH_CONDITION_FLAG_SET;
                
                have_ufpt_ras |= (update_ras(request.condition));
                
                request.take             = 1;                                              
                request.take_good        = 1;                                              
                request.flag             = (request.condition == BRANCH_CONDITION_FLAG_SET)?request.take_good:(not request.take_good);
                request.no_sequence      = (request.condition == BRANCH_CONDITION_FLAG_SET)?request.flag:not request.flag;
                request.is_accurate      = true ;
                request.miss_ifetch      = false;
                request.miss_decod       = false;
                request.miss_commit      = true;
                request.history          = i;                                              
                request.ras_address      = rand();                                   
                request.ras_index        = rand()%_param->_size_ras_index[context];
                request.ufpt_ptr         = ufpt_top [context];
//              request.upt_ptr;
                
                bool have_transaction = false;
                do
                  {
                    in_PREDICT_VAL              [port]->write((rand()%100)<percent_transaction_predict);
                    in_PREDICT_CONTEXT_ID       [port]->write(request.context     );
                    in_PREDICT_BTB_ADDRESS_SRC  [port]->write(request.address_src );
                    in_PREDICT_BTB_ADDRESS_DEST [port]->write(request.address_dest);
                    in_PREDICT_BTB_CONDITION    [port]->write(request.condition   );
                    in_PREDICT_BTB_LAST_TAKE    [port]->write(request.take        );
                    in_PREDICT_BTB_IS_ACCURATE  [port]->write(request.is_accurate );
                    in_PREDICT_DIR_HISTORY      [port]->write(request.history     );
                    in_PREDICT_RAS_ADDRESS      [port]->write(request.ras_address );
                    in_PREDICT_RAS_INDEX        [port]->write(request.ras_index   );
                    
                    if (_param->_have_port_depth)
                    TEST(Tdepth_t,out_DEPTH_MIN [context]->read(), upt_bottom [context]);
                    TEST(Tdepth_t,out_DEPTH_MAX [context]->read(), upt_top [context]);
                    
                    SC_START(0); // fct melay
                    
                    LABEL("PREDICT         [%d] %d - %d (accurate : %d).",
                          port,
                          in_PREDICT_VAL [port]->read(),
                          out_PREDICT_ACK [port]->read(),
                          in_PREDICT_BTB_IS_ACCURATE [port]->read());
                    
                    if (in_PREDICT_VAL [port]->read() and out_PREDICT_ACK [port]->read())
                      {
                        LABEL("PREDICT         [%d] - Transaction accepted",port);
                        have_transaction = true;
                        
                        if (_param->_have_port_depth)
                          TEST(Tprediction_ptr_t,out_PREDICT_UPDATE_PREDICTION_ID [port]->read(),ufpt_top [context]);
                        
                        ufpt_top [context] = (ufpt_top [context]+1)%_param->_size_ufpt_queue[context];
                      }
                    
                    SC_START(1); // transition
                    
                  } while (not have_transaction);
                
                ufpt.push_back(request); // to update
                
                in_PREDICT_VAL [port]->write(0);
                
                if (_param->_have_port_depth)
                  TEST(Tdepth_t,out_DEPTH_MIN [context]->read(), upt_bottom [context]);
                TEST(Tdepth_t,out_DEPTH_MAX [context]->read(), upt_top [context]);
              }
          }

          std::list<request_t>::iterator it_event;
          {
            LABEL("BRANCH_COMPLETE - Miss ifetch");
            
            uint32_t port = rand() % _param->_nb_inst_branch_complete;
            
            LABEL("  * port    : %d",port);
            
            // middle
            it_event = upt.begin();
            for (uint32_t i=0; i < (upt.size()>>1); ++i)
              it_event ++;

            for (std::list<request_t>::iterator it_upt = it_event;
                 it_upt != upt.end();
                 ++it_upt)
              it_upt->miss_commit = true;

            if (update_ras(it_event->condition))
              {
                it_event->address_good = ~(it_event->address_dest);
              }
            else
              {
                it_event->address_good = it_event->address_dest;
                it_event->flag         = not it_event->flag;
                it_event->no_sequence  = not it_event->no_sequence;
                it_event->take_good    = not it_event->take_good;
              }

            event = *it_event;

            
// 	  for (uint32_t i=0; i<_param->_size_ufpt_queue[context]; i++)
// 	  for (uint32_t i=0; i<upt.size(); i++)
            // just one
            {
	      bool have_transaction = false;
              
	      do
		{
		  in_BRANCH_COMPLETE_VAL        [port]->write((rand()%100)<percent_transaction_branch_complete);
		  in_BRANCH_COMPLETE_CONTEXT_ID [port]->write(it_event->context     );
		  in_BRANCH_COMPLETE_DEPTH      [port]->write(it_event->upt_ptr     );
		  in_BRANCH_COMPLETE_ADDRESS    [port]->write(it_event->address_good);
		  in_BRANCH_COMPLETE_NO_SEQUENCE[port]->write(it_event->no_sequence );

                  if (_param->_have_port_depth)
                  TEST(Tdepth_t,out_DEPTH_MIN [context]->read(), upt_bottom [context]);
                  TEST(Tdepth_t,out_DEPTH_MAX [context]->read(), upt_top [context]);
		  
		  SC_START(0);
		  
		  LABEL("BRANCH_COMPLETE [%d] %d - %d.",port,in_BRANCH_COMPLETE_VAL [port]->read(),out_BRANCH_COMPLETE_ACK [port]->read());
		  
		  if (in_BRANCH_COMPLETE_VAL [port]->read() and out_BRANCH_COMPLETE_ACK [port]->read())
		    {
		      LABEL("BRANCH_COMPLETE [%d] - Transaction accepted",port);
                      LABEL("  * CONTEXT_ID  : %d"  ,it_event->context     );
                      LABEL("  * DEPTH       : %d"  ,it_event->upt_ptr     );
                      LABEL("  * CONDITION   : %d"  ,it_event->condition   );
                      LABEL("  * ADDRESS     : %.8x",it_event->address_good);
                      LABEL("  * FLAG        : %d"  ,it_event->flag        );
                      LABEL("  * NO_SEQUENCE : %d"  ,it_event->no_sequence );

		      have_transaction = true;
		      
		      TEST(Tcontrol_t,out_BRANCH_COMPLETE_MISS_PREDICTION[port]->read(),it_event->miss_commit );
		      TEST(Tcontrol_t,out_BRANCH_COMPLETE_TAKE           [port]->read(),it_event->take_good   );
		      TEST(Taddress_t,out_BRANCH_COMPLETE_ADDRESS_SRC    [port]->read(),it_event->address_src );
		      TEST(Taddress_t,out_BRANCH_COMPLETE_ADDRESS_DEST   [port]->read(),it_event->address_good);

                      upt_top_event [it_event->context] = upt_top [it_event->context];
                      upt_top       [it_event->context] = it_event->upt_ptr;
		    }
		  
		  SC_START(1);
		} while (not have_transaction);
              
	      in_BRANCH_COMPLETE_VAL [port]->write(0);
	      
              if (_param->_have_port_depth)
              TEST(Tdepth_t,out_DEPTH_MIN [context]->read(), upt_bottom [context]);
              TEST(Tdepth_t,out_DEPTH_MAX [context]->read(), upt_top [context]);
	    }
          }

          {
            LABEL("BRANCH_COMPLETE - Hit ifetch");
            
            uint32_t port = rand() % _param->_nb_inst_branch_complete;
            
            LABEL("  * port    : %d",port);
            
            std::list<request_t>::iterator it_upt = upt.begin();
            
            while (it_upt != it_event)
            {
	      bool have_transaction = false;
              
	      do
		{
		  in_BRANCH_COMPLETE_VAL        [port]->write((rand()%100)<percent_transaction_branch_complete);
		  in_BRANCH_COMPLETE_CONTEXT_ID [port]->write(it_upt->context     );
		  in_BRANCH_COMPLETE_DEPTH      [port]->write(it_upt->upt_ptr     );
		  in_BRANCH_COMPLETE_ADDRESS    [port]->write(it_upt->address_dest);
		  in_BRANCH_COMPLETE_NO_SEQUENCE[port]->write(it_upt->no_sequence );

                  if (_param->_have_port_depth)
                  TEST(Tdepth_t,out_DEPTH_MIN [context]->read(), upt_bottom [context]);
                  TEST(Tdepth_t,out_DEPTH_MAX [context]->read(), upt_top [context]);
		  
		  SC_START(0);
		  
		  LABEL("BRANCH_COMPLETE [%d] %d - %d.",port,in_BRANCH_COMPLETE_VAL [port]->read(),out_BRANCH_COMPLETE_ACK [port]->read());
		  
		  if (in_BRANCH_COMPLETE_VAL [port]->read() and out_BRANCH_COMPLETE_ACK [port]->read())
		    {
		      LABEL("BRANCH_COMPLETE [%d] - Transaction accepted",port);
                      LABEL("  * CONTEXT_ID  : %d"  ,it_upt->context     );
                      LABEL("  * DEPTH       : %d"  ,it_upt->upt_ptr     );
                      LABEL("  * CONDITION   : %d"  ,it_upt->condition   );
                      LABEL("  * ADDRESS     : %.8x",it_upt->address_dest);
                      LABEL("  * FLAG        : %d"  ,it_upt->flag        );
                      LABEL("  * NO_SEQUENCE : %d"  ,it_event->no_sequence );

		      have_transaction = true;
		      
		      TEST(Tcontrol_t,out_BRANCH_COMPLETE_MISS_PREDICTION[port]->read(),it_upt->miss_commit );
		      TEST(Tcontrol_t,out_BRANCH_COMPLETE_TAKE           [port]->read(),it_upt->take        );
                      it_upt->take_good = it_upt->take;
		      TEST(Taddress_t,out_BRANCH_COMPLETE_ADDRESS_SRC    [port]->read(),it_upt->address_src );
		      TEST(Taddress_t,out_BRANCH_COMPLETE_ADDRESS_DEST   [port]->read(),it_upt->address_dest);

                      it_upt++;
		    }
		  
		  SC_START(1);
		} while (not have_transaction);
              
	      in_BRANCH_COMPLETE_VAL [port]->write(0);
	      
              if (_param->_have_port_depth)
              TEST(Tdepth_t,out_DEPTH_MIN [context]->read(), upt_bottom [context]);
              TEST(Tdepth_t,out_DEPTH_MAX [context]->read(), upt_top [context]);
	    }
          }
          
          if (have_ufpt_ras)
            {
              LABEL("UPDATE - Update UPFT");
              
              uint32_t port = 0;
              
              LABEL("  * port    : %d",port);
              std::list<request_t>::iterator it_ufpt = ufpt.end();
              -- it_ufpt;
              
              for (uint32_t i=0; i<_param->_size_ufpt_queue[context]; i++)
                {
                  bool have_transaction = false;
                  
                  do
                    {
                      in_UPDATE_ACK [port]->write((rand()%100)<percent_transaction_update);
                      
//                    if (_param->_have_port_depth)
//                    TEST(Tdepth_t,out_DEPTH_MIN [context]->read(), ufpt_bottom [context]);
//                    TEST(Tdepth_t,out_DEPTH_MAX [context]->read(), ufpt_top [context]);
		  
                      SC_START(0);
                      
                      LABEL("UPDATE [%d] %d - %d.",port,out_UPDATE_VAL [port]->read(),in_UPDATE_ACK [port]->read());
                      
                      if (out_UPDATE_VAL [port]->read() and in_UPDATE_ACK [port]->read())
                        {
                          LABEL("UPDATE [%d] - Transaction accepted",port);
                          have_transaction = true;
                          
                          if (_param->_have_port_context_id)
                          TEST(Tcontext_t         ,out_UPDATE_CONTEXT_ID            [port]->read(),it_ufpt->context);
                          TEST(Tcontrol_t         ,out_UPDATE_MISS_PREDICTION       [port]->read(),(it_ufpt->miss_ifetch or
                                                                                                    it_ufpt->miss_decod  or
                                                                                                    it_ufpt->miss_commit ));
//                        if (update_btb(it_ufpt->condition) or
//                            update_dir(it_ufpt->condition))
//                        TEST(Tcontrol_t         ,out_UPDATE_DIRECTION_GOOD        [port]->read(),it_ufpt->take_good);
                          TEST(Tcontrol_t         ,out_UPDATE_BTB_VAL               [port]->read(),0);
//                        if (update_btb(it_ufpt->condition))
//                          {
//                        TEST(Taddress_t         ,out_UPDATE_BTB_ADDRESS_SRC       [port]->read(),it_ufpt->address_src);
//                        TEST(Taddress_t         ,out_UPDATE_BTB_ADDRESS_DEST      [port]->read(),it_ufpt->address_dest);
//                        TEST(Tbranch_condition_t,out_UPDATE_BTB_CONDITION         [port]->read(),it_ufpt->condition);
//                          }
                          TEST(Tcontrol_t         ,out_UPDATE_DIR_VAL               [port]->read(),0);

//                        if (update_dir(it_ufpt->condition))
//                        if (_param->_have_port_history)
//                        TEST(Thistory_t         ,out_UPDATE_DIR_HISTORY           [port]->read(),it_ufpt->history);
//                        TEST(Tcontrol_t         ,out_UPDATE_RAS_VAL               [port]->read(),update_ras(it_ufpt->condition));
                          if (update_ras(it_ufpt->condition))
                            {
//                            TEST(Tcontrol_t         ,out_UPDATE_RAS_FLUSH             [port]->read(),0);
                              TEST(Tcontrol_t         ,out_UPDATE_RAS_PUSH              [port]->read(),push_ras  (it_ufpt->condition));
                              TEST(Taddress_t         ,out_UPDATE_RAS_ADDRESS           [port]->read(),it_ufpt->ras_address);
                              TEST(Tptr_t             ,out_UPDATE_RAS_INDEX             [port]->read(),it_ufpt->ras_index);
                              TEST(Tcontrol_t         ,out_UPDATE_RAS_PREDICTION_IFETCH [port]->read(),not it_ufpt->miss_ifetch);
                            }
                        }
                      
                      SC_START(1);
                    } while (not have_transaction);
                  
                  -- it_ufpt;
                  
                  
                  in_UPDATE_ACK [port]->write(0);
//                if (_param->_have_port_depth)
//                TEST(Tdepth_t,out_DEPTH_MIN [context]->read(), ufpt_bottom [context]);
//                TEST(Tdepth_t,out_DEPTH_MAX [context]->read(), ufpt_top [context]);
                }
            }
          ufpt.clear();

          {
            LABEL("UPDATE - upt (after event)");
            
            uint32_t port = 0;
            
            LABEL("  * port    : %d",port);
            std::list<request_t>::iterator it_upt = upt.end();

//             for (uint32_t i=0; i<upt.size(); i++)
            do
              {
                --it_upt;
                
                bool have_transaction = false;
                
                if (need_update(it_upt->condition))
                do
                  {
                    in_UPDATE_ACK [port]->write((rand()%100)<percent_transaction_update);

//                   if (_param->_have_port_depth)
//                   TEST(Tdepth_t,out_DEPTH_MIN [context]->read(), upt_bottom [context]);
//                   TEST(Tdepth_t,out_DEPTH_MAX [context]->read(), upt_top [context]);
		  
                    SC_START(0);
                    
                    LABEL("UPDATE [%d] %d - %d.",port,out_UPDATE_VAL [port]->read(),in_UPDATE_ACK [port]->read());
                    
                    if (out_UPDATE_VAL [port]->read() and in_UPDATE_ACK [port]->read())
                      {
                        LABEL("UPDATE [%d] - Transaction accepted",port);
                        LABEL("  * address_src                : %.8x",it_upt->address_src);
                        LABEL("  * out_UPDATE_BTB_ADDRESS_SRC : %.8x",out_UPDATE_BTB_ADDRESS_SRC[port]->read());

                        have_transaction = true;
                        
                        bool btb_val = ((it_upt == it_event) and
                                        (update_btb(it_upt->condition)));
                        bool dir_val = ((it_upt == it_event) and
                                        update_dir(it_upt->condition) and 
                                        not (it_upt->miss_ifetch or it_upt->miss_decod));
                        bool ras_val = update_ras(it_upt->condition);

                        if (_param->_have_port_context_id)
                        TEST(Tcontext_t         ,out_UPDATE_CONTEXT_ID            [port]->read(),it_upt->context);
                        TEST(Tcontrol_t         ,out_UPDATE_MISS_PREDICTION       [port]->read(),it_upt->miss_commit);
                        TEST(Tcontrol_t         ,out_UPDATE_BTB_VAL               [port]->read(),btb_val);

                        if (btb_val)
                          {
                        TEST(Taddress_t         ,out_UPDATE_BTB_ADDRESS_SRC       [port]->read(),it_upt->address_src);
                        TEST(Taddress_t         ,out_UPDATE_BTB_ADDRESS_DEST      [port]->read(),it_upt->address_dest);
                        TEST(Tbranch_condition_t,out_UPDATE_BTB_CONDITION         [port]->read(),it_upt->condition);
                          }
                        TEST(Tcontrol_t         ,out_UPDATE_DIR_VAL               [port]->read(),dir_val);
                        
                        if (dir_val)
                          {
                        TEST(Tcontrol_t         ,out_UPDATE_DIRECTION_GOOD        [port]->read(),it_upt->take_good);
                        if (_param->_have_port_history)
                        TEST(Thistory_t         ,out_UPDATE_DIR_HISTORY           [port]->read(),it_upt->history);
                          }
                        TEST(Tcontrol_t         ,out_UPDATE_RAS_VAL               [port]->read(),ras_val);

                        if (ras_val)
                          {
//                      TEST(Tcontrol_t         ,out_UPDATE_RAS_FLUSH             [port]->read(),0);
                        TEST(Tcontrol_t         ,out_UPDATE_RAS_PUSH              [port]->read(),push_ras  (it_upt->condition));
                        TEST(Taddress_t         ,out_UPDATE_RAS_ADDRESS           [port]->read(),it_upt->ras_address);
                        TEST(Tptr_t             ,out_UPDATE_RAS_INDEX             [port]->read(),it_upt->ras_index);
                        TEST(Tcontrol_t         ,out_UPDATE_RAS_PREDICTION_IFETCH [port]->read(),not it_upt->miss_ifetch);
                          }

//                         -- it_upt;
                      }
                    
                    SC_START(1);
                  } while (not have_transaction);
              
                upt.pop_back();
                in_UPDATE_ACK [port]->write(0);
//               if (_param->_have_port_depth)
//               TEST(Tdepth_t,out_DEPTH_MIN [context]->read(), upt_bottom [context]);
//               TEST(Tdepth_t,out_DEPTH_MAX [context]->read(), upt_top [context]);
              }
            while (it_upt != it_event);

          }
          
          {
            LABEL("BRANCH_EVENT - have miss decod");
            
            uint32_t port = context;
            
            {
              bool have_transaction = false;
              
              do
                {
                  in_BRANCH_EVENT_ACK [port]->write((rand()%100)<percent_transaction_branch_event);
                  
                  SC_START(0);
                  
                  LABEL("BRANCH_EVENT [%d] %d - %d.",port,out_BRANCH_EVENT_VAL [port]->read(),in_BRANCH_EVENT_ACK [port]->read());
                  
                  if (out_BRANCH_EVENT_VAL [port]->read() and in_BRANCH_EVENT_ACK [port]->read())
                    {
                      LABEL("BRANCH_EVENT [%d] - Transaction accepted",port);
                      have_transaction = true;
                      
                      LABEL("  * event.address_src  : %.8x,",event.address_src );
                      LABEL("  * event.address_good : %.8x,",event.address_good);
                      LABEL("  * event.take         : %.8x,",event.take        );
                      
                      TEST(Tdepth_t  ,out_BRANCH_EVENT_DEPTH            [port]->read(),event.upt_ptr);
                      TEST(Taddress_t,out_BRANCH_EVENT_ADDRESS_SRC      [port]->read(),event.address_src);
                      TEST(Tcontrol_t,out_BRANCH_EVENT_ADDRESS_DEST_VAL [port]->read(),event.take_good);
                      if (event.take_good)
                      TEST(Taddress_t,out_BRANCH_EVENT_ADDRESS_DEST     [port]->read(),event.address_good);
                      
                      event.address_src  = 0;
                      event.take         = 0;
                      event.address_dest = 0;
                    }
                  
                  SC_START(1);
                } while (not have_transaction);
              
	      in_BRANCH_EVENT_ACK [port]->write(0);
            }
          }

          {
            LABEL("EVENT_STATE");
            
            SC_START(1);
            in_EVENT_VAL   [context]->write(1);
            in_EVENT_TYPE  [context]->write(EVENT_TYPE_MISS_SPECULATION);
            
            SC_START(1);
            in_EVENT_VAL   [context]->write(0);
            in_EVENT_TYPE  [context]->write(EVENT_TYPE_NONE            );
          }

          {
            LABEL("UPDATE - upt (before event)");
            
            uint32_t port = 0;
            
            LABEL("  * port    : %d",port);
            LABEL("  * size    : %d",upt.size());
            std::list<request_t>::iterator it_upt = upt.begin();

            for (uint32_t i=0; i<upt.size(); i++)
              {
                bool have_transaction = false;
                
                do
                  {
                    in_UPDATE_ACK [port]->write((rand()%100)<percent_transaction_update);

//                   if (_param->_have_port_depth)
//                   TEST(Tdepth_t,out_DEPTH_MIN [context]->read(), upt_bottom [context]);
//                   TEST(Tdepth_t,out_DEPTH_MAX [context]->read(), upt_top [context]);
		  
                    SC_START(0);
                    
                    LABEL("UPDATE [%d] %d - %d.",port,out_UPDATE_VAL [port]->read(),in_UPDATE_ACK [port]->read());
                    
                    if (out_UPDATE_VAL [port]->read() and in_UPDATE_ACK [port]->read())
                      {
                        LABEL("UPDATE [%d] - Transaction accepted",port);
                        have_transaction = true;
                        
                        if (_param->_have_port_context_id)
                        TEST(Tcontext_t         ,out_UPDATE_CONTEXT_ID            [port]->read(),it_upt->context);
                        TEST(Tcontrol_t         ,out_UPDATE_MISS_PREDICTION       [port]->read(),it_upt->miss_commit);
                        TEST(Tcontrol_t         ,out_UPDATE_DIRECTION_GOOD        [port]->read(),it_upt->take_good);
                        TEST(Tcontrol_t         ,out_UPDATE_BTB_VAL               [port]->read(),update_btb(it_upt->condition));
                        if (update_btb(it_upt->condition))
                          {
                        TEST(Taddress_t         ,out_UPDATE_BTB_ADDRESS_SRC       [port]->read(),it_upt->address_src);
                        TEST(Taddress_t         ,out_UPDATE_BTB_ADDRESS_DEST      [port]->read(),it_upt->address_dest);
                        TEST(Tbranch_condition_t,out_UPDATE_BTB_CONDITION         [port]->read(),it_upt->condition);
                          }
                        TEST(Tcontrol_t         ,out_UPDATE_DIR_VAL               [port]->read(),update_dir(it_upt->condition) and not (it_upt->miss_ifetch or it_upt->miss_decod));
                        
                        if (update_dir(it_upt->condition))
                        if (_param->_have_port_history)
                        TEST(Thistory_t         ,out_UPDATE_DIR_HISTORY           [port]->read(),it_upt->history);
                        TEST(Tcontrol_t         ,out_UPDATE_RAS_VAL               [port]->read(),update_ras(it_upt->condition));
                        if (update_ras(it_upt->condition))
                          {
//                      TEST(Tcontrol_t         ,out_UPDATE_RAS_FLUSH             [port]->read(),0);
                        TEST(Tcontrol_t         ,out_UPDATE_RAS_PUSH              [port]->read(),push_ras  (it_upt->condition));
                        TEST(Taddress_t         ,out_UPDATE_RAS_ADDRESS           [port]->read(),it_upt->ras_address);
                        TEST(Tptr_t             ,out_UPDATE_RAS_INDEX             [port]->read(),it_upt->ras_index);
                        TEST(Tcontrol_t         ,out_UPDATE_RAS_PREDICTION_IFETCH [port]->read(),not it_upt->miss_ifetch);
                          }

                        ++ it_upt;
                      }
                    
                    SC_START(1);
                  } while (not have_transaction);
                
                in_UPDATE_ACK [port]->write(0);
//               if (_param->_have_port_depth)
//               TEST(Tdepth_t,out_DEPTH_MIN [context]->read(), upt_bottom [context]);
//               TEST(Tdepth_t,out_DEPTH_MAX [context]->read(), upt_top [context]);
              }
          }
          upt.clear();

          // Wait Garbage Collector
          {
            LABEL("GARBAGE COLLECTOR");
            LABEL(" * upt bottom : %d",upt_bottom [context]);
            LABEL(" * upt top    : %d",upt_top    [context]);

            upt_top    [context] = (upt_top_event [context]);
            upt_bottom [context] = (upt_top       [context]);

            while ((upt_bottom [context] != out_DEPTH_MIN [context]->read()) or
                   (upt_top    [context] != out_DEPTH_MAX [context]->read()))
              {
                SC_START(1);
              }
            
          }
        }
     
    }// ITERATION

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

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

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

  delete in_CLOCK;
  delete in_NRESET;

  // ~~~~~[ Interface : "predict" ]~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  delete []  in_PREDICT_VAL                 ;
  delete [] out_PREDICT_ACK                 ;
  delete []  in_PREDICT_CONTEXT_ID          ;
  delete []  in_PREDICT_BTB_ADDRESS_SRC     ;
  delete []  in_PREDICT_BTB_ADDRESS_DEST    ;
  delete []  in_PREDICT_BTB_CONDITION       ;
  delete []  in_PREDICT_BTB_LAST_TAKE       ;
  delete []  in_PREDICT_BTB_IS_ACCURATE     ;
  delete []  in_PREDICT_DIR_HISTORY         ;
  delete []  in_PREDICT_RAS_ADDRESS         ;
  delete []  in_PREDICT_RAS_INDEX           ;
  delete [] out_PREDICT_UPDATE_PREDICTION_ID;
  
  // ~~~~~[ Interface : "decod" ]~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  delete []  in_DECOD_VAL                   ;
  delete [] out_DECOD_ACK                   ;
  delete []  in_DECOD_CONTEXT_ID            ;
  delete []  in_DECOD_BTB_ADDRESS_SRC       ;
  delete []  in_DECOD_BTB_ADDRESS_DEST      ;
  delete []  in_DECOD_BTB_CONDITION         ;
  delete []  in_DECOD_BTB_LAST_TAKE         ;
  delete []  in_DECOD_RAS_ADDRESS           ;
  delete []  in_DECOD_RAS_INDEX             ;
  delete []  in_DECOD_MISS_IFETCH           ;
  delete []  in_DECOD_MISS_DECOD            ;
  delete []  in_DECOD_UPDATE_PREDICTION_ID  ;
//delete [] out_DECOD_DEPTH                 ;
  delete []  in_DECOD_IS_ACCURATE           ;
  
  // ~~~~~[ Interface : "branch_complete" ]~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  delete []  in_BRANCH_COMPLETE_VAL            ;
  delete [] out_BRANCH_COMPLETE_ACK            ;
  delete []  in_BRANCH_COMPLETE_CONTEXT_ID     ;
  delete []  in_BRANCH_COMPLETE_DEPTH          ;
  delete []  in_BRANCH_COMPLETE_ADDRESS        ;
  delete []  in_BRANCH_COMPLETE_NO_SEQUENCE    ;
  delete [] out_BRANCH_COMPLETE_MISS_PREDICTION;
  delete [] out_BRANCH_COMPLETE_TAKE           ;
  delete [] out_BRANCH_COMPLETE_ADDRESS_SRC    ;
  delete [] out_BRANCH_COMPLETE_ADDRESS_DEST   ;

  // ~~~~~[ Interface : "branch_event" ]~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  delete [] out_BRANCH_EVENT_VAL            ;
  delete []  in_BRANCH_EVENT_ACK            ;
//delete [] out_BRANCH_EVENT_CONTEXT_ID     ;
  delete [] out_BRANCH_EVENT_DEPTH          ;
//delete [] out_BRANCH_EVENT_MISS_PREDICTION;
  delete [] out_BRANCH_EVENT_ADDRESS_SRC    ;
  delete [] out_BRANCH_EVENT_ADDRESS_DEST_VAL;
  delete [] out_BRANCH_EVENT_ADDRESS_DEST   ;
  
  // ~~~~~[ Interface : "update" ]~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  delete [] out_UPDATE_VAL                  ;
  delete []  in_UPDATE_ACK                  ;
  delete [] out_UPDATE_CONTEXT_ID           ;
  delete [] out_UPDATE_MISS_PREDICTION      ;
  delete [] out_UPDATE_DIRECTION_GOOD       ;
  delete [] out_UPDATE_BTB_VAL              ;
  delete [] out_UPDATE_BTB_ADDRESS_SRC      ;
  delete [] out_UPDATE_BTB_ADDRESS_DEST     ;
  delete [] out_UPDATE_BTB_CONDITION        ;
  delete [] out_UPDATE_DIR_VAL              ;
  delete [] out_UPDATE_DIR_HISTORY          ;
  delete [] out_UPDATE_RAS_VAL              ;
  delete [] out_UPDATE_RAS_FLUSH            ;
  delete [] out_UPDATE_RAS_PUSH             ;
  delete [] out_UPDATE_RAS_ADDRESS          ;
  delete [] out_UPDATE_RAS_INDEX            ;
  delete [] out_UPDATE_RAS_PREDICTION_IFETCH;

  DELETE1_SC_SIGNAL( in_EVENT_VAL                      ,_param->_nb_context);
  DELETE1_SC_SIGNAL(out_EVENT_ACK                      ,_param->_nb_context);
  DELETE1_SC_SIGNAL( in_EVENT_TYPE                     ,_param->_nb_context);
  DELETE1_SC_SIGNAL( in_EVENT_DEPTH                    ,_param->_nb_context);

  // ~~~~~[ Interface : "depth" ]~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  delete [] out_DEPTH_CURRENT;
  delete [] out_DEPTH_MIN;
  delete [] out_DEPTH_MAX;

#endif

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