#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 95 2008-12-16 16:24:26Z 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_STATE_OK                    , // Can predict
      EVENT_STATE_FLUSH_UFPT            , // in decod  stage, detect a miss, continue to execute but flush ufpt
      EVENT_STATE_FLUSH_UFPT_AND_UPT    , // in commit stage, detect a miss, stop context and flush ufpt and upt
      EVENT_STATE_FLUSH_UPT             , // in commit stage, detect a miss, 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 envent (send by Context State)
    } 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_OK            , // branch is updated,       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;
  };

  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
  };


// 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)

}; // 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_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_FLUSH_UFPT              : return "flush_ufpt"             ; break;
      case morpheo::behavioural::core::multi_front_end::front_end::prediction_unit::update_prediction_table::EVENT_STATE_FLUSH_UFPT_AND_UPT      : return "flush_ufpt_and_upt"     ; break;
      case morpheo::behavioural::core::multi_front_end::front_end::prediction_unit::update_prediction_table::EVENT_STATE_FLUSH_UPT               : return "flush_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_and_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_OK     : return "end_ok"    ; 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;
      }
  };

}; // end namespace morpheo              

#endif
