#ifdef SYSTEMC /* * $Id: Context_State_transition.cpp 83 2008-05-09 18:00:21Z rosiere $ * * [ Description ] * */ #include "Behavioural/Core/Multi_Front_end/Front_end/Context_State/include/Context_State.h" namespace morpheo { namespace behavioural { namespace core { namespace multi_front_end { namespace front_end { namespace context_state { #undef FUNCTION #define FUNCTION "Context_State::transition" void Context_State::transition (void) { log_begin(Context_State,FUNCTION); if (PORT_READ(in_NRESET) == 0) { for (uint32_t i=0; i<_param->_nb_context; i++) reg_STATE [i] = CONTEXT_STATE_OK; } else { // ------------------------------------------------------------------- // -----[ DECOD_EVENT ]----------------------------------------------- // ------------------------------------------------------------------- for (uint32_t i=0; i<_param->_nb_decod_unit; i++) if (PORT_READ(in_DECOD_EVENT_VAL [i]) and internal_DECOD_EVENT_ACK [i]) { Tcontext_t context = (_param->_have_port_context_id )?PORT_READ(in_DECOD_EVENT_CONTEXT_ID [i]):0; Tdepth_t depth = (_param->_have_port_max_depth )?PORT_READ(in_DECOD_EVENT_DEPTH [i]):0; Tdepth_t depth_cur = reg_EVENT_DEPTH [context]; Tdepth_t depth_base = (_param->_have_port_depth [context])?PORT_READ(in_DEPTH_TAIL [context]):0; Tdepth_t depth_max = _param->_size_depth [context]; Tdepth_t depth0 = (depth_cur>=depth_base)?(depth_cur-depth_base):((depth_cur+depth_max-depth_base)); Tdepth_t depth1 = (depth >=depth_base)?(depth -depth_base):((depth +depth_max-depth_base)); context_state_t state = reg_STATE [context]; Tevent_type_t type = PORT_READ(in_DECOD_EVENT_TYPE [i]); // miss > excep > spr/sync uint8_t priority0 = (state == CONTEXT_STATE_KO_MISS)?2:((state == CONTEXT_STATE_KO_EXCEP)?1:0); uint8_t priority1 = (state == EVENT_TYPE_EXCEPTION)?1:0; // is_valid = can modify local information // if context_state_ok : yes // if context_state_ko : test the depth, and the priority of envent bool is_valid = ((state == CONTEXT_STATE_OK) or (depth1< depth0) or ((depth1==depth0) and (priority1>priority0))); if (is_valid) { // decod : // type : csync, psync, msync, spr_access (l.mac, l.maci, l.macrc, l.msb, l.mfspr, l.mtspr), exception (l.sys) context_state_t state_next = state; Taddress_t address = PORT_READ(in_DECOD_EVENT_ADDRESS [i]); Tcontrol_t is_delay_slot = PORT_READ(in_DECOD_EVENT_IS_DELAY_SLOT [i]); switch (type) { case EVENT_TYPE_EXCEPTION : { state_next = CONTEXT_STATE_KO_EXCEP; break; } case EVENT_TYPE_SPR_ACCESS : { state_next = CONTEXT_STATE_KO_SPR ; address++; // take next address if (is_delay_slot) throw ERRORMORPHEO(FUNCTION,"SPR access in delay slot, not supported.\n"); break; } case EVENT_TYPE_MSYNC : { state_next = CONTEXT_STATE_KO_MSYNC; address++; // take next address if (is_delay_slot) throw ERRORMORPHEO(FUNCTION,"SPR access in delay slot, not supported.\n"); break; } case EVENT_TYPE_PSYNC : { state_next = CONTEXT_STATE_KO_PSYNC; address++; // take next address if (is_delay_slot) throw ERRORMORPHEO(FUNCTION,"SPR access in delay slot, not supported.\n"); break; } case EVENT_TYPE_CSYNC : { state_next = CONTEXT_STATE_KO_CSYNC; address++; // take next address if (is_delay_slot) throw ERRORMORPHEO(FUNCTION,"SPR access in delay slot, not supported.\n"); break; } case EVENT_TYPE_NONE : case EVENT_TYPE_MISS_SPECULATION : case EVENT_TYPE_BRANCH_NO_ACCURATE : default : { throw ERRORMORPHEO(FUNCTION,toString(_("DECOD_EVENT [%d] : invalid event_type : %s.\n"),i,toString(type).c_str())); } } reg_STATE [context] = state_next; reg_EVENT_ADDRESS [context] = address; reg_EVENT_ADDRESS_EPCR [context] = PORT_READ(in_DECOD_EVENT_ADDRESS_EPCR [i]); reg_EVENT_ADDRESS_EPCR_VAL [context] = 1; //reg_EVENT_ADDRESS_EEAR [context] reg_EVENT_ADDRESS_EEAR_VAL [context] = 0; reg_EVENT_IS_DELAY_SLOT [context] = is_delay_slot; //reg_EVENT_IS_DS_TAKE [context] = 0; reg_EVENT_DEPTH [context] = depth; } } // ------------------------------------------------------------------- // -----[ COMMIT_EVENT ]---------------------------------------------- // ------------------------------------------------------------------- for (uint32_t i=0; i<_param->_nb_ooo_engine; i++) if (PORT_READ(in_COMMIT_EVENT_VAL [i]) and internal_COMMIT_EVENT_ACK [i]) { Tcontext_t context = (_param->_have_port_context_id )?PORT_READ(in_COMMIT_EVENT_CONTEXT_ID [i]):0; Tdepth_t depth = (_param->_have_port_max_depth )?PORT_READ(in_COMMIT_EVENT_DEPTH [i]):0; Tdepth_t depth_cur = reg_EVENT_DEPTH [context]; Tdepth_t depth_base = (_param->_have_port_depth [context])?PORT_READ(in_DEPTH_TAIL [context]):0; Tdepth_t depth_max = _param->_size_depth [context]; Tdepth_t depth0 = (depth_cur>=depth_base)?(depth_cur-depth_base):((depth_cur+depth_max-depth_base)); Tdepth_t depth1 = (depth >=depth_base)?(depth -depth_base):((depth +depth_max-depth_base)); context_state_t state = reg_STATE [context]; Tevent_type_t type = PORT_READ(in_COMMIT_EVENT_TYPE [i]); // miss > excep > spr/sync uint8_t priority0 = (state == CONTEXT_STATE_KO_MISS)?2:((state == CONTEXT_STATE_KO_EXCEP)?1:0); uint8_t priority1 = 1; // is_valid = can modify local information // if context_state_ok : yes // if context_state_ko : test the depth, and the priority of envent bool is_valid = ((state == CONTEXT_STATE_OK) or (depth1< depth0) or ((depth1==depth0) and (priority1>priority0))); if (is_valid) { // commit // type : exception context_state_t state_next = state; switch (type) { case EVENT_TYPE_EXCEPTION : {state_next = CONTEXT_STATE_KO_EXCEP; break;} case EVENT_TYPE_SPR_ACCESS : case EVENT_TYPE_MSYNC : case EVENT_TYPE_PSYNC : case EVENT_TYPE_CSYNC : case EVENT_TYPE_NONE : case EVENT_TYPE_MISS_SPECULATION : case EVENT_TYPE_BRANCH_NO_ACCURATE : default : { throw ERRORMORPHEO(FUNCTION,toString(_("COMMIT_EVENT [%d] : invalid event_type : %s.\n"),i,toString(type).c_str())); } } reg_STATE [context] = state_next; reg_EVENT_ADDRESS [context] = PORT_READ(in_COMMIT_EVENT_ADDRESS [i]); reg_EVENT_ADDRESS_EPCR [context] = PORT_READ(in_COMMIT_EVENT_ADDRESS_EPCR [i]); reg_EVENT_ADDRESS_EPCR_VAL [context] = 1; reg_EVENT_ADDRESS_EEAR [context] = PORT_READ(in_COMMIT_EVENT_ADDRESS_EEAR [i]); reg_EVENT_ADDRESS_EEAR_VAL [context] = PORT_READ(in_COMMIT_EVENT_ADDRESS_EEAR_VAL [i]); reg_EVENT_IS_DELAY_SLOT [context] = PORT_READ(in_COMMIT_EVENT_IS_DELAY_SLOT [i]); //reg_EVENT_IS_DS_TAKE [context] = 0; reg_EVENT_DEPTH [context] = depth; } } // ------------------------------------------------------------------- // -----[ BRANCH_COMPLETE ]------------------------------------------- // ------------------------------------------------------------------- for (uint32_t i=0; i<_param->_nb_inst_branch_complete; i++) if (PORT_READ(in_BRANCH_COMPLETE_VAL [i]) and internal_BRANCH_COMPLETE_ACK [i]) { if (PORT_READ(in_BRANCH_COMPLETE_MISS_PREDICTION [i])) { Tcontext_t context = (_param->_have_port_context_id )?PORT_READ(in_BRANCH_COMPLETE_CONTEXT_ID [i]):0; Tdepth_t depth = (_param->_have_port_max_depth )?PORT_READ(in_BRANCH_COMPLETE_DEPTH [i]):0; Tdepth_t depth_cur = reg_EVENT_DEPTH [context]; Tdepth_t depth_base = (_param->_have_port_depth [context])?PORT_READ(in_DEPTH_TAIL [context]):0; Tdepth_t depth_max = _param->_size_depth [context]; Tdepth_t depth0 = (depth_cur>=depth_base)?(depth_cur-depth_base):((depth_cur+depth_max-depth_base)); Tdepth_t depth1 = (depth >=depth_base)?(depth -depth_base):((depth +depth_max-depth_base)); context_state_t state = reg_STATE [context]; // miss > excep > spr/sync uint8_t priority0 = (state == CONTEXT_STATE_KO_MISS)?2:((state == CONTEXT_STATE_KO_EXCEP)?1:0); uint8_t priority1 = 2; // is_valid = can modify local information // if context_state_ok : yes // if context_state_ko : test the depth, and the priority of envent bool is_valid = ((state == CONTEXT_STATE_OK) or (depth1< depth0) or ((depth1==depth0) and (priority1>priority0))); if (is_valid) { // commit Tcontrol_t take = PORT_READ(in_BRANCH_COMPLETE_TAKE [i]); reg_STATE [context] = CONTEXT_STATE_KO_MISS; reg_EVENT_ADDRESS [context] = PORT_READ(in_BRANCH_COMPLETE_ADDRESS_SRC [i])+1; //DELAY_SLOT reg_EVENT_ADDRESS_EPCR [context] = PORT_READ(in_BRANCH_COMPLETE_ADDRESS_DEST [i]); reg_EVENT_ADDRESS_EPCR_VAL [context] = take; // if not take : in sequence //reg_EVENT_ADDRESS_EEAR [context]; //reg_EVENT_ADDRESS_EEAR_VAL [context]; reg_EVENT_IS_DELAY_SLOT [context] = take; reg_EVENT_IS_DS_TAKE [context] = take; reg_EVENT_DEPTH [context] = depth; } } } // ------------------------------------------------------------------- // -----[ EVENT ]----------------------------------------------------- // ------------------------------------------------------------------- for (uint32_t i=0; i<_param->_nb_context; i++) if (internal_EVENT_VAL [i] and PORT_READ(in_EVENT_ACK [i])) { // Write pc context_state_t state = reg_STATE [i]; switch (state) { case CONTEXT_STATE_KO_EXCEP_ADDR : { reg_STATE [i] = CONTEXT_STATE_KO_EXCEP_SPR; break; } case CONTEXT_STATE_KO_MISS_ADDR : case CONTEXT_STATE_KO_PSYNC_ADDR : case CONTEXT_STATE_KO_CSYNC_ADDR : { reg_STATE [i] = CONTEXT_STATE_OK; break; } default : { #ifdef DEBUG_TEST throw ERRORMORPHEO(FUNCTION,toString(_("SPR[%d], Invalid state : %s.\n"),i,toString(state).c_str())); #endif break; } } } // ------------------------------------------------------------------- // -----[ SPR ]------------------------------------------------------- // ------------------------------------------------------------------- for (uint32_t i=0; i<_param->_nb_context; i++) if (internal_SPR_VAL [i] and PORT_READ(in_SPR_ACK [i])) { // Write spr #ifdef DEBUG_TEST context_state_t state = reg_STATE [i]; if (state != CONTEXT_STATE_KO_EXCEP_SPR) throw ERRORMORPHEO(FUNCTION,toString(_("SPR[%d], Invalid state : %s.\n"),i,toString(state).c_str())); #endif reg_STATE [i] = CONTEXT_STATE_OK; } // ------------------------------------------------------------------- // -----[ next state ]------------------------------------------------ // ------------------------------------------------------------------- for (uint32_t i=0; i<_param->_nb_context; i++) { uint32_t x = _param->_link_context_to_decod_unit [i]; uint32_t y = _param->_link_decod_unit_to_ooo_engine [x]; Tcounter_t inst_all = PORT_READ(in_NB_INST_COMMIT_ALL [y]) + PORT_READ(in_NB_INST_DECOD_ALL [x]); Tcounter_t inst_mem = PORT_READ(in_NB_INST_COMMIT_MEM [y]) + PORT_READ(in_NB_INST_DECOD_ALL [x]); context_state_t state = reg_STATE [i]; switch (state) { case CONTEXT_STATE_OK : { // nothing, wait an event break; } case CONTEXT_STATE_KO_EXCEP : { // Wait end of all instruction if (inst_all == 0) state = CONTEXT_STATE_KO_EXCEP_ADDR; break; } case CONTEXT_STATE_KO_MISS : { // Wait end of all instruction if (inst_all == 0) state = CONTEXT_STATE_KO_MISS_ADDR; break; } case CONTEXT_STATE_KO_EXCEP_ADDR : { // nothing, wait the update of internal register (pc) break; } case CONTEXT_STATE_KO_EXCEP_SPR : { // nothing, wait the update of internal register (epcr, eear, sr, esr) break; } case CONTEXT_STATE_KO_MISS_ADDR : { // nothing, wait the update of internal register (pc) break; } case CONTEXT_STATE_KO_PSYNC : { // Wait end of all instruction if (inst_all == 0) // state = CONTEXT_STATE_KO_PSYNC_FLUSH; state = CONTEXT_STATE_KO_PSYNC_ADDR ; break; } // case CONTEXT_STATE_KO_PSYNC_FLUSH : // { // // nothing, wait end of flush (ifetch) // break; // } case CONTEXT_STATE_KO_PSYNC_ADDR : { // nothing, wait the pc write break; } case CONTEXT_STATE_KO_CSYNC : { // Wait end of all instruction if (inst_all == 0) state = CONTEXT_STATE_KO_CSYNC_ADDR ; // state = CONTEXT_STATE_KO_CSYNC_FLUSH; break; } // case CONTEXT_STATE_KO_CSYNC_FLUSH : // { // // nothing, wait end of flush (all internal structure) // break; // } case CONTEXT_STATE_KO_CSYNC_ADDR : { // nothing, wait the pc write break; } case CONTEXT_STATE_KO_MSYNC : { // Wait end of memory instruction if (inst_mem == 0) state = CONTEXT_STATE_KO_MSYNC_ISSUE; break; } case CONTEXT_STATE_KO_MSYNC_ISSUE : { // Wait the msync issue if (inst_mem != 0) state = CONTEXT_STATE_KO_MSYNC_EXEC; break; } case CONTEXT_STATE_KO_MSYNC_EXEC : { // Wait the end of msync if (inst_mem == 0) state = CONTEXT_STATE_OK; break; } case CONTEXT_STATE_KO_SPR : { // Wait end of all instruction if (inst_all == 0) state = CONTEXT_STATE_KO_SPR_ISSUE; break; } case CONTEXT_STATE_KO_SPR_ISSUE : { // Wait the spr_access issue if (inst_all != 0) state = CONTEXT_STATE_KO_SPR_EXEC; break; } case CONTEXT_STATE_KO_SPR_EXEC : { // Wait the spr_access execution if (inst_all == 0) state = CONTEXT_STATE_OK; break; } default : { throw ERRORMORPHEO(FUNCTION,toString(_("Context[%d], Unknow state : %s.\n"),i,toString(state).c_str())); } } reg_STATE [i] = state; } } #if DEBUG >= DEBUG_TRACE for (uint32_t i=0; i<_param->_nb_context; i++) { log_printf(TRACE,Context_State,FUNCTION,"Context State [%d]",i); log_printf(TRACE,Context_State,FUNCTION," * reg_STATE : %s" ,toString(reg_STATE [i]).c_str()); log_printf(TRACE,Context_State,FUNCTION," * reg_EVENT_ADDRESS : 0x%x",reg_EVENT_ADDRESS [i]); log_printf(TRACE,Context_State,FUNCTION," * reg_EVENT_ADDRESS_EPCR : 0x%x",reg_EVENT_ADDRESS_EPCR [i]); log_printf(TRACE,Context_State,FUNCTION," * reg_EVENT_ADDRESS_EPCR_VAL : %d" ,reg_EVENT_ADDRESS_EPCR_VAL [i]); log_printf(TRACE,Context_State,FUNCTION," * reg_EVENT_ADDRESS_EEAR : 0x%x",reg_EVENT_ADDRESS_EEAR [i]); log_printf(TRACE,Context_State,FUNCTION," * reg_EVENT_ADDRESS_EEAR_VAL : %d" ,reg_EVENT_ADDRESS_EEAR_VAL [i]); log_printf(TRACE,Context_State,FUNCTION," * reg_EVENT_IS_DELAY_SLOT : %d" ,reg_EVENT_IS_DELAY_SLOT [i]); log_printf(TRACE,Context_State,FUNCTION," * reg_EVENT_IS_DS_TAKE : %d" ,reg_EVENT_IS_DS_TAKE [i]); log_printf(TRACE,Context_State,FUNCTION," * reg_EVENT_DEPTH : %d" ,reg_EVENT_DEPTH [i]); } #endif #if defined(STATISTICS) or defined(VHDL_TESTBENCH) end_cycle (); #endif log_end(Context_State,FUNCTION); }; }; // end namespace context_state }; // end namespace front_end }; // end namespace multi_front_end }; // end namespace core }; // end namespace behavioural }; // end namespace morpheo #endif