/* Given a stage number, express the name in a string (6/12) */ #include "instdef.h" #include "timeds.h" /* Added by Sibin M on Oct 25, 2004. * Process of cleaning up the TA for C++ */ #include "isa.h" #include "lib.h" #include "instdecl.h" #include #include #include /* Added by Sibin M on Oct 25, 2004. * Process of cleaning up the TA for C++ */ #include /* TODO: Check if the subpath code works TODO: Check if all the parameter variables introduced are required TODO: Check out the timed BB changes */ // #define __SIB_DEBUG__ #ifdef __SIB_DEBUG__ #define printc printf extern bool sib_verbose ; #endif // __SIB_DEBUG__ extern bool only_fetch; extern int memory_count; extern bool verbose; extern int inst_end_cycles[CARD_INST_SET][NUM_DATASIZES][NUM_STAGES][NUM_CASES]; char *stage_name( int stage_number ) { static char name[4]; /*AMOL:Changed Here*/ switch (stage_number) { case 0 : strcpy (name, "IF"); break; case 1 : strcpy (name, "ID"); break; case 2 : strcpy (name, "EX"); break; case 3 : strcpy (name, "WB"); break; default: strcpy (name, "XXX"); } return name; } /*WARNING COMMENT FROM DR. HEALY'S CODE*/ /* These 2 functions that follow convert between a register name (string) and an arbitrary number that corresponds to each. They were coded by Dr. Whalley on 4/24/1995 Modified 10/17/1998 to allow constant instead of register: just return 0. This is saying the source register is %g0 (always zero). There should be no data dependency problem, since no compiler-generated instruction writes to %g0. */ int reg2int( char* reg ) { return 0; } void int2reg( int num, char* reg ) { sprintf(reg,"r%d",num); } // GOPI: Changed here int is_flop( char* inst_name ) { if(inst_name [0] == 'f') { return 1; } else if ((inst_name[0] == 'l') && (inst_name[1] == 'f')) { // Doubt: Check with Sibin if Floating point Load comes under FLOP } else if ((inst_name[0] == 's') && (inst_name[1] == 't') && (inst_name[2] == 'f')) { // Doubt: Check with Sibin if Floating point Stores comes under FLOP } else return 0; } int dest_in_op3( char* name ) { if (strcmp (name, "add") == 0 || strcmp (name, "and") == 0 || strcmp (name, "sub") == 0 || strcmp (name, "addu") == 0 || strcmp (name, "subu") == 0 || strcmp (name, "or") == 0 || strcmp (name, "xor") == 0 || strcmp (name, "nor") == 0 || strcmp (name, "sllv") == 0 || strcmp (name, "srlv") == 0 || strcmp (name, "srav") == 0 || strcmp (name, "slt") == 0 || strcmp (name, "sltu") == 0 || strcmp (name, "add.s") == 0 || strcmp (name, "add.d") == 0 || strcmp (name, "sub.s") == 0 || strcmp (name, "sub.d") == 0 || strcmp (name, "mul.s") == 0 || strcmp (name, "mul.d") == 0 || strcmp (name, "div.s") == 0 || strcmp (name, "div.d") == 0 || is_load_inst(name) || strcmp (name, "mfhi") ==0 || strcmp(name, "mthi")==0 || strcmp (name, "mflo") ==0 || strcmp(name, "mtlo")==0 || strcmp (name, "andi") ==0 || strcmp (name, "addiu")==0 || strcmp (name, "addi") ==0 || strcmp(name, "ori")==0 || strcmp (name, "xori")==0 || strcmp(name, "slti") ==0 || strcmp (name, "sltiu")==0 || strcmp(name,"abs.s")==0 || strcmp(name,"abs.d")==0 || strcmp(name,"mov.s")==0 || strcmp(name,"mov.d")==0 || strcmp(name,"neg.s")==0 || strcmp(name,"neg.d")==0 || strcmp(name,"cvt.s.d")==0 || strcmp(name,"cvt.s.w")==0 || strcmp(name,"cvt.d.s")==0 || strcmp(name,"cvt.d.w")==0 || strcmp(name,"cvt.w.s")==0 || strcmp(name,"cvt.w.d")==0 || strcmp(name,"move")==0 || strcmp(name, "li") ==0 ) return 0; } int is_load_inst( char* name ) { /*GOPI: Changed here */ if ((name[0] == 'l' ) { return 1; } else return 0; } int is_store_inst( char* name ) { /*GOPI:Changed here*/ if ((name[0] == 's' )&& (name[1] == 't' )) { return 1; } else return 0; } /* is_branch - compare an opcode to see if it is that of a branch instruction 7/23/98 */ int is_branch( int opcode ) { /* Modified by Sibin M on Mar. 18, 2004. * Added the following opcodes in the list of branch instructions. */ /*GOPI: Changed here */ if((opcode > 29) && (opcode < 190)) { return 1; } else return 0; } int is_call( int opcode ) { /*GOPI: Changed here*/ switch (opcode) { case BL: case BLA: case BCL: case BCLA: case BCLR: case BCLRL: case BCCTR case BCCTRL: case BTL: case BTLA: case BDNZL: case BDNZLA: case BDNZTL: case BDNZTLA: case BDNZFL: case BDNZFLA: case BDZL: case BDZLA: case BDZTL: case BDZTLA: case BDZFL: case BDZFLA: case BLTL: case BLTLA: case BLEL: case BLELA: case BEQL: case BEQLA: case BGEL: case BGELA: case BGTL: case BGTLA: case BNL: case BNLA: case BNLL: case BNLLA: case BNEL: case BNELA: case BNGL: case BNGLA: case BSOL: case BSOLA: case BNSL: case BNSLA: case BUNL: case BUNLA: case BNUL: case BNULA: return 1; default: return 0; } } /* We need to jump over inner loops or functions so not to wait too long * while counting unnecessary cycles in step 38 (5/14) * The 3rd test in the if-statement ensures we don't repeat jumps. */ struct cycle_jump_node *calc_cycle_jump( row *begin_use, row *end_use, int pipeline_cycles[], int num_path_inst ) { int i, stage; struct cycle_jump_node *cycle_jump_temp = NULL, *cycle_jump_head = NULL; for (i = num_path_inst - 1; i >= 0; --i) { if (only_fetch) { if (end_use[i][IF] != NEVER && end_use[i][IF] + 1 < begin_use[i+1][IF] && (cycle_jump_head == NULL || cycle_jump_head->to != begin_use[i+1][IF])) { memory_count += sizeof (struct cycle_jump_node); cycle_jump_temp = (struct cycle_jump_node *) malloc (sizeof (struct cycle_jump_node)); cycle_jump_temp->from = end_use[i][IF]; cycle_jump_temp->to = begin_use[i+1][IF]; cycle_jump_temp->next = cycle_jump_head; cycle_jump_head = cycle_jump_temp; } } else { // GOPI: Changed here for (stage = EX; stage < NUM_STAGES; ++stage) if (end_use[i][stage] != NEVER && end_use[i][stage] < begin_use[i+1][IF] && (cycle_jump_head == NULL || cycle_jump_head->to != begin_use[i+1][IF])) { memory_count += sizeof (struct cycle_jump_node); cycle_jump_temp = (struct cycle_jump_node *) malloc (sizeof (struct cycle_jump_node)); cycle_jump_temp->from = larger(pipeline_cycles[i],end_use[i][stage]); cycle_jump_temp -> to = begin_use[i+1][IF]; cycle_jump_temp -> next = cycle_jump_head; cycle_jump_head = cycle_jump_temp; } } } return cycle_jump_head; } void weird_fix1( int* path_end_cycles, int cycle_diff, int* path_cycles) { /*AMOL:Probably needed for PPC because it is not 2 stage - Ask Sibin */ } int set_instr_size( struct instruct* inf_inst_ptr) { return SINGLE_SIZE; } int dest_ready_stage( struct instruct* inf_inst_ptr, int inst_data_type ) { // GOPI: Changed here // In the case of PPC, there is no separate MEM stage. The EX stage combines the execution and the memory stages return EX; } void set_src_needed( int* stage_src1_needed, int* stage_src2_needed, int* stage_src3_needed, int num_path_inst, struct instruct *inf_inst_ptr) { /*AMOL: Probably used for diff type of inst like store store/dest - Ask Sibin*/ /*if (is_store_inst (inf_inst_ptr->inst)) { stage_src1_needed[num_path_inst] = IS; --- there is no issue stage in PPC..Why is IS used here? stage_src2_needed[num_path_inst] = IS; --- there is no issue stage in PPC..WHy is IS used here? stage_src3_needed[num_path_inst] = EX; } else if (dest_in_op3 (inf_inst_ptr->inst)) { stage_src1_needed[num_path_inst] = IS; stage_src2_needed[num_path_inst] = IS; stage_src3_needed[num_path_inst] = NO_STAGE; --- Why is NO_STAGE used here ? } else { if (*(inf_inst_ptr->op1.reg_list) !='\0') stage_src1_needed[num_path_inst] = IS; else stage_src1_needed[num_path_inst] = NO_STAGE; if (*(inf_inst_ptr->op2.reg_list) !='\0') stage_src2_needed[num_path_inst] = IS; else stage_src2_needed[num_path_inst] = NO_STAGE; if (*(inf_inst_ptr->op3.reg_list) !='\0') stage_src3_needed[num_path_inst] = IS; else stage_src3_needed[num_path_inst] = NO_STAGE; }*/ } int check_branch_misprediction( struct instruct* inf_inst_ptr, struct inst_num_node* inst_num_head ) { /*AMOL: No need to change*/ int i; struct inst_num_node *inst_num_temp = NULL; if (is_branch(inf_inst_ptr->inst_type)) { for (inst_num_temp = inst_num_head; inst_num_temp->next; inst_num_temp = inst_num_temp->next) { if (inst_num_temp->num == inf_inst_ptr->number) { i = inst_num_temp->next->num; break; } } if (inf_inst_ptr->data_type == 50) if (inf_inst_ptr->number > i) return 1; if (inf_inst_ptr->data_type == 100) if (inf_inst_ptr->number < i) return 1; } return 0; } void branch_penalty_after_loop( int* earliest_start ) { int stage; /*GOPI: Changed here */ for( stage = IF; stage < WB; stage++) earliest_start[stage] = earliest_start[EX]; } void initialize_end_use( row* end_use, int num_path_inst, int* this_inst_end_cycles ) { /*AMOL: No Change*/ end_use[num_path_inst][EX] = get_end_use (EX, num_path_inst, this_inst_end_cycles, end_use); } void add_misprediction_penalty( bool& prev_Mispredicted_branch, row* end_use, int num_path_inst ) { /*AMOL: Probably the second line with end_use needs to be changed*/ if (prev_Mispredicted_branch) { if (verbose) printf("ADDING MISPREDICT PENALTY \n"); end_use[num_path_inst][IF] = end_use[num_path_inst-1][EX] +1; end_use[num_path_inst-1][EX] ++; // Why is this done ? prev_Mispredicted_branch = false; } } void calculate_end_use( int* this_inst_end_cycles, row* end_use, row* begin_use, int num_path_inst, int only_fetch, int* inst_cond_code, int* cc_set, int* inst_data_type, struct instruct* inf_inst_ptr, int size, int tcase ) { int stage, j; /*AMOL: This needs to be changed.*/ end_use[num_path_inst][ID] = larger (end_use[num_path_inst][IF] + 1, end_use[num_path_inst-1][IS]) ; end_use[num_path_inst][IS] = larger (end_use[num_path_inst][ID] + 1, end_use[num_path_inst-1][EX]); if (end_use[num_path_inst][EX] ==0 ){ printf("ERROR"); exit(1); } stage = IS; if (! only_fetch && stage == IS && inst_cond_code[num_path_inst] == COND_USED) { *cc_set = 0; for (j = num_path_inst - 1; j >= 0; j--) if (inst_cond_code[j] == COND_SET && inst_data_type[j] == inst_data_type[num_path_inst]) { *cc_set = end_use[j][EX]; break; } if (*cc_set > end_use[num_path_inst][IS]) { if (verbose) printf ("must wait for cc till\n", *cc_set); end_use[num_path_inst][IS] = *cc_set; } } /* handle end of EX and CA, similar to the ID */ for (stage = EX; stage != NO_STAGE && stage <= next_stage (EX, this_inst_end_cycles); stage = next_stage (stage, this_inst_end_cycles)) { end_use[num_path_inst][stage] = get_end_use (stage, num_path_inst, this_inst_end_cycles, end_use); } /*BY NOW ALL THE STAGE INFO IN END USE IS CALCULATED */ /* end_use of FPEX, WB, FWB */ /*BOOKMARK- remove artifact stages */ /*TAKING CARE OF THE MEM AND WB STAGES */ if (this_inst_end_cycles[MEM] > 0 && this_inst_end_cycles[WB] > 0) end_use[num_path_inst][WB] = end_use[num_path_inst][MEM] + 1; } void data_access( struct instruct * inf_inst_ptr, int * this_inst_end_cycles, int * this_inst_beg_cycles, int data_status, int *dcache_misses, struct instr_history * history, bool& prev_MEM_Miss, int DC_MISS_LATENCY) { int i; if (is_load_inst (inf_inst_ptr->inst) || is_store_inst (inf_inst_ptr->inst)) { history->is_mem_op = true; if (data_status) { for (i=IF; i < WB; i++) { // GOPI: Changed here. if (this_inst_end_cycles[i] >0) this_inst_end_cycles[i]+=/*DC_HIT_LATENCY*/ + DC_MISS_LATENCY; } if (verbose) printf("Adding the DATA MISS \n"); *dcache_misses+=1; history->dcache_miss = true; prev_MEM_Miss = true; } else { for (i=IF; i < WB; i++) { // Gopi: Changed here if (this_inst_end_cycles[i] >0) this_inst_end_cycles[i]+=0;//DC_HIT_LATENCY ; } prev_MEM_Miss = false; history->dcache_miss = false; } } } void add_data_hazard_penalty(int delay,int * this_inst_end_cycles, int *end_use, struct instruct *inf_inst_ptr){ /*AMOL: Change here.*/ int prev, stage; /*BOOKMARK- data hazard delays are available only at ID and later -- Changed from IS to ID */ if (delay > 0 && this_inst_end_cycles[IS] != 0 ) // ! is_store_inst(inf_inst_ptr->inst)) { end_use[ID] = larger(end_use[ID] + delay, end_use[ID] + 1); } if (delay > 0 && ! is_store_inst(inf_inst_ptr->inst)) { for (prev = ID, stage = EX; stage < NUM_STAGES; ++stage) { if (this_inst_end_cycles[stage] == 0) continue; end_use[stage] = end_use[ID] + this_inst_end_cycles[ID] - this_inst_end_cycles[stage]; if (stage != WB) { end_use[stage] = larger (end_use[stage], end_use[stage+1]); } else end_use[WB] = end_use[MEM] + 1; // Gopi: Check this. May need change. prev = stage; } } } void calculate_begin_use(int *begin_use, int *end_use, int * this_inst_end_cycles){ int stage, next; /*AMOL: nothing to change*/ for (stage = IF; stage != EX; ) { next = next_stage (stage, this_inst_end_cycles); if (next == UNUSED) break; if (this_inst_end_cycles[stage] > 0 && this_inst_end_cycles[next] > 0) begin_use[next] = end_use[stage] + 1; stage = next; } } void calculate_cc_reg(int *inst_cond_code, int *inst_data_type,int *src_needed, int *end_use, int *release_time){ /*AMOL: Should not be conditional*/ // #ifdef TRASH - Gopi: Removed the conditional compilation if (*inst_cond_code == COND_USED && *inst_data_type == INTEGER && *src_needed == NEVER) { *src_needed = end_use[ID]; if (verbose) printf ("int-cc needed by %d\n", end_use[ID]); } if (*inst_cond_code == COND_USED && *inst_data_type == FLOP && *src_needed == NEVER) { *src_needed = end_use[ID]; if (verbose) printf ("flop-cc needed by %d\n", end_use[ID]); } if (*inst_cond_code == COND_SET && *inst_data_type == INTEGER) { *release_time = end_use[EX]; if (verbose) printf ("int-cc set at %d\n", end_use[EX]); } if (*inst_cond_code == COND_SET && *inst_data_type == FLOP) { *release_time = end_use[EX];/*NO MORE FPEX*/ if (verbose) printf ("flop-cc set at %d\n", end_use[EX]); } // #endif - Gopi: Removed the conditional compilation } // Gopi: The below function is not used either in time.cpp or in isa.cpp. So can be safely removed. /* Function check_update_variable_cycles() . * * Added by Sibin M on April 19, 2004. * Certain instructions, such as "sbrs", "sbrc", "sbis", "sbic", etc. take a variable number of cycles. * In the case of the above instructions, it's as follows : * Cycles: * 1 if condition is false (no skip) * 2 if condition is true (skip is executed) and the instruction skipped is 1 word * 3 if condition is true (skip is executed) and the instruction skipped is 2 words * * Hence, care must be taken to return the correct number of cycles, based on the the number of iterations * left in the loop. * * If it's NOT the last iteration, then return 1 cycle and NOT 3 * * If it IS the last isntruction, then return 3 cycles. * * The function takes the instruction code(opcode) as one of the arguments. It also takes, this_inst_end_cycles[] as * an argument, and modifies it IF necessary. * The following two steps are added : * * Check to see if the opcode lies between 41 and 44 ( inclusive ) - for the above 4 instructions. * * If so, check next to see how many iterations remain. Make a decision on number of cycles based on that. * * Change the IF part of this_inst_end_cycles to reflect the correct number of cycles. * * Return value indicated whether a change has occured. */ bool check_update_variable_cycles( int opcode, int this_inst_end_cycles[], int iterations_handled, int max_iterations ) { /*AMOL: Difficult to say*/ /* Check opcode to see if opcode belongs to one of the "sb.." instructions. */ if( ( opcode == SBIS ) || ( opcode == SBRS ) || ( opcode == SBIC ) || ( opcode == SBRC ) ) { if( ( max_iterations - iterations_handled ) > 1 ) { /* Change ONLY if it's NOT the last iteration of the loop. */ this_inst_end_cycles[IF] = 2 ; return true ; } } /* No change was made */ return false ; } // Gopi: The below function needs to be changed for PPC ISA as the instructions mulhwu[.], mulhw[.], mulli, mullw[o][.], lmw, // lwsi, lwsx, stmw, stswi, stswx have variable number of execution cycles depending on the number of words. /* Function : adjust_for_variable_cycles() . * * Added by Sibin M on April 26, 2004. * Certain instructions, such as "sbrs", "sbrc", "sbis", "sbic", etc. take a variable number of cycles. * In the case of the above instructions, it's as follows : * Cycles: * 1 if condition is false (no skip) * 2 if condition is true (skip is executed) and the instruction skipped is 1 word * 3 if condition is true (skip is executed) and the instruction skipped is 2 words * * Hence, we must adjust the number of cycles calculated so far, in the following manner : * - Check to see if the instruction is the last one in the current path or not. * - If it is, then use the largest number of cycles ( 3 in this case ), as it will be patched * in with the next pipeline stage. * - If not, i.e. it is an instruction inside the path, then no skip kas occurred and it has fallen * through...hence taking the minimum ( 1 in this case ) cycles. * * This function must be called in the pipeline "glueing" stage - i.e. where the various paths are * added together to fit like a jigsaw puzzle. * * Steps to follow : * - Go through all the paths in the "path_head" variable, and for each go through the "path_list". * - Locate the block. * - Go through the instructions in the block. See if they are the required instructions. * - If so, check to see if they are the last instructions in the block - check to see if * a valid "next" pointer exists. * - If so, decrement the extra two cycles from the various structures. * * * Further Modification by Sibin M on May 06, 2004. * o handle all branch instructions "br**". * Branch instructions take variable cycles : * - 1 if condition is false * - 2 if condition is true. * * So, as in the above case of the "sbrs" etc., inside the intructions-level loop, * check to see if the instruction is a "br**" instruction, i.e. it's opcode >= 45 and <= 64. * If so, then add an extra cycle to everything. * * Return value the number of cycles to be deducted from total_time. */ int adjust_for_variable_cycles( struct inf_func_element* inf, struct loop_path_node* path_head, struct loop_path_node* longest_path_ptr, struct union_list_node* end_head[], struct union_list_node* prev_end_head[], int path_cycles, int max_pipeline ) { /**/ bool longest_path_handled = false ; struct loop_path_node* path_ptr = path_head ; struct loop_block_list* ploop_block = NULL ; struct instruct* pinstruction ; struct block_element* pinf_block ; int diff = 0 ; int stage ; /* First go through all the paths. */ for( path_ptr = path_head ; path_ptr ; path_ptr = path_ptr->next ) { /* Check to see if the longest_path_ptr has been handled or not. */ if( path_ptr == longest_path_ptr ) longest_path_handled = true ; for ( ploop_block = path_ptr->path_list; ploop_block ; ploop_block = ploop_block->next) { /* Find the inf block corresponding to the current path. */ pinf_block = Locate_Inf_Block( inf, ploop_block->block_number ) ; /* Now look at each instruction in the inf block and make changes where appropriate. */ for( pinstruction = pinf_block->instruct_list ; pinstruction ; pinstruction = pinstruction->next ) { /* For all branch ( i.e. "br**" instructions. * If the current instruction is a branch, and is the last one in the current path, * then add one cycle. */ /*AMOL: The branch instruction for the ppc be added here*/ if( ( pinstruction->inst_type >= BRBS ) && ( pinstruction->inst_type <= BRID ) ) { // Found a branch, now check to see if it's the last in current path. if( !pinstruction->next ) { // It is the last one. "Add" 1 cycle to everything. path_ptr->path_cycles += 1 ; diff -= 1 ; path_ptr->end_cycles[IF] += 1 ; // path_ptr->end_cycles[EX] += 1 ; } } /* This is for the "sbrs" and related instructions. * Now check if the instruction is the last one in the path or not. * If not, then we must reduce the number of cycles. * If it is the last, then do nothing. */ if( !ploop_block->next ) break ; /* Not the last instruction. * Now, see if it is the right instruction. */ /*AMOL: No idea what is done with the special branches*/ if( ( pinstruction->inst_type == SBIS ) || ( pinstruction->inst_type == SBRS ) || ( pinstruction->inst_type == SBIC ) || ( pinstruction->inst_type == SBRC ) ) { // Remove the Extra cycles. path_ptr->path_cycles -= 2 ; diff += 2 ; path_ptr->end_cycles[IF] -= 1 ; } } } /* Check to see if the longest_path_ptr has been handled or not. if( path_ptr == longest_path_ptr ) longest_path_handled = true ; */ /* Update the cycles value for the end_head variable. */ for( stage = 0 ; stage < NUM_STAGES ; ++stage ) { if( path_cycles < max_pipeline ) { if( path_ptr->end_cycles[stage] + (max_pipeline - path_cycles) < end_head[stage]->cycles ) end_head[stage]->cycles = path_ptr->end_cycles[stage] + (max_pipeline - path_cycles); } else { if( path_ptr->end_cycles[stage] < end_head[stage]->cycles ) end_head[stage]->cycles = path_ptr->end_cycles[stage]; } } } /* IF the occupant of the end_head happens to be one of the above instructions, then we reduce the * number of cycles of the IF stage by 1. * IF the occupant of prev_end_head happens tp one of the above instructions, then we reduce the number * of cycles of the OF stage by 3. */ /* if( ( end_head[IF]->occupant->inst_type == SBIS ) || ( end_head[IF]->occupant->inst_type == SBRS ) || ( end_head[IF]->occupant->inst_type == SBIC ) || ( end_head[IF]->occupant->inst_type == SBRC ) ) end_head[IF]->cycles -= 1 ; */ /* if( ( prev_end_head[IF]->occupant->inst_type == SBIS ) || ( prev_end_head[IF]->occupant->inst_type == SBRS ) || ( prev_end_head[IF]->occupant->inst_type == SBIC ) || ( prev_end_head[IF]->occupant->inst_type == SBRC ) ) prev_end_head[IF]->cycles -= 3 ; */ /* If longest_path_ptr has NOT been handled, then do so right here. * Hmmm...must it really be handled here ? Won't it be included above ? */ return diff ; } int get_cycles(row *end_use,int num_path_inst, int only_fetch){ int path_cycles, i; /* #ifdef __SIB_DEBUG__ if( sib_verbose ) { printc( " --- \n" ) ; printc( "get_cycles() : Enter...path_cycles = %d \t only_fetch = %d \n", path_cycles, only_fetch ) ; printc( " --- \n" ) ; } #endif // __SIB_DEBUG__ */ /* Gopi: Commented the code /* path_cycles = 0; if (only_fetch) path_cycles = end_use[num_path_inst][IF]; else { for (i = num_path_inst; i >= 0; i--) { if (end_use[i][EX] > 0) { if (end_use[i][EX] > path_cycles) path_cycles = end_use[i][EX]; break; } } /*AMOL: Probably for other stages we need to run the for loop }*/ /* #ifdef __SIB_DEBUG__ if( sib_verbose ) { printc( " --- \n" ) ; printc( "get_cycles() : Exit...path_cycles = %d \n", path_cycles ) ; printc( " --- \n" ) ; } #endif // __SIB_DEBUG__ */ path_cycles = 0; if (only_fetch) path_cycles = end_use[num_path_inst][IF]; else { for (i = num_path_inst; i >= 0; i--) if (end_use[i][WB] > 0) { if (end_use[i][WB] > path_cycles) path_cycles = end_use[i][WB]; break; } for (i = num_path_inst; i >= 0; i--) if (end_use[i][EX] > 0) // Changed frm MEM to EX { if (end_use[i][EX] > path_cycles) // Changed frm MEM to EX path_cycles = end_use[i][MEM]; // Changed frm MEM to EX break; } } return path_cycles; return path_cycles; } void print_inst_time(row *begin_use,row * end_use,int num_path_inst, int * path_pipeline){ // Gopi: Changed here int stage , i; if (verbose) { printf ("inst %9s %9s %9s %9s\n", "IF", "ID", "EX", "WB"); for (i = 0; i <= num_path_inst; i++) { printf ("#%3d: ", path_pipeline[i]); for (stage = 0; stage < NUM_STAGES; stage++) printf ("%4d-%4d ", begin_use[i][stage], end_use[i][stage]); printf ("\n"); } printf ("\n"); } } void print_table_head(){ /*AMOL: change to add more stages*/ // Gopi: Changed here printf(" cycle # IF ID EX WB inst fetched\n"); printf("--------- -- -- -- -- ------------\n"); } void update_end_use(row *end_use,int num_path_inst,int * this_inst_end_cycles){ poss_update (&end_use[num_path_inst][IF], end_use[num_path_inst - 1][ID], "wait for ID after a miss"); } int ex_time( int inst, int size, enum time_case tcase) { /*BOOKMARK- only EX stage exists */ /*AMOL: Probably we need to change some stuff here ??? */ return inst_end_cycles[inst][size][IF][(int) tcase] - inst_end_cycles[inst][size][EX][(int) tcase]; }