#ifdef SYSTEMC /* * $Id: Branch_Target_Buffer_Register_transition.cpp 128 2009-06-26 08:43:23Z rosiere $ * * [ 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::transition" void Branch_Target_Buffer_Register::transition (void) { log_begin(Branch_Target_Buffer_Register,FUNCTION); log_function(Branch_Target_Buffer_Register,FUNCTION,_name.c_str()); if (PORT_READ(in_NRESET) == 0) { for (uint32_t i=0; i<_param->_size_bank; i++) for (uint32_t j=0; j<_param->_associativity; j++) { reg_BTB [i][j]._val = false; reg_BTB [i][j]._context = 0; // not necessary reg_BTB [i][j]._address_dest_val = 0; // not necessary reg_BTB [i][j]._address_src = 0; // not necessary reg_BTB [i][j]._address_dest = 0; // not necessary reg_BTB [i][j]._condition = 0; // not necessary reg_BTB [i][j]._last_take = 0; // not necessary reg_BTB [i][j]._accurate = 0; // not necessary } } else { if (not _param->_have_port_victim) { genMealy_decod (); genMealy_update (); } // ======================================================= // =====[ PREDICT ]======================================= // ======================================================= // ======================================================= // =====[ DECOD ]========================================= // ======================================================= for (uint32_t i=0; i<_param->_nb_inst_decod; i++) if (PORT_READ(in_DECOD_VAL [i]) and internal_DECOD_ACK [i]) { bool hit = internal_DECOD_HIT [i]; // uint32_t num_bank = internal_DECOD_NUM_BANK [i]; // uint32_t num_entry = (hit)?internal_DECOD_NUM_ENTRY [i]:((_param->_have_port_victim)?PORT_READ(in_DECOD_VICTIM [i]):0); // detect new branch !!! insert in branch target buffer if (not hit) { // =====[ Miss Case ] uint32_t num_bank = internal_DECOD_NUM_BANK [i]; uint32_t num_entry = (_param->_have_port_victim)?PORT_READ(in_DECOD_VICTIM [i]):0; // dest_val if not jr or jalr Tbranch_condition_t cond = PORT_READ(in_DECOD_CONDITION [i]); bool dest_val = not ((cond == BRANCH_CONDITION_READ_REGISTER_WITHOUT_WRITE_STACK) or (cond == BRANCH_CONDITION_READ_REGISTER_WITH_WRITE_STACK ) or (cond == BRANCH_CONDITION_READ_STACK )); reg_BTB[num_bank][num_entry]._val = 1; reg_BTB[num_bank][num_entry]._context = (_param->_have_port_context_id)?PORT_READ(in_DECOD_CONTEXT_ID [i]):0; reg_BTB[num_bank][num_entry]._address_src = PORT_READ(in_DECOD_ADDRESS_SRC [i]); reg_BTB[num_bank][num_entry]._address_dest = PORT_READ(in_DECOD_ADDRESS_DEST [i]); reg_BTB[num_bank][num_entry]._address_dest_val = dest_val; reg_BTB[num_bank][num_entry]._condition = cond; reg_BTB[num_bank][num_entry]._last_take = PORT_READ(in_DECOD_LAST_TAKE [i]); reg_BTB[num_bank][num_entry]._accurate = (PORT_READ(in_DECOD_IS_ACCURATE [i]))?_param->_first_accurate_if_hit:_param->_first_accurate_if_miss; } // else (hit) : no update -> it's not the last result of the branch } // ======================================================= // =====[ UPDATE ]========================================= // ======================================================= for (uint32_t i=0; i<_param->_nb_inst_update; i++) if (PORT_READ(in_UPDATE_VAL [i]) and internal_UPDATE_ACK [i]) { log_printf(TRACE,Branch_Target_Buffer_Register,FUNCTION," * UPDATE [%d]",i); bool hit = internal_UPDATE_HIT [i]; uint32_t num_bank = internal_UPDATE_NUM_BANK [i]; uint32_t num_entry = (hit)?internal_UPDATE_NUM_ENTRY [i]:((_param->_have_port_victim)?PORT_READ(in_UPDATE_VICTIM [i]):0); bool miss_pred = PORT_READ(in_UPDATE_MISS_PREDICTION [i]); // detect new branch !!! insert in branch target buffer log_printf(TRACE,Branch_Target_Buffer_Register,FUNCTION," * hit : %d",hit); log_printf(TRACE,Branch_Target_Buffer_Register,FUNCTION," * miss_pred : %d",miss_pred); log_printf(TRACE,Branch_Target_Buffer_Register,FUNCTION," * num_bank : %d",num_bank ); log_printf(TRACE,Branch_Target_Buffer_Register,FUNCTION," * num_entry : %d",num_entry); Tcounter_t accurate_new = 0; if (hit) { // =====[ Hit Case ] // * Have destination // * if cond == read_register or read_stack : destination valid in commit stage // * if cond != read_register or read_stack : destination valid in decod stage // * in all case : is valid in this step Tcounter_t accurate_old = reg_BTB[num_bank][num_entry]._accurate; log_printf(TRACE,Branch_Target_Buffer_Register,FUNCTION," * accurate_old : %d",accurate_old); // hit : increase accurate // miss : decrease accurate accurate_new = (miss_pred)?((accurate_old>0)?(accurate_old-1):accurate_old):((accurate_old<_param->_accurate_max)?(accurate_old+1):accurate_old); // test if accurate go to the threshold if ((accurate_old >= _param->_accurate_limit) and (accurate_new < _param->_accurate_limit)) { log_printf(TRACE,Branch_Target_Buffer_Register,FUNCTION," * decrease downto the accurate_limid (%d)",_param->_accurate_limit); accurate_new = 0; } //reg_BTB[num_bank][num_entry]._val : no update because hit //reg_BTB[num_bank][num_entry]._context : no update because hit //reg_BTB[num_bank][num_entry]._address_src : no update because hit //reg_BTB[num_bank][num_entry]._condition : no update because hit } else { // =====[ Miss Case ] //reg_BTB[num_bank][num_entry]._val = 1; //reg_BTB[num_bank][num_entry]._context = (_param->_have_port_context_id)?PORT_READ(in_UPDATE_CONTEXT_ID [i]):0; //reg_BTB[num_bank][num_entry]._address_src = PORT_READ(in_UPDATE_ADDRESS_SRC [i]); //reg_BTB[num_bank][num_entry]._condition = PORT_READ(in_UPDATE_CONDITION [i]); accurate_new = (miss_pred)?_param->_first_accurate_if_miss:_param->_first_accurate_if_hit; // reg_BTB[num_bank][num_entry]._val = 1; // reg_BTB[num_bank][num_entry]._context = (_param->_have_port_context_id)?PORT_READ(in_UPDATE_CONTEXT_ID [i]):0; // reg_BTB[num_bank][num_entry]._address_src = PORT_READ(in_UPDATE_ADDRESS_SRC [i]); // reg_BTB[num_bank][num_entry]._condition = PORT_READ(in_UPDATE_CONDITION [i]); // reg_BTB[num_bank][num_entry]._last_take = PORT_READ(in_UPDATE_LAST_TAKE [i]); // reg_BTB[num_bank][num_entry]._address_dest_val = 0; } // =====[ All Case ] // if (reg_BTB[num_bank][num_entry]._address_dest_val == 0) // { // reg_BTB[num_bank][num_entry]._address_dest_val = 1; // reg_BTB[num_bank][num_entry]._address_dest = PORT_READ(in_UPDATE_ADDRESS_DEST [i]); // } log_printf(TRACE,Branch_Target_Buffer_Register,FUNCTION," * accurate_new : %d",accurate_new); reg_BTB[num_bank][num_entry]._val = 1; reg_BTB[num_bank][num_entry]._context = (_param->_have_port_context_id)?PORT_READ(in_UPDATE_CONTEXT_ID [i]):0; reg_BTB[num_bank][num_entry]._address_src = PORT_READ(in_UPDATE_ADDRESS_SRC [i]); reg_BTB[num_bank][num_entry]._condition = PORT_READ(in_UPDATE_CONDITION [i]); reg_BTB[num_bank][num_entry]._last_take = PORT_READ(in_UPDATE_LAST_TAKE [i]); reg_BTB[num_bank][num_entry]._address_dest_val = 1; reg_BTB[num_bank][num_entry]._address_dest = PORT_READ(in_UPDATE_ADDRESS_DEST [i]); reg_BTB[num_bank][num_entry]._accurate = accurate_new; } #if (DEBUG >= DEBUG_TRACE) and DEBUG_Branch_Target_Buffer_Register log_printf(TRACE,Branch_Target_Buffer_Register,FUNCTION," * Dump BTB"); for (uint32_t i=0; i<_param->_size_bank; i++) for (uint32_t j=0; j<_param->_associativity; j++) log_printf(TRACE,Branch_Target_Buffer_Register,FUNCTION," [%.4d][%.4d] %d - %.4d %.8x (%.8x) %.1d %.8x (%.8x) %.3d %.1d %.4d", i,j, reg_BTB [i][j]._val , reg_BTB [i][j]._context , reg_BTB [i][j]._address_src , reg_BTB [i][j]._address_src <<2, reg_BTB [i][j]._address_dest_val, reg_BTB [i][j]._address_dest , reg_BTB [i][j]._address_dest<<2 , reg_BTB [i][j]._condition , reg_BTB [i][j]._last_take , reg_BTB [i][j]._accurate ); #endif } #if defined(STATISTICS) or defined(VHDL_TESTBENCH) end_cycle (); #endif log_end(Branch_Target_Buffer_Register,FUNCTION); }; }; // 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