#ifdef SYSTEMC /* * $Id: Address_management_transition.cpp 107 2009-02-10 23:03:25Z rosiere $ * * [ Description ] * */ #include "Behavioural/Core/Multi_Front_end/Front_end/Ifetch_unit/Address_management/include/Address_management.h" namespace morpheo { namespace behavioural { namespace core { namespace multi_front_end { namespace front_end { namespace ifetch_unit { namespace address_management { #undef FUNCTION #define FUNCTION "Address_management::transition" void Address_management::transition (void) { log_begin(Address_management,FUNCTION); log_function(Address_management,FUNCTION,_name.c_str()); if (PORT_READ(in_NRESET) == 0) { // nothing is valid reg_PC_ACCESS_VAL = 0; reg_PC_CURRENT_VAL = 0; reg_PC_NEXT_VAL = 1; reg_PC_NEXT = 0x100>>2; reg_PC_NEXT_IS_DS_TAKE = 0; uint32_t index = reg_PC_NEXT % _param->_nb_instruction; for (uint32_t i=0; i<_param->_nb_instruction; i++) reg_PC_NEXT_INSTRUCTION_ENABLE [i] = 0; reg_PC_NEXT_INSTRUCTION_ENABLE [index] = 1; reg_PC_NEXT_INST_IFETCH_PTR = 0; reg_PC_NEXT_BRANCH_STATE = 0; reg_PC_NEXT_BRANCH_UPDATE_PREDICTION_ID = 0; reg_PC_NEXT_NEXT_VAL = 0; } else { // ========================================= // ===== PREDICT =========================== // ========================================= if (PORT_READ(in_PREDICT_ACK) and internal_PREDICT_VAL) { bool branch_is_current = reg_PC_NEXT_IS_DS_TAKE; if (branch_is_current) { if (_param->_have_port_inst_ifetch_ptr) reg_PC_CURRENT_INST_IFETCH_PTR = PORT_READ(in_PREDICT_INST_IFETCH_PTR ); reg_PC_CURRENT_BRANCH_STATE = PORT_READ(in_PREDICT_BRANCH_STATE ); if (_param->_have_port_depth) reg_PC_CURRENT_BRANCH_UPDATE_PREDICTION_ID = PORT_READ(in_PREDICT_BRANCH_UPDATE_PREDICTION_ID); } else { if (_param->_have_port_inst_ifetch_ptr) reg_PC_NEXT_INST_IFETCH_PTR = PORT_READ(in_PREDICT_INST_IFETCH_PTR ); reg_PC_NEXT_BRANCH_STATE = PORT_READ(in_PREDICT_BRANCH_STATE ); if (_param->_have_port_depth) reg_PC_NEXT_BRANCH_UPDATE_PREDICTION_ID = PORT_READ(in_PREDICT_BRANCH_UPDATE_PREDICTION_ID); } for (uint32_t i=0; i<_param->_nb_instruction; i++) reg_PC_NEXT_INSTRUCTION_ENABLE [i] = PORT_READ(in_PREDICT_INSTRUCTION_ENABLE [i]); reg_PC_NEXT_NEXT_VAL = 1; // address is valid reg_PC_NEXT_NEXT = PORT_READ(in_PREDICT_PC_NEXT ); reg_PC_NEXT_NEXT_IS_DS_TAKE = PORT_READ(in_PREDICT_PC_NEXT_IS_DS_TAKE ); #ifdef STATISTICS if (usage_is_set(_usage,USE_STATISTICS)) (*_stat_nb_transaction_predict) ++; #endif } // ========================================= // ===== ADDRESS =========================== // ========================================= // transaction with icache if (internal_ADDRESS_VAL and PORT_READ(in_ADDRESS_ACK)) { reg_PC_ACCESS_VAL = 0; #ifdef STATISTICS if (usage_is_set(_usage,USE_STATISTICS)) { (*_stat_nb_transaction_address) ++; for (uint32_t i=0; i<_param->_nb_instruction; i++) if (reg_PC_ACCESS_INSTRUCTION_ENABLE [i] == true) (*_stat_sum_packet_size) ++; } #endif } // Shift register if (not reg_PC_ACCESS_VAL and reg_PC_CURRENT_VAL and reg_PC_NEXT_VAL and reg_PC_NEXT_NEXT_VAL) { reg_PC_ACCESS_VAL = 1; // new request reg_PC_CURRENT_VAL = 0; // invalid current reg_PC_ACCESS = reg_PC_CURRENT ; reg_PC_ACCESS_IS_DS_TAKE = reg_PC_CURRENT_IS_DS_TAKE ; reg_PC_ACCESS_INST_IFETCH_PTR = reg_PC_CURRENT_INST_IFETCH_PTR ; reg_PC_ACCESS_BRANCH_STATE = reg_PC_CURRENT_BRANCH_STATE ; reg_PC_ACCESS_BRANCH_UPDATE_PREDICTION_ID = reg_PC_CURRENT_BRANCH_UPDATE_PREDICTION_ID; for (uint32_t i=0; i<_param->_nb_instruction; i++) reg_PC_ACCESS_INSTRUCTION_ENABLE [i] = reg_PC_CURRENT_INSTRUCTION_ENABLE [i]; } if (not reg_PC_CURRENT_VAL) { bool val = reg_PC_NEXT_VAL; reg_PC_CURRENT_VAL = val; // new PC_CURRENT if PC_NEXT is valid reg_PC_NEXT_VAL = 0; // invalid next if (val) { reg_PC_CURRENT = reg_PC_NEXT ; reg_PC_CURRENT_IS_DS_TAKE = reg_PC_NEXT_IS_DS_TAKE ; reg_PC_CURRENT_INST_IFETCH_PTR = reg_PC_NEXT_INST_IFETCH_PTR ; reg_PC_CURRENT_BRANCH_STATE = reg_PC_NEXT_BRANCH_STATE ; reg_PC_CURRENT_BRANCH_UPDATE_PREDICTION_ID = reg_PC_NEXT_BRANCH_UPDATE_PREDICTION_ID; for (uint32_t i=0; i<_param->_nb_instruction; i++) reg_PC_CURRENT_INSTRUCTION_ENABLE [i] = reg_PC_NEXT_INSTRUCTION_ENABLE [i]; } } if (not reg_PC_NEXT_VAL) { bool val = reg_PC_NEXT_NEXT_VAL; reg_PC_NEXT_VAL = val; // new PC_NEXT if PC_NEXT_NEXT is valid reg_PC_NEXT_NEXT_VAL = 0; // invalid next_next if (val) { reg_PC_NEXT = reg_PC_NEXT_NEXT ; reg_PC_NEXT_IS_DS_TAKE = reg_PC_NEXT_NEXT_IS_DS_TAKE ; // reg_PC_NEXT_INST_IFETCH_PTR = reg_PC_NEXT_NEXT_INST_IFETCH_PTR ; // reg_PC_NEXT_BRANCH_STATE = reg_PC_NEXT_NEXT_BRANCH_STATE ; // reg_PC_NEXT_BRANCH_UPDATE_PREDICTION_ID = reg_PC_NEXT_NEXT_BRANCH_UPDATE_PREDICTION_ID; // for (uint32_t i=0; i<_param->_nb_instruction; i++) // reg_PC_NEXT_INSTRUCTION_ENABLE [i] = reg_PC_NEXT_NEXT_INSTRUCTION_ENABLE [i]; } } // ========================================= // ===== EVENT ============================= // ========================================= if (PORT_READ(in_EVENT_VAL) and internal_EVENT_ACK) { log_printf(TRACE,Address_management,FUNCTION," * EVENT : Transaction"); log_printf(TRACE,Address_management,FUNCTION," * IS_DS_TAKE : %d" ,PORT_READ(in_EVENT_IS_DS_TAKE )); log_printf(TRACE,Address_management,FUNCTION," * ADDRESS : %.8x (%.8x)",PORT_READ(in_EVENT_ADDRESS ),PORT_READ(in_EVENT_ADDRESS )<<2); log_printf(TRACE,Address_management,FUNCTION," * ADDRESS_NEXT : %.8x (%.8x)",PORT_READ(in_EVENT_ADDRESS_NEXT ),PORT_READ(in_EVENT_ADDRESS_NEXT )<<2); log_printf(TRACE,Address_management,FUNCTION," * ADDRESS_NEXT_VAL : %d" ,PORT_READ(in_EVENT_ADDRESS_NEXT_VAL)); reg_PC_ACCESS_VAL = 0; reg_PC_CURRENT_VAL = 0; reg_PC_NEXT_VAL = 1; reg_PC_NEXT = PORT_READ(in_EVENT_ADDRESS); // Event is never is ds_take : // * branch miss speculation : can't be place a branch in delay slot // * load miss speculation : the load is execute, the event_address is the next address (also the destination of branch) // * exception : goto the first instruction of exception handler (also is not in delay slot). reg_PC_NEXT_IS_DS_TAKE = PORT_READ(in_EVENT_IS_DS_TAKE); // reg_PC_NEXT_INST_IFETCH_PTR = 0; // reg_PC_NEXT_BRANCH_STATE = BRANCH_STATE_NONE; // reg_PC_NEXT_BRANCH_UPDATE_PREDICTION_ID = 0; // only the instruction at the event address is valid, because we have no information on the branch presence in the instruction bundle. uint32_t index = reg_PC_NEXT % _param->_nb_instruction; for (uint32_t i=0; i<_param->_nb_instruction; i++) reg_PC_NEXT_INSTRUCTION_ENABLE [i] = 0; reg_PC_NEXT_INSTRUCTION_ENABLE [index] = 1; reg_PC_NEXT_NEXT_VAL = PORT_READ(in_EVENT_ADDRESS_NEXT_VAL); reg_PC_NEXT_NEXT = PORT_READ(in_EVENT_ADDRESS_NEXT); reg_PC_NEXT_NEXT_IS_DS_TAKE = 0;//?? // Note : is_ds_take = address_next_val // Because, is not ds take, can continue in sequence // #ifdef DEBUG_TEST // if (PORT_READ(in_EVENT_ADDRESS_NEXT_VAL) and not PORT_READ(in_EVENT_IS_DS_TAKE)) // throw ERRORMORPHEO(FUNCTION,_("Event : address_next_next_val but next is not a ds take")); // #endif #ifdef STATISTICS if (usage_is_set(_usage,USE_STATISTICS)) (*_stat_nb_transaction_event) ++; #endif } } #if defined(DEBUG) and DEBUG_Address_management and (DEBUG >= DEBUG_TRACE) log_printf(TRACE,Address_management,FUNCTION," * Dump PC"); { std::string instruction_enable; for (uint32_t i=0; i<_param->_nb_instruction; ++i) instruction_enable += toString(reg_PC_ACCESS_INSTRUCTION_ENABLE [i])+ " "; log_printf(TRACE,Address_management,FUNCTION," * Access : %d %d 0x%.8x (%.8x) - %.2d %.2d %.2d - %s", reg_PC_ACCESS_VAL, reg_PC_ACCESS_IS_DS_TAKE, reg_PC_ACCESS, reg_PC_ACCESS<<2, reg_PC_ACCESS_BRANCH_STATE, reg_PC_ACCESS_INST_IFETCH_PTR, reg_PC_ACCESS_BRANCH_UPDATE_PREDICTION_ID, instruction_enable.c_str() ); } { std::string instruction_enable; for (uint32_t i=0; i<_param->_nb_instruction; ++i) instruction_enable += toString(reg_PC_CURRENT_INSTRUCTION_ENABLE [i])+ " "; log_printf(TRACE,Address_management,FUNCTION," * Current : %d %d 0x%.8x (%.8x) - %.2d %.2d %.2d - %s", reg_PC_CURRENT_VAL, reg_PC_CURRENT_IS_DS_TAKE, reg_PC_CURRENT, reg_PC_CURRENT<<2, reg_PC_CURRENT_BRANCH_STATE, reg_PC_CURRENT_INST_IFETCH_PTR, reg_PC_CURRENT_BRANCH_UPDATE_PREDICTION_ID, instruction_enable.c_str() ); } { std::string instruction_enable; for (uint32_t i=0; i<_param->_nb_instruction; ++i) instruction_enable += toString(reg_PC_NEXT_INSTRUCTION_ENABLE [i])+ " "; log_printf(TRACE,Address_management,FUNCTION," * Next : %d %d 0x%.8x (%.8x) - %.2d %.2d %.2d - %s", reg_PC_NEXT_VAL, reg_PC_NEXT_IS_DS_TAKE, reg_PC_NEXT, reg_PC_NEXT<<2, reg_PC_NEXT_BRANCH_STATE, reg_PC_NEXT_INST_IFETCH_PTR, reg_PC_NEXT_BRANCH_UPDATE_PREDICTION_ID, instruction_enable.c_str()); } log_printf(TRACE,Address_management,FUNCTION," * Next_Next : %d %d 0x%.8x (%.8x)", reg_PC_NEXT_NEXT_VAL, reg_PC_NEXT_NEXT_IS_DS_TAKE, reg_PC_NEXT_NEXT, reg_PC_NEXT_NEXT<<2); #endif #if defined(STATISTICS) or defined(VHDL_TESTBENCH) end_cycle (); #endif log_end(Address_management,FUNCTION); }; }; // end namespace address_management }; // end namespace ifetch_unit }; // end namespace front_end }; // end namespace multi_front_end }; // end namespace core }; // end namespace behavioural }; // end namespace morpheo #endif