#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()); if (PORT_READ(in_NRESET)) { // Init Tcontrol_t ack [_param->_nb_context]; for (uint32_t i=0; i<_param->_nb_context; i++) ack [i] = 0; for (uint32_t i=0; i<_param->_nb_inst_branch_predict; i++) { log_printf(TRACE,Prediction_unit_Glue,FUNCTION," * PREDICT [%d]",i); // No access Tcontrol_t btb_val = false; Tcontrol_t dir_val = false; Tcontrol_t ras_val = false; Tcontrol_t upt_val = false; // Get ack Tcontrol_t btb_ack = PORT_READ(in_PREDICT_BTB_ACK [i]); Tcontrol_t dir_ack = PORT_READ(in_PREDICT_DIR_ACK [i]); Tcontrol_t ras_ack = PORT_READ(in_PREDICT_RAS_ACK [i]); Tcontrol_t upt_ack = PORT_READ(in_PREDICT_UPT_ACK [i]); // Read context_id Tcontext_t context = (reg_PREDICT_PRIORITY+i)%_param->_nb_context; // priority log_printf(TRACE,Prediction_unit_Glue,FUNCTION," * context : %d",context); // Now : ack transaction ack [context] = 1; if (PORT_READ(in_PREDICT_VAL[context]) == 0) { // Nothing log_printf(TRACE,Prediction_unit_Glue,FUNCTION," * not valid ..."); // btb_val = false; // dir_val = false; // ras_val = false; // upt_val = false; } else { // Have transaction log_printf(TRACE,Prediction_unit_Glue,FUNCTION," * valid ..."); // Read information (PC) 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]); log_printf(TRACE,Prediction_unit_Glue,FUNCTION," * pc_previous : 0x%.8x (0x%.8x)",pc_previous,pc_previous<<2); log_printf(TRACE,Prediction_unit_Glue,FUNCTION," * pc_current : 0x%.8x (0x%.8x)",pc_current ,pc_current <<2); log_printf(TRACE,Prediction_unit_Glue,FUNCTION," * pc_current_is_ds_take : %d" ,pc_current_is_ds_take); 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 // -> if pc_current is a ds take, then pc_previous is a branchement // get branchement address to send at the BTB Taddress_t address = (pc_current_is_ds_take)?pc_previous:pc_current; // Address_lsb = position in fetch packet 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%.8x (0x%.8x)",address,address<<2); log_printf(TRACE,Prediction_unit_Glue,FUNCTION," * address_lsb : %d" ,address_lsb); // STEP (2) - Test if branch (access at branch_target_buffer) // Access at the btb btb_val = true; // Create the request if (_param->_have_port_context_id) PORT_WRITE(out_PREDICT_BTB_CONTEXT_ID [i],context); PORT_WRITE(out_PREDICT_BTB_ADDRESS [i],address); // Transaction can be ack if btb is not busy ack [context] &= btb_ack; log_printf(TRACE,Prediction_unit_Glue,FUNCTION," * btb_ack : %d" ,btb_ack); // BTB_ack = 0 ? else can continue if (not btb_ack) continue; // Test a special case : // if pc_current is a delay slot, then pc_previous is a branchement instruction, also hit must be set. // else : an another branch instruction have eject this branch : can't accurate Tcontrol_t hit = PORT_READ(in_PREDICT_BTB_HIT[i]); Tcontrol_t is_accurate = not (pc_current_is_ds_take and not hit); Tcontrol_t btb_is_accurate = PORT_READ(in_PREDICT_BTB_IS_ACCURATE [i]); log_printf(TRACE,Prediction_unit_Glue,FUNCTION," * hit : %d" ,hit); log_printf(TRACE,Prediction_unit_Glue,FUNCTION," * is_accurate : %d" ,is_accurate); log_printf(TRACE,Prediction_unit_Glue,FUNCTION," * btb_is_accurate : %d" ,btb_is_accurate); // STEP (3) : Test if BTB find a branch instruction in the packet if (hit == 1) { log_printf(TRACE,Prediction_unit_Glue,FUNCTION," * BTB hit : no sequential order"); // STEP (3a) : branch - test condition bool use_dir = false; bool use_ras = false; bool use_upt = false; Taddress_t address_src = PORT_READ(in_PREDICT_BTB_ADDRESS_SRC [i]); Taddress_t address_src_lsb = address_src%_param->_nb_instruction [context]; inst_ifetch_ptr = address_src_lsb; log_printf(TRACE,Prediction_unit_Glue,FUNCTION," * address_src : 0x%.8x (0x%.8x)",address_src,address_src<<2); log_printf(TRACE,Prediction_unit_Glue,FUNCTION," * address_src_lsb : %d",address_src_lsb); // Special case : // * BTB hit and the branchement is the PC current and it's the last slot. // -> next pc must be the delay slot if ((not pc_current_is_ds_take) and // if pc_current is ds_take, then pc_next is the destination of branchement (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"); // Branch is the last slot : next paquet is the delay slot pc_next = address_src+1; // sequential pc_next_is_ds_take = 1; address_msb = _param->_nb_instruction [context]; // == (address_src_lsb+1) branch_state = BRANCH_STATE_NONE; } else { log_printf(TRACE,Prediction_unit_Glue,FUNCTION," * branch is not in the last slot of the packet"); Tbranch_condition_t condition = PORT_READ(in_PREDICT_BTB_CONDITION [i]); Taddress_t address_dest = PORT_READ(in_PREDICT_BTB_ADDRESS_DEST [i]); Tcontrol_t push ; Tcontrol_t direction; log_printf(TRACE,Prediction_unit_Glue,FUNCTION," * condition : %s" ,toString(condition).c_str()); log_printf(TRACE,Prediction_unit_Glue,FUNCTION," * address_src : 0x%.8x (0x%.8x)",address_src ,address_src <<2); log_printf(TRACE,Prediction_unit_Glue,FUNCTION," * address_dest : 0x%.8x (0x%.8x)",address_dest,address_dest<<2); switch (condition) { case BRANCH_CONDITION_NONE_WITHOUT_WRITE_STACK : // l.j { log_printf(TRACE,Prediction_unit_Glue,FUNCTION," * BRANCH_CONDITION_NONE_WITHOUT_WRITE_STACK"); // use none unit (dir and ras) use_upt = true; direction = true; pc_next = address_dest; branch_state = BRANCH_STATE_NSPEC_TAKE; // is_accurate &= btb_is_accurate; break; } case BRANCH_CONDITION_NONE_WITH_WRITE_STACK : // l.jal { log_printf(TRACE,Prediction_unit_Glue,FUNCTION," * BRANCH_CONDITION_NONE_WITH_WRITE_STACK"); use_upt = true; use_ras = true; push = true; direction = true; pc_next = address_dest; branch_state = BRANCH_STATE_NSPEC_TAKE; // is_accurate &= btb_is_accurate; break; } case BRANCH_CONDITION_FLAG_UNSET : // l.bnf case BRANCH_CONDITION_FLAG_SET : // l.bf { log_printf(TRACE,Prediction_unit_Glue,FUNCTION," * BRANCH_CONDITION_FLAG"); 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 } // is_accurate &= btb_is_accurate; break; } case BRANCH_CONDITION_READ_REGISTER_WITHOUT_WRITE_STACK : // l.jr (rb!=9) { log_printf(TRACE,Prediction_unit_Glue,FUNCTION," * BRANCH_CONDITION_READ_REGISTER_WITHOUT_WRITE_STACK"); use_upt = true; use_ras = true; push = true; direction = true; pc_next = address_dest; branch_state = BRANCH_STATE_SPEC_TAKE; is_accurate &= btb_is_accurate; break; } case BRANCH_CONDITION_READ_REGISTER_WITH_WRITE_STACK : // l.jalr { log_printf(TRACE,Prediction_unit_Glue,FUNCTION," * BRANCH_CONDITION_READ_REGISTER_WITH_WRITE_STACK"); use_upt = true; use_ras = true; push = true; direction = true; pc_next = address_dest; branch_state = BRANCH_STATE_NSPEC_TAKE; is_accurate &= btb_is_accurate; break; } case BRANCH_CONDITION_READ_STACK : // l.jr (rb==9) { log_printf(TRACE,Prediction_unit_Glue,FUNCTION," * BRANCH_CONDITION_READ_STACK"); log_printf(TRACE,Prediction_unit_Glue,FUNCTION," * ras_hit : %d",PORT_READ(in_PREDICT_RAS_HIT [i])); use_upt = true; use_ras = true; push = false; direction = true; address_dest = PORT_READ(in_PREDICT_RAS_HIT [i])?PORT_READ(in_PREDICT_RAS_ADDRESS_POP [i]):address_dest; pc_next = address_dest; branch_state = BRANCH_STATE_SPEC_TAKE; is_accurate &= (PORT_READ(in_PREDICT_RAS_HIT [i]) or btb_is_accurate); // if miss - prediction is not accurate break; } default : { ERRORMORPHEO(FUNCTION,"Unknow Condition"); break; } } log_printf(TRACE,Prediction_unit_Glue,FUNCTION," * direction : %d",direction); log_printf(TRACE,Prediction_unit_Glue,FUNCTION," * branch_state : %d",branch_state); log_printf(TRACE,Prediction_unit_Glue,FUNCTION," * pc_next : 0x%.8x (0x%.8x)",pc_next,pc_next<<2); if (use_dir) { ack[context] &= dir_ack; 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); } if (use_upt) { ack[context] &= upt_ack; if (_param->_have_port_context_id) 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],condition); 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] = (btb_ack and // (use_dir and dir_ack) and // (use_ras and ras_ack) and // (use_upt and upt_ack)); dir_val = (btb_ack and use_dir and // use_ras and // use_upt and // (not use_dir or (use_dir and dir_ack)) and (not use_ras or (use_ras and ras_ack)) and (not use_upt or (use_upt and upt_ack))); ras_val = (btb_ack and // use_dir and use_ras and // use_upt and (not use_dir or (use_dir and dir_ack)) and // (not use_ras or (use_ras and ras_ack)) and (not use_upt or (use_upt and upt_ack))); upt_val = (btb_ack and // use_dir and // use_ras and use_upt and (not use_dir or (use_dir and dir_ack)) and (not use_ras or (use_ras and ras_ack))// and // (not use_upt or (use_upt and upt_ack)) ); log_printf(TRACE,Prediction_unit_Glue,FUNCTION," * btb_{ val, ack} : %d, %d", btb_val, btb_ack); log_printf(TRACE,Prediction_unit_Glue,FUNCTION," * dir_{use, val, ack} : %d, %d, %d",use_dir,dir_val, dir_ack); log_printf(TRACE,Prediction_unit_Glue,FUNCTION," * ras_{use, val, ack} : %d, %d, %d",use_ras,ras_val, ras_ack); log_printf(TRACE,Prediction_unit_Glue,FUNCTION," * upt_{use, val, ack} : %d, %d, %d",use_upt,upt_val, upt_ack); // pc_next - is previously computed // branch_state - is previously computed // branch is in the last slot of the packet address_msb = (address_src_lsb+2); // +1 == delayed slot pc_next_is_ds_take = 0; } // 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"); // Take the address packet base and add new packet pc_next = pc_current-address_lsb+_param->_nb_instruction [context]; // sequential 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]; } log_printf(TRACE,Prediction_unit_Glue,FUNCTION," * address_msb : %d",address_msb); log_printf(TRACE,Prediction_unit_Glue,FUNCTION," * pc_next : 0x%.8x (0x%.8x)",pc_next,pc_next<<2); log_printf(TRACE,Prediction_unit_Glue,FUNCTION," * pc_next_is_ds_take : %d" ,pc_next_is_ds_take); // Write Output PORT_WRITE(out_PREDICT_PC_NEXT [context] , pc_next ); PORT_WRITE(out_PREDICT_PC_NEXT_IS_DS_TAKE [context] , pc_next_is_ds_take ); // Create enable mask Taddress_t address_limit_min = address_lsb; Taddress_t address_limit_max = ((pc_current_is_ds_take)?(address_lsb+1):address_msb); 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_limit_min); log_printf(TRACE,Prediction_unit_Glue,FUNCTION," * [%d:%d[ = 1",address_limit_min,address_limit_max); log_printf(TRACE,Prediction_unit_Glue,FUNCTION," * [%d:%d[ = 0",address_limit_max,_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); } // Write output 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