#ifdef SYSTEMC /* * $Id: Commit_unit_transition.cpp 112 2009-03-18 22:36:26Z rosiere $ * * [ Description ] * */ #include "Behavioural/Core/Multi_OOO_Engine/OOO_Engine/Commit_unit/include/Commit_unit.h" #include "Behavioural/include/Simulation.h" namespace morpheo { namespace behavioural { namespace core { namespace multi_ooo_engine { namespace ooo_engine { namespace commit_unit { #undef FUNCTION #define FUNCTION "Commit_unit::transition" void Commit_unit::transition (void) { log_begin(Commit_unit,FUNCTION); log_function(Commit_unit,FUNCTION,_name.c_str()); if (PORT_READ(in_NRESET) == 0) { // Clear all bank for (uint32_t i=0; i<_param->_nb_bank; i++) { _rob [i].clear(); reg_BANK_PTR [i] = 0; } // Reset pointer reg_NUM_BANK_HEAD = 0; reg_NUM_BANK_TAIL = 0; // Reset counter for (uint32_t i=0; i<_param->_nb_front_end; i++) for (uint32_t j=0; j<_param->_nb_context [i]; j++) { _nb_cycle_idle [i][j] = 0; reg_NB_INST_COMMIT_ALL [i][j] = 0; reg_NB_INST_COMMIT_MEM [i][j] = 0; reg_EVENT_STATE [i][j] = EVENT_STATE_NO_EVENT; reg_EVENT_FLUSH [i][j] = false; reg_EVENT_STOP [i][j] = false; // reg_PC_PREVIOUS [i][j] = (0x100-4)>>2; reg_PC_CURRENT [i][j] = (0x100 )>>2; reg_PC_CURRENT_IS_DS [i][j] = 0; reg_PC_CURRENT_IS_DS_TAKE [i][j] = 0; reg_PC_NEXT [i][j] = (0x100+4)>>2; } // Reset priority algorithm _priority_insert->reset(); } else { // Increase number idle cycle for (uint32_t i=0; i<_param->_nb_front_end; i++) for (uint32_t j=0; j<_param->_nb_context [i]; j++) _nb_cycle_idle [i][j] ++; // Compute next priority _priority_insert->transition(); // =================================================================== // =====[ GARBAGE COLLECTOR ]========================================= // =================================================================== for (uint32_t i=0; i<_param->_nb_front_end; i++) for (uint32_t j=0; j<_param->_nb_context [i]; j++) switch (reg_EVENT_STATE [i][j]) { case EVENT_STATE_EVENT : { if (internal_RETIRE_EVENT_VAL [i][j] and in_RETIRE_EVENT_ACK [i][j]) reg_EVENT_STATE [i][j] = EVENT_STATE_WAITEND ; break; } case EVENT_STATE_WAITEND : { Tcounter_t nb_inst_all = PORT_READ(in_NB_INST_DECOD_ALL [i][j]) + reg_NB_INST_COMMIT_ALL [i][j]; if (nb_inst_all == 0) { reg_EVENT_STATE [i][j] = EVENT_STATE_END; reg_EVENT_FLUSH [i][j] = false; //reg_EVENT_STOP [i][j] = false; } break; } case EVENT_STATE_END : { reg_EVENT_STATE [i][j] = EVENT_STATE_NO_EVENT; break; } // case EVENT_STATE_NO_EVENT : default : break; } // =================================================================== // =====[ INSERT ]==================================================== // =================================================================== for (uint32_t i=0; i<_param->_nb_bank; i++) if (internal_BANK_INSERT_VAL [i]) { // get rename unit source and instruction. uint32_t x = internal_BANK_INSERT_NUM_RENAME_UNIT [i]; uint32_t y = internal_BANK_INSERT_NUM_INST [i]; if (PORT_READ(in_INSERT_VAL [x][y])) { log_printf(TRACE,Commit_unit,FUNCTION," * INSERT [%d][%d]",x,y); // get information Tcontext_t front_end_id = (_param->_have_port_front_end_id)?PORT_READ(in_INSERT_FRONT_END_ID [x][y]):0; Tcontext_t context_id = (_param->_have_port_context_id )?PORT_READ(in_INSERT_CONTEXT_ID [x][y]):0; Ttype_t type = PORT_READ(in_INSERT_TYPE [x][y]); Toperation_t operation = PORT_READ(in_INSERT_OPERATION [x][y]); bool is_store = is_operation_memory_store(operation); Texception_t exception = PORT_READ(in_INSERT_EXCEPTION [x][y]); log_printf(TRACE,Commit_unit,FUNCTION," * front_end_id : %d",front_end_id); log_printf(TRACE,Commit_unit,FUNCTION," * context_id : %d",context_id); log_printf(TRACE,Commit_unit,FUNCTION," * type : %s",toString(type).c_str()); log_printf(TRACE,Commit_unit,FUNCTION," * operation : %d",operation ); log_printf(TRACE,Commit_unit,FUNCTION," * exception : %d",exception ); // Create new entry. entry_t * entry = new entry_t; entry->ptr = reg_BANK_PTR [i]; entry->front_end_id = front_end_id; entry->context_id = context_id ; entry->rename_unit_id = x; entry->depth = (_param->_have_port_depth)?PORT_READ(in_INSERT_DEPTH [x][y]):0; entry->type = type; entry->operation = operation; entry->is_delay_slot = PORT_READ(in_INSERT_IS_DELAY_SLOT [x][y]); // entry->address = PORT_READ(in_INSERT_ADDRESS [x][y]); entry->exception = exception; entry->exception_use = PORT_READ(in_INSERT_EXCEPTION_USE [x][y]); entry->use_store_queue = (type == TYPE_MEMORY) and ( is_store); entry->use_load_queue = (type == TYPE_MEMORY) and (not is_store); entry->store_queue_ptr_write = PORT_READ(in_INSERT_STORE_QUEUE_PTR_WRITE [x][y]); entry->load_queue_ptr_write = (_param->_have_port_load_queue_ptr)?PORT_READ(in_INSERT_LOAD_QUEUE_PTR_WRITE [x][y]):0; entry->read_ra = PORT_READ(in_INSERT_READ_RA [x][y]); entry->num_reg_ra_log = PORT_READ(in_INSERT_NUM_REG_RA_LOG [x][y]); entry->num_reg_ra_phy = PORT_READ(in_INSERT_NUM_REG_RA_PHY [x][y]); entry->read_rb = PORT_READ(in_INSERT_READ_RB [x][y]); entry->num_reg_rb_log = PORT_READ(in_INSERT_NUM_REG_RB_LOG [x][y]); entry->num_reg_rb_phy = PORT_READ(in_INSERT_NUM_REG_RB_PHY [x][y]); entry->read_rc = PORT_READ(in_INSERT_READ_RC [x][y]); entry->num_reg_rc_log = PORT_READ(in_INSERT_NUM_REG_RC_LOG [x][y]); entry->num_reg_rc_phy = PORT_READ(in_INSERT_NUM_REG_RC_PHY [x][y]); entry->write_rd = PORT_READ(in_INSERT_WRITE_RD [x][y]); entry->num_reg_rd_log = PORT_READ(in_INSERT_NUM_REG_RD_LOG [x][y]); entry->num_reg_rd_phy_old = PORT_READ(in_INSERT_NUM_REG_RD_PHY_OLD [x][y]); entry->num_reg_rd_phy_new = PORT_READ(in_INSERT_NUM_REG_RD_PHY_NEW [x][y]); entry->write_re = PORT_READ(in_INSERT_WRITE_RE [x][y]); entry->num_reg_re_log = PORT_READ(in_INSERT_NUM_REG_RE_LOG [x][y]); entry->num_reg_re_phy_old = PORT_READ(in_INSERT_NUM_REG_RE_PHY_OLD [x][y]); entry->num_reg_re_phy_new = PORT_READ(in_INSERT_NUM_REG_RE_PHY_NEW [x][y]); entry->no_sequence = type == TYPE_BRANCH; entry->speculative = true; #ifdef DEBUG entry->address = PORT_READ(in_INSERT_ADDRESS [x][y]); #endif entry->address_next = PORT_READ(in_INSERT_ADDRESS_NEXT [x][y]); #ifdef DEBUG entry->cycle_rob_in = sc_simulation_time(); entry->cycle_commit = sc_simulation_time(); #endif // Test if exception : // * yes : no execute instruction, wait ROB Head // * no : test type // * BRANCH : l.j -> branch is ended // other -> wait the execution end of branchment // * MEMORY : store -> wait store is at head of ROB // other -> wait end of instruction // * OTHER // bool flush = reg_EVENT_FLUSH [front_end_id][context_id]; // log_printf(TRACE,Commit_unit,FUNCTION," * flush : %d",flush); // if (flush) // { // entry->state = ROB_END_MISS; // All type (branch, memory and others), because, is not execute // } // else { if (exception == EXCEPTION_NONE) { Tcontrol_t no_execute = PORT_READ(in_INSERT_NO_EXECUTE [x][y]); // no_execute : l.j, l.nop, l.rfe log_printf(TRACE,Commit_unit,FUNCTION," * no_execute : %d",no_execute); switch (type) { case TYPE_BRANCH : {entry->state=(no_execute==1)?ROB_BRANCH_COMPLETE:ROB_BRANCH_WAIT_END ; break;} case TYPE_MEMORY : {entry->state=(is_store ==1)?ROB_STORE_WAIT_HEAD_OK:ROB_OTHER_WAIT_END; break;} default : {entry->state=(no_execute==1)?ROB_END_OK_SPECULATIVE:ROB_OTHER_WAIT_END; break;} } } else { // Have an exception : wait head of ROB // in_INSERT_NO_EXECUTE [x][y] : l.sys, l.trap entry->state = ROB_END_EXCEPTION_WAIT_HEAD; } } #ifdef STATISTICS if (usage_is_set(_usage,USE_STATISTICS)) (*_stat_nb_inst_insert [x]) ++; #endif // Push in rob _rob[i].push_back(entry); // Update counter and pointer reg_NB_INST_COMMIT_ALL [front_end_id][context_id] ++; if (type == TYPE_MEMORY) reg_NB_INST_COMMIT_MEM [front_end_id][context_id] ++; reg_NUM_BANK_TAIL = (reg_NUM_BANK_TAIL+1)%_param->_nb_bank; reg_BANK_PTR [i] = (reg_BANK_PTR [i]+1)%_param->_size_bank; } } // =================================================================== // =====[ COMMIT ]==================================================== // =================================================================== #ifdef STATISTICS if (usage_is_set(_usage,USE_STATISTICS)) (*_stat_nb_inst_commit_conflit_access) += internal_BANK_COMMIT_CONFLIT_ACCESS; #endif for (uint32_t i=0; i<_param->_nb_bank; i++) for (uint32_t j=0; j<_param->_nb_bank_access_commit; j++) if (internal_BANK_COMMIT_VAL [i][j]) { // An instruction is executed. Change state of this instruction uint32_t x = internal_BANK_COMMIT_NUM_INST [i][j]; if (PORT_READ(in_COMMIT_VAL [x]) and PORT_READ(in_COMMIT_WEN [x])) { log_printf(TRACE,Commit_unit,FUNCTION," * COMMIT [%d]",x); #ifdef STATISTICS if (usage_is_set(_usage,USE_STATISTICS)) (*_stat_nb_inst_commit) ++; #endif log_printf(TRACE,Commit_unit,FUNCTION," * num_bank : %d",i); // find the good entry !!! entry_t * entry = internal_BANK_COMMIT_ENTRY [i][j]; //Toperation_t operation = PORT_READ(in_COMMIT_OPERATION [x]); //Ttype_t type = PORT_READ(in_COMMIT_TYPE [x]); Texception_t exception = PORT_READ(in_COMMIT_EXCEPTION [x]); rob_state_t state = entry->state; Tcontext_t front_end_id = entry->front_end_id; Tcontext_t context_id = entry->context_id; // change state : test exception_use // * test if exception : exception and mask bool have_exception = false; bool have_miss_speculation = false; if (exception != EXCEPTION_NONE) { // Test if the instruction is a load and is a miss speculation (load is commit, but they have an dependence with a previous store) have_miss_speculation = (exception == EXCEPTION_MEMORY_MISS_SPECULATION); switch (entry->exception_use) { // Have overflow exception if bit overflow enable is set. case EXCEPTION_USE_RANGE : {have_exception = ((exception == EXCEPTION_RANGE) and PORT_READ(in_SPR_READ_SR_OVE[front_end_id][context_id])); break;} case EXCEPTION_USE_MEMORY_WITH_ALIGNMENT : {have_exception = ((exception == EXCEPTION_BUS_ERROR) or (exception == EXCEPTION_DATA_TLB ) or (exception == EXCEPTION_DATA_PAGE) or (exception == EXCEPTION_ALIGNMENT)); break;}; case EXCEPTION_USE_MEMORY_WITHOUT_ALIGNMENT : {have_exception = ((exception == EXCEPTION_BUS_ERROR) or (exception == EXCEPTION_DATA_TLB ) or (exception == EXCEPTION_DATA_PAGE)); break;}; case EXCEPTION_USE_CUSTOM_0 : {have_exception = (exception == EXCEPTION_CUSTOM_0); break;}; case EXCEPTION_USE_CUSTOM_1 : {have_exception = (exception == EXCEPTION_CUSTOM_1); break;}; case EXCEPTION_USE_CUSTOM_2 : {have_exception = (exception == EXCEPTION_CUSTOM_2); break;}; case EXCEPTION_USE_CUSTOM_3 : {have_exception = (exception == EXCEPTION_CUSTOM_3); break;}; case EXCEPTION_USE_CUSTOM_4 : {have_exception = (exception == EXCEPTION_CUSTOM_4); break;}; case EXCEPTION_USE_CUSTOM_5 : {have_exception = (exception == EXCEPTION_CUSTOM_5); break;}; case EXCEPTION_USE_CUSTOM_6 : {have_exception = (exception == EXCEPTION_CUSTOM_6); break;}; // Case already manage (decod stage -> in insert in ROB) case EXCEPTION_USE_TRAP : {have_exception = false; exception = EXCEPTION_NONE; break;}; case EXCEPTION_USE_NONE : {have_exception = false; exception = EXCEPTION_NONE; break;}; case EXCEPTION_USE_ILLEGAL_INSTRUCTION : {have_exception = false; exception = EXCEPTION_NONE; break;}; case EXCEPTION_USE_SYSCALL : {have_exception = false; exception = EXCEPTION_NONE; break;}; default : { throw ERRORMORPHEO(FUNCTION,_("Commit : invalid exception_use.\n")); break; } } } switch (state) { // Branch ... case ROB_BRANCH_WAIT_END : {state = (have_exception)?ROB_END_EXCEPTION_WAIT_HEAD:ROB_BRANCH_COMPLETE; break;} // Store KO case ROB_EVENT_WAIT_END : {state = ROB_END_KO_SPECULATIVE; break;} // Store OK, Load and other instruction case ROB_OTHER_WAIT_END : {state = (have_exception)?ROB_END_EXCEPTION_WAIT_HEAD:((have_miss_speculation)?ROB_END_LOAD_MISS_SPECULATIVE:ROB_END_OK_SPECULATIVE); break;} default : { throw ERRORMORPHEO(FUNCTION,toString(_("Commit : invalid state value (%s).\n"),toString(state).c_str())); break; } } if ((have_exception or have_miss_speculation) and (reg_EVENT_FLUSH [entry->front_end_id][entry->context_id] == 0)) reg_EVENT_STOP [entry->front_end_id][entry->context_id] = true; // update Re Order Buffer entry->state = state; entry->exception = exception; entry->flags = PORT_READ(in_COMMIT_FLAGS [x]); entry->no_sequence = PORT_READ(in_COMMIT_NO_SEQUENCE [x]); // jalr, jr : address_dest is in register if ((entry->type == TYPE_BRANCH) and (entry->operation == OPERATION_BRANCH_L_JALR) and (entry->read_rb)) entry->address_next = PORT_READ(in_COMMIT_ADDRESS [x]); #ifdef DEBUG entry->cycle_commit = sc_simulation_time(); #endif } } // =================================================================== // =====[ RETIRE ]==================================================== // =================================================================== for (uint32_t i=0; i<_param->_nb_bank; i++) { uint32_t num_bank = (internal_BANK_RETIRE_HEAD+i)%_param->_nb_bank; if (internal_BANK_RETIRE_VAL [num_bank]) { uint32_t x = internal_BANK_RETIRE_NUM_RENAME_UNIT [num_bank]; uint32_t y = internal_BANK_RETIRE_NUM_INST [num_bank]; log_printf(TRACE,Commit_unit,FUNCTION," * RETIRE [%d][%d]",x,y); log_printf(TRACE,Commit_unit,FUNCTION," * num_bank : %d",num_bank ); #ifdef DEBUG_TEST if (not PORT_READ(in_RETIRE_ACK [x][y])) throw ERRORMORPHEO(FUNCTION,_("Retire : retire_ack must be set.\n")); #endif entry_t * entry = _rob [num_bank].front(); rob_state_t state = entry->state; Tcontext_t front_end_id = entry->front_end_id; Tcontext_t context_id = entry->context_id ; uint32_t num_thread = _param->_translate_num_context_to_num_thread [front_end_id][context_id]; Ttype_t type = entry->type ; bool retire_ok = false; log_printf(TRACE,Commit_unit,FUNCTION," * front_end_id : %d",front_end_id ); log_printf(TRACE,Commit_unit,FUNCTION," * context_id : %d",context_id ); log_printf(TRACE,Commit_unit,FUNCTION," * rob_ptr : %d",((num_bank << _param->_shift_num_bank) | entry->ptr)); log_printf(TRACE,Commit_unit,FUNCTION," * num_thread : %d",num_thread ); log_printf(TRACE,Commit_unit,FUNCTION," * type : %s",toString(type).c_str()); log_printf(TRACE,Commit_unit,FUNCTION," * state : %s",toString(state).c_str()); if ((state == ROB_END_OK ) or // (state == ROB_END_KO ) or (state == ROB_END_BRANCH_MISS) or (state == ROB_END_LOAD_MISS )// or // (state == ROB_END_MISS ) or // (state == ROB_END_EXCEPTION ) ) { log_printf(TRACE,Commit_unit,FUNCTION," * retire_ok"); retire_ok = true; // reg_PC_PREVIOUS [front_end_id][context_id] = reg_PC_CURRENT [front_end_id][context_id]; reg_PC_CURRENT [front_end_id][context_id] = reg_PC_NEXT [front_end_id][context_id]; reg_PC_CURRENT_IS_DS [front_end_id][context_id] = entry->type == TYPE_BRANCH; reg_PC_CURRENT_IS_DS_TAKE [front_end_id][context_id] = entry->no_sequence; reg_PC_NEXT [front_end_id][context_id] = (entry->no_sequence)?(entry->address_next):(reg_PC_CURRENT [front_end_id][context_id]+1); // if (entry->address_next != reg_PC_NEXT [front_end_id][context_id]) // throw ERRORMORPHEO(FUNCTION,toString(_("Retire : Instruction's address_next (%.8x) is different of commit_unit's address_next (%.8x)"),entry->address_next,reg_PC_NEXT [front_end_id][context_id])); } if ((state == ROB_END_BRANCH_MISS) or (state == ROB_END_LOAD_MISS)) { reg_EVENT_STATE [front_end_id][context_id] = EVENT_STATE_EVENT; reg_EVENT_FLUSH [front_end_id][context_id] = true; reg_EVENT_STOP [front_end_id][context_id] = false; } #if defined(DEBUG) and defined(DEBUG_Commit_unit) and (DEBUG_Commit_unit == true) // log file instruction_log_file [num_thread] << "[" << sc_simulation_time() << "] " << "{" << ((retire_ok)?" OK ":"!KO!") << "} " << std::hex << "0x" << entry->address << " (0x" << (entry->address<<2) << ") " << std::dec << "[" << entry->cycle_rob_in << ", " << entry->cycle_commit << "] " << std::endl; #endif // Update nb_inst reg_NB_INST_COMMIT_ALL [front_end_id][context_id] --; if (type == TYPE_MEMORY) reg_NB_INST_COMMIT_MEM [front_end_id][context_id] --; reg_NUM_BANK_HEAD = (reg_NUM_BANK_HEAD+1)%_param->_nb_bank; _rob [num_bank].pop_front(); delete entry; // Transaction on retire interface : reset watch dog timer. _nb_cycle_idle [front_end_id][context_id] = 0; // Increase stop condition if (retire_ok) _simulation_nb_instruction_commited [num_thread] ++; #ifdef STATISTICS if (usage_is_set(_usage,USE_STATISTICS)) { (*_stat_nb_inst_retire [x]) ++; if (retire_ok) { (*_stat_nb_inst_retire_ok [num_thread]) ++; (*_stat_nb_inst_type [type] ) ++; } else (*_stat_nb_inst_retire_ko [num_thread]) ++; } #endif } } // =================================================================== // =====[ REEXECUTE ]================================================= // =================================================================== if (internal_REEXECUTE_VAL [0] and PORT_READ(in_REEXECUTE_ACK [0])) { log_printf(TRACE,Commit_unit,FUNCTION," * REEXECUTE [0]"); uint32_t num_bank = internal_REEXECUTE_NUM_BANK [0]; entry_t * entry = _rob [num_bank].front(); rob_state_t state = entry->state; switch (state) { case ROB_STORE_HEAD_OK : {state = ROB_OTHER_WAIT_END; break; } case ROB_STORE_HEAD_KO : {state = ROB_EVENT_WAIT_END; break; } default : {throw ERRORMORPHEO(FUNCTION,_("Reexecute : invalid state value.\n"));} } entry->state = state; } // =================================================================== // =====[ BRANCH_COMPLETE ]=========================================== // =================================================================== for (uint32_t i=0; i<_param->_nb_inst_branch_complete; i++) if (internal_BRANCH_COMPLETE_VAL [i] and PORT_READ(in_BRANCH_COMPLETE_ACK [i])) { log_printf(TRACE,Commit_unit,FUNCTION," * BRANCH_COMPLETE [%d]",i); log_printf(TRACE,Commit_unit,FUNCTION," * miss_prediction : %d",PORT_READ(in_BRANCH_COMPLETE_MISS_PREDICTION [i])); uint32_t num_bank = internal_BRANCH_COMPLETE_NUM_BANK [i]; entry_t * entry = _rob [num_bank].front(); #ifdef DEBUG_TEST rob_state_t state = entry->state; if (state != ROB_BRANCH_COMPLETE) throw ERRORMORPHEO(FUNCTION,_("Branch_complete : Invalid state value.\n")); #endif Tcontrol_t miss = PORT_READ(in_BRANCH_COMPLETE_MISS_PREDICTION [i]); entry->state = (miss)?ROB_END_BRANCH_MISS_SPECULATIVE:ROB_END_OK_SPECULATIVE; if (miss and (reg_EVENT_FLUSH [entry->front_end_id][entry->context_id] == 0)) reg_EVENT_STOP [entry->front_end_id][entry->context_id] = true; // entry->state = ROB_END_OK_SPECULATIVE; } // =================================================================== // =====[ UPDATE ]==================================================== // =================================================================== if (internal_UPDATE_VAL and PORT_READ(in_UPDATE_ACK)) { log_printf(TRACE,Commit_unit,FUNCTION," * UPDATE"); entry_t * entry = _rob [internal_UPDATE_NUM_BANK].front(); switch (entry->state) { // case ROB_END_EXCEPTION_UPDATE : // { // entry->state = ROB_END_KO; // throw ERRORMORPHEO(FUNCTION,_("Moore : exception is not yet supported (Coming Soon).\n")); // break; // } case ROB_END_LOAD_MISS_UPDATE : { log_printf(TRACE,Commit_unit,FUNCTION," * ROB_END_LOAD_MISS_UPDATE"); entry->state = ROB_END_LOAD_MISS; break; } default : { throw ERRORMORPHEO(FUNCTION,_("Update : invalid state.\n")); break; } } } // =================================================================== // =====[ EVENT ]===================================================== // =================================================================== // for (uint32_t i=0; i < _param->_nb_front_end; ++i) // for (uint32_t j=0; j < _param->_nb_context[i]; ++j) // if (PORT_READ(in_EVENT_VAL [i][j]) and internal_EVENT_ACK [i][j]) // { // log_printf(TRACE,Commit_unit,FUNCTION," * EVENT [%d][%d]",i,j); // reg_PC_CURRENT [i][j] = PORT_READ(in_EVENT_ADDRESS [i][j]); // reg_PC_CURRENT_IS_DS [i][j] = PORT_READ(in_EVENT_IS_DS_TAKE [i][j]); // ?? // reg_PC_CURRENT_IS_DS_TAKE [i][j] = PORT_READ(in_EVENT_IS_DS_TAKE [i][j]); // reg_PC_NEXT [i][j] = PORT_READ(in_EVENT_ADDRESS_NEXT [i][j]); // // PORT_READ(in_EVENT_ADDRESS_NEXT_VAL [i][j]); // } // =================================================================== // =====[ DEPTH - HEAD ]============================================== // =================================================================== for (uint32_t i=0; i<_param->_nb_bank; i++) if (not _rob[i].empty()) { // Scan all instruction in windows and test if instruction is speculative entry_t * entry = _rob [i].front(); Tcontext_t front_end_id = entry->front_end_id; Tcontext_t context_id = entry->context_id ; rob_state_t state = entry->state; Tdepth_t depth = entry->depth; Tdepth_t depth_min = (_param->_have_port_depth)?PORT_READ(in_DEPTH_MIN[front_end_id][context_id]):0; Tdepth_t depth_max = (_param->_have_port_depth)?PORT_READ(in_DEPTH_MAX[front_end_id][context_id]):0; Tcontrol_t depth_full = PORT_READ(in_DEPTH_FULL [front_end_id][context_id]); // 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 // All case // ....... min ...X... max ....... OK // ....... min ....... max ...X... KO // ...X... min ....... max ....... KO // ....... max ....... min ...X... OK // ...X... max ....... min ....... OK // ....... max ...X... min ....... KO bool flush = reg_EVENT_FLUSH [front_end_id][context_id]; bool speculative = entry->speculative and not (depth == depth_min); Tcontrol_t is_valid = ((not speculative or (speculative and (depth_full or // all is valid ((depth_min <= depth_max)? // test if depth is overflow ((depth >= depth_min) and (depth <=depth_max)): ((depth >= depth_min) or (depth <=depth_max)))))) and not flush); // Tcontrol_t is_valid = ((depth == depth_min) and not flush); log_printf(TRACE,Commit_unit,FUNCTION," * HEAD [%d]",i); log_printf(TRACE,Commit_unit,FUNCTION," * is_valid : %d ((depth == depth_min) and not flush)",is_valid); log_printf(TRACE,Commit_unit,FUNCTION," * depth : %d",depth ); log_printf(TRACE,Commit_unit,FUNCTION," * depth_min : %d",depth_min); log_printf(TRACE,Commit_unit,FUNCTION," * depth_max : %d",depth_max); log_printf(TRACE,Commit_unit,FUNCTION," * depth_full : %d",depth_full); log_printf(TRACE,Commit_unit,FUNCTION," * flush : %d",flush); //------------------------------------------------------ // test if instruction is miss speculative //------------------------------------------------------ if (not is_valid) { switch (state) { case ROB_BRANCH_WAIT_END : {state = ROB_EVENT_WAIT_END; break;} case ROB_BRANCH_COMPLETE : {state = ROB_END_MISS ; break;} case ROB_END_BRANCH_MISS : case ROB_END_BRANCH_MISS_SPECULATIVE : {state = ROB_END_MISS ; break;} case ROB_END_LOAD_MISS_UPDATE : case ROB_END_LOAD_MISS : case ROB_END_LOAD_MISS_SPECULATIVE : {state = ROB_END_MISS ; break;} case ROB_STORE_WAIT_HEAD_OK : {state = ROB_STORE_HEAD_KO ; break;} //case ROB_STORE_WAIT_HEAD_KO : {state = ; break;} case ROB_OTHER_WAIT_END : {state = ROB_EVENT_WAIT_END; break;} case ROB_END_OK : case ROB_END_OK_SPECULATIVE : {state = ROB_END_MISS ; break;} case ROB_END_KO : case ROB_END_KO_SPECULATIVE : {state = ROB_END_MISS ; break;} case ROB_END_EXCEPTION_UPDATE : case ROB_END_EXCEPTION : case ROB_END_EXCEPTION_WAIT_HEAD : {state = ROB_END_MISS ; break;} // don't change case ROB_STORE_HEAD_KO : {break;} case ROB_EVENT_WAIT_END : {break;} case ROB_END_MISS : {break;} // can't have miss speculation case ROB_STORE_HEAD_OK : default : { throw ERRORMORPHEO(FUNCTION,toString(_("Miss Speculation : Invalide state : %s.\n"),toString(state).c_str())); break; } } } //------------------------------------------------------ // test if instruction is not speculative //------------------------------------------------------ entry->speculative = speculative; // if (entry->depth == depth_min) if (not speculative) { switch (state) { case ROB_END_OK_SPECULATIVE : {state = ROB_END_OK ; break;} case ROB_END_KO_SPECULATIVE : {state = ROB_END_KO ; break;} case ROB_END_BRANCH_MISS_SPECULATIVE : {state = ROB_END_BRANCH_MISS ; break;} case ROB_END_LOAD_MISS_SPECULATIVE : {state = ROB_END_LOAD_MISS_UPDATE ; break;} default : {break;} // else, no change } } //------------------------------------------------------ // test if instruction is store and head //------------------------------------------------------ if (i == reg_NUM_BANK_HEAD) { switch (state) { case ROB_STORE_WAIT_HEAD_OK : {state = ROB_STORE_HEAD_OK; break;} case ROB_END_EXCEPTION_WAIT_HEAD : {state = ROB_END_EXCEPTION_UPDATE; break;} default : {break;} // else, no change } } entry->state = state; } } // =================================================================== // =====[ OTHER ]===================================================== // =================================================================== #ifdef STATISTICS for (uint32_t i=0; i<_param->_nb_bank; i++) if (usage_is_set(_usage,USE_STATISTICS)) *(_stat_bank_nb_inst [i]) += _rob[i].size(); #endif #if (DEBUG >= DEBUG_TRACE) and (DEBUG_Commit_unit == true) { log_printf(TRACE,Commit_unit,FUNCTION," * Dump ROB (Re-Order-Buffer)"); log_printf(TRACE,Commit_unit,FUNCTION," * num_bank_head : %d",reg_NUM_BANK_HEAD); log_printf(TRACE,Commit_unit,FUNCTION," * num_bank_tail : %d",reg_NUM_BANK_TAIL); for (uint32_t i=0; i<_param->_nb_front_end; i++) for (uint32_t j=0; j<_param->_nb_context [i]; j++) { log_printf(TRACE,Commit_unit,FUNCTION," * [%d][%d] - %d",i,j,_param->_translate_num_context_to_num_thread [i][j]); log_printf(TRACE,Commit_unit,FUNCTION," * EVENT_STATE : %s",toString(reg_EVENT_STATE [i][j]).c_str()); log_printf(TRACE,Commit_unit,FUNCTION," * EVENT_FLUSH : %d",reg_EVENT_FLUSH [i][j]); log_printf(TRACE,Commit_unit,FUNCTION," * EVENT_STOP : %d",reg_EVENT_STOP [i][j]); log_printf(TRACE,Commit_unit,FUNCTION," * NB_INST_ALL : %d",reg_NB_INST_COMMIT_ALL[i][j]); log_printf(TRACE,Commit_unit,FUNCTION," * NB_INST_MEM : %d",reg_NB_INST_COMMIT_MEM[i][j]); log_printf(TRACE,Commit_unit,FUNCTION," * PC_CURRENT : %.8x (%.8x) - %d %d",reg_PC_CURRENT [i][j],reg_PC_CURRENT [i][j]<<2, reg_PC_CURRENT_IS_DS [i][j], reg_PC_CURRENT_IS_DS_TAKE [i][j]); log_printf(TRACE,Commit_unit,FUNCTION," * PC_NEXT : %.8x (%.8x)",reg_PC_NEXT [i][j],reg_PC_NEXT [i][j]<<2); } for (uint32_t i=0; i<_param->_nb_bank; i++) { uint32_t num_bank = (reg_NUM_BANK_HEAD+i)%_param->_nb_bank; log_printf(TRACE,Commit_unit,FUNCTION," * Bank [%d] size : %d, ptr : %d",num_bank,(int)_rob[num_bank].size(), reg_BANK_PTR [i]); for (std::list::iterator it=_rob[num_bank].begin(); it!=_rob[num_bank].end(); it++) { log_printf(TRACE,Commit_unit,FUNCTION," [%.4d][%.4d] (%.4d) %.4d %.4d %.4d %.4d, %.3d %.3d, %.1d, %.1d %.4d, %.1d %.4d, %s", num_bank , (*it)->ptr , ((num_bank << _param->_shift_num_bank) | (*it)->ptr), (*it)->front_end_id , (*it)->context_id , (*it)->rename_unit_id , (*it)->depth , (*it)->type , (*it)->operation , (*it)->is_delay_slot , (*it)->use_store_queue , (*it)->store_queue_ptr_write , (*it)->use_load_queue , (*it)->load_queue_ptr_write , toString((*it)->state).c_str() ); log_printf(TRACE,Commit_unit,FUNCTION," %.1d %.2d %.6d, %.1d %.2d %.6d, %.1d %.1d %.6d, %.1d %.2d %.6d %.6d, %.1d %.1d %.6d %.6d ", (*it)->read_ra , (*it)->num_reg_ra_log , (*it)->num_reg_ra_phy , (*it)->read_rb , (*it)->num_reg_rb_log , (*it)->num_reg_rb_phy , (*it)->read_rc , (*it)->num_reg_rc_log , (*it)->num_reg_rc_phy , (*it)->write_rd , (*it)->num_reg_rd_log , (*it)->num_reg_rd_phy_old , (*it)->num_reg_rd_phy_new , (*it)->write_re , (*it)->num_reg_re_log , (*it)->num_reg_re_phy_old , (*it)->num_reg_re_phy_new ); log_printf(TRACE,Commit_unit,FUNCTION," %.2d %.2d %.1d %.1d %.1d - %.8x (%.8x) %.8x (%.8x)", (*it)->exception_use , (*it)->exception , (*it)->flags , (*it)->no_sequence , (*it)->speculative , (*it)->address , (*it)->address<<2 , (*it)->address_next , (*it)->address_next<<2 ); } } } #endif #ifdef DEBUG_TEST { uint32_t x=reg_NUM_BANK_HEAD; if (not _rob[x].empty()) { entry_t * entry = _rob [x].front(); if (false // or (entry->state == ROB_EMPTY ) // or (entry->state == ROB_BRANCH_WAIT_END ) // or (entry->state == ROB_BRANCH_COMPLETE ) // or (entry->state == ROB_STORE_WAIT_HEAD_OK ) // //or (entry->state == ROB_STORE_WAIT_HEAD_KO ) // or (entry->state == ROB_STORE_HEAD_OK ) // or (entry->state == ROB_STORE_HEAD_KO ) // or (entry->state == ROB_OTHER_WAIT_END ) // or (entry->state == ROB_EVENT_WAIT_END ) // or (entry->state == ROB_END_OK_SPECULATIVE ) or (entry->state == ROB_END_OK ) // or (entry->state == ROB_END_KO_SPECULATIVE ) // or (entry->state == ROB_END_KO ) // or (entry->state == ROB_END_BRANCH_MISS_SPECULATIVE) or (entry->state == ROB_END_BRANCH_MISS ) // or (entry->state == ROB_END_LOAD_MISS_SPECULATIVE ) // or (entry->state == ROB_END_LOAD_MISS_UPDATE ) or (entry->state == ROB_END_LOAD_MISS ) // or (entry->state == ROB_END_MISS ) // or (entry->state == ROB_END_EXCEPTION_WAIT_HEAD ) // or (entry->state == ROB_END_EXCEPTION_UPDATE ) // or (entry->state == ROB_END_EXCEPTION ) ) if (entry->address != reg_PC_CURRENT[entry->front_end_id][entry->context_id]) throw ERRORMORPHEO(FUNCTION,toString(_("Rob top address (%x) is different of reg_PC_CURRENT[%d][%d] (%x).\n"), entry->address, entry->front_end_id, entry->context_id, reg_PC_CURRENT[entry->front_end_id][entry->context_id])); } } #endif #if defined(STATISTICS) or defined(VHDL_TESTBENCH) end_cycle (); #endif // Stop Condition for (uint32_t i=0; i<_param->_nb_front_end; i++) for (uint32_t j=0; j<_param->_nb_context [i]; j++) if (_nb_cycle_idle [i][j] >= debug_idle_cycle) throw ERRORMORPHEO(FUNCTION,toString(_("Thread [%d] is idle since %.0f cycles.\n"),_param->_translate_num_context_to_num_thread[i][j],_nb_cycle_idle [i][j])); log_end(Commit_unit,FUNCTION); }; }; // end namespace commit_unit }; // end namespace ooo_engine }; // end namespace multi_ooo_engine }; // end namespace core }; // end namespace behavioural }; // end namespace morpheo #endif