#ifdef SYSTEMC
/*
 * $Id$
 *
 * [ Description ]
 * 
 */

#include "Behavioural/Core/Multi_Front_end/Front_end/Prediction_unit/Update_Prediction_Table/include/Update_Prediction_Table.h"

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


#undef  FUNCTION
#define FUNCTION "Update_Prediction_Table::genMealy_branch_complete"
  void Update_Prediction_Table::genMealy_branch_complete (void)
  {
    log_printf(FUNC,Update_Prediction_Table,FUNCTION,"Begin");
    
    for (uint32_t i=0; i<_param->_nb_inst_branch_complete; i++)
      {
	Tcontext_t          context   = (_param->_have_port_context_id)?PORT_READ(in_BRANCH_COMPLETE_CONTEXT_ID [i]):0;
	Tdepth_t            depth     = (_param->_have_port_max_depth )?PORT_READ(in_BRANCH_COMPLETE_DEPTH      [i]):0;
	Tcontrol_t          miss      = false;
	Tcontrol_t          take      = reg_UPDATE_PREDICTION_TABLE [context][depth]._last_take   ;
	Taddress_t          addr_dest = reg_UPDATE_PREDICTION_TABLE [context][depth]._address_dest;
	Tbranch_condition_t condition = reg_UPDATE_PREDICTION_TABLE [context][depth]._condition   ;

	switch (condition)
	  {
	  case BRANCH_CONDITION_NONE_WITHOUT_WRITE_STACK          : // l.j
	  case BRANCH_CONDITION_NONE_WITH_WRITE_STACK             : // l.jal
	    {
	      //miss      : always hit
	      //addr_dest : know in decod stage
	      break;
	    }
	  case BRANCH_CONDITION_FLAG_UNSET                        : // l.bnf
	    {
	      Tcontrol_t take_good = PORT_READ(in_BRANCH_COMPLETE_FLAG [i]) == 0;
	      miss = (take != take_good);
	      take = take_good;
	      //addr_dest : know in decod stage
	      break;
	    }
	  case BRANCH_CONDITION_FLAG_SET                          : // l.bf
	    {
// 	      log_printf(TRACE,Update_Prediction_Table,FUNCTION,"  * BRANCH_CONDITION_FLAG_SET");
	      
	      Tcontrol_t take_good = PORT_READ(in_BRANCH_COMPLETE_FLAG [i]) == 1;
	      miss = (take != take_good);
	      take = take_good;

// 	      log_printf(TRACE,Update_Prediction_Table,FUNCTION,"    * flag      : %d",PORT_READ(in_BRANCH_COMPLETE_FLAG [i]));
// 	      log_printf(TRACE,Update_Prediction_Table,FUNCTION,"    * take_good : %d",take_good);
// 	      log_printf(TRACE,Update_Prediction_Table,FUNCTION,"    * miss      : %d",miss);
	      
	      //addr_dest : know in decod stage
	      break;
	    }
	  case BRANCH_CONDITION_READ_REGISTER_WITHOUT_WRITE_STACK : // l.jr (rb!=r9)
	  case BRANCH_CONDITION_READ_REGISTER_WITH_WRITE_STACK    : // l.jalr
	  case BRANCH_CONDITION_READ_STACK                        : // l.jr (rb==r9)
	    {
	      Taddress_t addr_good = PORT_READ(in_BRANCH_COMPLETE_ADDRESS [i]);
	      miss = ((take == 1) and
		      (addr_dest = addr_good));
	      take = 1;
	      addr_dest = addr_good;
	      break;
	    }
	  }

// 	log_printf(TRACE,Update_Prediction_Table,FUNCTION,"  * miss      : %d",miss);
// 	log_printf(TRACE,Update_Prediction_Table,FUNCTION,"  * take      : %d",take);
// 	log_printf(TRACE,Update_Prediction_Table,FUNCTION,"  * address   : %x",addr_dest);

	internal_BRANCH_COMPLETE_MISS_PREDICTION [i] = miss     ;
	internal_BRANCH_COMPLETE_TAKE            [i] = take     ;
	internal_BRANCH_COMPLETE_ADDRESS_DEST    [i] = addr_dest;

	PORT_WRITE(out_BRANCH_COMPLETE_MISS_PREDICTION [i], internal_BRANCH_COMPLETE_MISS_PREDICTION [i]);
	PORT_WRITE(out_BRANCH_COMPLETE_TAKE            [i], internal_BRANCH_COMPLETE_TAKE            [i]);
	PORT_WRITE(out_BRANCH_COMPLETE_ADDRESS_SRC     [i], reg_UPDATE_PREDICTION_TABLE [context][depth]._address_src);
	PORT_WRITE(out_BRANCH_COMPLETE_ADDRESS_DEST    [i], internal_BRANCH_COMPLETE_ADDRESS_DEST    [i]);
      }

    log_printf(FUNC,Update_Prediction_Table,FUNCTION,"End");
  };

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

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