#ifdef SYSTEMC /* * $Id: Commit_unit_transition.cpp 145 2010-10-13 18:15:51Z 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) { while(not _rob[i].empty()) { delete _rob[i].front(); _rob[i].pop_front(); } reg_BANK_PTR [i] = 0; } // Reset pointer reg_NUM_BANK_HEAD = 0; reg_NUM_BANK_TAIL = 0; reg_NUM_PTR_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_EVENT_STATE [i][j] = COMMIT_EVENT_STATE_NO_EVENT; // reg_EVENT_FLUSH [i][j] = false; // reg_EVENT_STOP [i][j] = false; // reg_EVENT_NUM_BANK [i][j] = 0; // not necessary // reg_EVENT_NUM_PTR [i][j] = 0; // not necessary // reg_EVENT_CAN_RESTART [i][j] = 0; // not necessary reg_EVENT_PACKET [i][j] = 0; // not necessary reg_EVENT_DEPTH [i][j] = 0; // not necessary reg_EVENT_NB_INST [i][j] = 0; reg_EVENT_LAST [i][j] = false; reg_EVENT_LAST_NUM_BANK [i][j] = 0; // not necessary reg_EVENT_LAST_NUM_PTR [i][j] = 0; // not necessary reg_EVENT_NEXT_STOP [i][j] = false; reg_EVENT_NEXT_PACKET [i][j] = 0; // not necessary // 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; reg_NB_INST_COMMIT_ALL [i][j] = 0; reg_NB_INST_COMMIT_MEM [i][j] = 0; if (_param->_front_end_rat_scheme[i] == RAT_DEPTH_SAVE) for (uint32_t k=0; k<_param->_nb_branch_speculated[i][j]; ++k) reg_NB_INST_DEPTH [i][j][k] = 0; } // Resert RAT_UPDATE_TABLE for (uint32_t i=0; i<_param->_nb_front_end; i++) for (uint32_t j=0; j<_param->_nb_context[i]; j++) { for (uint32_t k=0; k<_param->_nb_general_register_logic; k++) rat_gpr_update_table [i][j][k] = false; // not necessary for (uint32_t k=0; k<_param->_nb_special_register_logic; k++) rat_spr_update_table [i][j][k] = false; // not necessary } // Reset priority algorithm _priority_insert->reset(); } else { #ifdef STATISTICS uint32_t stat_nb_inst_insert [_param->_nb_rename_unit]; uint32_t stat_nb_inst_retire [_param->_nb_rename_unit]; uint32_t stat_nb_inst_commit [_param->_nb_rename_unit]; if (usage_is_set(_usage,USE_STATISTICS)) for (uint32_t i=0; i<_param->_nb_rename_unit; ++i) { stat_nb_inst_insert [i] = 0; stat_nb_inst_retire [i] = 0; stat_nb_inst_commit [i] = 0; } #endif // 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++) { // Test if can_restart : (can_restart is to signal at the state than the decod_queue is empty) // * no previous can_restart (trap for one) // * and decod_queue is empty // * and have an event or have a futur event // if (not reg_EVENT_CAN_RESTART [i][j] and // (PORT_READ(in_NB_INST_DECOD_ALL [i][j]) == 0) and // (reg_EVENT_STOP [i][j] or (reg_EVENT_STATE [i][j] != COMMIT_EVENT_STATE_NO_EVENT))) // reg_EVENT_CAN_RESTART [i][j] = true; // Test event state switch (reg_EVENT_STATE [i][j]) { case COMMIT_EVENT_STATE_EVENT : { // Have an event, test if all composant have ack if (internal_RETIRE_EVENT_VAL [i][j] and in_RETIRE_EVENT_ACK [i][j]) { // A minor optimisation : test if wait_decod is previously empty. // if (not reg_EVENT_CAN_RESTART [i][j]) // reg_EVENT_STATE [i][j] = COMMIT_EVENT_STATE_WAIT_DECOD; // else reg_EVENT_STATE [i][j] = COMMIT_EVENT_STATE_WAIT_END; // Reset update_table for (uint32_t k=0; k<_param->_nb_general_register_logic; k++) rat_gpr_update_table [i][j][k] = false; for (uint32_t k=0; k<_param->_nb_special_register_logic; k++) rat_spr_update_table [i][j][k] = false; } break; } // case COMMIT_EVENT_STATE_WAIT_DECOD : // { // // Wait flush of decod_queue. // // Test if can restart now // if (reg_EVENT_CAN_RESTART [i][j]) // { // //reg_EVENT_FLUSH [i][j] = false; // // A minor optimisation : test if the last element is already retire // if (not reg_EVENT_LAST [i][j]) // reg_EVENT_STATE [i][j] = COMMIT_EVENT_STATE_WAIT_END; // else // reg_EVENT_STATE [i][j] = COMMIT_EVENT_STATE_END; // } // break; // } // case COMMIT_EVENT_STATE_WAIT_END : // { // // Wait the flush of Re Order Buffer. // // Test if the last element is retire // if (reg_EVENT_LAST [i][j]) // reg_EVENT_STATE [i][j] = COMMIT_EVENT_STATE_END ; // break; // } // case COMMIT_EVENT_STATE_END : // { // // Just one cycle // // flush of re order buffer is finish // reg_EVENT_LAST [i][j] = false; // if (not reg_EVENT_NEXT_STOP [i][j]) // reg_EVENT_STATE [i][j] = COMMIT_EVENT_STATE_NO_EVENT; // else // { // reg_EVENT_NEXT_STOP [i][j] = false; // reg_EVENT_PACKET [i][j] = reg_EVENT_NEXT_PACKET [i][j]; // reg_EVENT_STATE [i][j] = COMMIT_EVENT_STATE_NOT_YET_EVENT; // // reg_EVENT_STOP [i][j] = true; // reg_EVENT_LAST_NUM_BANK [i][j] = ((reg_NUM_BANK_TAIL==0)?_param->_nb_bank:reg_NUM_BANK_TAIL)-1; // reg_EVENT_LAST_NUM_PTR [i][j] = reg_NUM_PTR_TAIL; // } // break; // } case COMMIT_EVENT_STATE_WAIT_END : { // Wait the flush of Re Order Buffer. // Test if the last element is retire if (reg_EVENT_LAST [i][j]) { // flush of re order buffer is finish reg_EVENT_LAST [i][j] = false; if (not reg_EVENT_NEXT_STOP [i][j]) reg_EVENT_STATE [i][j] = COMMIT_EVENT_STATE_NO_EVENT; else { uint32_t next_packet = reg_EVENT_NEXT_PACKET [i][j]; reg_EVENT_STATE [i][j] = COMMIT_EVENT_STATE_NOT_YET_EVENT; reg_EVENT_NEXT_STOP [i][j] = false; reg_EVENT_PACKET [i][j] = next_packet; // reg_EVENT_DEPTH [i][j] = _rob[next_packet].depth; reg_EVENT_NB_INST [i][j] = reg_NB_INST_COMMIT_ALL [i][j]; //reg_EVENT_STOP [i][j] = true; reg_EVENT_LAST_NUM_BANK [i][j] = ((reg_NUM_BANK_TAIL==0)?_param->_nb_bank:reg_NUM_BANK_TAIL)-1; reg_EVENT_LAST_NUM_PTR [i][j] = reg_NUM_PTR_TAIL; } } break; } //case COMMIT_EVENT_STATE_NO_EVENT : //case COMMIT_EVENT_STATE_NOT_YET_EVENT : default : break; } } // =================================================================== // =====[ INSERT ]==================================================== // =================================================================== { // for (uint32_t i=0; i<_param->_nb_rename_unit; i++) // for (uint32_t j=0; j<_param->_nb_inst_insert[i]; j++) // log_printf(TRACE,Commit_unit,FUNCTION," * INSERT_VAL [%d][%d] : %d",i,j,PORT_READ(in_INSERT_VAL [i][j])); // variable to count instruction insert uint32_t nb_insert = 0; for (uint32_t i=0; i<_param->_nb_bank; i++) { // compute first bank number uint32_t num_bank = (reg_NUM_BANK_TAIL+i)%_param->_nb_bank; if (internal_BANK_INSERT_VAL [num_bank]) { // get rename unit source and instruction. uint32_t x = internal_BANK_INSERT_NUM_RENAME_UNIT [num_bank]; uint32_t y = internal_BANK_INSERT_NUM_INST [num_bank]; // Test if an instruction is valid // (all in_order insert combinatory is in rename_unit ) 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]); Tcontrol_t no_execute = PORT_READ(in_INSERT_NO_EXECUTE [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 and write information entry_t * entry = new entry_t; uint32_t ptr = reg_BANK_PTR [num_bank]; // entry->restore = false; entry->ptr = ptr; 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; #ifdef STATISTICS entry->instruction = PORT_READ(in_INSERT_INSTRUCTION [x][y]); #endif 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) and (not no_execute); entry->use_load_queue = (type == TYPE_MEMORY) and (not is_store) and (not no_execute); 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; #ifdef DEBUG 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]); #endif entry->read_rb = PORT_READ(in_INSERT_READ_RB [x][y]); #ifdef DEBUG 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]); #endif 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->flags = 0; // not necessary 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 = simulation_cycle(); entry->cycle_commit = simulation_cycle(); #endif // Test if exception : // * yes : no execute instruction, wait ROB Head // * no : test if no_execute (== instruction is flushed) // else 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 { if (exception == EXCEPTION_NONE) { // 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=(no_execute==1)?ROB_END_OK_SPECULATIVE:(entry->state=(is_store==1)?ROB_STORE_WAIT_END_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 entry in rob _rob[num_bank].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] ++; if (_param->_front_end_rat_scheme[front_end_id] == RAT_DEPTH_SAVE) reg_NB_INST_DEPTH [front_end_id][context_id][entry->depth] ++; // flush = present event or future event. // * present event = don't can restart // bool flush = reg_EVENT_FLUSH [front_end_id][context_id]; // bool flush = (((reg_EVENT_STATE [front_end_id][context_id] == COMMIT_EVENT_STATE_EVENT) or // (reg_EVENT_STATE [front_end_id][context_id] == COMMIT_EVENT_STATE_WAIT_DECOD)) or // (reg_EVENT_STOP [front_end_id][context_id])); // New instruction from decod_queue. Flush if : // * future event (instruction don't need execute because they are a previous event (miss load/branch or exception)) // * or present_event // * and not can_restart (previous empty decod queue), because between the event_stop (branch_complete) and the state event (miss in head), many cycle is occured. // bool flush = ((// present event // ((reg_EVENT_STATE [front_end_id][context_id] == COMMIT_EVENT_STATE_EVENT) or // (reg_EVENT_STATE [front_end_id][context_id] == COMMIT_EVENT_STATE_WAIT_DECOD) // ) or // futur event // reg_EVENT_STOP [front_end_id][context_id]) // // can't restart // and not reg_EVENT_CAN_RESTART[front_end_id][context_id] // ); // if (flush) // { // // A new invalid instruction is push in rob -> new last instruction // reg_EVENT_LAST [front_end_id][context_id] = false; // reg_EVENT_LAST_NUM_BANK [front_end_id][context_id] = num_bank; // reg_EVENT_LAST_NUM_PTR [front_end_id][context_id] = ptr; // } // Update pointer reg_NUM_PTR_TAIL = ptr; reg_BANK_PTR [num_bank] = (reg_BANK_PTR [num_bank]+1)%_param->_size_bank; nb_insert ++; } } } // Update pointer reg_NUM_BANK_TAIL = (reg_NUM_BANK_TAIL+nb_insert)%_param->_nb_bank; } // =================================================================== // =====[ COMMIT ]==================================================== // =================================================================== #ifdef STATISTICS if (usage_is_set(_usage,USE_STATISTICS)) (*_stat_nb_inst_commit_conflit_access) += internal_BANK_COMMIT_CONFLIT_ACCESS; #endif // For each commit instruction ... for (uint32_t i=0; i<_param->_nb_bank; i++) for (uint32_t j=0; j<_param->_nb_bank_access_commit; j++) // ... test if an instruction have finish this execution if (internal_BANK_COMMIT_VAL [i][j]) { // An instruction is executed -> Change state of this instruction // Get information uint32_t x = internal_BANK_COMMIT_NUM_INST [i][j]; // Test if instruction is valid and is enable // (can be disable if this instruction is reexecute) if (PORT_READ(in_COMMIT_VAL [x]) and PORT_READ(in_COMMIT_WEN [x])) { log_printf(TRACE,Commit_unit,FUNCTION," * COMMIT [%d]",x); log_printf(TRACE,Commit_unit,FUNCTION," * num_bank : %d",i); // find the good entry !!! entry_t * entry = internal_BANK_COMMIT_ENTRY [i][j]; #ifdef STATISTICS if (usage_is_set(_usage,USE_STATISTICS)) stat_nb_inst_commit [entry->rename_unit_id] ++; #endif log_printf(TRACE,Commit_unit,FUNCTION," * ptr : %d",entry->ptr); //Toperation_t operation = PORT_READ(in_COMMIT_OPERATION [x]); Ttype_t type = entry->type; Tcontrol_t no_sequence = PORT_READ(in_COMMIT_NO_SEQUENCE [x]); // Tcontrol_t cancel = PORT_READ(in_COMMIT_CANCEL [x]); #if 0 if ((type == TYPE_MEMORY) and no_sequence) continue; #endif 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 bool have_exception = false; bool have_miss_speculation = false; // Test if have an exception ... 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 -> need restart pipeline) have_miss_speculation = (exception == EXCEPTION_MEMORY_MISS_SPECULATION); // * Test if the exception generated can be trap by this exception 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; } } } log_printf(TRACE,Commit_unit,FUNCTION," * have_exception : %d",have_exception ); log_printf(TRACE,Commit_unit,FUNCTION," * have_miss_speculation : %d",have_miss_speculation); // Next state depends of previous state switch (state) { // Branch : if no exception, the branchement can be completed case ROB_BRANCH_WAIT_END : { if (not have_exception) state = ROB_BRANCH_COMPLETE; else state = ROB_END_EXCEPTION_WAIT_HEAD; break; } // Previous event -> set state as execute case ROB_STORE_KO_WAIT_END : case ROB_EVENT_WAIT_END : { state = ROB_END_KO_SPECULATIVE; break; } // No previous event - Load and other instruction case ROB_STORE_OK_WAIT_END : case ROB_OTHER_WAIT_END : { if (not have_exception) { if (not have_miss_speculation) state = ROB_END_OK_SPECULATIVE; else state = ROB_END_LOAD_MISS_SPECULATIVE; } else state = ROB_END_EXCEPTION_WAIT_HEAD; break; } case ROB_STORE_WAIT_END_OK : { if (not have_exception) state = ROB_STORE_OK; else state = ROB_STORE_EVENT; break; } case ROB_STORE_WAIT_END_KO : { // if (not have_exception) state = ROB_STORE_KO; // else // state = ROB_END_EXCEPTION_WAIT_HEAD; break; } default : { throw ERRORMORPHEO(FUNCTION,toString(_("Commit [%d] : Bank [%d][%d], invalid state value (%s).\n"),x,i,j,toString(state).c_str())); break; } } // Commit an instruction ... // Test if have an event (miss_speculation or exception) if (have_exception or have_miss_speculation) { // Two case : // if no previous manage event -> generate an event // if previous manage event -> next generate an event // bool flush = reg_EVENT_FLUSH [front_end_id][context_id]; bool flush = ((reg_EVENT_STATE [front_end_id][context_id] == COMMIT_EVENT_STATE_EVENT) or // (reg_EVENT_STATE [front_end_id][context_id] == COMMIT_EVENT_STATE_WAIT_DECOD) or (reg_EVENT_STATE [front_end_id][context_id] == COMMIT_EVENT_STATE_WAIT_END)// or // (reg_EVENT_STATE [front_end_id][context_id] == COMMIT_EVENT_STATE_END) ); uint32_t packet = ((entry->ptr << _param->_shift_num_slot) | i); uint32_t _top = ((_rob[ reg_NUM_BANK_HEAD].front()->ptr << _param->_shift_num_slot) | reg_NUM_BANK_HEAD); log_printf(TRACE,Commit_unit,FUNCTION," * flush : %d",flush); log_printf(TRACE,Commit_unit,FUNCTION," * packet : %d",packet); if (not flush) { bool can = true; // test have a previous event detected (event_stop = 1) // if yes, test if the actual event if "before (in order)" that the previous event if (reg_EVENT_STATE [front_end_id][context_id] == COMMIT_EVENT_STATE_NOT_YET_EVENT) { // Compare packet_id (by construction instruction is insert in order by increase packet_id) uint32_t _old = reg_EVENT_PACKET [front_end_id][context_id]; uint32_t _new = packet; if (_old < _top) _old = _old+_param->_size_queue; if (_new < _top) _new = _new+_param->_size_queue; if (_new < _old) reg_EVENT_PACKET [front_end_id][context_id] = packet; else can = false; } else reg_EVENT_PACKET [front_end_id][context_id] = packet; if (can) { // have an error, stop issue instruction reg_EVENT_STATE [front_end_id][context_id] = COMMIT_EVENT_STATE_NOT_YET_EVENT; // reg_EVENT_DEPTH [front_end_id][context_id] = _rob[packet].depth; reg_EVENT_NB_INST [front_end_id][context_id] = reg_NB_INST_COMMIT_ALL [front_end_id][context_id]; //reg_EVENT_STOP [front_end_id][context_id] = true; reg_EVENT_LAST_NUM_BANK [front_end_id][context_id] = ((reg_NUM_BANK_TAIL==0)?_param->_nb_bank:reg_NUM_BANK_TAIL)-1; reg_EVENT_LAST_NUM_PTR [front_end_id][context_id] = reg_NUM_PTR_TAIL; } } else { bool find = true; log_printf(TRACE,Commit_unit,FUNCTION," * reg_EVENT_NEXT_STOP : %d",reg_EVENT_NEXT_STOP [front_end_id][context_id]); log_printf(TRACE,Commit_unit,FUNCTION," * reg_EVENT_NEXT_PACKET : %d",reg_EVENT_NEXT_PACKET[front_end_id][context_id]); // already manage an event. if (reg_EVENT_NEXT_STOP [front_end_id][context_id]) { // after last ? uint32_t _old = reg_EVENT_NEXT_PACKET [front_end_id][context_id]; uint32_t _new = packet; log_printf(TRACE,Commit_unit,FUNCTION," * _top : %d",_top ); log_printf(TRACE,Commit_unit,FUNCTION," * _old (before) : %d",_old ); log_printf(TRACE,Commit_unit,FUNCTION," * _new (before) : %d",_new ); if (_old < _top) _old = _old+_param->_size_queue; if (_new < _top) _new = _new+_param->_size_queue; if (_new > _old) reg_EVENT_NEXT_PACKET [front_end_id][context_id] = packet; else find = false; log_printf(TRACE,Commit_unit,FUNCTION," * _old (after) : %d",_old ); log_printf(TRACE,Commit_unit,FUNCTION," * _new (after) : %d",_new ); } else { // after last ? uint32_t _old = ((reg_EVENT_LAST_NUM_PTR [front_end_id][context_id] << _param->_shift_num_slot) | reg_EVENT_LAST_NUM_BANK [front_end_id][context_id]); uint32_t _new = packet; log_printf(TRACE,Commit_unit,FUNCTION," * _top : %d",_top ); log_printf(TRACE,Commit_unit,FUNCTION," * _old (before) : %d",_old ); log_printf(TRACE,Commit_unit,FUNCTION," * _new (before) : %d",_new ); if (_old < _top) _old = _old+_param->_size_queue; if (_new < _top) _new = _new+_param->_size_queue; if (_new > _old) reg_EVENT_NEXT_PACKET [front_end_id][context_id] = packet; else find = false; log_printf(TRACE,Commit_unit,FUNCTION," * _old (after) : %d",_old ); log_printf(TRACE,Commit_unit,FUNCTION," * _new (after) : %d",_new ); } log_printf(TRACE,Commit_unit,FUNCTION," * find : %d",find); if (find) reg_EVENT_NEXT_STOP [front_end_id][context_id] = true; // in all case : need stop } } // Update Re Order Buffer entry->state = state; entry->exception = exception; entry->flags = PORT_READ(in_COMMIT_FLAGS [x]); entry->no_sequence = no_sequence; // jalr, jr : address_dest is in register if (( 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->load_data = PORT_READ(in_COMMIT_ADDRESS [x]); entry->cycle_commit = simulation_cycle(); #endif } } // =================================================================== // =====[ RETIRE ]==================================================== // =================================================================== for (uint32_t i=0; i<_param->_nb_bank; i++) { // Compute bank number uint32_t num_bank = (internal_BANK_RETIRE_HEAD+i)%_param->_nb_bank; // Test if have an request if (internal_BANK_RETIRE_VAL [num_bank]) { // Take num instruction uint32_t x = internal_BANK_RETIRE_NUM_RENAME_UNIT [num_bank]; #ifdef DEBUG uint32_t y = internal_BANK_RETIRE_NUM_INST [num_bank]; #endif 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 #ifdef STATISTICS if (usage_is_set(_usage,USE_STATISTICS)) stat_nb_inst_retire [x] ++; #endif // Read information entry_t * entry = _rob [num_bank].front(); entry->state_old = entry->state; entry->state = ROB_END; // Update RAT_UPDATE_TABLE Tcontext_t front_end_id = entry->front_end_id; Tcontext_t context_id = entry->context_id ; if (entry->write_rd and internal_BANK_RETIRE_RESTORE_RD_PHY_OLD [num_bank]) rat_gpr_update_table [front_end_id][context_id][entry->num_reg_rd_log] = true; if (entry->write_re and internal_BANK_RETIRE_RESTORE_RE_PHY_OLD [num_bank]) rat_spr_update_table [front_end_id][context_id][entry->num_reg_re_log] = true; } } for (uint32_t i=0; i<_param->_nb_bank; i++) { // Compute bank number bool can_continue = false; uint32_t num_bank = reg_NUM_BANK_HEAD; if (not _rob [num_bank].empty ()) { entry_t * entry = _rob [num_bank].front(); if (entry->state == ROB_END) { log_printf(TRACE,Commit_unit,FUNCTION," * RETIRE_ROB [%d]",num_bank); can_continue = true; 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]; rob_state_t state = entry->state_old; Ttype_t type = entry->type ; Toperation_t operation = entry->operation ; bool retire_ok = false; uint32_t packet_id = ((entry->ptr << _param->_shift_num_slot) | num_bank); 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",packet_id ); 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()); // Test if the instruction is valid // (BRANCH_MISS = instruction branch is valid, but have make an invalid prediction) // (LOAD_MISS = instruction load is valid, but have make an invalid result) 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; // Update PC information // 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] = 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); } // Test if have an event if ((state == ROB_END_BRANCH_MISS) or (state == ROB_END_LOAD_MISS)) { reg_EVENT_STATE [front_end_id][context_id] = COMMIT_EVENT_STATE_EVENT; reg_EVENT_TYPE [front_end_id][context_id] = rob_state_to_event_type(state); // reg_EVENT_STOP [front_end_id][context_id] = false; // instruction flow can continue reg_EVENT_LAST [front_end_id][context_id] = false; // it the head ! reg_EVENT_PACKET [front_end_id][context_id] = packet_id; reg_EVENT_DEPTH [front_end_id][context_id] = entry->depth; // // If event is an load_miss, many instruction can be inserted. // // -> new last instruction // if (state == ROB_END_LOAD_MISS) // { // // reg_EVENT_CAN_RESTART [front_end_id][context_id] = false; // reg_EVENT_LAST_NUM_BANK [front_end_id][context_id] = ((reg_NUM_BANK_TAIL==0)?_param->_nb_bank:reg_NUM_BANK_TAIL)-1; // reg_EVENT_LAST_NUM_PTR [front_end_id][context_id] = reg_NUM_PTR_TAIL; // } } // Test if this instruction is the last instruction of an event // * need event // * packet id = last packet id // for (uint32_t x=0; x<_param->_nb_front_end; x++) // for (uint32_t y=0; y<_param->_nb_context [x]; y++) // if (((reg_EVENT_STATE [x][y] != COMMIT_EVENT_STATE_NO_EVENT ) and // (reg_EVENT_STATE [x][y] != COMMIT_EVENT_STATE_NOT_YET_EVENT)) and // (reg_EVENT_LAST_NUM_BANK [x][y] == num_bank ) and // (reg_EVENT_LAST_NUM_PTR [x][y] == entry->ptr )) // reg_EVENT_LAST [x][y] = true; if (reg_EVENT_NB_INST [front_end_id][context_id] > 0) { reg_EVENT_NB_INST [front_end_id][context_id] --; if (reg_EVENT_NB_INST [front_end_id][context_id] == 0) reg_EVENT_LAST [front_end_id][context_id] = true; } // 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] --; if (_param->_front_end_rat_scheme[front_end_id] == RAT_DEPTH_SAVE) reg_NB_INST_DEPTH [front_end_id][context_id][entry->depth] --; // Update pointer reg_NUM_BANK_HEAD = (num_bank+1)%_param->_nb_bank; // Reset watch dog timer because have transaction on retire interface _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)) { if (retire_ok) { uint32_t instruction = entry->instruction; (*_stat_nb_inst_retire_ok [num_thread] ) ++; (*_stat_nb_inst_instruction [instruction]) ++; (*_stat_nb_inst_type [type] ) ++; //uint32_t index = (_stat_last_inst [num_thread] << SIZE_INSTRUCTION) | instruction; uint32_t index = ((_stat_last_inst_type [num_thread] << (SIZE_TYPE+2*SIZE_OPERATION)) | (_stat_last_inst_operation [num_thread] << (SIZE_TYPE+ SIZE_OPERATION)) | ( type << ( SIZE_OPERATION)) | ( operation )); _stat_inst_fusion [num_thread][index] ++; //_stat_last_inst [num_thread] = instruction; _stat_last_inst_type [num_thread] = type ; _stat_last_inst_operation [num_thread] = operation ; } else (*_stat_nb_inst_retire_ko [num_thread]) ++; } #endif #if defined(DEBUG) and defined(DEBUG_Commit_unit) and (DEBUG_Commit_unit == true) if (log_file_generate) { // log file instruction_log_file [num_thread] << "[" << simulation_cycle() << "] " << std::hex << (entry->address<<2) << " (" << (entry->address) << ") " << std::dec << "[" << entry->cycle_rob_in << ", " << entry->cycle_commit << "] " << "{" << ((retire_ok)?"OK":"KO") << "} "; if ((type == TYPE_MEMORY) and is_operation_memory_load(operation)) instruction_log_file [num_thread] << std::hex << entry->load_data << std::dec; instruction_log_file [num_thread] << std::endl; } #endif // Remove entry delete entry; _rob [num_bank].pop_front(); } } if (not can_continue) break; // stop scan } // =================================================================== // =====[ REEXECUTE ]================================================= // =================================================================== // Test if have an reexecute instruction (an store in head of rob) for (uint32_t i=0; i<_param->_nb_inst_reexecute; ++i) if (internal_REEXECUTE_VAL [i] and PORT_READ(in_REEXECUTE_ACK [i])) { log_printf(TRACE,Commit_unit,FUNCTION," * REEXECUTE [%d]",i); uint32_t num_bank = internal_REEXECUTE_NUM_BANK [i]; entry_t * entry = _rob [num_bank].front(); rob_state_t state = entry->state; // Change state switch (state) { case ROB_STORE_OK : {state = ROB_STORE_OK_WAIT_END; break; } case ROB_STORE_KO : {state = ROB_STORE_KO_WAIT_END; break; } case ROB_STORE_EVENT : {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++) // Test if the prediction_unit have accept the branch complete transaction if (internal_BRANCH_COMPLETE_VAL [i] and PORT_READ(in_BRANCH_COMPLETE_ACK [i])) { log_printf(TRACE,Commit_unit,FUNCTION," * BRANCH_COMPLETE [%d]",i); // Read information 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]); log_printf(TRACE,Commit_unit,FUNCTION," * miss_prediction : %d",miss); entry->state = (miss)?ROB_END_BRANCH_MISS_SPECULATIVE:ROB_END_OK_SPECULATIVE; // bool flush = reg_EVENT_FLUSH [entry->front_end_id][entry->context_id]; // Branch_complete can be execute if // * no present event // * futur event and most not speculative that the event // Also, test if in this cycle, they have not an most recently event !!! if (miss) { bool can = true; uint32_t packet = ((entry->ptr << _param->_shift_num_slot) | num_bank); // test if this packet is before previous event if (reg_EVENT_STATE [entry->front_end_id][entry->context_id] == COMMIT_EVENT_STATE_NOT_YET_EVENT) { uint32_t _top = ((_rob[ reg_NUM_BANK_HEAD].front()->ptr << _param->_shift_num_slot) | reg_NUM_BANK_HEAD); uint32_t _old = reg_EVENT_PACKET [entry->front_end_id][entry->context_id]; uint32_t _new = packet; if (_old < _top) _old = _old+_param->_size_queue; if (_new < _top) _new = _new+_param->_size_queue; if (_new < _old) reg_EVENT_PACKET [entry->front_end_id][entry->context_id] = packet; else can = false; } else reg_EVENT_PACKET [entry->front_end_id][entry->context_id] = packet; if (can) { // In all case, stop instruction flow reg_EVENT_STATE [entry->front_end_id][entry->context_id] = COMMIT_EVENT_STATE_NOT_YET_EVENT; // reg_EVENT_DEPTH [entry->front_end_id][entry->context_id] = _rob[packet]._depth; reg_EVENT_NB_INST [entry->front_end_id][entry->context_id] = reg_NB_INST_COMMIT_ALL [entry->front_end_id][entry->context_id]; // reg_EVENT_STOP [entry->front_end_id][entry->context_id] = true; // reg_EVENT_CAN_RESTART [entry->front_end_id][entry->context_id] = false; reg_EVENT_LAST_NUM_BANK [entry->front_end_id][entry->context_id] = ((reg_NUM_BANK_TAIL==0)?_param->_nb_bank:reg_NUM_BANK_TAIL)-1; reg_EVENT_LAST_NUM_PTR [entry->front_end_id][entry->context_id] = reg_NUM_PTR_TAIL; } } } // =================================================================== // =====[ UPDATE ]==================================================== // =================================================================== // Update when exception or load_miss if (internal_UPDATE_VAL and PORT_READ(in_UPDATE_ACK)) { log_printf(TRACE,Commit_unit,FUNCTION," * UPDATE"); // Change state 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 ]============================================== // =================================================================== { bool can_continue [_param->_nb_front_end][_param->_max_nb_context]; uint32_t event_nb_inst [_param->_nb_front_end][_param->_max_nb_context]; bool is_speculative [_param->_nb_front_end][_param->_max_nb_context]; for (uint32_t i=0; i<_param->_nb_front_end; i++) for (uint32_t j=0; j<_param->_nb_context [i]; j++) { event_nb_inst [i][j] = 0; is_speculative[i][j] = false; can_continue [i][j] = (((reg_EVENT_NB_INST [i][j] == 0) or ( event_nb_inst [i][j] < reg_EVENT_NB_INST [i][j])) and not reg_EVENT_LAST [i][j]); } // Read all instruction of all top bank for (uint32_t i=0; i<_param->_nb_bank; i++) { uint32_t num_bank = (reg_NUM_BANK_HEAD+i)%_param->_nb_bank; // Test if have an instruction if (not _rob[num_bank].empty()) { // Scan all instruction in windows and test if instruction is speculative entry_t * entry = _rob [num_bank].front(); uint32_t num_packet = ((entry->ptr << _param->_shift_num_slot) | num_bank); Tcontext_t front_end_id = entry->front_end_id; Tcontext_t context_id = entry->context_id ; log_printf(TRACE,Commit_unit,FUNCTION," * HEAD [%d] - %d",num_bank,num_packet); 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," * EVENT_LAST : %d",reg_EVENT_LAST [front_end_id][context_id]); log_printf(TRACE,Commit_unit,FUNCTION," * EVENT_NB_INST : %d",reg_EVENT_NB_INST [front_end_id][context_id]); log_printf(TRACE,Commit_unit,FUNCTION," * event_nb_inst : %d", event_nb_inst [front_end_id][context_id]); // scan while last event instruction is not retire if (can_continue [front_end_id][context_id]) { // Read information 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_STATE [front_end_id][context_id] == COMMIT_EVENT_STATE_EVENT) or // (reg_EVENT_STATE [front_end_id][context_id] == COMMIT_EVENT_STATE_WAIT_DECOD) or (reg_EVENT_STATE [front_end_id][context_id] == COMMIT_EVENT_STATE_WAIT_END)); bool speculative = is_speculative [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); // no event Tcontrol_t is_valid = not flush; //Tcontrol_t is_valid = ((depth == depth_min) and not flush); 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," * speculative : %d",speculative); log_printf(TRACE,Commit_unit,FUNCTION," * flush : %d",flush); log_printf(TRACE,Commit_unit,FUNCTION," * state (before) : %s",toString(state).c_str()); // //------------------------------------------------------ // // Event ? // //------------------------------------------------------ // if ((reg_EVENT_STATE [front_end_id][context_id] == COMMIT_EVENT_STATE_NOT_YET_EVENT) and // (reg_EVENT_PACKET [front_end_id][context_id] == num_packet)) // { // switch (state) // { // 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;} // case ROB_END_BRANCH_MISS : // case ROB_END_LOAD_MISS : // case ROB_END : // {break;} // default : // { // throw ERRORMORPHEO(FUNCTION,toString(_("Head [%d] : invalid state (%s)"),num_packet,toString(state).c_str())); // break; // } // } // } //------------------------------------------------------ // test if instruction is miss speculative //------------------------------------------------------ if (not is_valid) { // Change state 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 : case ROB_END_LOAD_MISS_UPDATE : case ROB_END_LOAD_MISS_SPECULATIVE : {state = ROB_END_MISS ; break;} case ROB_STORE_OK : {state = ROB_STORE_KO ; break;} case ROB_STORE_WAIT_END_OK : {state = ROB_STORE_WAIT_END_KO; break;} case ROB_STORE_OK_WAIT_END : {state = ROB_STORE_KO_WAIT_END; 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 state -> wait case ROB_STORE_WAIT_END_KO : {break;} case ROB_STORE_KO : {break;} case ROB_STORE_KO_WAIT_END : {break;} case ROB_STORE_EVENT : {break;} case ROB_EVENT_WAIT_END : {break;} case ROB_END_MISS : {break;} case ROB_END : {break;} // can't have miss speculation -> invalid state default : { throw ERRORMORPHEO(FUNCTION,toString(_("Miss Speculation : Invalide state : %s.\n"),toString(state).c_str())); break; } } } //------------------------------------------------------ // test if instruction is branch not finish //------------------------------------------------------ switch (state) { case ROB_BRANCH_WAIT_END : case ROB_BRANCH_COMPLETE : { is_speculative [front_end_id][context_id] = true; break; } default : break; } //------------------------------------------------------ // test if instruction is not speculative //------------------------------------------------------ // entry->speculative = speculative; // if (entry->depth == depth_min) // test if instruction is speculative (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 wait head and is the top of rob //------------------------------------------------------ // TODO : retire OOO if (i == 0) { 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 } } // Write new state entry->state = state; log_printf(TRACE,Commit_unit,FUNCTION," * state (after ) : %s",toString(state).c_str()); // log_printf(TRACE,Commit_unit,FUNCTION," * Stop Scan !!!"); event_nb_inst [front_end_id][context_id] ++; // stop if : // * begin event // * end event if (((reg_EVENT_STATE [front_end_id][context_id] == COMMIT_EVENT_STATE_NOT_YET_EVENT) and (reg_EVENT_PACKET[front_end_id][context_id] == num_packet)) or ((reg_EVENT_NB_INST [front_end_id][context_id] > 0) and ( event_nb_inst [front_end_id][context_id] >= reg_EVENT_NB_INST [front_end_id][context_id]))) can_continue [front_end_id][context_id] = false; } } } } #ifdef STATISTICS if (usage_is_set(_usage,USE_STATISTICS)) { for (uint32_t i=0; i<_param->_nb_bank; i++) *(_stat_bank_nb_inst [i]) += _rob[i].size(); for (uint32_t i=0; i<_param->_nb_front_end; i++) for (uint32_t j=0; j<_param->_nb_context [i]; j++) { uint32_t num_thread = _param->_translate_num_context_to_num_thread [i][j]; switch (reg_EVENT_STATE [i][j]) { case COMMIT_EVENT_STATE_NO_EVENT : (*_stat_nb_cycle_state_no_event [num_thread])++; break; case COMMIT_EVENT_STATE_NOT_YET_EVENT : (*_stat_nb_cycle_state_not_yet_event [num_thread])++; break; case COMMIT_EVENT_STATE_EVENT : (*_stat_nb_cycle_state_event [num_thread])++; break; case COMMIT_EVENT_STATE_WAIT_END : (*_stat_nb_cycle_state_wait_end [num_thread])++; break; } } for (uint32_t i=0; i<_param->_nb_rename_unit; ++i) { (*_stat_nb_inst_insert [i]) += stat_nb_inst_insert [i]; (*_stat_nb_inst_retire [i]) += stat_nb_inst_retire [i]; (*_stat_nb_inst_commit [i]) += stat_nb_inst_commit [i]; } } #endif } // =================================================================== // =====[ OTHER ]===================================================== // =================================================================== #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); log_printf(TRACE,Commit_unit,FUNCTION," * num_ptr_tail : %d",reg_NUM_PTR_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 - %s",toString(reg_EVENT_STATE [i][j]).c_str(),toString(commit_event_state_to_event_state(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," * EVENT : %d (bank %d, ptr %d)",((reg_EVENT_NUM_PTR [i][j] << _param->_shift_num_slot) | reg_EVENT_NUM_BANK [i][j]), reg_EVENT_NUM_BANK [i][j],reg_EVENT_NUM_PTR [i][j]); // log_printf(TRACE,Commit_unit,FUNCTION," * EVENT_CAN_RESTART : %d",reg_EVENT_CAN_RESTART [i][j]); log_printf(TRACE,Commit_unit,FUNCTION," * EVENT_DEPTH : %d",reg_EVENT_DEPTH [i][j]); log_printf(TRACE,Commit_unit,FUNCTION," * EVENT_TYPE : %s",toString(reg_EVENT_TYPE [i][j]).c_str()); log_printf(TRACE,Commit_unit,FUNCTION," * EVENT_LAST : %d - packet %d - ptr %d (bank %d, ptr %d)",reg_EVENT_LAST [i][j],reg_EVENT_PACKET[i][j],((reg_EVENT_LAST_NUM_PTR [i][j] << _param->_shift_num_slot) | reg_EVENT_LAST_NUM_BANK [i][j]), reg_EVENT_LAST_NUM_BANK [i][j],reg_EVENT_LAST_NUM_PTR [i][j]); log_printf(TRACE,Commit_unit,FUNCTION," * EVENT_NEXT : stop : %d - packet : %d",reg_EVENT_NEXT_STOP [i][j],reg_EVENT_NEXT_PACKET[i][j]); log_printf(TRACE,Commit_unit,FUNCTION," * NB_INST_ALL : all : %d - mem : %d - event : %d",reg_NB_INST_COMMIT_ALL[i][j], reg_NB_INST_COMMIT_MEM[i][j],reg_EVENT_NB_INST[i][j]); log_printf(TRACE,Commit_unit,FUNCTION," * PC : %.8x (%.8x) - %d %d - %.8x (%.8x)",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],reg_PC_NEXT [i][j],reg_PC_NEXT [i][j]<<2); } std::list::iterator iter [_param->_nb_bank]; 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]); iter [num_bank] = _rob[num_bank].begin(); } bool all_empty = false; uint32_t nb_write_rd = 0; uint32_t nb_write_re = 0; while (not all_empty) { all_empty = true; for (uint32_t i=0; i<_param->_nb_bank; i++) { uint32_t num_bank = (reg_NUM_BANK_HEAD+i)%_param->_nb_bank; std::list::iterator it = iter[num_bank]; if (it != _rob[num_bank].end()) { all_empty = false; nb_write_rd += ((*it)->write_rd)?1:0; nb_write_re += ((*it)->write_re)?1:0; log_printf(TRACE,Commit_unit,FUNCTION," [%.4d][%.4d] %.4d %.4d %.4d %.4d, %.3d %.3d, %.1d, %.1d %.4d, %.1d %.4d, %s", 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," (%.4d) %.1d %.2d %.6d, %.1d %.2d %.6d, %.1d %.1d %.6d, %.1d %.2d %.6d %.6d, %.1d %.1d %.6d %.6d ", (((*it)->ptr << _param->_shift_num_slot) | num_bank), (*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 - %.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 ); iter [num_bank] ++; } } } log_printf(TRACE,Commit_unit,FUNCTION," * Dump RAT_Update Table"); for (uint32_t i=0; i<_param->_nb_front_end; ++i) for (uint32_t j=0; j<_param->_nb_context[i]; ++j) { { std::string str = ""; for (uint32_t k=0; k<_param->_nb_general_register_logic; k++) str+=toString("%.1d ",rat_gpr_update_table[i][j][k]); log_printf(TRACE,Commit_unit,FUNCTION," * GPR [%d][%d] %s",i,j,str.c_str()); } { std::string str = ""; for (uint32_t k=0; k<_param->_nb_special_register_logic; k++) str+=toString("%.1d ",rat_spr_update_table[i][j][k]); log_printf(TRACE,Commit_unit,FUNCTION," * GPR [%d][%d] %s",i,j,str.c_str()); } } log_printf(TRACE,Commit_unit,FUNCTION," * nb_write_rd : %d",nb_write_rd); log_printf(TRACE,Commit_unit,FUNCTION," * nb_write_re : %d",nb_write_re); } #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 (0x%x) is different of reg_PC_CURRENT[%d][%d] (0x%x).\n"), entry->address, entry->front_end_id, entry->context_id, reg_PC_CURRENT[entry->front_end_id][entry->context_id])); } } { uint32_t NB_INST [_param->_nb_front_end][_param->_max_nb_context]; for (uint32_t i=0; i<_param->_nb_front_end; i++) for (uint32_t j=0; j<_param->_nb_context [i]; j++) NB_INST [i][j] = 0; //reg_EVENT_NB_INST [i][j]; for (uint32_t i=0; i<_param->_nb_bank; ++i) for (std::list::iterator it=_rob[i].begin(); it!=_rob [i].end(); ++it) NB_INST [(*it)->front_end_id][(*it)->context_id] ++; for (uint32_t i=0; i<_param->_nb_front_end; i++) for (uint32_t j=0; j<_param->_nb_context [i]; j++) if (NB_INST [i][j] != reg_NB_INST_COMMIT_ALL [i][j]) throw ERRORMORPHEO(FUNCTION,toString(_("Context [%d][%d] have not the good nb_inst (%d in rob, %d in register).\n"),i,j,NB_INST[i][j], reg_NB_INST_COMMIT_ALL [i][j])); } #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