#ifdef SYSTEMC /* * $Id: Return_Address_Stack_transition.cpp 111 2009-02-27 18:37:40Z rosiere $ * * [ Description ] * */ #include "Behavioural/Core/Multi_Front_end/Front_end/Prediction_unit/Return_Address_Stack/include/Return_Address_Stack.h" namespace morpheo { namespace behavioural { namespace core { namespace multi_front_end { namespace front_end { namespace prediction_unit { namespace return_address_stack { #undef FUNCTION #define FUNCTION "Return_Address_Stack::transition" void Return_Address_Stack::transition (void) { log_begin(Return_Address_Stack,FUNCTION); log_function(Return_Address_Stack,FUNCTION,_name.c_str()); if (PORT_READ(in_NRESET)==0) { // Reset all structure for (uint32_t i=0; i<_param->_nb_context; i++) { reg_TOP [i] = 0; // reg_BOTTOM [i] = 0; reg_NB_ELT [i] = 0; reg_PREDICT_TOP [i] = 0; // reg_PREDICT_BOTTOM [i] = 0; reg_PREDICT_NB_ELT [i] = 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]) { log_printf(TRACE,Return_Address_Stack,FUNCTION," * PREDICT [%d] : Transaction",i); // Read information and pointer Tcontext_t context = (_param->_have_port_context_id)?PORT_READ(in_PREDICT_CONTEXT_ID [i]):0; Tcontrol_t push = PORT_READ(in_PREDICT_PUSH [i]); Tptr_t top_old = reg_PREDICT_TOP [context]; Tptr_t top_new = top_old; // Tptr_t bottom_old = reg_PREDICT_BOTTOM [context]; // Tptr_t bottom_new = bottom_old; Tptr_t nb_elt_old = reg_PREDICT_NB_ELT [context]; Tptr_t nb_elt_new = nb_elt_old; log_printf(TRACE,Return_Address_Stack,FUNCTION," * context : %d",context); // Hit : push or not empty // Miss : ifetch is stall, no update // Test if hit if (internal_PREDICT_HIT [i]) { log_printf(TRACE,Return_Address_Stack,FUNCTION," * before"); log_printf(TRACE,Return_Address_Stack,FUNCTION," * reg_predict_top : %d",top_old); // log_printf(TRACE,Return_Address_Stack,FUNCTION," * reg_predict_bottom : %d",bottom_old); log_printf(TRACE,Return_Address_Stack,FUNCTION," * reg_predict_nb_elt : %d",nb_elt_old); // Test if push if (push) { Taddress_t address = PORT_READ(in_PREDICT_ADDRESS_PUSH [i]); log_printf(TRACE,Return_Address_Stack,FUNCTION," * push (call procedure)"); log_printf(TRACE,Return_Address_Stack,FUNCTION," * address_push : 0x%.8x",address); // push : increase the top (circular) top_new = (top_old+1)%_param->_size_queue[context]; // Write new value in Queue reg_stack [context][top_new]._address = address; // Test if full // -> is full, the push erase the oldest value in stack, also nb_elt is the same // -> is not full, increase nb_elt // if (nb_elt_old==_param->_size_queue[context]) // bottom_new = (bottom_old+1)%_param->_size_queue[context]; // else // nb_elt_new ++; if (nb_elt_old!=_param->_size_queue[context]) nb_elt_new ++; } else { // pop log_printf(TRACE,Return_Address_Stack,FUNCTION," * pop (return procedure)"); // Test if the stack is empty if (nb_elt_old>0) { top_new = (top_old==0)?(_param->_size_queue[context]-1):(top_old-1); nb_elt_new --; } // no else : can't pop } // Write new pointer reg_PREDICT_TOP [context] = top_new; // reg_PREDICT_BOTTOM [context] = bottom_new; reg_PREDICT_NB_ELT [context] = nb_elt_new; log_printf(TRACE,Return_Address_Stack,FUNCTION," * after"); log_printf(TRACE,Return_Address_Stack,FUNCTION," * reg_predict_top : %d",top_new); // log_printf(TRACE,Return_Address_Stack,FUNCTION," * reg_predict_bottom : %d",bottom_new); log_printf(TRACE,Return_Address_Stack,FUNCTION," * reg_predict_nb_elt : %d",nb_elt_new); } } // =================================================================== // =====[ DECOD ]===================================================== // =================================================================== for (uint32_t i=0; i<_param->_nb_inst_decod; i++) if (PORT_READ(in_DECOD_VAL [i]) and internal_DECOD_ACK [i]) { log_printf(TRACE,Return_Address_Stack,FUNCTION," * DECOD [%d] : Transaction",i); // Read information Tcontext_t context = (_param->_have_port_context_id)?PORT_READ(in_DECOD_CONTEXT_ID [i]):0; Tcontrol_t push = PORT_READ(in_DECOD_PUSH [i]); // Read pointer Tptr_t top_old = reg_TOP [context]; Tptr_t top_new = top_old; // Tptr_t bottom_old = reg_BOTTOM [context]; // Tptr_t bottom_new = bottom_old; Tptr_t nb_elt_old = reg_NB_ELT [context]; Tptr_t nb_elt_new = nb_elt_old; log_printf(TRACE,Return_Address_Stack,FUNCTION," * context : %d",context); log_printf(TRACE,Return_Address_Stack,FUNCTION," * before"); log_printf(TRACE,Return_Address_Stack,FUNCTION," * reg_predict_top : %d",top_old); // log_printf(TRACE,Return_Address_Stack,FUNCTION," * reg_predict_bottom : %d",bottom_old); log_printf(TRACE,Return_Address_Stack,FUNCTION," * reg_predict_nb_elt : %d",nb_elt_old); // Test if push if (push) { Taddress_t address = PORT_READ(in_DECOD_ADDRESS_PUSH [i]); log_printf(TRACE,Return_Address_Stack,FUNCTION," * push (call procedure)"); log_printf(TRACE,Return_Address_Stack,FUNCTION," * address_push : 0x%.8x",address); // push : increase the top (circular) top_new = (top_old+1)%_param->_size_queue[context]; // Write new value in Queue reg_stack [context][top_new]._address = address; // Test if full // -> is full, the push erase the oldest value in stack, also nb_elt is the same // -> is not full, increase nb_elt // if (nb_elt_old==_param->_size_queue[context]) // bottom_new = (bottom_old+1)%_param->_size_queue[context]; // else // nb_elt_new ++; if (nb_elt_old!=_param->_size_queue[context]) nb_elt_new ++; } else { // pop log_printf(TRACE,Return_Address_Stack,FUNCTION," * pop (return procedure)"); // Test if the stack is empty if (nb_elt_old>0) { top_new = (top_old==0)?(_param->_size_queue[context]-1):(top_old-1); nb_elt_new --; } // no else : can't pop } // Write new pointer reg_TOP [context] = top_new; // reg_BOTTOM [context] = bottom_new; reg_NB_ELT [context] = nb_elt_new; log_printf(TRACE,Return_Address_Stack,FUNCTION," * after"); log_printf(TRACE,Return_Address_Stack,FUNCTION," * reg_predict_top : %d",top_new); // log_printf(TRACE,Return_Address_Stack,FUNCTION," * reg_predict_bottom : %d",bottom_new); log_printf(TRACE,Return_Address_Stack,FUNCTION," * reg_predict_nb_elt : %d",nb_elt_new); // have previous miss of ifetch ? // 2 miss : // 1) miss predict : is very limited (local at context), can be update very quickly // 2) miss decod : result is in commit stage ... // manage by Update_Fetch_Prediction_Table and Update_Prediction_Table // Note : // if decod miss : ifetch can have predict call and return branchement. Also, the head of decod can be false Tcontrol_t miss = PORT_READ(in_DECOD_MISS_PREDICTION [i]); log_printf(TRACE,Return_Address_Stack,FUNCTION," * miss : %d",miss); if (miss) { // reg_PREDICT_BOTTOM [context] = reg_BOTTOM [context]; reg_PREDICT_TOP [context] = reg_TOP [context]; reg_PREDICT_NB_ELT [context] = reg_NB_ELT [context]; } } // =================================================================== // =====[ 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,Return_Address_Stack,FUNCTION," * UPDATE [%d] : Transaction",i); Tcontext_t context_id = (_param->_have_port_context_id)?PORT_READ(in_UPDATE_CONTEXT_ID [i]):0; Tcontrol_t flush = PORT_READ(in_UPDATE_FLUSH [i]); log_printf(TRACE,Return_Address_Stack,FUNCTION," * context_id : %d",context_id); log_printf(TRACE,Return_Address_Stack,FUNCTION," * flush : %d",flush ); // An miss prediction on call/return = Return Address Stack is corrupted. if (flush) { Tcontrol_t push = PORT_READ(in_UPDATE_PUSH [i]); Tptr_t value = (push)?1:0; // All pointer is set at 0 reg_TOP [context_id] = value; // reg_BOTTOM [context_id] = 0; reg_NB_ELT [context_id] = value; reg_PREDICT_TOP [context_id] = value; // reg_PREDICT_BOTTOM [context_id] = 0; reg_PREDICT_NB_ELT [context_id] = value; if (push) { // reinsert push value Taddress_t address = PORT_READ(in_UPDATE_ADDRESS [i]); log_printf(TRACE,Return_Address_Stack,FUNCTION," * flush and push"); log_printf(TRACE,Return_Address_Stack,FUNCTION," * address_push : 0x%.8x",address); reg_stack [context_id][value]._address = address; } } else { // if miss_prediction -> restore queue // else, the prediction is correct Tcontrol_t miss_prediction = PORT_READ(in_UPDATE_MISS_PREDICTION [i]); log_printf(TRACE,Return_Address_Stack,FUNCTION," * miss_prediction : %d",miss_prediction); #ifdef DEBUG_TEST Tptr_t index = PORT_READ(in_UPDATE_INDEX [i]); Tcontrol_t prediction_ifetch = PORT_READ(in_UPDATE_PREDICTION_IFETCH [i]); log_printf(TRACE,Return_Address_Stack,FUNCTION," * index : %d",index); log_printf(TRACE,Return_Address_Stack,FUNCTION," * prediction_ifetch : %d",prediction_ifetch); // if (prediction_ifetch) // { // if (index != reg_PREDICT_TOP [context_id]) // throw ERRORMORPHEO(FUNCTION,_("Index is different of predict_top")); // } // else // { // if (index != reg_TOP [context_id]) // throw ERRORMORPHEO(FUNCTION,_("Index is different of top")); // } #endif if (miss_prediction) { Tcontrol_t push = PORT_READ(in_UPDATE_PUSH [i]); log_printf(TRACE,Return_Address_Stack,FUNCTION," * push : %d",push); #ifndef DEBUG_TEST Tptr_t index = PORT_READ(in_UPDATE_INDEX [i]); Tcontrol_t prediction_ifetch = PORT_READ(in_UPDATE_PREDICTION_IFETCH [i]); log_printf(TRACE,Return_Address_Stack,FUNCTION," * index : %d",index); log_printf(TRACE,Return_Address_Stack,FUNCTION," * prediction_ifetch : %d",prediction_ifetch); #endif Tptr_t top_old = (prediction_ifetch)?reg_PREDICT_TOP [context_id]:reg_TOP [context_id]; Tptr_t top_new = top_old; // Tptr_t bottom_old = (prediction_ifetch)?reg_PREDICT_BOTTOM [context_id]:reg_BOTTOM [context_id]; // Tptr_t bottom_new = bottom_old; Tptr_t nb_elt_old = (prediction_ifetch)?reg_PREDICT_NB_ELT [context_id]:reg_NB_ELT [context_id]; Tptr_t nb_elt_new = nb_elt_old; log_printf(TRACE,Return_Address_Stack,FUNCTION," * before"); if (prediction_ifetch) { log_printf(TRACE,Return_Address_Stack,FUNCTION," * reg_predict_top : %d",top_old); // log_printf(TRACE,Return_Address_Stack,FUNCTION," * reg_predict_bottom : %d",bottom_old); log_printf(TRACE,Return_Address_Stack,FUNCTION," * reg_predict_nb_elt : %d",nb_elt_old); } else { log_printf(TRACE,Return_Address_Stack,FUNCTION," * reg_top : %d",top_old); // log_printf(TRACE,Return_Address_Stack,FUNCTION," * reg_bottom : %d",bottom_old); log_printf(TRACE,Return_Address_Stack,FUNCTION," * reg_nb_elt : %d",nb_elt_old); } // if previous is push, pop the value // else is previous is pop, push the poped value if (push) { log_printf(TRACE,Return_Address_Stack,FUNCTION," * previous is push, now pop"); // previous is push, now must be pop // Test if the stack is empty (if previous flush) if (nb_elt_old>0) { top_new = (top_old==0)?(_param->_size_queue[context_id]-1):(top_old-1); nb_elt_new --; } } else { log_printf(TRACE,Return_Address_Stack,FUNCTION," * previous is pop, now push"); // previous is pop, now must be push Taddress_t address = PORT_READ(in_UPDATE_ADDRESS [i]); log_printf(TRACE,Return_Address_Stack,FUNCTION," * address : 0x%.8x",address); // push : increase the top (circular) // if (nb_elt_old==_param->_size_queue[context_id]) // bottom_new = (bottom_old+1)%_param->_size_queue[context_id]; // else // nb_elt_new ++; if (nb_elt_old!=_param->_size_queue[context_id]) nb_elt_new ++; top_new = index; reg_stack [context_id][top_new]._address = address; } log_printf(TRACE,Return_Address_Stack,FUNCTION," * after"); if (prediction_ifetch) { log_printf(TRACE,Return_Address_Stack,FUNCTION," * reg_predict_top : %d",reg_TOP [context_id]); // log_printf(TRACE,Return_Address_Stack,FUNCTION," * reg_predict_bottom : %d",reg_BOTTOM [context_id]); log_printf(TRACE,Return_Address_Stack,FUNCTION," * reg_predict_nb_elt : %d",reg_NB_ELT [context_id]); reg_PREDICT_TOP [context_id] = reg_TOP [context_id]; // reg_PREDICT_BOTTOM [context_id] = reg_BOTTOM [context_id]; reg_PREDICT_NB_ELT [context_id] = reg_NB_ELT [context_id]; // log_printf(TRACE,Return_Address_Stack,FUNCTION," * reg_predict_top : %d",top_new ); // // log_printf(TRACE,Return_Address_Stack,FUNCTION," * reg_predict_bottom : %d",bottom_new); // log_printf(TRACE,Return_Address_Stack,FUNCTION," * reg_predict_nb_elt : %d",nb_elt_new); // reg_PREDICT_TOP [context_id] = top_new ; // // reg_PREDICT_BOTTOM [context_id] = bottom_new; // reg_PREDICT_NB_ELT [context_id] = nb_elt_new; } else { log_printf(TRACE,Return_Address_Stack,FUNCTION," * reg_top : %d",top_new); // log_printf(TRACE,Return_Address_Stack,FUNCTION," * reg_bottom : %d",bottom_new); log_printf(TRACE,Return_Address_Stack,FUNCTION," * reg_nb_elt : %d",nb_elt_new); reg_TOP [context_id] = top_new ; // reg_BOTTOM [context_id] = bottom_new; reg_NB_ELT [context_id] = nb_elt_new; reg_PREDICT_TOP [context_id] = top_new ; // reg_PREDICT_BOTTOM [context_id] = bottom_new; reg_PREDICT_NB_ELT [context_id] = nb_elt_new; } } } } } #if defined(DEBUG_Return_Address_Stack) and DEBUG>=DEBUG_TRACE log_printf(TRACE,Return_Address_Stack,FUNCTION," * Dump RAS"); for (uint32_t i=0; i<_param->_nb_context; ++i) { log_printf(TRACE,Return_Address_Stack,FUNCTION," * Return Address Stack [%d]",i); log_printf(TRACE,Return_Address_Stack,FUNCTION," * reg_TOP : %d",reg_TOP [i]); // log_printf(TRACE,Return_Address_Stack,FUNCTION," * reg_BOTTOM : %d",reg_BOTTOM [i]); log_printf(TRACE,Return_Address_Stack,FUNCTION," * reg_NB_ELT : %d",reg_NB_ELT [i]); log_printf(TRACE,Return_Address_Stack,FUNCTION," * reg_PREDICT_TOP : %d",reg_PREDICT_TOP [i]); // log_printf(TRACE,Return_Address_Stack,FUNCTION," * reg_PREDICT_BOTTOM : %d",reg_PREDICT_BOTTOM [i]); log_printf(TRACE,Return_Address_Stack,FUNCTION," * reg_PREDICT_NB_ELT : %d",reg_PREDICT_NB_ELT [i]); for (uint32_t j=0; j<_param->_size_queue[i]; ++j) log_printf(TRACE,Return_Address_Stack,FUNCTION," [%d] %.8x (%.8x)",j,reg_stack [i][j]._address,reg_stack [i][j]._address<<2); } #endif #if defined(STATISTICS) or defined(VHDL_TESTBENCH) end_cycle (); #endif log_end(Return_Address_Stack,FUNCTION); }; }; // end namespace return_address_stack }; // end namespace prediction_unit }; // end namespace front_end }; // end namespace multi_front_end }; // end namespace core }; // end namespace behavioural }; // end namespace morpheo #endif