#ifdef SYSTEMC /* * $Id$ * * [ 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::genMoore" void Update_Prediction_Table::genMoore (void) { log_begin(Update_Prediction_Table,FUNCTION); log_function(Update_Prediction_Table,FUNCTION,_name.c_str()); if (PORT_READ(in_NRESET) == 1) { // =================================================================== // =====[ DEPTH ]===================================================== // =================================================================== for (uint32_t i=0; i<_param->_nb_context; i++) { // is a valid instruction ? // If DEPTH_CURRENT : // equal at DEPTH_MIN -> not speculative // not include ]DEPTH_MIN:DEPTH_MAX] -> previous branch miss // include ]DEPTH_MIN:DEPTH_MAX] -> speculative uint32_t bottom = reg_UPT_BOTTOM [i]; uint32_t top = reg_UPT_TOP [i]; bool empty = reg_UPT_EMPTY [i]; // Depth_val is set when state is ok and the UPT[top] is empty PORT_WRITE(out_DEPTH_VAL [i],((reg_UPDATE_PREDICTION_TABLE [i][top]._state == UPDATE_PREDICTION_STATE_EMPTY) and (reg_UFPT_EVENT_STATE [i] == UFPT_EVENT_STATE_OK) and (reg_UPT_EVENT_STATE [i] == UPT_EVENT_STATE_OK) )); if (_param->_have_port_depth) { PORT_WRITE(out_DEPTH_CURRENT [i], top); PORT_WRITE(out_DEPTH_MIN [i], bottom); PORT_WRITE(out_DEPTH_MAX [i], top); } PORT_WRITE(out_DEPTH_FULL [i], not empty and (top == bottom)); } // =================================================================== // =====[ UPDATE ]==================================================== // =================================================================== { bool flush_ufpt [_param->_nb_context]; // event ufpt -> restore RAS, else update upt bool flush_upt [_param->_nb_context]; // event upt -> restore RAS, else restore others structure bool ufpt_can_update [_param->_nb_context]; bool upt_can_update [_param->_nb_context]; Tdepth_t tab_ufpt_depth [_param->_nb_context]; Tdepth_t tab_upt_depth [_param->_nb_context]; // Init for (uint32_t i=0; i<_param->_nb_context; i++) { ufpt_event_state_t ufpt_event_state = reg_UFPT_EVENT_STATE [i]; upt_event_state_t upt_event_state = reg_UPT_EVENT_STATE [i]; flush_ufpt [i] = (ufpt_event_state == UFPT_EVENT_STATE_KO_FLUSH); flush_upt [i] = ((upt_event_state == UPT_EVENT_STATE_KO_MISS_FLUSH_UPT) or (upt_event_state == UPT_EVENT_STATE_KO_EVENT_FLUSH_UPT)); ufpt_can_update [i] = true; upt_can_update [i] = true; tab_ufpt_depth [i] = reg_UFPT_UPDATE [i]; tab_upt_depth [i] = reg_UPT_UPDATE [i]; } for (uint32_t i=0; i<_param->_nb_inst_update; i++) { Tcontext_t context = (reg_UPDATE_PRIORITY+i)%_param->_nb_context; log_printf(TRACE,Update_Prediction_Table,FUNCTION," * UPDATE [%d] (genMoore)",i); log_printf(TRACE,Update_Prediction_Table,FUNCTION," * context : %d",context); log_printf(TRACE,Update_Prediction_Table,FUNCTION," * flush_ufpt : %d",flush_ufpt[context]); log_printf(TRACE,Update_Prediction_Table,FUNCTION," * flush_upt : %d",flush_upt [context]); Tcontrol_t val = false; Tcontrol_t val_without_ack = false; Tcontrol_t miss_prediction = 0; // not necessary init Tcontrol_t direction_good = 0; // not necessary init Tcontrol_t prediction_ifetch = 0; // not necessary init Tcontrol_t btb_val = 0; // not necessary init Taddress_t btb_address_src = 0; // not necessary init Taddress_t btb_address_dest = 0; // not necessary init Tbranch_condition_t btb_condition = 0; // not necessary init Tcontrol_t dir_val = 0; // not necessary init Thistory_t dir_history = 0; // not necessary init Tcontrol_t ras_val = 0; // not necessary init Tcontrol_t ras_flush = 0; // not necessary init Tcontrol_t ras_push = 0; // not necessary init Taddress_t ras_address = 0; // not necessary init Tptr_t ras_index = 0; // not necessary init // Test if update fetch prediction table need update port if (flush_ufpt [context]) { if (ufpt_can_update [context]) { // Update Fetch Prediction Table // An update of ufpt is to previous miss. Just restore Prediction_unit // Read information Tdepth_t depth = tab_ufpt_depth[context]; ufpt_state_t state = reg_UPDATE_FETCH_PREDICTION_TABLE [context][depth]._state; Tbranch_condition_t condition = reg_UPDATE_FETCH_PREDICTION_TABLE [context][depth]._condition; log_printf(TRACE,Update_Prediction_Table,FUNCTION," * Update Fetch Prediction Table"); log_printf(TRACE,Update_Prediction_Table,FUNCTION," * depth : %d",depth ); log_printf(TRACE,Update_Prediction_Table,FUNCTION," * state : %s",toString(state ).c_str()); log_printf(TRACE,Update_Prediction_Table,FUNCTION," * condition : %s",toString(condition).c_str()); val = (state == UPDATE_FETCH_PREDICTION_STATE_EVENT); // val_without_ack = not update_ras(condition); miss_prediction = 1; // need update, also previous miss // direction_good = ; prediction_ifetch = 1; btb_val = 0; // don't update btb (is update by the event branch) // btb_address_src = reg_UPDATE_PREDICTION_TABLE [context][depth]._address_src ; // btb_address_dest = reg_UPDATE_PREDICTION_TABLE [context][depth]._address_dest; // btb_condition = condition; dir_val = update_dir(condition); dir_history = reg_UPDATE_PREDICTION_TABLE [context][depth]._history; ras_val = update_ras(condition); // repop/ repush data -> don't corrupt ras ras_flush = 0; // no ras corruption ras_push = push_ras(condition); ras_address = reg_UPDATE_FETCH_PREDICTION_TABLE [context][depth]._address_ras; ras_index = reg_UPDATE_FETCH_PREDICTION_TABLE [context][depth]._index_ras; internal_UPDATE_FROM_UFPT [i] = true; internal_UPDATE_DEPTH [i] = depth; internal_UPDATE_RAS [i] = false; // Warning : don't update same entry if (depth == reg_UFPT_BOTTOM[context]) ufpt_can_update [context] = false; else // update pointer tab_ufpt_depth[context] = ((depth==0)?_param->_size_ufpt_queue[context]:depth)-1; } } else { if (upt_can_update [context]) { // Update Prediction Table // Read information Tdepth_t depth = tab_upt_depth[context]; upt_state_t state = reg_UPDATE_PREDICTION_TABLE [context][depth]._state; Tbranch_condition_t condition = reg_UPDATE_PREDICTION_TABLE [context][depth]._condition; Tcontrol_t ifetch = reg_UPDATE_PREDICTION_TABLE [context][depth]._ifetch_prediction; log_printf(TRACE,Update_Prediction_Table,FUNCTION," * Update Prediction Table"); log_printf(TRACE,Update_Prediction_Table,FUNCTION," * depth : %d",depth ); log_printf(TRACE,Update_Prediction_Table,FUNCTION," * state : %s",toString(state ).c_str()); log_printf(TRACE,Update_Prediction_Table,FUNCTION," * condition : %s",toString(condition).c_str()); // is the valid branch (valid branch hit, or valid branch miss) Tcontrol_t state_is_ok_ko = ((state == UPDATE_PREDICTION_STATE_OK ) or (state == UPDATE_PREDICTION_STATE_KO )); if (not flush_upt [context]) { // no event, just update predictor val = (state == UPDATE_PREDICTION_STATE_OK); val_without_ack = false; } else { // event, restore event (if need update) val = ( (state == UPDATE_PREDICTION_STATE_KO ) or ((state == UPDATE_PREDICTION_STATE_EVENT) and need_update(condition))); val_without_ack = ( (state == UPDATE_PREDICTION_STATE_EVENT) and not need_update(condition)); } miss_prediction = (state != UPDATE_PREDICTION_STATE_OK); direction_good = reg_UPDATE_PREDICTION_TABLE [context][depth]._good_take ; prediction_ifetch = ifetch; btb_val = state_is_ok_ko and update_btb(condition); btb_address_src = reg_UPDATE_PREDICTION_TABLE [context][depth]._address_src ; btb_address_dest = reg_UPDATE_PREDICTION_TABLE [context][depth]._address_dest; btb_condition = condition; dir_val = ifetch and update_dir(condition); // if not ifetch, then static prediction -> history is wrong dir_history = reg_UPDATE_PREDICTION_TABLE [context][depth]._history ; ras_val = update_ras(condition); // repop/ repush data -> don't corrupt ras ras_flush = (state == UPDATE_PREDICTION_STATE_KO); // miss prediction on RAS -> RAS is corrupted ras_push = push_ras(condition); // If corrupt, RAS must be flushed. // Also, if instruction l.jal, l.jalr, push addr+2 (delay slot), else (no flush) restore RAS ras_address = (ras_flush)?(reg_UPDATE_PREDICTION_TABLE [context][depth]._address_src+2):reg_UPDATE_PREDICTION_TABLE [context][depth]._address_ras; ras_index = reg_UPDATE_PREDICTION_TABLE [context][depth]._index_ras; internal_UPDATE_FROM_UFPT [i] = false; internal_UPDATE_DEPTH [i] = depth; internal_UPDATE_RAS [i] = flush_upt [context]; // Warning : don't update same entry if (flush_upt [context]) { // Stop condition if ((depth == reg_UPT_BOTTOM[context]) or not (val or val_without_ack)) upt_can_update [context] = false; // flush -> ptr is decrease tab_upt_depth[context] = (depth==0)?(_param->_size_upt_queue[context]-1):(depth-1); } else { // Stop condition if ((depth == reg_UPT_TOP [context]) or not (val or val_without_ack)) upt_can_update [context] = false; // flush -> ptr is increase tab_upt_depth[context] = (depth+1)%_param->_size_upt_queue[context]; } } } log_printf(TRACE,Update_Prediction_Table,FUNCTION," * val : %d",val ); log_printf(TRACE,Update_Prediction_Table,FUNCTION," * val_without_ack : %d",val_without_ack); log_printf(TRACE,Update_Prediction_Table,FUNCTION," * miss_prediction : %d",miss_prediction); log_printf(TRACE,Update_Prediction_Table,FUNCTION," * direction_good : %d",direction_good ); log_printf(TRACE,Update_Prediction_Table,FUNCTION," * btb_val : %d",btb_val); log_printf(TRACE,Update_Prediction_Table,FUNCTION," * dir_val : %d",dir_val); log_printf(TRACE,Update_Prediction_Table,FUNCTION," * ras_val : %d",ras_val); internal_UPDATE_VAL [i] = val; internal_UPDATE_VAL_WITHOUT_ACK [i] = val_without_ack; internal_UPDATE_CONTEXT_ID [i] = context; PORT_WRITE(out_UPDATE_VAL [i],internal_UPDATE_VAL [i]); if (val) { if (_param->_have_port_context_id) PORT_WRITE(out_UPDATE_CONTEXT_ID [i],context ); PORT_WRITE(out_UPDATE_MISS_PREDICTION [i],miss_prediction ); PORT_WRITE(out_UPDATE_DIRECTION_GOOD [i],direction_good ); PORT_WRITE(out_UPDATE_PREDICTION_IFETCH [i],prediction_ifetch ); PORT_WRITE(out_UPDATE_BTB_VAL [i],btb_val ); PORT_WRITE(out_UPDATE_BTB_ADDRESS_SRC [i],btb_address_src ); PORT_WRITE(out_UPDATE_BTB_ADDRESS_DEST [i],btb_address_dest ); PORT_WRITE(out_UPDATE_BTB_CONDITION [i],btb_condition ); PORT_WRITE(out_UPDATE_DIR_VAL [i],dir_val ); if (_param->_have_port_history) PORT_WRITE(out_UPDATE_DIR_HISTORY [i],dir_history ); PORT_WRITE(out_UPDATE_RAS_VAL [i],ras_val ); PORT_WRITE(out_UPDATE_RAS_FLUSH [i],ras_flush ); PORT_WRITE(out_UPDATE_RAS_PUSH [i],ras_push ); PORT_WRITE(out_UPDATE_RAS_ADDRESS [i],ras_address ); PORT_WRITE(out_UPDATE_RAS_INDEX [i],ras_index ); } } } // =================================================================== // =====[ BRANCH_EVENT ]============================================== // =================================================================== // For all context ... for (uint32_t i=0; i<_param->_nb_context; i++) { // ... send an event if upt must be update the context Tcontrol_t val = ((reg_UPT_EVENT_STATE [i] == UPT_EVENT_STATE_KO_DECODE_UPDATE_CONTEXT) or (reg_UPT_EVENT_STATE [i] == UPT_EVENT_STATE_KO_COMMIT_UPDATE_CONTEXT)); PORT_WRITE(out_BRANCH_EVENT_VAL [i],val); if (_param->_have_port_depth) PORT_WRITE(out_BRANCH_EVENT_DEPTH [i],reg_EVENT_DEPTH [i]); PORT_WRITE(out_BRANCH_EVENT_ADDRESS_SRC [i],reg_EVENT_ADDRESS_SRC [i]); PORT_WRITE(out_BRANCH_EVENT_ADDRESS_DEST_VAL [i],reg_EVENT_ADDRESS_DEST_VAL [i]); PORT_WRITE(out_BRANCH_EVENT_ADDRESS_DEST [i],reg_EVENT_ADDRESS_DEST [i]); PORT_WRITE(out_BRANCH_EVENT_CAN_CONTINUE [i],reg_EVENT_CAN_CONTINUE [i]); internal_BRANCH_EVENT_VAL [i] = val; } } else { // Reset for (uint32_t i=0; i<_param->_nb_inst_update; i++) { internal_UPDATE_VAL [i] = 0; internal_UPDATE_VAL_WITHOUT_ACK [i] = 0; } for (uint32_t i=0; i<_param->_nb_context; i++) { internal_BRANCH_EVENT_VAL [i] = 0; } } log_end(Update_Prediction_Table,FUNCTION); }; }; // 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