#ifdef SYSTEMC
/*
 * $Id: Two_Level_Branch_Predictor_genMealy_predict.cpp 111 2009-02-27 18:37:40Z rosiere $
 *
 * [ Description ]
 * 
 */

#include "Behavioural/Core/Multi_Front_end/Front_end/Prediction_unit/Direction/Meta_Predictor/Two_Level_Branch_Predictor/include/Two_Level_Branch_Predictor.h"

namespace morpheo                    {
namespace behavioural {
namespace core {
namespace multi_front_end {
namespace front_end {
namespace prediction_unit {
namespace direction {
namespace meta_predictor {
namespace two_level_branch_predictor {


#undef  FUNCTION
#define FUNCTION "Two_Level_Branch_Predictor::genMealy_predict"
  void Two_Level_Branch_Predictor::genMealy_predict (void)
  {
    log_begin(Two_Level_Branch_Predictor,FUNCTION);
    log_function(Two_Level_Branch_Predictor,FUNCTION,_name.c_str());

    // ===================================================================
    // =====[ PREDICT ]===================================================
    // ===================================================================

    for (uint32_t i=0; i<_param->_nb_inst_predict; ++i)
//       if (PORT_READ(in_PREDICT_VAL[i]))
        {
          log_printf(TRACE,Two_Level_Branch_Predictor,FUNCTION,"  * PREDICT [%d]",i);

          Taddress_t address     = PORT_READ(in_PREDICT_ADDRESS   [i]);
          Thistory_t history     = 0;
          Tcontrol_t direction;

          log_printf(TRACE,Two_Level_Branch_Predictor,FUNCTION,"  * address          : 0x%.8x",address);

          Thistory_t pht_bht_history = 0;
          if (_param->_have_bht)
            {
              Thistory_t bht_num_reg = address & _param->_bht_address_mask;
              Thistory_t bht_history = reg_BHT [bht_num_reg];
              pht_bht_history = bht_history;

              log_printf(TRACE,Two_Level_Branch_Predictor,FUNCTION,"  * bht_history      : 0x%x",bht_history);
              log_printf(TRACE,Two_Level_Branch_Predictor,FUNCTION,"  * bht_num_reg      : %d",bht_num_reg);

              history   = (bht_history << _param->_bht_history_rshift)&_param->_bht_history_mask ;
              direction = (bht_history >> (_param->_bht_size_shifter-1))&1;

              if (_param->_update_on_prediction)
              internal_PREDICT_BHT_NUM_REG [i] = bht_num_reg;
            }

          if (_param->_have_pht)
            {
              Thistory_t pht_num_bank= (address>>_param->_pht_address_bank_rshift)&_param->_pht_address_bank_mask;
              Thistory_t pht_num_reg = (pht_bht_history xor ((address&_param->_pht_address_share_mask)<<_param->_pht_address_share_lshift));
              Thistory_t pht_history = reg_PHT [pht_num_bank][pht_num_reg];
              
              log_printf(TRACE,Two_Level_Branch_Predictor,FUNCTION,"  * bht_history      : 0x%x",pht_bht_history);
              log_printf(TRACE,Two_Level_Branch_Predictor,FUNCTION,"  * pht_history      : 0x%x",pht_history);
              log_printf(TRACE,Two_Level_Branch_Predictor,FUNCTION,"  * pht_num_reg      : %d",pht_num_reg);
              log_printf(TRACE,Two_Level_Branch_Predictor,FUNCTION,"  * pht_num_bank     : %d",pht_num_bank);
              
              history  |= (pht_history << _param->_pht_history_rshift)&_param->_pht_history_mask;
              direction = (pht_history >> (_param->_pht_size_counter-1))&1;

              if (_param->_update_on_prediction)
                {
              internal_PREDICT_PHT_NUM_REG [i] = pht_num_reg;
              internal_PREDICT_PHT_NUM_BANK[i] = pht_num_bank;
                }
            }

          log_printf(TRACE,Two_Level_Branch_Predictor,FUNCTION,"  * direction        : %d",direction);
          log_printf(TRACE,Two_Level_Branch_Predictor,FUNCTION,"  * history          : 0x%x",history);

          PORT_WRITE(out_PREDICT_DIRECTION [i],direction);
          PORT_WRITE(out_PREDICT_HISTORY   [i],history  );
        }

    log_end(Two_Level_Branch_Predictor,FUNCTION);
  };

}; // end namespace two_level_branch_predictor
}; // end namespace meta_predictor
}; // end namespace direction
}; // end namespace prediction_unit
}; // end namespace front_end
}; // end namespace multi_front_end
}; // end namespace core

}; // end namespace behavioural
}; // end namespace morpheo              
#endif
