#ifdef SYSTEMC /* * $Id: Context_State_transition.cpp 88 2008-12-10 18:31:39Z 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); 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; } } else { // ------------------------------------------------------------------- // -----[ 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]) { // throw ERRORMORPHEO(FUNCTION,_("Not yet implemented (Comming Soon).\n")); 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->_array_size_depth [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 > excep > spr/sync uint8_t priority0 = (state == CONTEXT_STATE_KO_MISS)?2:((state == EVENT_TYPE_EXCEPTION)?1:0); uint8_t priority1 = 2; // miss // 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) { reg_STATE [i] = CONTEXT_STATE_KO_MISS; 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] = 1; // address_dest is valid //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] = 0;// ?? reg_EVENT_DEPTH [i] = depth; } } // ------------------------------------------------------------------- // -----[ 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_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->_array_size_depth [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 > 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 ]---------------------------------------------- // ------------------------------------------------------------------- if (PORT_READ(in_COMMIT_EVENT_VAL ) and internal_COMMIT_EVENT_ACK ) { 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->_array_size_depth [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)?2:((state == CONTEXT_STATE_KO_EXCEP)?1:0); uint8_t priority1 = 1; // exception // 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 : 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] = 1; 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; } } // ------------------------------------------------------------------- // -----[ 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_depth )?PORT_READ(in_BRANCH_COMPLETE_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->_array_size_depth [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]; // miss > excep > spr/sync uint8_t priority0 = (state == CONTEXT_STATE_KO_MISS)?2:((state == CONTEXT_STATE_KO_EXCEP)?1:0); uint8_t priority1 = 2; // miss // 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] = 0; 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_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])) { // 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; } // ------------------------------------------------------------------- // -----[ 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_all = PORT_READ(in_NB_INST_COMMIT_ALL[i]) + PORT_READ(in_NB_INST_DECOD_ALL [i]); Tcounter_t inst_mem = PORT_READ(in_NB_INST_COMMIT_MEM[i]) + PORT_READ(in_NB_INST_DECOD_ALL [i]); 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; } 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 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]); } #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