#ifdef SYSTEMC /* * $Id$ * * [ Description ] * */ #include "Behavioural/Core/Multi_Front_end/Front_end/Prediction_unit/Prediction_unit_Glue/include/Prediction_unit_Glue.h" namespace morpheo { namespace behavioural { namespace core { namespace multi_front_end { namespace front_end { namespace prediction_unit { namespace prediction_unit_glue { #undef FUNCTION #define FUNCTION "Prediction_unit_Glue::genMealy_predict" void Prediction_unit_Glue::genMealy_predict (void) { log_begin(Prediction_unit_Glue,FUNCTION); log_function(Prediction_unit_Glue,FUNCTION,_name.c_str()); Tcontrol_t ack [_param->_nb_context]; for (uint32_t i=0; i<_param->_nb_context; i++) { ack [i] = 0; // if (_param->_have_port_depth) // { // PORT_WRITE(out_DEPTH_TAIL [i],PORT_READ(in_DEPTH_UPT_TAIL [i])); // } // PORT_WRITE(out_DEPTH_NB_BRANCH [i],PORT_READ(in_DEPTH_UPT_NB_BRANCH [i])); } for (uint32_t i=0; i<_param->_nb_inst_branch_predict; i++) { log_printf(TRACE,Prediction_unit_Glue,FUNCTION," * PREDICT [%d]",i); Tcontrol_t btb_val; Tcontrol_t dir_val; Tcontrol_t ras_val; Tcontrol_t upt_val; Tcontext_t context = (reg_PREDICT_PRIORITY+i)%_param->_nb_context; log_printf(TRACE,Prediction_unit_Glue,FUNCTION," * context : %d",context); ack [context] = 1; if (PORT_READ(in_PREDICT_VAL[context]) == 0) { log_printf(TRACE,Prediction_unit_Glue,FUNCTION," * not valid ..."); btb_val = false; dir_val = false; ras_val = false; upt_val = false; } else { log_printf(TRACE,Prediction_unit_Glue,FUNCTION," * valid ..."); Taddress_t pc_previous = PORT_READ(in_PREDICT_PC_PREVIOUS [context]); Taddress_t pc_current = PORT_READ(in_PREDICT_PC_CURRENT [context]); Tcontrol_t pc_current_is_ds_take = PORT_READ(in_PREDICT_PC_CURRENT_IS_DS_TAKE [context]); Taddress_t pc_next ; Tcontrol_t pc_next_is_ds_take ; Tbranch_state_t branch_state ; // Tprediction_ptr_t branch_update_prediction_id ; Tinst_ifetch_ptr_t inst_ifetch_ptr ; // STEP (1) - Compute the address source Taddress_t address = (pc_current_is_ds_take)?pc_previous:pc_current; Taddress_t address_lsb = pc_current%_param->_nb_instruction [context]; //if pc_current_is_ds_take, then pc_current%_param->_nb_instruction [context] == 0 Taddress_t address_msb; log_printf(TRACE,Prediction_unit_Glue,FUNCTION," * address : 0x%x",address); // STEP (2) - Test if branch (access at branch_target_buffer) btb_val = true; ack [context] &= PORT_READ(in_PREDICT_BTB_ACK [i]); if (_param->_have_port_context_id) PORT_WRITE(out_PREDICT_BTB_CONTEXT_ID [i],context); PORT_WRITE(out_PREDICT_BTB_ADDRESS [i],address); // special case : // if pc_current_is_ds, then pc_previous have branch, also hit must be set. // else : a another branch have eject this branch : can't accurate Tcontrol_t hit = PORT_READ(in_PREDICT_BTB_HIT[i]); Tcontrol_t is_accurate = PORT_READ(in_PREDICT_BTB_IS_ACCURATE [i]) and not (pc_current_is_ds_take and not hit); // STEP (3) : Test if have branch in the packet if (hit == 1) { // STEP (3a) : branch - test condition bool use_dir = false; bool use_ras = false; bool use_upt = false; Tbranch_condition_t cond = PORT_READ(in_PREDICT_BTB_CONDITION [i]); Taddress_t address_src = PORT_READ(in_PREDICT_BTB_ADDRESS_SRC [i]); Taddress_t address_dest = PORT_READ(in_PREDICT_BTB_ADDRESS_DEST [i]); Tcontrol_t push; Tcontrol_t direction; switch (cond) { case BRANCH_CONDITION_NONE_WITHOUT_WRITE_STACK : // l.j { // use none unit (dir, upt and ras) direction = true; pc_next = address_dest; branch_state = BRANCH_STATE_NSPEC_TAKE; break; } case BRANCH_CONDITION_NONE_WITH_WRITE_STACK : // l.jal { use_upt = true; use_ras = true; push = true; direction = true; pc_next = address_dest; branch_state = BRANCH_STATE_NSPEC_TAKE; break; } case BRANCH_CONDITION_FLAG_UNSET : // l.bnf case BRANCH_CONDITION_FLAG_SET : // l.bf { use_upt = true; use_dir = true; // Test direction direction = PORT_READ(in_PREDICT_DIR_DIRECTION [i]); // Direction is not the "flag predict" ... also flag_unset and flag_set is the same if (direction = 1) { branch_state = BRANCH_STATE_SPEC_TAKE; pc_next = address_dest; } else { branch_state = BRANCH_STATE_SPEC_NTAKE; pc_next = address_src+2; // +1 = delay slot } break; } case BRANCH_CONDITION_READ_REGISTER_WITHOUT_WRITE_STACK : // l.jr (rb!=9) { use_upt = true; use_ras = true; push = true; direction = true; pc_next = address_dest; branch_state = BRANCH_STATE_SPEC_TAKE; break; } case BRANCH_CONDITION_READ_REGISTER_WITH_WRITE_STACK : // l.jalr { use_upt = true; use_ras = true; push = true; direction = true; pc_next = address_dest; branch_state = BRANCH_STATE_NSPEC_TAKE; break; } case BRANCH_CONDITION_READ_STACK : // l.jr (rb==9) { use_upt = true; use_ras = true; push = false; direction = true; pc_next = PORT_READ(in_PREDICT_RAS_ADDRESS_POP [i]); branch_state = BRANCH_STATE_SPEC_TAKE; break; } default : { ERRORMORPHEO(FUNCTION,"Unknow Condition"); break; } } if (use_dir) { ack[context] &= PORT_READ(in_PREDICT_DIR_ACK [i]); PORT_WRITE(out_PREDICT_DIR_ADDRESS_SRC [i], address_src); PORT_WRITE(out_PREDICT_DIR_STATIC [i], address_dest_have_port_context_id) PORT_WRITE(out_PREDICT_RAS_CONTEXT_ID [i], context); PORT_WRITE(out_PREDICT_RAS_PUSH [i], push); PORT_WRITE(out_PREDICT_RAS_ADDRESS_PUSH [i], address_src+2); is_accurate &= PORT_READ(in_PREDICT_RAS_HIT [i]); // if miss - prediction is not accurate } if (use_upt) { ack[context] &= PORT_READ(in_PREDICT_UPT_ACK [i]); PORT_WRITE(out_PREDICT_UPT_CONTEXT_ID [i],context); PORT_WRITE(out_PREDICT_UPT_BTB_ADDRESS_SRC [i],address_src); PORT_WRITE(out_PREDICT_UPT_BTB_ADDRESS_DEST [i],address_dest); PORT_WRITE(out_PREDICT_UPT_BTB_CONDITION [i],cond); PORT_WRITE(out_PREDICT_UPT_BTB_LAST_TAKE [i],direction); PORT_WRITE(out_PREDICT_UPT_BTB_IS_ACCURATE [i],is_accurate); // PORT_WRITE(out_PREDICT_UPT_DIR_HISTORY [i],PORT_READ(in_PREDICT_DIR_HISTORY [i])); PORT_WRITE(out_PREDICT_UPT_RAS_ADDRESS [i],PORT_READ(in_PREDICT_RAS_ADDRESS_POP [i])); // PORT_WRITE(out_PREDICT_UPT_RAS_INDEX [i],PORT_READ(in_PREDICT_RAS_INDEX [i])); } // ack = 1 if : // * btb_ack // * use_dir and dir_ack // * use_ras and ras_ack // * use_upt and upt_ack // ack [context] = (PORT_READ(in_PREDICT_BTB_ACK [i]) and // (use_dir and PORT_READ(in_PREDICT_DIR_ACK [i])) and // (use_ras and PORT_READ(in_PREDICT_RAS_ACK [i])) and // (use_upt and PORT_READ(in_PREDICT_UPT_ACK [i]))); dir_val = (use_dir and PORT_READ(in_PREDICT_BTB_ACK [i]) and (not use_ras or (use_ras and PORT_READ(in_PREDICT_RAS_ACK [i]))) and (not use_upt or (use_upt and PORT_READ(in_PREDICT_UPT_ACK [i])))); ras_val = (use_ras and PORT_READ(in_PREDICT_BTB_ACK [i]) and (not use_dir or (use_dir and PORT_READ(in_PREDICT_DIR_ACK [i]))) and (not use_upt or (use_upt and PORT_READ(in_PREDICT_UPT_ACK [i])))); upt_val = (use_upt and PORT_READ(in_PREDICT_BTB_ACK [i]) and (not use_dir or (use_dir and PORT_READ(in_PREDICT_DIR_ACK [i]))) and (not use_ras or (use_ras and PORT_READ(in_PREDICT_RAS_ACK [i])))); // pc_next - is previously computed // branch_state - is previously computed Taddress_t address_src_lsb = address_src%_param->_nb_instruction [context]; log_printf(TRACE,Prediction_unit_Glue,FUNCTION," * address_src : 0x%x",address_src); log_printf(TRACE,Prediction_unit_Glue,FUNCTION," * address_src_lsb : %d",address_src_lsb); if (address_src_lsb == (_param->_nb_instruction [context]-1)) { // branch is in the last slot of the packet log_printf(TRACE,Prediction_unit_Glue,FUNCTION," * branch is in the last slot of the packet"); address_msb = _param->_nb_instruction [context]; // == (address_src_lsb+1) pc_next_is_ds_take = 1; } else { // branch is in the last slot of the packet address_msb = (address_src_lsb+2); // +1 == delayed slot pc_next_is_ds_take = 0; } log_printf(TRACE,Prediction_unit_Glue,FUNCTION," * address_msb : %d",address_msb); inst_ifetch_ptr = address_src_lsb; // branch_update_prediction_id = (_param->_have_port_depth)?((PORT_READ(in_DEPTH_UPT_TAIL[context])+PORT_READ(in_DEPTH_UPT_NB_BRANCH [context]))%_param->_array_size_depth[context]):0; } else { // STEP (3b) : Sequential order : compute next paquet log_printf(TRACE,Prediction_unit_Glue,FUNCTION," * BTB miss : sequential order"); pc_next = address-address_lsb+_param->_nb_instruction [context]; // sequencial pc_next_is_ds_take = 0; // no branch, also no delay slot inst_ifetch_ptr = 0; branch_state = BRANCH_STATE_NONE; // branch_update_prediction_id = 0; address_msb = _param->_nb_instruction [context]; } PORT_WRITE(out_PREDICT_PC_NEXT [context] , pc_next ); PORT_WRITE(out_PREDICT_PC_NEXT_IS_DS_TAKE [context] , pc_next_is_ds_take ); log_printf(TRACE,Prediction_unit_Glue,FUNCTION," * instruction enable :"); log_printf(TRACE,Prediction_unit_Glue,FUNCTION," * nb_inst : %d",_param->_nb_instruction [context]); log_printf(TRACE,Prediction_unit_Glue,FUNCTION," * [0:%d[ = 0",address_lsb); log_printf(TRACE,Prediction_unit_Glue,FUNCTION," * [%d:%d[ = 1",address_lsb,((pc_current_is_ds_take)?1:address_msb)); log_printf(TRACE,Prediction_unit_Glue,FUNCTION," * [%d:%d[ = 0",((pc_current_is_ds_take)?1:address_msb),_param->_nb_instruction [context]); for (uint32_t j=0; j_nb_instruction [context]; j++) PORT_WRITE(out_PREDICT_INSTRUCTION_ENABLE [context][j], 0); // After last address (branch) : not valid if (_param->_have_port_inst_ifetch_ptr) PORT_WRITE(out_PREDICT_INST_IFETCH_PTR [context] , inst_ifetch_ptr ); PORT_WRITE(out_PREDICT_BRANCH_STATE [context] , branch_state ); if (_param->_have_port_depth) PORT_WRITE(out_PREDICT_BRANCH_UPDATE_PREDICTION_ID [context] , PORT_READ(in_PREDICT_UPT_BRANCH_UPDATE_PREDICTION_ID [i])); } // Write output PORT_WRITE(out_PREDICT_BTB_VAL [i], btb_val); PORT_WRITE(out_PREDICT_DIR_VAL [i], dir_val); PORT_WRITE(out_PREDICT_RAS_VAL [i], ras_val); PORT_WRITE(out_PREDICT_UPT_VAL [i], upt_val); } for (uint32_t i=0; i<_param->_nb_context; i++) PORT_WRITE(out_PREDICT_ACK[i],ack[i]); log_end(Prediction_unit_Glue,FUNCTION); }; }; // end namespace prediction_unit_glue }; // end namespace prediction_unit }; // end namespace front_end }; // end namespace multi_front_end }; // end namespace core }; // end namespace behavioural }; // end namespace morpheo #endif