/************************************************************************************* * Microbench Benchmark: mbcedpp * ------------------------------------------ * Filename: mbcedpp.c * Author : Yuanhua Yu * Date : 25/12/1999 *------------------------------------------------------------------------------------- * * Function: 1.Measuring the cache size and associativity of Level-I cache and * * 2.Measuring the effective data path parallelism of Level_I cache and * * 3.Measuring the cache size of Level-II cache and * * 4.Measuring the hit read time of Level-I and Level-II cache. * * Methods: 1. Independent sequential array read access * 2. Dependent sequential array read but wait for the address * 3. Dependent sequential array read without waiting * 4. Random accessing sequence but waiting for the address * 5. Random accessing sequence without waiting for the address * * History: 10/10/1999 First version * 25/10/1999 Second version * 25/12/1999 Third version * * Parameters: TOTAL_ACCESS----- control the number of operations : (4096*4096*32) * ARR_SIZE_0 ----- array size starts(bytes) : 1024 * ARR_SIZE_1 ----- array size ends(bytes)-mode 1 : 32768 * ARR_SIZE_2 ----- array size ends(bytes)-mode 2 : 4194304 * ARR_STEP ----- step of array size increment(bytes): 1024 * STRIDE ----- distance between to accessed items : 8/16 (items) * NUM_WAYS ----- number of circular access sequences: 4 * * Variable: arr_size --- arr_size = arr_size / (sizeof(ATYPE))(items) * arr_mode --- increment mode of the array size : 0/1 * * Functions: * independent_access(): * wait_access() : * dependent_nowait() : * seq_circular() : * random_seq() : * random_parallel() : * random_sequence() : * random_circular() : * set_parameters() : * get_parameters() : * write_file_head() : * ****************************************************************************************/ #include #include #include #include #include #include #define TOTAL_ACCESS (4096*4096*16) #define STRIDE 32 #define NUM_WAYS 3 #define ARR_SIZE_0 1024 #define ARR_SIZE_1 (1024*32) #define ARR_SIZE_2 (1024*1024*8) #define ARR_STEP 1024 #define ATYPE long /*----------------------------------------------------------------------------------*/ void write_file_head(FILE *fp, char mname[255],long stride,int option); void independent_access(long arr_size, FILE *fp); void dependent_wait(long arr_size, FILE *fp); void dependent_nowait(long arr_size, FILE *fp); void seq_circular(volatile long *array,long max_index,long stride,long num_ways); void random_seq(long arr_size, FILE *fp); void random_parallel(long arr_size, FILE *fp); void random_sequence(volatile long *array, long max_index); void random_circular(volatile long *array, long max_index, long num_ways, long *s); void set_parameters(char mname[15],int *step_mode); void get_parameters(char mname[15],char fname[25],int *step_mode); /*----------------------------------------------------------------------------------*/ int main(char **av, int ac) { int option, step_mode=0; long arr_size; char file_name[255],machine_name[255]; FILE *fp; option = 1; while(option>=0 && option<7) { printf("\n Cache Capacity and Associativity Measurement \n"); printf("----------------------------------------------------------\n"); printf(" 0. All of the above tests\n"); printf(" 1. Wait accessing \n"); printf(" 2. Independentt accessing without wainting\n"); printf(" 3. Dependent accessing without waiting\n"); printf(" 4. Random accessing\n"); printf(" 5. Random accessing without waiting\n"); printf(" 6. Set parameters\n"); printf(" 7. Exit\n"); printf("----------------------------------------------------------\n"); printf(" Option(0-7) .... "); scanf("%d", &option); if(option ==6) { set_parameters(machine_name,&step_mode); continue; } get_parameters(machine_name,file_name,&step_mode); fp = fopen(file_name,"a+"); if(fp == NULL) { perror("Error: Can't open file !"); exit(1); } if (option == 1 || option == 0) { write_file_head(fp,machine_name,STRIDE*sizeof(ATYPE),1); if(step_mode == 0) for(arr_size=ARR_SIZE_0;arr_size<=ARR_SIZE_1;arr_size+=ARR_STEP) independent_access(arr_size,fp); if(step_mode == 1) for(arr_size=ARR_SIZE_0;arr_size<=ARR_SIZE_2;arr_size=arr_size*2) independent_access(arr_size,fp); fprintf(fp,"\n\n"); } if (option == 2 || option == 0 ) { write_file_head(fp,machine_name,STRIDE*sizeof(ATYPE),2); if(step_mode == 0) for(arr_size=ARR_SIZE_0;arr_size<=ARR_SIZE_1;arr_size+=ARR_STEP) dependent_wait(arr_size,fp); if(step_mode == 1) for(arr_size=ARR_SIZE_0;arr_size<=ARR_SIZE_2;arr_size=arr_size*2) dependent_wait(arr_size,fp); fprintf(fp,"\n\n"); } if (option == 3 || option == 0 ) { write_file_head(fp,machine_name,STRIDE*sizeof(ATYPE),3); if(step_mode == 0) for(arr_size=ARR_SIZE_0;arr_size<=ARR_SIZE_1;arr_size+=ARR_STEP) dependent_nowait(arr_size,fp); if(step_mode == 1) for(arr_size=ARR_SIZE_0;arr_size<=ARR_SIZE_2;arr_size=arr_size*2) dependent_nowait(arr_size,fp); fprintf(fp,"\n\n"); } if (option == 4 || option == 0 ) { write_file_head(fp,machine_name,STRIDE*sizeof(ATYPE),4); if(step_mode == 0) for(arr_size=ARR_SIZE_0;arr_size<=ARR_SIZE_1;arr_size+=ARR_STEP) random_seq(arr_size,fp); if(step_mode == 1) for(arr_size=ARR_SIZE_0;arr_size<=ARR_SIZE_2;arr_size=arr_size*2) random_seq(arr_size,fp); fprintf(fp,"\n\n"); } if (option == 5 || option == 0 ) { write_file_head(fp,machine_name,STRIDE*sizeof(ATYPE),5); if(step_mode == 0) for(arr_size=ARR_SIZE_0;arr_size<=ARR_SIZE_1;arr_size+=ARR_STEP) random_parallel(arr_size,fp); if(step_mode == 1) for(arr_size=ARR_SIZE_0;arr_size<=ARR_SIZE_2;arr_size=arr_size*2) random_parallel(arr_size,fp); fprintf(fp,"\n\n"); } } fclose(fp); return 0; } void independent_access(long arr_size, FILE *fp) /*--------------------------------------------------------------------------*/ /* Function: Measure the cache memory with a sequential accessing array */ /* */ /*--------------------------------------------------------------------------*/ { volatile ATYPE *va; register ATYPE s1; register long i,j,loop; unsigned long start_time,stop_time; double time_cost, cost_per_op; arr_size = arr_size / (sizeof(ATYPE)); va = (ATYPE *) calloc(arr_size, sizeof(ATYPE)); loop = TOTAL_ACCESS/arr_size*STRIDE; for (i=0; i0 || block_no>=max_index ) { continue; } else { array[index] = block_no; index = block_no; break; } } } return; } void random_circular(volatile long *array, long max_index, long num_ways, long *s) /*-------------------------------------------------------------------------------*/ /* Function: build up a num_ways ways circular random accsessing sequence. */ /* num_ways --- the number of the circles. */ /*-------------------------------------------------------------------------------*/ { long i, j, k,lc1,lc2, distance; distance = max_index/num_ways - 1; lc1 = 0; for(i=0; i=distance) { lc1 = array[lc2]; array[lc2] = s[i]; break; } k++; lc2=lc1; lc1=array[lc1]; } } return; } void set_parameters(char mname[15],int *step_mode) /*----------------------------------------------------------------------------*/ /* Function: Config the needed parameters from keyboard and */ /* form a name for the data file and save the them */ /* in the TLB_Config.data . */ /*----------------------------------------------------------------------------*/ { char fname[25]; FILE *fp; printf(" The Machine Name: "); scanf("%s",mname); printf(" Mode of array size increment(0/1): "); scanf("%d", step_mode); strcpy(fname,"Capacity_"); strcat(fname,mname); strcat(fname,".dat"); fp = fopen("Capacity_Config.dat","w"); if(fp == NULL) { perror("Error: Can't open file !"); exit(1); } fprintf(fp,"%s\n",mname); fprintf(fp,"%s\n",fname); fprintf(fp,"%d\n",*step_mode); fclose(fp); return; } void get_parameters(char mname[15],char fname[25],int *step_mode) /*---------------------------------------------------------------------------*/ /* Function: get the parameters needed from file TLB_Config.dat */ /*---------------------------------------------------------------------------*/ { FILE *fp; fp = fopen("Capacity_Config.dat","r"); if(fp == NULL) { perror("Error: Can't open file !"); exit(1); } fscanf(fp,"%s\n",mname); fscanf(fp,"%s\n",fname); fscanf(fp,"%d\n",step_mode); fclose(fp); return; } void write_file_head(FILE *fp,char mname[255],long stride,int option) /*----------------------------------------------------------------------------*/ /* Funtion: write some given parameters to the head of the data file */ /*----------------------------------------------------------------------------*/ { time_t tm; char time_buf[255]; time(&tm); strcpy(time_buf, ctime(&tm)); printf("\n\nTest date: %s", time_buf ); printf("----------------------------------------------------------\n"); fprintf(fp,"--------- Measurement of Cache Capacity -----------\n"); fprintf(fp,"\n Manchine: %s", mname ); fprintf(fp,"\nStride(bytes): %d", stride); fprintf(fp,"\n Test date: %s", time_buf ); if( option == 1) fprintf(fp," Method: dependent_wait --- %d",option); else if (option == 2) fprintf(fp," Method: Independent_access --- %d",option); else if (option == 3) fprintf(fp," Method: dependent_nowait --- %d",option); else if (option == 4) fprintf(fp," Method: random_sequential --- %d",option); else if (option == 5) fprintf(fp," Method: random_parallel --- %d",option); else ; fprintf(fp,"\n-----------------------------------------------------\n"); printf("ARR_SIZE(byte) Access_T(ns)\tTotal_T(s)\n"); fprintf(fp,"ARR_SIZE(byte) Access_T(ns)\tTotal_T(s)\n"); }