#ifdef SYSTEMC /* * $Id: Update_Prediction_Table_transition.cpp 82 2008-05-01 16:48:45Z rosiere $ * * [ 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::transition" void Update_Prediction_Table::transition (void) { log_printf(FUNC,Update_Prediction_Table,FUNCTION,"Begin"); if (PORT_READ(in_NRESET) == 0) { for (uint32_t i=0; i<_param->_nb_context; i++) { reg_TOP [i] = 0; reg_BOTTOM [i] = 0; reg_NB_ELT [i] = 0; reg_NB_ELT_UPDATE [i] = 0; reg_NB_ELT_NEED_UPDATE [i] = 0; for (uint32_t j=0; j<_param->_size_queue[i]; j++) reg_UPDATE_PREDICTION_TABLE [i][j]._state = UPDATE_PREDICTION_STATE_EMPTY; } reg_UPDATE_PRIORITY = 0; } else { // =================================================================== // =====[ PREDICT ]=================================================== // =================================================================== for (uint32_t i=0; i<_param->_nb_inst_predict; i++) if (PORT_READ(in_PREDICT_VAL[i]) and internal_PREDICT_ACK [i]) { Tcontext_t context = (_param->_have_port_context_id)?PORT_READ(in_PREDICT_CONTEXT_ID [i]):0; uint32_t top = reg_TOP [context]; log_printf(TRACE,Update_Prediction_Table,FUNCTION,"PREDICT[%d] - Accepted",i); log_printf(TRACE,Update_Prediction_Table,FUNCTION," * context : %d",context); log_printf(TRACE,Update_Prediction_Table,FUNCTION," * top : %d",top); log_printf(TRACE,Update_Prediction_Table,FUNCTION," * nb_elt : %d",reg_NB_ELT[context]); reg_UPDATE_PREDICTION_TABLE [context][top]._state = UPDATE_PREDICTION_STATE_WAIT_DECOD; reg_UPDATE_PREDICTION_TABLE [context][top]._ifetch_prediction = true; reg_UPDATE_PREDICTION_TABLE [context][top]._condition = PORT_READ(in_PREDICT_BTB_CONDITION [i]); reg_UPDATE_PREDICTION_TABLE [context][top]._address_src = PORT_READ(in_PREDICT_BTB_ADDRESS_SRC [i]); reg_UPDATE_PREDICTION_TABLE [context][top]._address_dest = PORT_READ(in_PREDICT_BTB_ADDRESS_DEST [i]); reg_UPDATE_PREDICTION_TABLE [context][top]._last_take = PORT_READ(in_PREDICT_BTB_LAST_TAKE [i]); //reg_UPDATE_PREDICTION_TABLE [context][top]._good_take reg_UPDATE_PREDICTION_TABLE [context][top]._history = (_param->_have_port_history)?PORT_READ(in_PREDICT_DIR_HISTORY [i]):0; reg_UPDATE_PREDICTION_TABLE [context][top]._address_ras = PORT_READ(in_PREDICT_RAS_ADDRESS [i]); reg_UPDATE_PREDICTION_TABLE [context][top]._index_ras = PORT_READ(in_PREDICT_RAS_INDEX [i]); reg_TOP [context] = (top+1)%_param->_size_queue [context]; reg_NB_ELT [context] ++; } // =================================================================== // =====[ DECOD ]===================================================== // =================================================================== for (uint32_t i=0; i<_param->_nb_inst_decod; i++) if (PORT_READ(in_DECOD_VAL[i]) and internal_DECOD_ACK [i]) { Tcontext_t context = (_param->_have_port_context_id)?PORT_READ(in_DECOD_CONTEXT_ID [i]):0; Tcontrol_t miss_ifetch = PORT_READ(in_DECOD_MISS_IFETCH [i]); Tcontrol_t miss_decod = PORT_READ(in_DECOD_MISS_DECOD [i]); log_printf(TRACE,Update_Prediction_Table,FUNCTION,"DECOD[%d] - Accepted",i); log_printf(TRACE,Update_Prediction_Table,FUNCTION," * context : %d",context); log_printf(TRACE,Update_Prediction_Table,FUNCTION," * miss_ifetch : %d",miss_ifetch); log_printf(TRACE,Update_Prediction_Table,FUNCTION," * miss_decod : %d",miss_decod); log_printf(TRACE,Update_Prediction_Table,FUNCTION," * nb_elt : %d",reg_NB_ELT[context]); // Test if miss ifetch // miss ifetch = decod a branch and the predict unit have not predict this branch ... gloup :P if (miss_ifetch or miss_decod) { Tdepth_t depth = (_param->_have_port_max_depth)?PORT_READ(in_DECOD_UPDATE_PREDICTION_ID [i]):0; Tdepth_t top = reg_TOP [context]; reg_UPDATE_PREDICTION_TABLE [context][top]._state = UPDATE_PREDICTION_STATE_WAITEND; reg_UPDATE_PREDICTION_TABLE [context][top]._ifetch_prediction = false; // static prediction reg_UPDATE_PREDICTION_TABLE [context][top]._condition = PORT_READ(in_DECOD_BTB_CONDITION [i]); reg_UPDATE_PREDICTION_TABLE [context][top]._address_src = PORT_READ(in_DECOD_BTB_ADDRESS_SRC [i]); reg_UPDATE_PREDICTION_TABLE [context][top]._address_dest = PORT_READ(in_DECOD_BTB_ADDRESS_DEST [i]); reg_UPDATE_PREDICTION_TABLE [context][top]._last_take = PORT_READ(in_DECOD_BTB_LAST_TAKE [i]); //reg_UPDATE_PREDICTION_TABLE [context][top]._good_take //reg_UPDATE_PREDICTION_TABLE [context][top]._history reg_UPDATE_PREDICTION_TABLE [context][top]._address_ras = PORT_READ(in_DECOD_RAS_ADDRESS [i]); reg_UPDATE_PREDICTION_TABLE [context][top]._index_ras = PORT_READ(in_DECOD_RAS_INDEX [i]); // Invalid all previous "ifetch" prediction // (ifetch prediction = prediction make in fetch stage and not again comming in decod stage) uint32_t nb_elt_miss = ((top> depth)?top:(top+_param->_size_queue[context]))-depth; uint32_t nb_elt_need_update = 0; for (uint32_t j=0; j_size_queue[context]; // Ifetch have make a prediction and it's a miss // When ifetch predict : // * btb is not change -> needn't update // * direction is not change -> needn't update // * ras have change -> need update Tbranch_condition_t cond = reg_UPDATE_PREDICTION_TABLE [context][k]._condition; if ((cond == BRANCH_CONDITION_NONE_WITH_WRITE_STACK) or (cond == BRANCH_CONDITION_READ_REGISTER_WITH_WRITE_STACK) or (cond == BRANCH_CONDITION_READ_STACK)) { nb_elt_need_update ++; reg_UPDATE_PREDICTION_TABLE [context][k]._state = UPDATE_PREDICTION_STATE_KO; } else { reg_UPDATE_PREDICTION_TABLE [context][k]._state = UPDATE_PREDICTION_STATE_END; } } reg_UPDATE_PREDICTION_TABLE [context][depth]._state = UPDATE_PREDICTION_STATE_EVENT; // rewrite reg_TOP [context] = (depth+1)%_param->_size_queue [context]; reg_NB_ELT_NEED_UPDATE [context] += nb_elt_need_update; reg_NB_ELT [context] ++; } else { // Normal case : branch is previous predicated, change state of branch Tdepth_t depth = (_param->_have_port_max_depth)?PORT_READ(in_DECOD_UPDATE_PREDICTION_ID [i]):0; reg_UPDATE_PREDICTION_TABLE [context][depth]._state = UPDATE_PREDICTION_STATE_WAITEND; } } // =================================================================== // =====[ BRANCH_COMPLETE ]=========================================== // =================================================================== for (uint32_t i=0; i<_param->_nb_inst_branch_complete; i++) if (PORT_READ(in_BRANCH_COMPLETE_VAL[i]) and internal_BRANCH_COMPLETE_ACK [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; log_printf(TRACE,Update_Prediction_Table,FUNCTION,"BRANCH_COMPLETE[%d] - Accepted",i); log_printf(TRACE,Update_Prediction_Table,FUNCTION," * context : %d",context); log_printf(TRACE,Update_Prediction_Table,FUNCTION," * depth : %d",depth); log_printf(TRACE,Update_Prediction_Table,FUNCTION," * nb_elt : %d",reg_NB_ELT[context]); if (internal_BRANCH_COMPLETE_MISS_PREDICTION [i]) { // Miss case reg_UPDATE_PREDICTION_TABLE [context][depth]._state = UPDATE_PREDICTION_STATE_EVENT; // Another prediction (prediction with depth higer) Tdepth_t top = reg_TOP [context]; uint32_t nb_elt_miss = ((top> depth)?top:(top+_param->_size_queue[context]))-depth; uint32_t nb_elt_need_update = 1; for (uint32_t j=1; j_size_queue[context]; // Ifetch have make a prediction and it's a miss // When ifetch predict : // * btb is not change -> needn't update // * direction is not change -> needn't update // * ras have change -> need update Tbranch_condition_t cond = reg_UPDATE_PREDICTION_TABLE [context][k]._condition; if ((cond == BRANCH_CONDITION_NONE_WITH_WRITE_STACK) or (cond == BRANCH_CONDITION_READ_REGISTER_WITH_WRITE_STACK) or (cond == BRANCH_CONDITION_READ_STACK)) { nb_elt_need_update ++; reg_UPDATE_PREDICTION_TABLE [context][k]._state = UPDATE_PREDICTION_STATE_KO; } else { reg_UPDATE_PREDICTION_TABLE [context][k]._state = UPDATE_PREDICTION_STATE_END; } } reg_NB_ELT_NEED_UPDATE [context] += nb_elt_need_update; // Update pointer : reg_TOP [context] = depth; reg_NB_ELT [context] -= nb_elt_miss; } else { // Hit case #ifdef DEBUG_TEST if (reg_UPDATE_PREDICTION_TABLE [context][depth]._state != UPDATE_PREDICTION_STATE_WAITEND) ERRORMORPHEO(FUNCTION,"Branche complete : invalid state"); #endif reg_UPDATE_PREDICTION_TABLE [context][depth]._state = UPDATE_PREDICTION_STATE_OK; } // In all case : update good_take and address_destination reg_UPDATE_PREDICTION_TABLE [context][depth]._good_take = internal_BRANCH_COMPLETE_TAKE [i]; reg_UPDATE_PREDICTION_TABLE [context][depth]._address_dest = internal_BRANCH_COMPLETE_ADDRESS_DEST [i]; } // =================================================================== // =====[ UPDATE ]==================================================== // =================================================================== for (uint32_t i=0; i<_param->_nb_inst_update; i++) if (internal_UPDATE_VAL[i] and PORT_READ(in_UPDATE_ACK [i])) { Tcontext_t context = internal_UPDATE_CONTEXT_ID [i]; Tdepth_t depth = internal_UPDATE_DEPTH [i]; log_printf(TRACE,Update_Prediction_Table,FUNCTION,"UPDATE[%d] - Accepted",i); log_printf(TRACE,Update_Prediction_Table,FUNCTION," * context : %d",context); log_printf(TRACE,Update_Prediction_Table,FUNCTION," * depth : %d",depth); if (reg_UPDATE_PREDICTION_TABLE [context][depth]._state == UPDATE_PREDICTION_STATE_KO) reg_NB_ELT_NEED_UPDATE [context] --; reg_UPDATE_PREDICTION_TABLE [context][depth]._state = UPDATE_PREDICTION_STATE_END; } // Round robin reg_UPDATE_PRIORITY = (reg_UPDATE_PRIORITY+1)%_param->_nb_context; // =================================================================== // =====[ BRANCH_EVENT ]============================================== // =================================================================== for (uint32_t i=0; i<_param->_nb_context; i++) if (internal_BRANCH_EVENT_VAL [i] and PORT_READ(in_BRANCH_EVENT_ACK [i])) { Tdepth_t depth = internal_BRANCH_EVENT_DEPTH [i]; reg_UPDATE_PREDICTION_TABLE [i][depth]._state = UPDATE_PREDICTION_STATE_KO; } // =================================================================== // =====[ GARBAGE COLLECTOR ]========================================= // =================================================================== for (uint32_t i=0; i<_param->_nb_context; i++) { uint32_t bottom = reg_BOTTOM [i]; // Test if the tail of queue is finish (ok or ko and update) if (reg_UPDATE_PREDICTION_TABLE [i][bottom]._state == UPDATE_PREDICTION_STATE_END) { log_printf(TRACE,Update_Prediction_Table,FUNCTION,"GARBAGE_COLLECTOR"); log_printf(TRACE,Update_Prediction_Table,FUNCTION," * context : %d",i); log_printf(TRACE,Update_Prediction_Table,FUNCTION," * bottom : %d",bottom); reg_UPDATE_PREDICTION_TABLE [i][bottom]._state = UPDATE_PREDICTION_STATE_EMPTY; reg_BOTTOM [i] = (bottom+1)%_param->_size_queue [i]; if (reg_NB_ELT [i]>0) reg_NB_ELT [i] --; } } } #if (DEBUG >= DEBUG_TRACE) log_printf(TRACE,Update_Prediction_Table,FUNCTION,"Dump Update_Prediction_Table"); log_printf(TRACE,Update_Prediction_Table,FUNCTION," * reg_UPDATE_PRIORITY : %d",reg_UPDATE_PRIORITY); for (uint32_t i=0; i<_param->_nb_context; i++) { log_printf(TRACE,Update_Prediction_Table,FUNCTION," * Update_Prediction_Table [%d]",i); log_printf(TRACE,Update_Prediction_Table,FUNCTION," * reg_TOP : %d",reg_TOP [i]); log_printf(TRACE,Update_Prediction_Table,FUNCTION," * reg_BOTTOM : %d",reg_BOTTOM [i]); log_printf(TRACE,Update_Prediction_Table,FUNCTION," * reg_NB_ELT : %d",reg_NB_ELT [i]); log_printf(TRACE,Update_Prediction_Table,FUNCTION," * reg_NB_ELT_NEED_UPDATE : %d",reg_NB_ELT_NEED_UPDATE [i]); for (uint32_t j=0; j<_param->_size_queue[i]; j++) log_printf(TRACE,Update_Prediction_Table,FUNCTION," [%d] %s %x",j,toString(reg_UPDATE_PREDICTION_TABLE [i][j]._state).c_str(),reg_UPDATE_PREDICTION_TABLE [i][j]._address_src); } #endif #if defined(STATISTICS) or defined(VHDL_TESTBENCH) end_cycle (); #endif 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