#ifdef SYSTEMC /* * $Id: Commit_unit_transition.cpp 88 2008-12-10 18:31:39Z 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::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) { for (uint32_t i=0; i<_param->_nb_bank; i++) { _rob [i].clear(); reg_BANK_PTR [i] = 0; } reg_NUM_BANK_HEAD = 0; reg_NUM_BANK_TAIL = 0; for (uint32_t i=0; i<_param->_nb_front_end; i++) for (uint32_t j=0; j<_param->_nb_context [i]; j++) { reg_NB_INST_COMMIT_ALL [i][j] = 0; reg_NB_INST_COMMIT_MEM [i][j] = 0; } _priority_insert->reset(); } else { // next priority _priority_insert->transition(); // =================================================================== // =====[ INSERT ]==================================================== // =================================================================== for (uint32_t i=0; i<_param->_nb_bank; i++) if (internal_BANK_INSERT_VAL [i]) { 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); #ifdef STATISTICS if (usage_is_set(_usage,USE_STATISTICS)) (*_stat_nb_inst_insert [x]) ++; #endif 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]); 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(type).c_str()); log_printf(TRACE,Commit_unit,FUNCTION," * operation : %d",operation ); log_printf(TRACE,Commit_unit,FUNCTION," * exception : %d",exception ); 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_operation_memory_store(operation)); entry->use_load_queue = (type == TYPE_MEMORY) and (not is_operation_memory_store(operation)); 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]); 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=ROB_STORE_WAIT_HEAD_OK; break;} default : {entry->state=(no_execute==1)?ROB_END_OK_SPECULATIVE:ROB_OTHER_WAIT_END; break;} } } else { // in_INSERT_NO_EXECUTE [x][y] : l.sys, l.trap entry->state = ROB_END_EXCEPTION_WAIT_HEAD; } _rob[i].push_back(entry); // 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_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]) { 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 // Tpacket_t packet_id = (_param->_have_port_rob_ptr )?(PORT_READ(in_COMMIT_PACKET_ID [x])&_param->_mask_size_bank):0; log_printf(TRACE,Commit_unit,FUNCTION," * num_bank : %d",i); // log_printf(TRACE,Commit_unit,FUNCTION," * packet_id : %d",(_param->_have_port_rob_ptr )?(PORT_READ(in_COMMIT_PACKET_ID [x])):0); // log_printf(TRACE,Commit_unit,FUNCTION," * num_entry : %d",packet_id); // test pandex with ptr_write. // Tpacket_t index = (packet_id_size_bank+reg_BANK_PTR [i]-packet_id); // 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 if exception : exception and mask bool have_exception = false; if (exception != EXCEPTION_NONE) switch (entry->exception_use) { 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 EXCEPTION_USE_TRAP : {have_exception = false; break;}; case EXCEPTION_USE_NONE : {have_exception = false; break;}; case EXCEPTION_USE_ILLEGAL_INSTRUCTION : {have_exception = false; break;}; case EXCEPTION_USE_SYSCALL : {have_exception = false; break;}; default : { throw ERRORMORPHEO(FUNCTION,_("Commit : invalid exception_use.\n")); break; } } if (not have_exception) { switch (state) { case ROB_OTHER_WAIT_END : {state = ROB_END_OK_SPECULATIVE; break;} case ROB_BRANCH_WAIT_END : {state = ROB_BRANCH_COMPLETE ; break;} case ROB_MISS_WAIT_END : {state = ROB_END_KO_SPECULATIVE; break;} default : { throw ERRORMORPHEO(FUNCTION,toString(_("Commit : invalid state value (%s).\n"),toString(state).c_str())); break; } } // can have an exception, but this instruction is not sensible a this exception exception = EXCEPTION_NONE; } else { #ifdef DEBUG_TEST if ((entry->type == TYPE_MEMORY) and (exception == EXCEPTION_MEMORY_LOAD_SPECULATIVE)) throw ERRORMORPHEO(FUNCTION,_("Commit : invalid exception.\n")); #endif switch (state) { case ROB_OTHER_WAIT_END : case ROB_BRANCH_WAIT_END : {state = ROB_END_EXCEPTION_WAIT_HEAD; break;} case ROB_MISS_WAIT_END : {state = ROB_END_KO_SPECULATIVE ; break;} default : { throw ERRORMORPHEO(FUNCTION,_("Commit : invalid state value.\n")); break; } } } // 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]); entry->data_commit = PORT_READ(in_COMMIT_ADDRESS [x]); } } // =================================================================== // =====[ RETIRE ]==================================================== // =================================================================== for (uint32_t i=0; i<_param->_nb_bank; i++) if (internal_BANK_RETIRE_VAL [i]) { uint32_t x = internal_BANK_RETIRE_NUM_RENAME_UNIT [i]; uint32_t y = internal_BANK_RETIRE_NUM_INST [i]; log_printf(TRACE,Commit_unit,FUNCTION," * RETIRE [%d][%d]",x,y); #ifdef STATISTICS if (usage_is_set(_usage,USE_STATISTICS)) (*_stat_nb_inst_retire [x]) ++; #endif #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 [i].front(); Tcontext_t front_end_id = entry->front_end_id; Tcontext_t context_id = entry->context_id ; Ttype_t type = entry->type ; // 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 [i].pop_front(); delete entry; } // =================================================================== // =====[ REEXECUTE ]================================================= // =================================================================== if (internal_REEXECUTE_VAL [0] and PORT_READ(in_REEXECUTE_ACK [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_MISS_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])) { 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 entry->state = ROB_END_OK_SPECULATIVE; } // =================================================================== // =====[ EVENT ]===================================================== // =================================================================== // =================================================================== // =====[ 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 = PORT_READ(in_DEPTH_MAX[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 Tcontrol_t is_valid = ((depth == depth_min) or ((depth_min < depth_max)? (depth depth_min) or (depth < depth_max)))); //------------------------------------------------------ // test if instruction is miss speculative //------------------------------------------------------ if (not is_valid) { switch (state) { case ROB_BRANCH_WAIT_END : {state = ROB_MISS_WAIT_END; break;} case ROB_BRANCH_COMPLETE : {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_MISS_WAIT_END; break;} case ROB_END_OK_SPECULATIVE : {state = ROB_END_MISS ; break;} case ROB_END_KO_SPECULATIVE : {state = ROB_END_MISS ; break;} case ROB_END_EXCEPTION_WAIT_HEAD : {state = ROB_END_MISS ; break;} // don't change case ROB_STORE_HEAD_KO : {break;} case ROB_MISS_WAIT_END : {break;} case ROB_END_MISS : {break;} // can't have miss speculation case ROB_STORE_HEAD_OK : case ROB_END_OK : case ROB_END_KO : case ROB_END_EXCEPTION : default : { throw ERRORMORPHEO(FUNCTION,_("Miss Speculation : Invalide state.\n")); break; } } } //------------------------------------------------------ // test if instruction is not speculative //------------------------------------------------------ if (entry->depth == depth_min) { switch (state) { case ROB_END_OK_SPECULATIVE : {state = ROB_END_OK ; break;} case ROB_END_KO_SPECULATIVE : {state = ROB_END_KO ; break;} default : {break;} } } //------------------------------------------------------ // 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; break;} default : {break;} } } entry->state = state; } } // =================================================================== // =====[ OTHER ]===================================================== // =================================================================== 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," * num_inst[%d][%d] all : %d, mem : %d",i,j,reg_NB_INST_COMMIT_ALL[i][j],reg_NB_INST_COMMIT_MEM[i][j]); for (uint32_t i=0; i<_param->_nb_bank; i++) { log_printf(TRACE,Commit_unit,FUNCTION," * Bank[%d] size : %d, ptr : %d",i,(int)_rob[i].size(), reg_BANK_PTR [i]); #ifdef STATISTICS if (usage_is_set(_usage,USE_STATISTICS)) *(_stat_bank_nb_inst [i]) += _rob[i].size(); #endif uint32_t x=0; for (std::list::iterator it=_rob[i].begin(); it!=_rob[i].end(); it++) { log_printf(TRACE,Commit_unit,FUNCTION," [%d] %.8x (%.8x) %s - ptr : %d", x, (*it)->address, (*it)->address<<2, toString((*it)->state).c_str(), (*it)->ptr); x++; } } #if defined(STATISTICS) or defined(VHDL_TESTBENCH) end_cycle (); #endif 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