#ifdef SYSTEMC /* * $Id: Decod_genMealy.cpp 145 2010-10-13 18:15:51Z rosiere $ * * [ Description ] * */ #include "Behavioural/Core/Multi_Front_end/Front_end/Decod_unit/Decod/include/Decod.h" namespace morpheo { namespace behavioural { namespace core { namespace multi_front_end { namespace front_end { namespace decod_unit { namespace decod { #undef FUNCTION #define FUNCTION "Decod::genMealy" void Decod::genMealy (void) { log_begin(Decod,FUNCTION); log_function(Decod,FUNCTION,_name.c_str()); if (PORT_READ(in_NRESET)) { //----------------------------------- // Initialization //----------------------------------- Tcontrol_t context_event_val = false; Tcontrol_t ifetch_ack [_param->_nb_context][_param->_max_nb_inst_fetch]; for (uint32_t i=0; i<_param->_nb_context; i++) for (uint32_t j=0; j<_param->_nb_inst_fetch[i]; j++) ifetch_ack [i][j] = false; Tcontrol_t predict_val [_param->_nb_inst_decod]; Tcontrol_t decod_val [_param->_nb_inst_decod]; for (uint32_t i=0; i<_param->_nb_inst_decod; i++) { decod_val [i] = false; predict_val [i] = false; } Tcontrol_t can_continue [_param->_nb_context]; Tcontrol_t have_decod_branch [_param->_nb_context]; Tcontext_t CONTEXT_EVENT_CONTEXT_ID = 0; Tdepth_t CONTEXT_EVENT_DEPTH = 0; Tevent_type_t CONTEXT_EVENT_TYPE = 0; Tcontrol_t CONTEXT_EVENT_IS_DELAY_SLOT = 0; Tgeneral_data_t CONTEXT_EVENT_ADDRESS = 0; Tgeneral_data_t CONTEXT_EVENT_ADDRESS_EPCR = 0; for (uint32_t i=0; i<_param->_nb_context; i++) { internal_CONTEXT_HAVE_TRANSACTION [i] = false; internal_CONTEXT_ADDRESS_PREVIOUS [i] = reg_CONTEXT_ADDRESS_PREVIOUS [i]; internal_CONTEXT_IS_DELAY_SLOT [i] = reg_CONTEXT_IS_DELAY_SLOT [i]; // internal_CONTEXT_SAVE_RAT [i] = reg_CONTEXT_SAVE_RAT [i]; can_continue [i] = PORT_READ(in_CONTEXT_DECOD_ENABLE [i]); have_decod_branch [i] = false; } //----------------------------------- // Loop of decod //----------------------------------- // scan all decod "slot_out" std::list * select = _priority->select(); std::list::iterator it=select->begin(); for (uint32_t i=0; i<_param->_nb_inst_decod; i++) { log_printf(TRACE,Decod,FUNCTION," * DECOD [%d]",i); bool ifetch_val = false; while ((it != select->end()) and // have a no scanned instruction from ifetch_unit ? // (decod_val [i] == false) and // have not a previous selected entry? (ifetch_val == false) and // not find ifetch instruction valid (context_event_val == false)) // Have not a context_event (spr_access, exception, ...) (ONCE CONTEXT PER CYCLE (context state moore easy)) { // predict_val [i] = false; Tcontext_t x = it->grp; // num_front_end uint32_t y = it->elt; // num_instruction log_printf(TRACE,Decod,FUNCTION," * IFETCH [%d][%d]",x,y); log_printf(TRACE,Decod,FUNCTION," * in_IFETCH_VAL : %d",PORT_READ(in_IFETCH_VAL [x][y])); log_printf(TRACE,Decod,FUNCTION," * can_continue : %d",can_continue [x] ); // Test if this instruction is valid if ((PORT_READ(in_IFETCH_VAL [x][y]) == 1) and // entry is valid (can_continue [x] == 1)) // context can decod instruction (have not a previous event) { log_printf(TRACE,Decod,FUNCTION," * decod_ack : %d",PORT_READ(in_DECOD_ACK [i])); ifetch_val = true; decod_val [i] = true; // fetch_val and decod_enable ifetch_ack [x][y] = PORT_READ(in_DECOD_ACK [i]); // fetch_val and decod_enable and decod_ack Tgeneral_data_t addr = PORT_READ(in_IFETCH_ADDRESS [x][y]); // Read instruction and set default value _decod_instruction->_instruction = PORT_READ(in_IFETCH_INSTRUCTION [x][y]); _decod_instruction->_context_id = x; _decod_instruction->_address_previous = internal_CONTEXT_ADDRESS_PREVIOUS [x]; _decod_instruction->_address = addr; //Compute the current address _decod_instruction->_address_next = addr+1; _decod_instruction->_is_delay_slot = internal_CONTEXT_IS_DELAY_SLOT [x]; #ifdef STATISTICS _decod_instruction->_opcod = -1; // not necessary #endif _decod_instruction->_type = 0; // not necessary _decod_instruction->_operation = 0; // not necessary _decod_instruction->_no_execute = 0; // not necessary _decod_instruction->_has_immediat = 0; // not necessary _decod_instruction->_immediat = 0; // not necessary _decod_instruction->_read_ra = 0; // not necessary _decod_instruction->_num_reg_ra = 0; // not necessary _decod_instruction->_read_rb = 0; // not necessary _decod_instruction->_num_reg_rb = 0; // not necessary _decod_instruction->_read_rc = 0; // not necessary _decod_instruction->_num_reg_rc = 0; // not necessary _decod_instruction->_write_rd = 0; // not necessary _decod_instruction->_num_reg_rd = 0; // not necessary _decod_instruction->_write_re = 0; // not necessary _decod_instruction->_num_reg_re = 0; // not necessary _decod_instruction->_exception_use = EXCEPTION_USE_NONE; // not necessary _decod_instruction->_exception = EXCEPTION_DECOD_NONE; // not necessary _decod_instruction->_branch_condition = 0; // not necessary // _decod_instruction->_branch_stack_write = 0; // not necessary _decod_instruction->_branch_direction = 0; // not necessary _decod_instruction->_event_type = EVENT_TYPE_NONE; // not necessary // Test if ifetch_unit have an exception (per example : IBERR) Texception_t ifetch_exception = PORT_READ(in_IFETCH_EXCEPTION [x][y]); if (ifetch_exception == EXCEPTION_IFETCH_NONE) { // No exception, can Decod ! log_printf(TRACE,Decod,FUNCTION," * address : %.8x (%.8x)",addr,(addr<<2)); log_printf(TRACE,Decod,FUNCTION," * is_delay_slot : %d",internal_CONTEXT_IS_DELAY_SLOT [x]); instruction_decod (_decod_instruction, _decod_param[x]); log_printf(TRACE,Decod,FUNCTION," * address_next : %.8x (%.8x)",_decod_instruction->_address_next,(_decod_instruction->_address_next<<2)); } else { // Exception : transform this instruction in a nop // * INSTRUCTION_TLB // * INSTRUCTION_PAGE // * BUS_ERROR log_printf(TRACE,Decod,FUNCTION," * exception -> change instruction in a l.nop"); instruction_l_nop (_decod_instruction, _decod_param[x]); _decod_instruction->_exception_use = EXCEPTION_USE_NONE; _decod_instruction->_exception = exception_ifetch_to_exception_decod(ifetch_exception); if (_decod_instruction->_is_delay_slot) _decod_instruction->_address_next = _decod_instruction->_address_previous; else _decod_instruction->_address_next = _decod_instruction->_address; _decod_instruction->_event_type = EVENT_TYPE_EXCEPTION; } Ttype_t type = _decod_instruction->_type; Tdepth_t depth = (_param->_have_port_depth)?PORT_READ(in_CONTEXT_DEPTH [x]):0; Tbranch_condition_t branch_condition = _decod_instruction->_branch_condition; // Save RAT if instruction is a branch and is conditionnal (not l.j and not l.jal) //Tcontrol_t save_rat = internal_CONTEXT_SAVE_RAT [x]; // Tcontrol_t save_rat = ((type == TYPE_BRANCH) and // not ((branch_condition==BRANCH_CONDITION_NONE_WITHOUT_WRITE_STACK) or // (branch_condition==BRANCH_CONDITION_NONE_WITH_WRITE_STACK))); Tcontrol_t save_rat = ((type == TYPE_BRANCH) and not (branch_condition==BRANCH_CONDITION_NONE_WITHOUT_WRITE_STACK)); // FIXME : depth+1 valid ??????? if ((_param->_nb_branch_speculated[x] > 0) and have_decod_branch [x]) depth = (depth+1)%_param->_nb_branch_speculated[x]; // Write output if (_param->_have_port_context_id) PORT_WRITE(out_DECOD_CONTEXT_ID [i], x); if (_param->_have_port_depth) PORT_WRITE(out_DECOD_DEPTH [i], depth); #ifdef STATISTICS PORT_WRITE(out_DECOD_INSTRUCTION [i], _decod_instruction->_opcod ); #endif PORT_WRITE(out_DECOD_TYPE [i], type); PORT_WRITE(out_DECOD_OPERATION [i], _decod_instruction->_operation ); PORT_WRITE(out_DECOD_NO_EXECUTE [i], _decod_instruction->_no_execute ); PORT_WRITE(out_DECOD_IS_DELAY_SLOT [i], _decod_instruction->_is_delay_slot ); PORT_WRITE(out_DECOD_SAVE_RAT [i], save_rat); #ifdef DEBUG PORT_WRITE(out_DECOD_ADDRESS [i], addr); #endif PORT_WRITE(out_DECOD_ADDRESS_NEXT [i], _decod_instruction->_address_next ); PORT_WRITE(out_DECOD_HAS_IMMEDIAT [i], _decod_instruction->_has_immediat ); PORT_WRITE(out_DECOD_IMMEDIAT [i], _decod_instruction->_immediat ); PORT_WRITE(out_DECOD_READ_RA [i], _decod_instruction->_read_ra ); PORT_WRITE(out_DECOD_NUM_REG_RA [i], _decod_instruction->_num_reg_ra ); PORT_WRITE(out_DECOD_READ_RB [i], _decod_instruction->_read_rb ); PORT_WRITE(out_DECOD_NUM_REG_RB [i], _decod_instruction->_num_reg_rb ); PORT_WRITE(out_DECOD_READ_RC [i], _decod_instruction->_read_rc ); PORT_WRITE(out_DECOD_NUM_REG_RC [i], _decod_instruction->_num_reg_rc ); PORT_WRITE(out_DECOD_WRITE_RD [i],(_decod_instruction->_num_reg_rd!=0)?_decod_instruction->_write_rd:0); // don't write in RD if RD=0 PORT_WRITE(out_DECOD_NUM_REG_RD [i], _decod_instruction->_num_reg_rd ); PORT_WRITE(out_DECOD_WRITE_RE [i], _decod_instruction->_write_re ); PORT_WRITE(out_DECOD_NUM_REG_RE [i], _decod_instruction->_num_reg_re ); PORT_WRITE(out_DECOD_EXCEPTION_USE [i], _decod_instruction->_exception_use ); PORT_WRITE(out_DECOD_EXCEPTION [i], _decod_instruction->_exception ); // Branch predictor can accept : the depth is valid log_printf(TRACE,Decod,FUNCTION," * context_depth_val : %d",PORT_READ(in_CONTEXT_DEPTH_VAL [x])); decod_val [i] &= PORT_READ(in_CONTEXT_DEPTH_VAL [x]); ifetch_ack [x][y] &= PORT_READ(in_CONTEXT_DEPTH_VAL [x]); if (type == TYPE_BRANCH) { log_printf(TRACE,Decod,FUNCTION," * Instruction is branch"); log_printf(TRACE,Decod,FUNCTION," * predict_val : %d",ifetch_ack [x][y]); log_printf(TRACE,Decod,FUNCTION," * predict_ack : %d",PORT_READ(in_PREDICT_ACK [i])); log_printf(TRACE,Decod,FUNCTION," * address src : %.8x (%.8x)",_decod_instruction->_address ,_decod_instruction->_address <<2); log_printf(TRACE,Decod,FUNCTION," * address dest : %.8x (%.8x)",_decod_instruction->_address_next,_decod_instruction->_address_next<<2); // test if have already decod an branch : ONCE BRANCH PER CONTEXT predict_val [i] = not have_decod_branch [x] and ifetch_ack [x][y]; // and decod_val [i] decod_val [i] &= not have_decod_branch [x] and PORT_READ(in_PREDICT_ACK [i]);// predict_ack and fetch_val and decod_enable ifetch_ack [x][y] &= not have_decod_branch [x] and PORT_READ(in_PREDICT_ACK [i]);// predict_ack and fetch_val and decod_enable and decod_ack // can continue is set if direction is "not take" (also, continue is sequential order) // can_continue [x] = false; // one branch per context, the DS don't execute can_continue [x]&= PORT_READ(in_PREDICT_CAN_CONTINUE [i]); // one branch per context, the DS don't execute have_decod_branch [x] = true; log_printf(TRACE,Decod,FUNCTION," * predict_can_continue : %d",PORT_READ(in_PREDICT_CAN_CONTINUE [i])); } Tbranch_state_t ifetch_branch_state = PORT_READ(in_IFETCH_BRANCH_STATE [x][y]); if (_param->_have_port_context_id) PORT_WRITE(out_PREDICT_CONTEXT_ID [i],x); // PORT_WRITE(out_PREDICT_MATCH_INST_IFETCH_PTR [i],y == ((_param->_have_port_inst_ifetch_ptr)?PORT_READ(in_IFETCH_INST_IFETCH_PTR [x]):0)); PORT_WRITE(out_PREDICT_MATCH_INST_IFETCH_PTR [i],ifetch_branch_state != BRANCH_STATE_NONE); PORT_WRITE(out_PREDICT_BRANCH_STATE [i],ifetch_branch_state); if (_param->_have_port_depth) PORT_WRITE(out_PREDICT_BRANCH_UPDATE_PREDICTION_ID [i],PORT_READ(in_IFETCH_BRANCH_UPDATE_PREDICTION_ID [x][y])); PORT_WRITE(out_PREDICT_BRANCH_CONDITION [i],branch_condition); // PORT_WRITE(out_PREDICT_BRANCH_STACK_WRITE [i],_decod_instruction->_branch_stack_write); PORT_WRITE(out_PREDICT_BRANCH_DIRECTION [i],_decod_instruction->_branch_direction ); PORT_WRITE(out_PREDICT_ADDRESS_SRC [i],_decod_instruction->_address ); PORT_WRITE(out_PREDICT_ADDRESS_DEST [i],_decod_instruction->_address_next ); Tevent_type_t event_type = _decod_instruction->_event_type; if (event_type != EVENT_TYPE_NONE) { log_printf(TRACE,Decod,FUNCTION," * Instruction make an EVENT (%s)",toString(event_type).c_str()); log_printf(TRACE,Decod,FUNCTION," * context_event_ack : %d",PORT_READ(in_CONTEXT_EVENT_ACK)); // speculative jump at the exception handler // if type = TYPE_BRANCH, also event_type == EVENT_TYPE_NONE context_event_val = ifetch_ack [x][y]; // and decod_val [i] decod_val [i] &= PORT_READ(in_CONTEXT_EVENT_ACK);// context_event_ack and fetch_val and decod_enable ifetch_ack [x][y] &= PORT_READ(in_CONTEXT_EVENT_ACK);// context_event_ack and fetch_val and decod_enable and decod_ack CONTEXT_EVENT_CONTEXT_ID = x; CONTEXT_EVENT_DEPTH = depth; CONTEXT_EVENT_TYPE = _decod_instruction->_event_type; CONTEXT_EVENT_IS_DELAY_SLOT = _decod_instruction->_is_delay_slot; CONTEXT_EVENT_ADDRESS = _decod_instruction->_address; CONTEXT_EVENT_ADDRESS_EPCR = _decod_instruction->_address_next ; } // fetch_ack = // ((event_type == EVENT_TYPE_NONE) or ((event_type != EVENT_TYPE_NONE) and context_event_ack)) and // ((type == TYPE_BRANCH ) or ((type != TYPE_BRANCH ) and predict_ack )) and // fetch_val and decod_ack and decod_enable and true (is decod_val) // To compute the "next previous" address Tcontrol_t have_transaction = ifetch_ack [x][y]; internal_CONTEXT_HAVE_TRANSACTION [x] |= have_transaction; if (have_transaction) { internal_CONTEXT_ADDRESS_PREVIOUS [x] = addr; internal_CONTEXT_IS_DELAY_SLOT [x] = (type == TYPE_BRANCH); // next is a delay slot if current have branch type // internal_CONTEXT_SAVE_RAT [x] = ((type == TYPE_BRANCH) and not no_execute); } can_continue [x] &= have_transaction; // to have a in order decod !!! if a previous instruction can decod, also next instruction can't decod. log_printf(TRACE,Decod,FUNCTION," * have_transaction : %d",have_transaction); } log_printf(TRACE,Decod,FUNCTION," - num_(decod, context, fetch) : %d %d %d",i, x, y); log_printf(TRACE,Decod,FUNCTION," - ifetch_ack : %d",ifetch_ack [x][y]); log_printf(TRACE,Decod,FUNCTION," - context_event_val : %d",context_event_val ); log_printf(TRACE,Decod,FUNCTION," - predict_val : %d",predict_val [i] ); log_printf(TRACE,Decod,FUNCTION," - decod_val : %d",decod_val [i] ); it ++; } } //----------------------------------- // Write output //----------------------------------- for (uint32_t i=0; i<_param->_nb_context; i++) for (uint32_t j=0; j<_param->_nb_inst_fetch[i]; j++) PORT_WRITE(out_IFETCH_ACK [i][j], ifetch_ack [i][j]); PORT_WRITE(out_CONTEXT_EVENT_VAL, context_event_val); if (_param->_have_port_context_id) PORT_WRITE(out_CONTEXT_EVENT_CONTEXT_ID , CONTEXT_EVENT_CONTEXT_ID ); if (_param->_have_port_depth) PORT_WRITE(out_CONTEXT_EVENT_DEPTH , CONTEXT_EVENT_DEPTH ); PORT_WRITE(out_CONTEXT_EVENT_TYPE , CONTEXT_EVENT_TYPE ); PORT_WRITE(out_CONTEXT_EVENT_IS_DELAY_SLOT, CONTEXT_EVENT_IS_DELAY_SLOT); PORT_WRITE(out_CONTEXT_EVENT_ADDRESS , CONTEXT_EVENT_ADDRESS ); PORT_WRITE(out_CONTEXT_EVENT_ADDRESS_EPCR , CONTEXT_EVENT_ADDRESS_EPCR ); for (uint32_t i=0; i<_param->_nb_inst_decod; i++) { PORT_WRITE(out_PREDICT_VAL [i], predict_val [i]); PORT_WRITE(out_DECOD_VAL [i], decod_val [i]); #ifdef STATISTICS internal_DECOD_VAL [i] = decod_val [i]; #endif } } else { for (uint32_t i=0; i<_param->_nb_context; i++) { internal_CONTEXT_HAVE_TRANSACTION [i] = false; // internal_CONTEXT_ADDRESS_PREVIOUS [i] = reg_CONTEXT_ADDRESS_PREVIOUS [i]; // internal_CONTEXT_IS_DELAY_SLOT [i] = reg_CONTEXT_IS_DELAY_SLOT [i]; for (uint32_t j=0; j<_param->_nb_inst_fetch[i]; j++) PORT_WRITE(out_IFETCH_ACK [i][j], 0); } PORT_WRITE(out_CONTEXT_EVENT_VAL, 0); for (uint32_t i=0; i<_param->_nb_inst_decod; i++) { PORT_WRITE(out_PREDICT_VAL [i], 0); PORT_WRITE(out_DECOD_VAL [i], 0); #ifdef STATISTICS internal_DECOD_VAL [i] = 0; #endif } } log_end(Decod,FUNCTION); }; }; // end namespace decod }; // end namespace decod_unit }; // end namespace front_end }; // end namespace multi_front_end }; // end namespace core }; // end namespace behavioural }; // end namespace morpheo #endif