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

#include "Behavioural/Core/Multi_Front_end/Front_end/Prediction_unit/Branch_Target_Buffer/Branch_Target_Buffer_Register/include/Branch_Target_Buffer_Register.h"

namespace morpheo                    {
namespace behavioural {
namespace core {
namespace multi_front_end {
namespace front_end {
namespace prediction_unit {
namespace branch_target_buffer {
namespace branch_target_buffer_register {

#undef  FUNCTION
#define FUNCTION "Branch_Target_Buffer_Register::genMealy_predict"
  void Branch_Target_Buffer_Register::genMealy_predict (void)
  {
    log_printf(FUNC,Branch_Target_Buffer_Register,FUNCTION,"Begin");

    for (uint32_t i=0; i<_param->_nb_inst_predict; i++)
      {
	Tcontext_t      context   = (_param->_have_port_context_id)?PORT_READ(in_PREDICT_CONTEXT_ID  [i]):0;
	Tgeneral_data_t address   = PORT_READ(in_PREDICT_ADDRESS [i]);
	uint32_t        num_bank  = (address>>_param->_shift_bank)&_param->_mask_bank;

	Tgeneral_data_t address_tag    =  address >> _param->_shift_tag    ;
	Tgeneral_data_t address_offset = (address >> _param->_shift_offset)&_param->_mask_offset;

// 	log_printf(TRACE,Branch_Target_Buffer_Register,FUNCTION,"address_    (tag, bank, offset) : %.8x %.8x %.8x",address_tag,num_bank, address_offset);

	for (uint32_t j=0; j<_param->_associativity; j++)
	  {
	    Tgeneral_data_t address_src_tag    =  reg_BTB[num_bank][j]._address_src >> _param->_shift_tag    ;
	    Tgeneral_data_t address_src_offset = (reg_BTB[num_bank][j]._address_src >> _param->_shift_offset)&_param->_mask_offset;

	    Tcontrol_t hit = ((reg_BTB[num_bank][j]._val         == 1             ) and
			      (reg_BTB[num_bank][j]._context     == context       ) and
			      (address_src_tag                   == address_tag   ) and
			      //address_bank is the same
			      (address_src_offset                >= address_offset));

// 	    log_printf(TRACE,Branch_Target_Buffer_Register,FUNCTION,"address_src (tag, bank, offset) : %.8x %.8x %.8x - hit : %d",address_src_tag,num_bank,address_src_offset, hit);

	    // Hit :
	    //  * entry is valid
	    //  * context is the same
	    //  * address_src must be higher that the address, because the address lower is previous the current pc.
	    PORT_WRITE(out_PREDICT_HIT          [i][j],hit);
	    PORT_WRITE(out_PREDICT_ADDRESS_SRC  [i][j],reg_BTB[num_bank][j]._address_src );
	    PORT_WRITE(out_PREDICT_ADDRESS_DEST [i][j],reg_BTB[num_bank][j]._address_dest);
	    PORT_WRITE(out_PREDICT_CONDITION    [i][j],reg_BTB[num_bank][j]._condition   );
	    PORT_WRITE(out_PREDICT_LAST_TAKE    [i][j],reg_BTB[num_bank][j]._last_take   );
	    PORT_WRITE(out_PREDICT_IS_ACCURATE  [i][j],((reg_BTB[num_bank][j]._accurate >= _param->_accurate_limit) and
							(reg_BTB[num_bank][j]._address_dest_val == 1)));
	  }
      }

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

}; // end namespace branch_target_buffer_register
}; // end namespace branch_target_buffer
}; // end namespace prediction_unit
}; // end namespace front_end
}; // end namespace multi_front_end
}; // end namespace core

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