#ifdef SYSTEMC /* * $Id: Context_State_transition.cpp 145 2010-10-13 18:15:51Z 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 { // #define MANAGE_EVENT MANAGE_EVENT_WAIT_ALL // #define MANAGE_EVENT MANAGE_EVENT_WAIT_DECODE #define MANAGE_EVENT MANAGE_EVENT_NO_WAIT #define PRIORITY_MISS_LOAD 3 #define PRIORITY_MISS_BRANCH 2 #define PRIORITY_EXCEPTION 1 #define PRIORITY_NONE 0 #define get_priority(x) \ (((state == CONTEXT_STATE_KO_MISS_LOAD_ADDR ) or \ (state == CONTEXT_STATE_KO_MISS_LOAD_WAITEND ) or \ (state == CONTEXT_STATE_KO_MISS_LOAD_AND_BRANCH_ADDR ) or \ (state == CONTEXT_STATE_KO_MISS_LOAD_AND_BRANCH_WAITEND ) or \ (state == CONTEXT_STATE_KO_MISS_LOAD_AND_BRANCH_WAIT_UPDATE))?PRIORITY_MISS_LOAD: \ (((state == CONTEXT_STATE_KO_MISS_BRANCH_ADDR ) or \ (state == CONTEXT_STATE_KO_MISS_BRANCH_WAITEND ) or \ (state == CONTEXT_STATE_KO_MISS_BRANCH_INACCURATE ) or \ (state == CONTEXT_STATE_KO_MISS_BRANCH_WAIT_UPDATE ))?PRIORITY_MISS_BRANCH: \ ((state == EVENT_TYPE_EXCEPTION)?PRIORITY_EXCEPTION: \ 0))) #undef FUNCTION #define FUNCTION "Context_State::transition" void Context_State::transition (void) { log_begin(Context_State,FUNCTION); log_function(Context_State,FUNCTION,_name.c_str()); if (PORT_READ(in_NRESET) == 0) { for (uint32_t i=0; i<_param->_nb_context; i++) { reg_STATE [i] = CONTEXT_STATE_OK; reg_INTERRUPT_ENABLE [i] = 0; reg_EVENT_ADDRESS [i] = 0; // not necessary reg_EVENT_ADDRESS_EPCR [i] = 0; // not necessary reg_EVENT_ADDRESS_EPCR_VAL [i] = 0; // not necessary reg_EVENT_ADDRESS_EEAR [i] = 0; // not necessary reg_EVENT_ADDRESS_EEAR_VAL [i] = 0; // not necessary reg_EVENT_IS_DELAY_SLOT [i] = 0; // not necessary reg_EVENT_IS_DS_TAKE [i] = 0; // not necessary reg_EVENT_DEPTH [i] = 0; // not necessary reg_EVENT_FLUSH_ONLY [i] = 0; // not necessary } } else { // ------------------------------------------------------------------- // -----[ next state ]------------------------------------------------ // ------------------------------------------------------------------- for (uint32_t i=0; i<_param->_nb_context; i++) { // uint32_t x = _param->_link_context_to_decod_unit [i]; Tcounter_t inst_commit_all = PORT_READ(in_NB_INST_COMMIT_ALL[i]); // Tcounter_t inst_commit_mem = PORT_READ(in_NB_INST_COMMIT_MEM[i]); Tcounter_t inst_decod_all = PORT_READ(in_NB_INST_DECOD_ALL [i]); Tcounter_t inst_all = inst_commit_all + inst_decod_all; // Tcounter_t inst_mem = inst_commit_mem + inst_decod_all; bool condition = ( (MANAGE_EVENT == MANAGE_EVENT_WAIT_ALL )?(inst_all == 0): ((MANAGE_EVENT == MANAGE_EVENT_WAIT_DECODE)?(inst_decod_all == 0): true)); 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) // if (inst_decod_all == 0) state = CONTEXT_STATE_KO_EXCEP_ADDR; break; } case CONTEXT_STATE_KO_EXCEP_ADDR : { // nothing, wait the update of internal register (pc) break; } case CONTEXT_STATE_KO_MISS_BRANCH_WAIT_UPDATE : { // nothing : wait end of update upt break; } case CONTEXT_STATE_KO_MISS_BRANCH_WAITEND : { if (condition) // state = CONTEXT_STATE_OK; state = CONTEXT_STATE_KO_MISS_BRANCH_ADDR; break; } case CONTEXT_STATE_KO_MISS_BRANCH_INACCURATE : { if (inst_all == 0) // state = CONTEXT_STATE_OK; state = CONTEXT_STATE_OK; break; } case CONTEXT_STATE_KO_MISS_LOAD_WAITEND : { // Wait end of all instruction if (condition) state = CONTEXT_STATE_KO_MISS_LOAD_ADDR; break; } case CONTEXT_STATE_KO_EXCEP_SPR : { // nothing, wait the update of internal register (epcr, eear, sr, esr) break; } case CONTEXT_STATE_KO_MISS_BRANCH_ADDR : { // nothing, wait the update of internal register (pc) break; } case CONTEXT_STATE_KO_MISS_LOAD_ADDR : { // nothing, wait the update of internal register (pc) break; } case CONTEXT_STATE_KO_MISS_LOAD_AND_BRANCH_WAIT_UPDATE : { // nothing : wait end of update upt break; } case CONTEXT_STATE_KO_MISS_LOAD_AND_BRANCH_ADDR : { // nothing, wait the update of internal register (pc) break; } case CONTEXT_STATE_KO_MISS_LOAD_AND_BRANCH_WAITEND : { // Wait end of all instruction if (condition) // state = CONTEXT_STATE_OK; // @@@ TODO : make MISS fast (miss decod) state = CONTEXT_STATE_KO_MISS_LOAD_AND_BRANCH_ADDR; break; } // case CONTEXT_STATE_KO_PSYNC : // { // // Wait end of all instruction // if (inst_all == 0) // state = CONTEXT_STATE_KO_PSYNC_FLUSH; // break; // } case CONTEXT_STATE_KO_PSYNC_FLUSH : { // nothing, wait end of flush (ifetch) if (inst_all == 0) // state = CONTEXT_STATE_KO_PSYNC_ADDR; state = CONTEXT_STATE_OK; 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_FLUSH; // break; // } case CONTEXT_STATE_KO_CSYNC_FLUSH : { // nothing, wait end of flush (all internal structure) if (inst_all == 0) state = CONTEXT_STATE_KO_CSYNC_ADDR; 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_all == 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; } // ------------------------------------------------------------------- // -----[ BRANCH_EVENT ]---------------------------------------------- // ------------------------------------------------------------------- for (uint32_t i=0; i<_param->_nb_context; ++i) if (PORT_READ(in_BRANCH_EVENT_VAL [i]) and internal_BRANCH_EVENT_ACK [i]) { log_printf(TRACE,Context_State,FUNCTION," * BRANCH_EVENT [%d]",i); context_state_t state = reg_STATE [i]; Tdepth_t depth = (_param->_have_port_depth)?PORT_READ(in_BRANCH_EVENT_DEPTH [i]):0; Tdepth_t depth_cur = reg_EVENT_DEPTH [i]; Tdepth_t depth_min = (_param->_have_port_depth)?PORT_READ(in_DEPTH_MIN [i]):0; Tdepth_t depth_max = _param->_nb_inst_branch_speculated [i]; Tdepth_t depth0 = (depth_cur>=depth_min)?(depth_cur-depth_min):((depth_cur+depth_max-depth_min)); Tdepth_t depth1 = (depth >=depth_min)?(depth -depth_min):((depth +depth_max-depth_min)); // Tdepth_t depth0 = (depth_cur>=depth_min)?(depth_cur):((depth_cur+depth_max)); // Tdepth_t depth1 = (depth >=depth_min)?(depth ):((depth +depth_max)); // priority : miss_load > miss_branch > excep > spr/sync uint8_t priority0 = get_priority(state); uint8_t priority1 = PRIORITY_MISS_BRANCH; // miss // is_valid = can modify local information // if context_state_ok : yes // if context_state_ko : test the depth, and the priority of event bool is_valid = ((state == CONTEXT_STATE_OK) or (state == CONTEXT_STATE_KO_MISS_BRANCH_WAIT_UPDATE) or // (state == CONTEXT_STATE_KO_MISS_LOAD_AND_BRANCH_WAIT_UPDATE) or (depth1< depth0) or ((depth1==depth0) and (priority1>=priority0))); // >= because another branch can be a miss prediction with same depth bool is_invalid = priority0 == PRIORITY_MISS_LOAD; #ifdef DEBUG_TEST if ((state == CONTEXT_STATE_KO_MISS_BRANCH_WAIT_UPDATE) and (depth0 != depth1)) throw ERRORMORPHEO(FUNCTION,toString(_("BRANCH_EVENT[%d] : Invalid state : %s.\n"),i,toString(state).c_str())); #endif log_printf(TRACE,Context_State,FUNCTION," * state : %s",toString(state).c_str()); log_printf(TRACE,Context_State,FUNCTION," * depth : %d",depth ); log_printf(TRACE,Context_State,FUNCTION," * depth_cur : %d",depth_cur ); log_printf(TRACE,Context_State,FUNCTION," * depth_min : %d",depth_min ); log_printf(TRACE,Context_State,FUNCTION," * depth_max : %d",depth_max ); log_printf(TRACE,Context_State,FUNCTION," * depth0 : %d",depth0 ); log_printf(TRACE,Context_State,FUNCTION," * depth1 : %d",depth1 ); log_printf(TRACE,Context_State,FUNCTION," * priority0 : %d",priority0 ); log_printf(TRACE,Context_State,FUNCTION," * priority1 : %d",priority1 ); log_printf(TRACE,Context_State,FUNCTION," * is_valid : %d",is_valid ); log_printf(TRACE,Context_State,FUNCTION," * is_invalid : %d",is_invalid); if (is_valid and not is_invalid) { // reg_STATE [i] = CONTEXT_STATE_KO_MISS_BRANCH_ADDR; if (state == CONTEXT_STATE_KO_MISS_LOAD_AND_BRANCH_WAIT_UPDATE) { // #if (MANAGE_EVENT == MANAGE_EVENT_NO_WAIT) // reg_STATE [i] = CONTEXT_STATE_KO_MISS_LOAD_AND_BRANCH_ADDR; // #else reg_STATE [i] = CONTEXT_STATE_KO_MISS_LOAD_AND_BRANCH_WAITEND; // #endif } else { Tcontrol_t can_continue = PORT_READ(in_BRANCH_EVENT_CAN_CONTINUE [i]); Tcontrol_t dest_val = PORT_READ(in_BRANCH_EVENT_ADDRESS_DEST_VAL[i]); log_printf(TRACE,Context_State,FUNCTION," * dest_val : %d",dest_val ); log_printf(TRACE,Context_State,FUNCTION," * can_continue: %d",can_continue); if (can_continue) reg_STATE [i] = CONTEXT_STATE_KO_MISS_BRANCH_ADDR; else // cf UPT : dest_val = direction, accurate depend of jump type (e.g. jr is inacurate) // reg_STATE [i] = CONTEXT_STATE_KO_MISS_BRANCH_WAITEND; reg_STATE [i] = CONTEXT_STATE_KO_MISS_BRANCH_INACCURATE; reg_EVENT_ADDRESS [i] = PORT_READ(in_BRANCH_EVENT_ADDRESS_SRC [i])+1; // address delay slot reg_EVENT_ADDRESS_EPCR [i] = PORT_READ(in_BRANCH_EVENT_ADDRESS_DEST [i]); // address_next reg_EVENT_ADDRESS_EPCR_VAL [i] = dest_val; //reg_EVENT_ADDRESS_EEAR [i] = 0; reg_EVENT_ADDRESS_EEAR_VAL [i] = 0; reg_EVENT_IS_DELAY_SLOT [i] = 1; reg_EVENT_IS_DS_TAKE [i] = dest_val; reg_EVENT_DEPTH [i] = depth; reg_EVENT_FLUSH_ONLY [i] = can_continue; } } } // ------------------------------------------------------------------- // -----[ 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]) { log_printf(TRACE,Context_State,FUNCTION," * DECOD_EVENT [%d]",i); Tcontext_t context = (_param->_have_port_context_id )?PORT_READ(in_DECOD_EVENT_CONTEXT_ID [i]):0; Tdepth_t depth = (_param->_have_port_depth )?PORT_READ(in_DECOD_EVENT_DEPTH [i]):0; Tdepth_t depth_cur = reg_EVENT_DEPTH [context]; Tdepth_t depth_min = (_param->_have_port_depth )?PORT_READ(in_DEPTH_MIN [context]):0; Tdepth_t depth_max = _param->_nb_inst_branch_speculated [context]; Tdepth_t depth0 = (depth_cur>=depth_min)?(depth_cur-depth_min):((depth_cur+depth_max-depth_min)); Tdepth_t depth1 = (depth >=depth_min)?(depth -depth_min):((depth +depth_max-depth_min)); // Tdepth_t depth0 = (depth_cur>=depth_min)?(depth_cur):((depth_cur+depth_max)); // Tdepth_t depth1 = (depth >=depth_min)?(depth ):((depth +depth_max)); context_state_t state = reg_STATE [context]; Tevent_type_t type = PORT_READ(in_DECOD_EVENT_TYPE [i]); // miss_load > miss_branch > excep > spr/sync uint8_t priority0 = get_priority(state); uint8_t priority1 = (state == EVENT_TYPE_EXCEPTION)?PRIORITY_EXCEPTION:PRIORITY_NONE; // 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))); log_printf(TRACE,Context_State,FUNCTION," * depth : %d",depth ); log_printf(TRACE,Context_State,FUNCTION," * depth_cur : %d",depth_cur ); log_printf(TRACE,Context_State,FUNCTION," * depth_min : %d",depth_min ); log_printf(TRACE,Context_State,FUNCTION," * depth_max : %d",depth_max ); log_printf(TRACE,Context_State,FUNCTION," * depth0 : %d",depth0 ); log_printf(TRACE,Context_State,FUNCTION," * depth1 : %d",depth1 ); log_printf(TRACE,Context_State,FUNCTION," * priority0 : %d",priority0 ); log_printf(TRACE,Context_State,FUNCTION," * priority1 : %d",priority1 ); log_printf(TRACE,Context_State,FUNCTION," * is_valid : %d",is_valid ); if (is_valid) { log_printf(TRACE,Context_State,FUNCTION," * 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 : { log_printf(TRACE,Context_State,FUNCTION," * EVENT_TYPE_EXCEPTION"); state_next = CONTEXT_STATE_KO_EXCEP; break; } case EVENT_TYPE_SPR_ACCESS : { log_printf(TRACE,Context_State,FUNCTION," * EVENT_TYPE_SPR_ACCESS"); // state_next = CONTEXT_STATE_KO_SPR ; state_next = CONTEXT_STATE_KO_SPR_EXEC; address++; // take next address // if (is_delay_slot) // throw ERRORMORPHEO(FUNCTION,"SPR access in delay slot, not supported.\n"); break; } case EVENT_TYPE_MSYNC : { log_printf(TRACE,Context_State,FUNCTION," * EVENT_TYPE_MSYNC"); // state_next = CONTEXT_STATE_KO_MSYNC; state_next = CONTEXT_STATE_KO_MSYNC_EXEC; address++; // take next address // if (is_delay_slot) // throw ERRORMORPHEO(FUNCTION,"MSYNC in delay slot, not supported.\n"); break; } case EVENT_TYPE_PSYNC : { log_printf(TRACE,Context_State,FUNCTION," * EVENT_TYPE_PSYNC"); // state_next = CONTEXT_STATE_KO_PSYNC; state_next = CONTEXT_STATE_KO_PSYNC_FLUSH; address++; // take next address if (is_delay_slot) throw ERRORMORPHEO(FUNCTION,"PSYNC in delay slot, not supported.\n"); break; } case EVENT_TYPE_CSYNC : { log_printf(TRACE,Context_State,FUNCTION," * EVENT_TYPE_CSYNC"); // state_next = CONTEXT_STATE_KO_CSYNC; state_next = CONTEXT_STATE_KO_CSYNC_FLUSH; address++; // take next address if (is_delay_slot) throw ERRORMORPHEO(FUNCTION,"CSYNC in delay slot, not supported.\n"); break; } case EVENT_TYPE_NONE : case EVENT_TYPE_BRANCH_MISS_SPECULATION : case EVENT_TYPE_LOAD_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; reg_EVENT_FLUSH_ONLY [context] = false; } } // ------------------------------------------------------------------- // -----[ EVENT ]----------------------------------------------------- // ------------------------------------------------------------------- for (uint32_t i=0; i<_param->_nb_context; i++) if (internal_EVENT_VAL [i] and PORT_READ(in_EVENT_ACK [i])) { log_printf(TRACE,Context_State,FUNCTION," * EVENT [%d]",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_BRANCH_ADDR: // { // reg_STATE [i] = CONTEXT_STATE_KO_MISS_WAITEND; //@@@ TODO : make MISS fast (miss decod) // break; // } case CONTEXT_STATE_KO_MISS_LOAD_ADDR : case CONTEXT_STATE_KO_PSYNC_ADDR : case CONTEXT_STATE_KO_CSYNC_ADDR : { reg_STATE [i] = CONTEXT_STATE_OK; break; } case CONTEXT_STATE_KO_MISS_LOAD_AND_BRANCH_ADDR: { reg_STATE [i] = CONTEXT_STATE_KO_MISS_LOAD_ADDR; break; } default : { #ifdef DEBUG_TEST throw ERRORMORPHEO(FUNCTION,toString(_("SPR[%d], Invalid state : %s.\n"),i,toString(state).c_str())); #endif break; } } } // ------------------------------------------------------------------- // -----[ 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] and PORT_READ(in_BRANCH_COMPLETE_MISS_PREDICTION [i])) { log_printf(TRACE,Context_State,FUNCTION," * BRANCH_COMPLETE [%d]",i); Tcontext_t context_id = (_param->_have_port_context_id)?PORT_READ(in_BRANCH_COMPLETE_CONTEXT_ID [i]):0; context_state_t state = reg_STATE [context_id]; Tdepth_t depth = (_param->_have_port_depth)?PORT_READ(in_BRANCH_COMPLETE_DEPTH [i]):0; Tdepth_t depth_cur = reg_EVENT_DEPTH [context_id]; Tdepth_t depth_min = (_param->_have_port_depth)?PORT_READ(in_DEPTH_MIN [context_id]):0; Tdepth_t depth_max = _param->_nb_inst_branch_speculated [context_id]; Tdepth_t depth0 = (depth_cur>=depth_min)?(depth_cur-depth_min):((depth_cur+depth_max-depth_min)); Tdepth_t depth1 = (depth >=depth_min)?(depth -depth_min):((depth +depth_max-depth_min)); // Tdepth_t depth0 = (depth_cur>=depth_min)?(depth_cur):((depth_cur+depth_max)); // Tdepth_t depth1 = (depth >=depth_min)?(depth ):((depth +depth_max)); // priority : miss_load > miss_branch > excep > spr/sync uint8_t priority0 = get_priority(state); uint8_t priority1 = PRIORITY_MISS_BRANCH; // miss // is_valid = can modify local information // if context_state_ok : yes // if context_state_ko : test the depth, and the priority of event bool is_valid = ((state == CONTEXT_STATE_OK) or (depth1< depth0) or ((depth1==depth0) and (priority1>=priority0))); // >= because another branch can be a miss prediction with same depth log_printf(TRACE,Context_State,FUNCTION," * context_id: %d",context_id); log_printf(TRACE,Context_State,FUNCTION," * depth : %d",depth ); log_printf(TRACE,Context_State,FUNCTION," * depth_cur : %d",depth_cur ); log_printf(TRACE,Context_State,FUNCTION," * depth_min : %d",depth_min ); log_printf(TRACE,Context_State,FUNCTION," * depth_max : %d",depth_max ); log_printf(TRACE,Context_State,FUNCTION," * depth0 : %d",depth0 ); log_printf(TRACE,Context_State,FUNCTION," * depth1 : %d",depth1 ); log_printf(TRACE,Context_State,FUNCTION," * priority0 : %d",priority0 ); log_printf(TRACE,Context_State,FUNCTION," * priority1 : %d",priority1 ); log_printf(TRACE,Context_State,FUNCTION," * is_valid : %d",is_valid ); if (is_valid) { // reg_STATE [context_id] = CONTEXT_STATE_KO_MISS_BRANCH_ADDR; reg_STATE [context_id] = CONTEXT_STATE_KO_MISS_BRANCH_WAIT_UPDATE; reg_EVENT_DEPTH [context_id] = depth; reg_EVENT_FLUSH_ONLY [context_id] = false; } } // ------------------------------------------------------------------- // -----[ COMMIT_EVENT ]---------------------------------------------- // ------------------------------------------------------------------- if (PORT_READ(in_COMMIT_EVENT_VAL ) and internal_COMMIT_EVENT_ACK ) { log_printf(TRACE,Context_State,FUNCTION," * COMMIT_EVENT"); Tcontext_t context = (_param->_have_port_context_id)?PORT_READ(in_COMMIT_EVENT_CONTEXT_ID ):0; Tdepth_t depth = (_param->_have_port_depth )?PORT_READ(in_COMMIT_EVENT_DEPTH ):0; // Tdepth_t depth_cur = reg_EVENT_DEPTH [context]; // Tdepth_t depth_min = (_param->_have_port_depth )?PORT_READ(in_DEPTH_MIN [context]):0; // Tdepth_t depth_max = _param->_nb_inst_branch_speculated [context]; // Tdepth_t depth0 = (depth_cur>=depth_min)?(depth_cur-depth_min):((depth_cur+depth_max-depth_min)); // Tdepth_t depth1 = (depth >=depth_min)?(depth -depth_min):((depth +depth_max-depth_min)); // // Tdepth_t depth0 = (depth_cur>=depth_min)?(depth_cur):((depth_cur+depth_max)); // // Tdepth_t depth1 = (depth >=depth_min)?(depth ):((depth +depth_max)); context_state_t state = reg_STATE [context]; Tevent_type_t type = PORT_READ(in_COMMIT_EVENT_TYPE ); // // miss > excep > spr/sync // uint8_t priority0 = ((state == CONTEXT_STATE_KO_MISS_BRANCH_ADDR ) or // (state == CONTEXT_STATE_KO_MISS_LOAD_ADDR ) or // (state == CONTEXT_STATE_KO_MISS_LOAD_AND_BRANCH_ADDR ) or // (state == CONTEXT_STATE_KO_MISS_BRANCH_WAITEND ) or // (state == CONTEXT_STATE_KO_MISS_BRANCH_WAIT_UPDATE ) or // (state == CONTEXT_STATE_KO_MISS_LOAD_WAITEND ) or // (state == CONTEXT_STATE_KO_MISS_LOAD_AND_BRANCH_WAITEND))?2:((state == CONTEXT_STATE_KO_EXCEP)?1:0); // uint8_t priority1 = (state == EVENT_TYPE_EXCEPTION)?1:2; // else load_miss_speculation (EVENT_TYPE_MISS_SPECULATION) // // 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 commit send an event, also they have not yet event previous this instruction bool is_valid = true; log_printf(TRACE,Context_State,FUNCTION," * depth : %d",depth ); // log_printf(TRACE,Context_State,FUNCTION," * depth_cur : %d",depth_cur ); // log_printf(TRACE,Context_State,FUNCTION," * depth_min : %d",depth_min ); // log_printf(TRACE,Context_State,FUNCTION," * depth_max : %d",depth_max ); // log_printf(TRACE,Context_State,FUNCTION," * depth0 : %d",depth0 ); // log_printf(TRACE,Context_State,FUNCTION," * depth1 : %d",depth1 ); // log_printf(TRACE,Context_State,FUNCTION," * priority0 : %d",priority0 ); // log_printf(TRACE,Context_State,FUNCTION," * priority1 : %d",priority1 ); log_printf(TRACE,Context_State,FUNCTION," * is_valid : %d",is_valid ); 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_LOAD_MISS_SPECULATION : { // Test if previous branch occure switch (state) { case CONTEXT_STATE_KO_MISS_BRANCH_WAIT_UPDATE : { state_next = CONTEXT_STATE_KO_MISS_LOAD_AND_BRANCH_WAIT_UPDATE; break; } case CONTEXT_STATE_KO_MISS_BRANCH_ADDR : case CONTEXT_STATE_KO_MISS_BRANCH_WAITEND : case CONTEXT_STATE_KO_MISS_BRANCH_INACCURATE : case CONTEXT_STATE_KO_MISS_LOAD_AND_BRANCH_ADDR : case CONTEXT_STATE_KO_MISS_LOAD_AND_BRANCH_WAITEND : { // #if (MANAGE_EVENT == MANAGE_EVENT_NO_WAIT) // state_next = CONTEXT_STATE_KO_MISS_LOAD_AND_BRANCH_ADDR; // #else state_next = CONTEXT_STATE_KO_MISS_LOAD_AND_BRANCH_WAITEND; // #endif break; } default : { // #if (MANAGE_EVENT == MANAGE_EVENT_NO_WAIT) // state_next = CONTEXT_STATE_KO_MISS_LOAD_ADDR; // #else state_next = CONTEXT_STATE_KO_MISS_LOAD_WAITEND; // #endif break; } } depth = (depth+1)%_param->_nb_inst_branch_speculated[context]; break; } case EVENT_TYPE_BRANCH_MISS_SPECULATION : case EVENT_TYPE_SPR_ACCESS : case EVENT_TYPE_MSYNC : case EVENT_TYPE_PSYNC : case EVENT_TYPE_CSYNC : case EVENT_TYPE_NONE : // case EVENT_TYPE_BRANCH_NO_ACCURATE : default : { throw ERRORMORPHEO(FUNCTION,toString(_("COMMIT_EVENT : invalid event_type : %s.\n"),toString(type).c_str())); } } reg_STATE [context] = state_next; reg_EVENT_ADDRESS [context] = PORT_READ(in_COMMIT_EVENT_ADDRESS ); reg_EVENT_ADDRESS_EPCR [context] = PORT_READ(in_COMMIT_EVENT_ADDRESS_EPCR ); reg_EVENT_ADDRESS_EPCR_VAL [context] = PORT_READ(in_COMMIT_EVENT_ADDRESS_EPCR_VAL ); reg_EVENT_ADDRESS_EEAR [context] = PORT_READ(in_COMMIT_EVENT_ADDRESS_EEAR ); reg_EVENT_ADDRESS_EEAR_VAL [context] = PORT_READ(in_COMMIT_EVENT_ADDRESS_EEAR_VAL ); reg_EVENT_IS_DELAY_SLOT [context] = PORT_READ(in_COMMIT_EVENT_IS_DELAY_SLOT ); reg_EVENT_IS_DS_TAKE [context] = 0; reg_EVENT_DEPTH [context] = depth; reg_EVENT_FLUSH_ONLY [context] = false; } } // ------------------------------------------------------------------- // -----[ SPR_EVENT ]------------------------------------------------- // ------------------------------------------------------------------- for (uint32_t i=0; i<_param->_nb_context; i++) if (internal_SPR_EVENT_VAL [i] and PORT_READ(in_SPR_EVENT_ACK [i])) { log_printf(TRACE,Context_State,FUNCTION," * SPR_EVENT [%d]",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_EVENT[%d], Invalid state : %s.\n"),i,toString(state).c_str())); #endif reg_STATE [i] = CONTEXT_STATE_OK; } // ------------------------------------------------------------------- // -----[ INTERRUPT ]------------------------------------------------- // ------------------------------------------------------------------- for (uint32_t i=0; i<_param->_nb_context; ++i) { reg_INTERRUPT_ENABLE [i] = PORT_READ(in_INTERRUPT_ENABLE [i]) and PORT_READ(in_SPR_SR_IEE [i]); if (reg_INTERRUPT_ENABLE [i]) throw ERRORMORPHEO(FUNCTION,toString(_("Context[%d], Have an interruption, Not yet supported (Comming Soon).\n"),i)); } #if (MANAGE_EVENT == MANAGE_EVENT_NO_WAIT) for (uint32_t i=0; i<_param->_nb_context; i++) switch (reg_STATE [i]) { case CONTEXT_STATE_KO_MISS_BRANCH_WAITEND : reg_STATE [i] = CONTEXT_STATE_KO_MISS_BRANCH_ADDR ; break; case CONTEXT_STATE_KO_MISS_LOAD_WAITEND : reg_STATE [i] = CONTEXT_STATE_KO_MISS_LOAD_ADDR ; break; case CONTEXT_STATE_KO_MISS_LOAD_AND_BRANCH_WAITEND : reg_STATE [i] = CONTEXT_STATE_KO_MISS_LOAD_AND_BRANCH_ADDR; break; default : break; } #endif } #ifdef STATISTICS if (usage_is_set(_usage,USE_STATISTICS)) for (uint32_t i=0; i<_param->_nb_context; ++i) switch(reg_STATE[i]) { case CONTEXT_STATE_OK : (*_stat_nb_cycle_state_ok [i])++; break; case CONTEXT_STATE_KO_EXCEP : case CONTEXT_STATE_KO_EXCEP_ADDR : case CONTEXT_STATE_KO_EXCEP_SPR : (*_stat_nb_cycle_state_ko_excep [i])++; break; case CONTEXT_STATE_KO_MISS_BRANCH_INACCURATE : case CONTEXT_STATE_KO_MISS_BRANCH_WAIT_UPDATE : case CONTEXT_STATE_KO_MISS_BRANCH_ADDR : case CONTEXT_STATE_KO_MISS_BRANCH_WAITEND : (*_stat_nb_cycle_state_ko_miss_branch [i])++; break; case CONTEXT_STATE_KO_MISS_LOAD_ADDR : case CONTEXT_STATE_KO_MISS_LOAD_WAITEND : (*_stat_nb_cycle_state_ko_miss_load [i])++; break; case CONTEXT_STATE_KO_MISS_LOAD_AND_BRANCH_WAIT_UPDATE: case CONTEXT_STATE_KO_MISS_LOAD_AND_BRANCH_ADDR : case CONTEXT_STATE_KO_MISS_LOAD_AND_BRANCH_WAITEND : (*_stat_nb_cycle_state_ko_miss_load_and_branch [i])++; break; // case CONTEXT_STATE_KO_MSYNC : // case CONTEXT_STATE_KO_MSYNC_ISSUE : case CONTEXT_STATE_KO_MSYNC_EXEC : (*_stat_nb_cycle_state_ko_msync [i])++; break; // case CONTEXT_STATE_KO_PSYNC : case CONTEXT_STATE_KO_PSYNC_FLUSH : case CONTEXT_STATE_KO_PSYNC_ADDR : (*_stat_nb_cycle_state_ko_psync [i])++; break; // case CONTEXT_STATE_KO_CSYNC : case CONTEXT_STATE_KO_CSYNC_FLUSH : case CONTEXT_STATE_KO_CSYNC_ADDR : (*_stat_nb_cycle_state_ko_csync [i])++; break; // case CONTEXT_STATE_KO_SPR : // case CONTEXT_STATE_KO_SPR_ISSUE : case CONTEXT_STATE_KO_SPR_EXEC : (*_stat_nb_cycle_state_ko_spr [i])++; break; } #endif #if DEBUG >= DEBUG_TRACE for (uint32_t i=0; i<_param->_nb_context; i++) { log_printf(TRACE,Context_State,FUNCTION," * Dump 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 (0x%x)",reg_EVENT_ADDRESS [i],reg_EVENT_ADDRESS [i]<<2); log_printf(TRACE,Context_State,FUNCTION," * reg_EVENT_ADDRESS_EPCR : 0x%x (0x%x)",reg_EVENT_ADDRESS_EPCR [i],reg_EVENT_ADDRESS_EPCR [i]<<2); 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 (0x%x)",reg_EVENT_ADDRESS_EEAR [i],reg_EVENT_ADDRESS_EEAR [i]<<2); 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]); log_printf(TRACE,Context_State,FUNCTION," * reg_EVENT_FLUSH_ONLY : %d" ,reg_EVENT_FLUSH_ONLY [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