#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::transition" void Branch_Target_Buffer_Register::transition (void) { log_printf(FUNC,Branch_Target_Buffer_Register,FUNCTION,"Begin"); 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; } else { // ======================================================= // =====[ 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 = _param->_first_accurate_if_hit; } // 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]) { 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 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; // hit : increase accurate // miss : decrease accurate Tcounter_t 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)) 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; } // =====[ All 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]); 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]._last_take = PORT_READ(in_UPDATE_LAST_TAKE [i]); reg_BTB[num_bank][num_entry]._accurate = accurate_new; } 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 - %.2d %.8x %.1d %.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_dest_val, reg_BTB [i][j]._address_dest , reg_BTB [i][j]._condition , reg_BTB [i][j]._last_take , reg_BTB [i][j]._accurate ); } #if defined(STATISTICS) or defined(VHDL_TESTBENCH) end_cycle (); #endif 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