#ifndef morpheo_behavioural_core_multi_front_end_front_end_prediction_unit_update_prediction_table_Types_h
#define morpheo_behavioural_core_multi_front_end_front_end_prediction_unit_update_prediction_table_Types_h

/*
 * $Id: Types.h 123 2009-06-08 20:43:30Z rosiere $
 *
 * [ Description ]
 * 
 */

#include "Behavioural/include/Types.h"

namespace morpheo {
namespace behavioural {
namespace core {
namespace multi_front_end {
namespace front_end {
namespace prediction_unit {
namespace update_prediction_table {

  typedef enum
    {
      EVENT_SOURCE_UFPT,
      EVENT_SOURCE_UPT 
    } event_source_t;

//   typedef enum
//     {
//       EVENT_STATE_OK                      , // Can predict
//       EVENT_STATE_MISS_FLUSH_UFPT         , // in decod  stage, detect a miss  , continue to execute but flush ufpt
//       EVENT_STATE_MISS_FLUSH_UFPT_AND_UPT , // in commit stage, detect a miss  , stop context and flush ufpt and upt
//       EVENT_STATE_MISS_FLUSH_UPT          , // in commit stage, detect a miss  , context is stop and ufpt is flush, update RAS
//       EVENT_STATE_EVENT_FLUSH_UFPT        , // in commit stage, detect an event, continue to execute but flush ufpt
//       EVENT_STATE_EVENT_FLUSH_UFPT_AND_UPT, // in commit stage, detect an event, stop context and flush ufpt and upt
//       EVENT_STATE_EVENT_FLUSH_UPT         , // in commit stage, detect an event, context is stop and ufpt is flush, update RAS
//       EVENT_STATE_UPDATE_CONTEXT          , // prediction unit is update, send signal to context manager
//       EVENT_STATE_WAIT_END_EVENT            // prediction unit is ok, wait the end of event (send by Context State)
//     } event_state_t;

  typedef enum
    {
      UFPT_EVENT_STATE_OK                     , // Can predict
      UFPT_EVENT_STATE_KO_FLUSH                 // Can't predict, flush ufpt
    } ufpt_event_state_t;

  typedef enum
    {
      UPT_EVENT_STATE_OK                              , // Can predict
      UPT_EVENT_STATE_KO_MISS_WAIT_UFPT               , // in decod  stage, detect a miss  , continue to execute but flush ufpt
      UPT_EVENT_STATE_KO_MISS_FLUSH_UPT               , // in commit stage, detect a miss  , context is stop and ufpt is flush, update RAS
      UPT_EVENT_STATE_KO_EVENT_WAIT_UFPT              , // in commit stage, detect an event, continue to execute but flush ufpt
      UPT_EVENT_STATE_KO_EVENT_FLUSH_UPT              , // in commit stage, detect an event, context is stop and ufpt is flush, update RAS
      UPT_EVENT_STATE_KO_DECODE_UPDATE_CONTEXT        , // prediction unit is update, send signal to context manager
      UPT_EVENT_STATE_KO_DECODE_WAIT_END_EVENT        , // prediction unit is ok, wait the end of event (send by Context State)
      UPT_EVENT_STATE_KO_COMMIT_UPDATE_CONTEXT        , // prediction unit is update, send signal to context manager
      UPT_EVENT_STATE_KO_COMMIT_WAIT_END_EVENT        , // prediction unit is ok, wait the end of event (send by Context State)
      UPT_EVENT_STATE_KO_COMMIT_WAIT_END_UPDATE         // prediction unit is ok, wait the end of event (send by Context State)
    } upt_event_state_t;

  typedef enum
    {
      UPDATE_FETCH_PREDICTION_STATE_EMPTY       , // Slot is empty
      UPDATE_FETCH_PREDICTION_STATE_WAIT_DECOD  , // Have make a prediction, wait decod
      UPDATE_FETCH_PREDICTION_STATE_EVENT       , // previous branch is a miss prediction
      UPDATE_FETCH_PREDICTION_STATE_END           // branch is updated 
    } ufpt_state_t;

  typedef enum
    {
      UPDATE_PREDICTION_STATE_EMPTY             , // Slot is empty
      UPDATE_PREDICTION_STATE_WAIT_END          , // Have make a prediction, wait branch_complete
      UPDATE_PREDICTION_STATE_OK                , // this branch is a hit prediction
      UPDATE_PREDICTION_STATE_KO                , // this branch is a miss prediction
      UPDATE_PREDICTION_STATE_EVENT             , // previous branch is a miss prediction
      UPDATE_PREDICTION_STATE_END               , // update pointer
//    UPDATE_PREDICTION_STATE_END_OK            , // branch is updated,       update pointer
//    UPDATE_PREDICTION_STATE_END_KO_WAIT_END   , // branch is updated, don't update pointer
      UPDATE_PREDICTION_STATE_END_KO              // branch is updated, don't update pointer
    } upt_state_t;

  class ufpt_entry_t
  {
  public : ufpt_state_t        _state            ;
  public : Tbranch_condition_t _condition        ;
  public : Taddress_t          _address_src      ;
  public : Taddress_t          _address_dest     ;
  public : Tcontrol_t          _last_take        ;
//public : Tcontrol_t          _good_take        ;
  public : Tcontrol_t          _is_accurate      ;
  public : Thistory_t          _history          ;
  public : Taddress_t          _address_ras      ;
  public : Tptr_t              _index_ras        ;
//public : Tcontrol_t          _ifetch_prediction;
//public : Tcontrol_t          _miss_commit      ;
  };

  class upt_entry_t
  {
  public : upt_state_t         _state            ;
  public : Tbranch_condition_t _condition        ;
  public : Taddress_t          _address_src      ;
  public : Taddress_t          _address_dest     ;
  public : Tcontrol_t          _last_take        ;
  public : Tcontrol_t          _good_take        ; // not in ufpt
  public : Tcontrol_t          _is_accurate      ;
  public : Thistory_t          _history          ;
  public : Taddress_t          _address_ras      ;
  public : Tptr_t              _index_ras        ;
  public : Tcontrol_t          _ifetch_prediction; // not in ufpt
  public : Tcontrol_t          _miss_commit      ; // not in ufpt

    // to branchement_log_file
  public : bool                _retire_ok        ;
  public : bool                _miss_prediction  ;
  };


// BRANCH_CONDITION_NONE_WITHOUT_WRITE_STACK          
// BRANCH_CONDITION_NONE_WITH_WRITE_STACK             
// BRANCH_CONDITION_FLAG_UNSET                        
// BRANCH_CONDITION_FLAG_SET                          
// BRANCH_CONDITION_READ_REGISTER_WITHOUT_WRITE_STACK 
// BRANCH_CONDITION_READ_REGISTER_WITH_WRITE_STACK    
// BRANCH_CONDITION_READ_STACK                        


#define update_btb(cond)  true

#define update_dir(cond)  ((cond == BRANCH_CONDITION_FLAG_UNSET) or \
                           (cond == BRANCH_CONDITION_FLAG_SET))

#define update_ras(cond)  ((cond == BRANCH_CONDITION_NONE_WITH_WRITE_STACK         ) or \
                           (cond == BRANCH_CONDITION_READ_REGISTER_WITH_WRITE_STACK) or \
                           (cond == BRANCH_CONDITION_READ_STACK                    ))

#define push_ras(cond)    ((cond == BRANCH_CONDITION_NONE_WITH_WRITE_STACK         ) or \
                           (cond == BRANCH_CONDITION_READ_REGISTER_WITH_WRITE_STACK))

#define pop_ras(cond)     ((cond == BRANCH_CONDITION_READ_STACK                    ))

#define need_update(cond) (update_ras(cond) or update_dir(cond))

}; // end namespace update_prediction_table
}; // end namespace prediction_unit
}; // end namespace front_end
}; // end namespace multi_front_end
}; // end namespace core
}; // end namespace behavioural

  template<> inline std::string toString<morpheo::behavioural::core::multi_front_end::front_end::prediction_unit::update_prediction_table::event_source_t>(const morpheo::behavioural::core::multi_front_end::front_end::prediction_unit::update_prediction_table::event_source_t& x)
  {
    switch (x)
      {
      case morpheo::behavioural::core::multi_front_end::front_end::prediction_unit::update_prediction_table::EVENT_SOURCE_UFPT : return "ufpt"; break;
      case morpheo::behavioural::core::multi_front_end::front_end::prediction_unit::update_prediction_table::EVENT_SOURCE_UPT  : return "upt" ; break;
      default    : return ""; break; 
      }
  };

//   template<> inline std::string toString<morpheo::behavioural::core::multi_front_end::front_end::prediction_unit::update_prediction_table::event_state_t>(const morpheo::behavioural::core::multi_front_end::front_end::prediction_unit::update_prediction_table::event_state_t& x)
//   {
//     switch (x)
//       {
//       case morpheo::behavioural::core::multi_front_end::front_end::prediction_unit::update_prediction_table::EVENT_STATE_OK                      : return "ok"                      ; break;
//       case morpheo::behavioural::core::multi_front_end::front_end::prediction_unit::update_prediction_table::EVENT_STATE_MISS_FLUSH_UFPT         : return "miss_flush_ufpt"         ; break;
//       case morpheo::behavioural::core::multi_front_end::front_end::prediction_unit::update_prediction_table::EVENT_STATE_MISS_FLUSH_UFPT_AND_UPT : return "miss_flush_ufpt_and_upt" ; break;
//       case morpheo::behavioural::core::multi_front_end::front_end::prediction_unit::update_prediction_table::EVENT_STATE_MISS_FLUSH_UPT          : return "miss_flush_upt"          ; break;
//       case morpheo::behavioural::core::multi_front_end::front_end::prediction_unit::update_prediction_table::EVENT_STATE_EVENT_FLUSH_UPT         : return "event_flush_upt"         ; break;
//       case morpheo::behavioural::core::multi_front_end::front_end::prediction_unit::update_prediction_table::EVENT_STATE_EVENT_FLUSH_UFPT        : return "event_flush_ufpt"        ; break;
//       case morpheo::behavioural::core::multi_front_end::front_end::prediction_unit::update_prediction_table::EVENT_STATE_EVENT_FLUSH_UFPT_AND_UPT: return "event_flush_ufpt_and_upt"; break;
//       case morpheo::behavioural::core::multi_front_end::front_end::prediction_unit::update_prediction_table::EVENT_STATE_UPDATE_CONTEXT          : return "update_context"          ; break;
//       case morpheo::behavioural::core::multi_front_end::front_end::prediction_unit::update_prediction_table::EVENT_STATE_WAIT_END_EVENT          : return "wait_end_event"          ; break;
//       default    : return ""; break; 
//       }
//   };

  template<> inline std::string toString<morpheo::behavioural::core::multi_front_end::front_end::prediction_unit::update_prediction_table::ufpt_state_t>(const morpheo::behavioural::core::multi_front_end::front_end::prediction_unit::update_prediction_table::ufpt_state_t& x)
  {
    switch (x)
      {
      case morpheo::behavioural::core::multi_front_end::front_end::prediction_unit::update_prediction_table::UPDATE_FETCH_PREDICTION_STATE_EMPTY      : return "empty"     ; break;
      case morpheo::behavioural::core::multi_front_end::front_end::prediction_unit::update_prediction_table::UPDATE_FETCH_PREDICTION_STATE_WAIT_DECOD : return "wait_decod"; break;
      case morpheo::behavioural::core::multi_front_end::front_end::prediction_unit::update_prediction_table::UPDATE_FETCH_PREDICTION_STATE_EVENT      : return "event"     ; break;
      case morpheo::behavioural::core::multi_front_end::front_end::prediction_unit::update_prediction_table::UPDATE_FETCH_PREDICTION_STATE_END        : return "end"       ; break;
      default    : return ""      ; break;
      }
  };

  template<> inline std::string toString<morpheo::behavioural::core::multi_front_end::front_end::prediction_unit::update_prediction_table::upt_state_t>(const morpheo::behavioural::core::multi_front_end::front_end::prediction_unit::update_prediction_table::upt_state_t& x)
  {
    switch (x)
      {
      case morpheo::behavioural::core::multi_front_end::front_end::prediction_unit::update_prediction_table::UPDATE_PREDICTION_STATE_EMPTY      : return "empty"     ; break;
      case morpheo::behavioural::core::multi_front_end::front_end::prediction_unit::update_prediction_table::UPDATE_PREDICTION_STATE_WAIT_END   : return "wait_end"  ; break;
      case morpheo::behavioural::core::multi_front_end::front_end::prediction_unit::update_prediction_table::UPDATE_PREDICTION_STATE_OK         : return "ok"        ; break;
      case morpheo::behavioural::core::multi_front_end::front_end::prediction_unit::update_prediction_table::UPDATE_PREDICTION_STATE_KO         : return "ko"        ; break;
      case morpheo::behavioural::core::multi_front_end::front_end::prediction_unit::update_prediction_table::UPDATE_PREDICTION_STATE_EVENT      : return "event"     ; break;
      case morpheo::behavioural::core::multi_front_end::front_end::prediction_unit::update_prediction_table::UPDATE_PREDICTION_STATE_END        : return "end"       ; break;
//    case morpheo::behavioural::core::multi_front_end::front_end::prediction_unit::update_prediction_table::UPDATE_PREDICTION_STATE_END_OK     : return "end_ok"    ; break;
//    case morpheo::behavioural::core::multi_front_end::front_end::prediction_unit::update_prediction_table::UPDATE_PREDICTION_STATE_END_KO_WAIT_END: return "end_ko_wait_end"    ; break;
      case morpheo::behavioural::core::multi_front_end::front_end::prediction_unit::update_prediction_table::UPDATE_PREDICTION_STATE_END_KO     : return "end_ko"    ; break;
      default    : return ""      ; break;
      }
  };

  template<> inline std::string toString<morpheo::behavioural::core::multi_front_end::front_end::prediction_unit::update_prediction_table::ufpt_event_state_t>(const morpheo::behavioural::core::multi_front_end::front_end::prediction_unit::update_prediction_table::ufpt_event_state_t& x)
  {
    switch (x)
      {
      case morpheo::behavioural::core::multi_front_end::front_end::prediction_unit::update_prediction_table::UFPT_EVENT_STATE_OK       : return "UFPT_EVENT_STATE_OK"       ; break;
      case morpheo::behavioural::core::multi_front_end::front_end::prediction_unit::update_prediction_table::UFPT_EVENT_STATE_KO_FLUSH : return "UFPT_EVENT_STATE_KO_FLUSH" ; break;
      default    : return ""; break; 
      }
  };

  template<> inline std::string toString<morpheo::behavioural::core::multi_front_end::front_end::prediction_unit::update_prediction_table::upt_event_state_t>(const morpheo::behavioural::core::multi_front_end::front_end::prediction_unit::update_prediction_table::upt_event_state_t& x)
  {
    switch (x)
      {
      case morpheo::behavioural::core::multi_front_end::front_end::prediction_unit::update_prediction_table::UPT_EVENT_STATE_OK                        : return "UPT_EVENT_STATE_OK"                        ; break;
      case morpheo::behavioural::core::multi_front_end::front_end::prediction_unit::update_prediction_table::UPT_EVENT_STATE_KO_MISS_WAIT_UFPT         : return "UPT_EVENT_STATE_KO_MISS_WAIT_UFPT"         ; break;
      case morpheo::behavioural::core::multi_front_end::front_end::prediction_unit::update_prediction_table::UPT_EVENT_STATE_KO_MISS_FLUSH_UPT         : return "UPT_EVENT_STATE_KO_MISS_FLUSH_UPT"         ; break;
      case morpheo::behavioural::core::multi_front_end::front_end::prediction_unit::update_prediction_table::UPT_EVENT_STATE_KO_EVENT_WAIT_UFPT        : return "UPT_EVENT_STATE_KO_EVENT_WAIT_UFPT"        ; break;
      case morpheo::behavioural::core::multi_front_end::front_end::prediction_unit::update_prediction_table::UPT_EVENT_STATE_KO_EVENT_FLUSH_UPT        : return "UPT_EVENT_STATE_KO_EVENT_FLUSH_UPT"        ; break;
      case morpheo::behavioural::core::multi_front_end::front_end::prediction_unit::update_prediction_table::UPT_EVENT_STATE_KO_DECODE_UPDATE_CONTEXT  : return "UPT_EVENT_STATE_KO_DECODE_UPDATE_CONTEXT"  ; break;
      case morpheo::behavioural::core::multi_front_end::front_end::prediction_unit::update_prediction_table::UPT_EVENT_STATE_KO_DECODE_WAIT_END_EVENT  : return "UPT_EVENT_STATE_KO_DECODE_WAIT_END_EVENT"  ; break;
      case morpheo::behavioural::core::multi_front_end::front_end::prediction_unit::update_prediction_table::UPT_EVENT_STATE_KO_COMMIT_UPDATE_CONTEXT  : return "UPT_EVENT_STATE_KO_COMMIT_UPDATE_CONTEXT"  ; break;
      case morpheo::behavioural::core::multi_front_end::front_end::prediction_unit::update_prediction_table::UPT_EVENT_STATE_KO_COMMIT_WAIT_END_EVENT  : return "UPT_EVENT_STATE_KO_COMMIT_WAIT_END_EVENT"  ; break;
      case morpheo::behavioural::core::multi_front_end::front_end::prediction_unit::update_prediction_table::UPT_EVENT_STATE_KO_COMMIT_WAIT_END_UPDATE : return "UPT_EVENT_STATE_KO_COMMIT_WAIT_END_UPDATE" ; break;
      default    : return ""; break; 
      }
  };

}; // end namespace morpheo              

#endif
