#ifdef SYSTEMC /* * $Id: Commit_unit_genMoore.cpp 139 2010-07-30 14:47:27Z rosiere $ * * [ Description ] * */ #include "Behavioural/Core/Multi_OOO_Engine/OOO_Engine/Commit_unit/include/Commit_unit.h" namespace morpheo { namespace behavioural { namespace core { namespace multi_ooo_engine { namespace ooo_engine { namespace commit_unit { #undef FUNCTION #define FUNCTION "Commit_unit::genMoore" void Commit_unit::genMoore (void) { log_begin(Commit_unit,FUNCTION); log_function(Commit_unit,FUNCTION,_name.c_str()); if (PORT_READ(in_NRESET)) { // =================================================================== // =====[ REEXECUTE ]================================================= // =================================================================== { uint32_t num_scan_bank = 0; // last scan bank bool can_continue = true; uint32_t event_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++) event_nb_inst [i][j] = 0; // for each reexecute_port for (uint32_t i=0; i<_param->_nb_inst_reexecute; ++i) { log_printf(TRACE,Commit_unit,FUNCTION," * REEXECUTE [%d]",i); // Store instruction comming Out Of Order in Load Store Unit. // Must be executed in no speculative mode. Also, send a signal when an Store is in head of ROB Tcontrol_t val = false; for (uint32_t j=num_scan_bank; j<_param->_nb_bank; j++) { num_scan_bank ++; // translate bank number uint32_t num_bank = (reg_NUM_BANK_HEAD+j)%_param->_nb_bank; log_printf(TRACE,Commit_unit,FUNCTION," * num_bank : %d",num_bank); // Test if the head of rob is not empty if (not _rob[num_bank].empty()) { log_printf(TRACE,Commit_unit,FUNCTION," * ROB is not empty"); // Read state 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 ; rob_state_t state = entry->state; // Test state // * store is ko, send signal at store_queue // * store_is ok, test if in head // val = (((state == ROB_STORE_OK) and (num_bank == (reg_NUM_BANK_HEAD))) or // (state == ROB_STORE_KO) or // (state == ROB_STORE_EVENT) // ); val = (((state == ROB_STORE_OK) and can_continue) or (state == ROB_STORE_KO) or (state == ROB_STORE_EVENT) ); event_nb_inst [front_end_id][context_id] ++; can_continue &= (((state == ROB_STORE_OK ) or (state == ROB_STORE_OK_WAIT_END ) or (state == ROB_END_OK_SPECULATIVE) or (state == ROB_END_OK ) or (state == ROB_END )) and not ((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)) and not ((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])) ); log_printf(TRACE,Commit_unit,FUNCTION," * val : %d",val); if (val) { internal_REEXECUTE_NUM_BANK [i] = num_bank; Tpacket_t packet_id = ((entry->ptr << _param->_shift_num_slot) | num_bank); log_printf(TRACE,Commit_unit,FUNCTION," * packet_id : %d",packet_id); // Reexecute store if (_param->_have_port_context_id) PORT_WRITE(out_REEXECUTE_CONTEXT_ID [i], entry->context_id ); if (_param->_have_port_front_end_id) PORT_WRITE(out_REEXECUTE_FRONT_END_ID [i], entry->front_end_id ); if (_param->_have_port_rob_ptr ) PORT_WRITE(out_REEXECUTE_PACKET_ID [i], packet_id ); PORT_WRITE(out_REEXECUTE_TYPE [i], entry->type ); PORT_WRITE(out_REEXECUTE_STORE_QUEUE_PTR_WRITE [i], entry->store_queue_ptr_write); PORT_WRITE(out_REEXECUTE_OPERATION [i], (state == ROB_STORE_OK)?OPERATION_MEMORY_STORE_HEAD_OK:OPERATION_MEMORY_STORE_HEAD_KO); break; // Stop scan } } } internal_REEXECUTE_VAL [i] = val; } } // =================================================================== // =====[ BRANCH_COMPLETE ]=========================================== // =================================================================== { // Branchement must be send at the prediction unit uint32_t num_scan_bank = 0; // last scan bank // for each port, find a valid branchement. for (uint32_t i=0; i<_param->_nb_inst_branch_complete; i++) { log_printf(TRACE,Commit_unit,FUNCTION," * BRANCH_COMPLETE [%d]",i); Tcontrol_t val = false; for (uint32_t j=num_scan_bank; j<_param->_nb_bank; j++) { num_scan_bank ++; // translate bank number uint32_t num_bank = (reg_NUM_BANK_HEAD+j)%_param->_nb_bank; log_printf(TRACE,Commit_unit,FUNCTION," * num_bank : %d",num_bank); // Test if in this bank, they have an instruction if (not _rob [num_bank].empty()) { log_printf(TRACE,Commit_unit,FUNCTION," * not empty"); // Read information 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 ; log_printf(TRACE,Commit_unit,FUNCTION," * front_end_id : %d",front_end_id); log_printf(TRACE,Commit_unit,FUNCTION," * context_id : %d",context_id ); // don't complete a branch when rob manage an present event if (((reg_EVENT_STATE [front_end_id][context_id] == COMMIT_EVENT_STATE_NO_EVENT) or (reg_EVENT_STATE [front_end_id][context_id] == COMMIT_EVENT_STATE_NOT_YET_EVENT)) and (state == ROB_BRANCH_COMPLETE)) { log_printf(TRACE,Commit_unit,FUNCTION," * find !!!"); // test if have a future event (stop is set) // log_printf(TRACE,Commit_unit,FUNCTION," * reg_EVENT_STOP : %d",reg_EVENT_STOP [front_end_id][context_id]); if (reg_EVENT_STATE [front_end_id][context_id] == COMMIT_EVENT_STATE_NOT_YET_EVENT) { // Have future event, can complete the branch if the event is most speculative than this branchement // Also, need compare packet_id (is order) uint32_t _top = ((_rob[reg_NUM_BANK_HEAD].front()->ptr << _param->_shift_num_slot) | reg_NUM_BANK_HEAD); uint32_t _old = reg_EVENT_PACKET [front_end_id][context_id]; uint32_t _new = ((entry->ptr << _param->_shift_num_slot) | num_bank); // 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) val = true; // log_printf(TRACE,Commit_unit,FUNCTION," * _old (after ) : %d",_old); // log_printf(TRACE,Commit_unit,FUNCTION," * _new (after ) : %d",_new); } else val = true; log_printf(TRACE,Commit_unit,FUNCTION," * val : %d",val); if (val) { // Have an valid branchement to complete internal_BRANCH_COMPLETE_NUM_BANK [i] = num_bank; if (_param->_have_port_front_end_id) PORT_WRITE(out_BRANCH_COMPLETE_FRONT_END_ID [i], front_end_id ); if (_param->_have_port_context_id) PORT_WRITE(out_BRANCH_COMPLETE_CONTEXT_ID [i], context_id ); if (_param->_have_port_depth) PORT_WRITE(out_BRANCH_COMPLETE_DEPTH [i], entry->depth ); PORT_WRITE(out_BRANCH_COMPLETE_ADDRESS [i], entry->address_next ); // PORT_WRITE(out_BRANCH_COMPLETE_FLAG [i],(entry->flags&FLAG_F)!=0); PORT_WRITE(out_BRANCH_COMPLETE_NO_SEQUENCE [i], entry->no_sequence ); break; // Stop scan } } } } internal_BRANCH_COMPLETE_VAL [i] = val; } } // =================================================================== // =====[ UPDATE ]==================================================== // =================================================================== { internal_UPDATE_VAL = 0; internal_UPDATE_NUM_BANK = reg_NUM_BANK_HEAD; // Test if have an instruction if (not _rob[internal_UPDATE_NUM_BANK].empty()) { log_printf(TRACE,Commit_unit,FUNCTION," * UPDATE"); log_printf(TRACE,Commit_unit,FUNCTION," * num_bank : %d",internal_UPDATE_NUM_BANK); entry_t * entry = _rob [internal_UPDATE_NUM_BANK].front(); // Test state // Update if exception or load miss switch (entry->state) { case ROB_END_EXCEPTION_UPDATE : { internal_UPDATE_VAL = 1; 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"); internal_UPDATE_VAL = 1; Tcontext_t front_end_id = entry->front_end_id; Tcontext_t context_id = entry->context_id ; log_printf(TRACE,Commit_unit,FUNCTION," * front_end_id : %d",front_end_id); log_printf(TRACE,Commit_unit,FUNCTION," * context_id : %d",context_id ); if (_param->_have_port_front_end_id) PORT_WRITE(out_UPDATE_FRONT_END_ID ,front_end_id); if (_param->_have_port_context_id) PORT_WRITE(out_UPDATE_CONTEXT_ID ,context_id ); if (_param->_have_port_depth) PORT_WRITE(out_UPDATE_DEPTH ,entry->depth); PORT_WRITE(out_UPDATE_TYPE ,EVENT_TYPE_LOAD_MISS_SPECULATION); // PORT_WRITE(out_UPDATE_IS_DELAY_SLOT ,reg_PC_CURRENT_IS_DS [front_end_id][context_id]); // PORT_WRITE(out_UPDATE_ADDRESS ,reg_PC_CURRENT [front_end_id][context_id]); // PORT_WRITE(out_UPDATE_ADDRESS_EPCR_VAL,reg_PC_CURRENT_IS_DS_TAKE [front_end_id][context_id]); // PORT_WRITE(out_UPDATE_ADDRESS_EPCR ,reg_PC_NEXT [front_end_id][context_id]); // PORT_WRITE(out_UPDATE_ADDRESS_EEAR_VAL,0); // // PORT_WRITE(out_UPDATE_ADDRESS_EEAR ,); PORT_WRITE(out_UPDATE_IS_DELAY_SLOT ,0); PORT_WRITE(out_UPDATE_ADDRESS ,reg_PC_NEXT [front_end_id][context_id]); PORT_WRITE(out_UPDATE_ADDRESS_EPCR_VAL,0); // PORT_WRITE(out_UPDATE_ADDRESS_EPCR ,); PORT_WRITE(out_UPDATE_ADDRESS_EEAR_VAL,0); // PORT_WRITE(out_UPDATE_ADDRESS_EEAR ,); break; } default : { // internal_UPDATE_VAL = 0; } } } log_printf(TRACE,Commit_unit,FUNCTION," * UPDATE (end)"); } // =================================================================== // =====[ NB_INST ]=================================================== // =================================================================== { #ifdef DEBUG_TEST bool empty = true; #endif for (uint32_t i=0; i<_param->_nb_front_end; i++) for (uint32_t j=0; j<_param->_nb_context [i]; j++) { #ifdef DEBUG_TEST empty &= (reg_NB_INST_COMMIT_ALL [i][j] == 0); #endif PORT_WRITE(out_NB_INST_COMMIT_ALL [i][j], reg_NB_INST_COMMIT_ALL [i][j]); PORT_WRITE(out_NB_INST_COMMIT_MEM [i][j], reg_NB_INST_COMMIT_MEM [i][j]); } #ifdef DEBUG_TEST PORT_WRITE(out_INFO_ROB_EMPTY,empty); #endif } // =================================================================== // =====[ RETIRE_EVENT ]============================================== // =================================================================== for (uint32_t i=0; i<_param->_nb_front_end; i++) for (uint32_t j=0; j<_param->_nb_context [i]; j++) { // bool flush = (((reg_EVENT_STATE [i][j] == COMMIT_EVENT_STATE_EVENT) or // (reg_EVENT_STATE [i][j] == COMMIT_EVENT_STATE_WAIT_DECOD)) and // not reg_EVENT_CAN_RESTART[i][j]); PORT_WRITE(out_RETIRE_EVENT_STATE [i][j], commit_event_state_to_event_state(reg_EVENT_STATE[i][j])); // PORT_WRITE(out_RETIRE_EVENT_FLUSH [i][j], flush); // PORT_WRITE(out_RETIRE_EVENT_STOP [i][j], reg_EVENT_STOP [i][j]); PORT_WRITE(out_RETIRE_EVENT_STOP [i][j], ((reg_EVENT_STATE [i][j] == COMMIT_EVENT_STATE_NOT_YET_EVENT) or reg_EVENT_NEXT_STOP [i][j])); if (_param->_rat_scheme[i] == RAT_DEPTH_SAVE) { PORT_WRITE(out_RETIRE_EVENT_TYPE [i][j], reg_EVENT_TYPE [i][j]); if (_param->_have_port_depth) PORT_WRITE(out_RETIRE_EVENT_DEPTH [i][j], reg_EVENT_DEPTH [i][j]); } } } else { for (uint32_t i=0; i<_param->_nb_inst_reexecute; ++i) { internal_REEXECUTE_VAL [i] = 0; // internal_REEXECUTE_NUM_BANK [i] = num_bank; } for (uint32_t i=0; i<_param->_nb_inst_branch_complete; i++) { internal_BRANCH_COMPLETE_VAL [i] = 0; // internal_BRANCH_COMPLETE_NUM_BANK [i] = num_bank; } internal_UPDATE_VAL = 0; // internal_UPDATE_NUM_BANK = reg_NUM_BANK_HEAD; for (uint32_t i=0; i<_param->_nb_front_end; i++) for (uint32_t j=0; j<_param->_nb_context [i]; j++) { PORT_WRITE(out_RETIRE_EVENT_STATE [i][j], commit_event_state_to_event_state(COMMIT_EVENT_STATE_NO_EVENT)); // PORT_WRITE(out_RETIRE_EVENT_FLUSH [i][j], flush); // PORT_WRITE(out_RETIRE_EVENT_STOP [i][j], reg_EVENT_STOP [i][j]); PORT_WRITE(out_RETIRE_EVENT_STOP [i][j], true); } } for (uint32_t i=0; i<_param->_nb_inst_reexecute; ++i) PORT_WRITE(out_REEXECUTE_VAL[i], internal_REEXECUTE_VAL [i]); for (uint32_t i=0; i<_param->_nb_inst_branch_complete; i++) PORT_WRITE(out_BRANCH_COMPLETE_VAL [i], internal_BRANCH_COMPLETE_VAL [i]); PORT_WRITE(out_UPDATE_VAL, internal_UPDATE_VAL); 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