|
PAPI
5.0.1.0
|
00001 /****************************/ 00002 /* THIS IS OPEN SOURCE CODE */ 00003 /****************************/ 00004 00005 /* 00006 * File: ppc64_events.c 00007 * Author: Maynard Johnson 00008 * maynardj@us.ibm.com 00009 * Mods: <your name here> 00010 * <your email address> 00011 */ 00012 00013 #include "papi_internal.h" 00014 #include <string.h> 00015 #include "libperfctr.h" 00016 00017 hwd_groups_t group_map[MAX_GROUPS] = { {0} 00018 , {0} 00019 , {0} 00020 , {0} 00021 , {0} 00022 }; 00023 native_event_entry_t native_table[PAPI_MAX_NATIVE_EVENTS]; 00024 00025 /* to initialize the native_table */ 00026 void 00027 perfctr_initialize_native_table( ) 00028 { 00029 int i, j; 00030 memset( native_table, 0, 00031 PAPI_MAX_NATIVE_EVENTS * sizeof ( native_event_entry_t ) ); 00032 for ( i = 0; i < PAPI_MAX_NATIVE_EVENTS; i++ ) { 00033 for ( j = 0; j < MAX_COUNTERS; j++ ) 00034 native_table[i].resources.counter_cmd[j] = -1; 00035 } 00036 } 00037 00038 00039 /* to setup native_table group value */ 00040 void 00041 perfctr_ppc64_setup_gps( int total, ntv_event_group_info_t * group_info ) 00042 { 00043 int i, j, gnum; 00044 00045 for ( i = 0; i < total; i++ ) { 00046 for ( j = 0; j < MAX_COUNTERS; j++ ) { 00047 if ( native_table[i].resources.selector & ( 1 << j ) ) { 00048 for ( gnum = 0; gnum < group_info->maxgroups; gnum++ ) { 00049 if ( native_table[i].resources.counter_cmd[j] == 00050 group_info->event_groups[gnum]->events[j] ) { 00051 native_table[i].resources.group[gnum / 32] |= 00052 1 << ( gnum % 32 ); 00053 } 00054 } 00055 } 00056 } 00057 } 00058 00059 for ( gnum = 0; gnum < group_info->maxgroups; gnum++ ) { 00060 group_map[gnum].mmcr0 = group_info->event_groups[gnum]->mmcr0; 00061 group_map[gnum].mmcr1L = group_info->event_groups[gnum]->mmcr1L; 00062 group_map[gnum].mmcr1U = group_info->event_groups[gnum]->mmcr1U; 00063 group_map[gnum].mmcra = group_info->event_groups[gnum]->mmcra; 00064 for ( i = 0; i < MAX_COUNTERS; i++ ) 00065 group_map[gnum].counter_cmd[i] = 00066 group_info->event_groups[gnum]->events[i]; 00067 } 00068 } 00069 00070 00071 /* to setup native_table values, and return number of entries */ 00072 int 00073 perfctr_ppc64_setup_native_table( ) 00074 { 00075 int pmc, ev, i, j, index; 00076 /* This is for initialisation-testing of consistency between 00077 native_name_map and our events file */ 00078 int itemCount = 0; 00079 index = 0; 00080 perfctr_initialize_native_table( ); 00081 ntv_event_info_t *info = perfctr_get_native_evt_info( ); 00082 if ( info == NULL ) { 00083 PAPIERROR( EVENT_INFO_FILE_ERROR ); 00084 return PAPI_ECMP; 00085 } 00086 ntv_event_t *wevp; 00087 for ( pmc = 0; pmc < info->maxpmcs; pmc++ ) { 00088 wevp = info->wev[pmc]; 00089 for ( ev = 0; ev < info->maxevents[pmc]; ev++, wevp++ ) { 00090 for ( i = 0; i < index; i++ ) { 00091 if ( strcmp( wevp->symbol, native_table[i].name ) == 0 ) { 00092 native_table[i].resources.selector |= 1 << pmc; 00093 native_table[i].resources.counter_cmd[pmc] = 00094 wevp->event_num; 00095 break; 00096 } 00097 } 00098 if ( i == index ) { 00099 //native_table[i].index=i; 00100 native_table[i].resources.selector |= 1 << pmc; 00101 native_table[i].resources.counter_cmd[pmc] = wevp->event_num; 00102 native_table[i].name = 00103 ( char * ) malloc( strlen( wevp->symbol ) + 1 ); 00104 strcpy( native_table[i].name, wevp->symbol ); 00105 native_table[i].description = wevp->description; 00106 index++; 00107 for ( j = 0; j < MAX_NATNAME_MAP_INDEX; j++ ) { 00108 /* It appears that here, if I'm right, that the events 00109 file entry matches the event from native_name_map, */ 00110 /* This here check is to ensure that native_name_map in fact 00111 has MAX_NATNAME_MAP_INDEX elements, or rather that it never 00112 tries to access one that has not been initialised. */ 00113 if ( native_name_map[j].name == NULL ) { 00114 SUBDBG( "native_name_map has a NULL at position %i\n", 00115 j ); 00116 PAPIERROR 00117 ( "Inconsistency between events_map file and events header." ); 00118 return PAPI_EBUG; 00119 } 00120 if ( strcmp( native_table[i].name, native_name_map[j].name ) 00121 == 0 ) { 00122 native_name_map[j].index = i; 00123 itemCount++; 00124 break; 00125 } 00126 } 00127 /* If we never set native_name_map[j], then there is an 00128 inconsistency between native_name_map and native_table */ 00129 if ( ( !( j < MAX_NATNAME_MAP_INDEX ) ) || 00130 native_name_map[j].index != i ) { 00131 SUBDBG 00132 ( "No match found between native_name_map and native_table. " 00133 "Values was %s at position %i in native_table.\n", 00134 native_table[i].name, i ); 00135 PAPIERROR 00136 ( "Inconsistency between native_name_map and events file." ); 00137 return PAPI_EBUG; 00138 } 00139 } 00140 } 00141 } 00142 /* given the previous evidence that native_name_map is a superset of 00143 native_table, ensuring this match in their cardinality shows them to 00144 be equivalent. */ 00145 if ( itemCount != MAX_NATNAME_MAP_INDEX ) { 00146 SUBDBG( "%i events found in native_table, but really should be %i\n", 00147 itemCount, MAX_NATNAME_MAP_INDEX ); 00148 PAPIERROR 00149 ( "Inconsistent cardinality between native_name_map and events file", 00150 itemCount, MAX_NATNAME_MAP_INDEX ); 00151 return PAPI_EBUG; 00152 } 00153 00154 ntv_event_group_info_t *gp_info = perfctr_get_native_group_info( ); 00155 if ( gp_info == NULL ) { 00156 perfctr_initialize_native_table( ); 00157 PAPIERROR( EVENT_INFO_FILE_ERROR ); 00158 return PAPI_ECMP; 00159 } 00160 00161 perfctr_ppc64_setup_gps( index, gp_info ); 00162 _papi_hwi_system_info.sub_info.num_native_events = index; 00163 00164 return check_native_name( ); 00165 } 00166 00167 int 00168 check_native_name( ) 00169 { 00170 enum native_name foo; 00171 int itemCount = 0; 00172 int i; 00173 00174 /* This should ensure that the cardinality of native_name is the same 00175 as that of native_name_map which may be true iff native_name 00176 expresses the same data as native_name_map and there is a 1:1 00177 mapping from one onto the other, though there is no guarantee of 00178 order. */ 00179 if ( ( NATNAME_GUARD - PAPI_NATIVE_MASK ) != MAX_NATNAME_MAP_INDEX ) { 00180 SUBDBG( "%i is the number of elements apparently in native_name, " 00181 "but really should be %i, according to native_name_map.\n", 00182 ( NATNAME_GUARD - PAPI_NATIVE_MASK ), MAX_NATNAME_MAP_INDEX ); 00183 PAPIERROR 00184 ( "Inconsistent cardinality between native_name and native_name_map " 00185 "detected in preliminary check\n" ); 00186 return PAPI_EBUG; 00187 } 00188 00189 /* The following is sanity checking only. It attempts to verify some level 00190 of consistency between native_name and native_name_map and native_table. 00191 This should imply that native_name is a subset of native_name_map. */ 00192 for ( foo = PAPI_NATIVE_MASK; foo < NATNAME_GUARD; foo++ ) { 00193 for ( i = 0; i < MAX_NATNAME_MAP_INDEX; i++ ) { 00194 /* Now, if the event we are on is the native event we seek... */ 00195 if ( ( native_name_map[i].index | PAPI_NATIVE_MASK ) == foo ) { 00196 itemCount++; 00197 break; 00198 } 00199 } 00200 } 00201 if ( itemCount != MAX_NATNAME_MAP_INDEX ) { 00202 SUBDBG( "Inconsistency between native_name_map and native_name. " 00203 "%i events matched, but really should be %i\n", itemCount, 00204 MAX_NATNAME_MAP_INDEX ); 00205 PAPIERROR 00206 ( "Inconsistent cardinality between native_name and native_name_map\n" ); 00207 return PAPI_EBUG; 00208 } 00209 00210 return PAPI_OK; 00211 } 00212 00213 static FILE * 00214 open_file( const char *fname ) 00215 { 00216 char *cpu; 00217 char *dot = "."; 00218 char *dot_dot = ".."; 00219 #ifdef _POWER5p 00220 cpu = "power5+"; 00221 #elif defined(_POWER5) 00222 cpu = "power5"; 00223 #elif defined(_PPC970) 00224 cpu = "ppc970"; 00225 #else 00226 cpu = ""; 00227 #endif 00228 char *dir = ( char * ) getenv( "PAPI_EVENTFILE_PATH" ); 00229 #ifdef PAPI_DATADIR 00230 if ( dir == NULL ) { 00231 dir = PAPI_DATADIR; 00232 } 00233 #endif 00234 /* If dir is still NULL, assume current dir holds event_data dir */ 00235 if ( dir == NULL ) 00236 dir = dot; 00237 00238 char *relative_pathname = ( char * ) malloc( strlen( "/" ) + 00239 strlen( "event_data" ) + 00240 strlen( "/" ) + strlen( cpu ) + 00241 strlen( "/" ) + 00242 strlen( fname ) + 1 ); 00243 strcpy( relative_pathname, "/" ); 00244 strcat( relative_pathname, "event_data" ); 00245 strcat( relative_pathname, "/" ); 00246 strcat( relative_pathname, cpu ); 00247 strcat( relative_pathname, "/" ); 00248 strcat( relative_pathname, fname ); 00249 /* Add a little extra space to the malloc for the case where dir = "." since 00250 * we may be trying dir = ".." later on. */ 00251 char *pathname = 00252 ( char * ) malloc( strlen( dir ) + strlen( relative_pathname ) + 4 ); 00253 int keep_trying; 00254 if ( strcmp( dir, dot ) == 0 ) 00255 keep_trying = 2; 00256 else 00257 keep_trying = 3; 00258 FILE *file = NULL; 00259 while ( file == NULL && keep_trying-- ) { 00260 strcpy( pathname, dir ); 00261 strcat( pathname, relative_pathname ); 00262 file = fopen( pathname, "r" ); 00263 if ( strcmp( dir, dot ) == 0 ) { 00264 dir = dot_dot; 00265 } else { 00266 dir = dot; 00267 } 00268 SUBDBG( "Attempt to open event data file %s %s successful.\n", pathname, 00269 ( file == NULL ) ? "was not" : "was" ); 00270 memset( pathname, '\0', sizeof ( pathname ) ); 00271 } 00272 00273 free( pathname ); 00274 free( relative_pathname ); 00275 return ( file ); 00276 } 00277 00278 static ntv_event_t * 00279 copy_buffer( ntv_event_t events[], int maxevents ) 00280 { 00281 ntv_event_t *cur_wev, *start_wev; 00282 start_wev = ( ntv_event_t * ) malloc( sizeof ( ntv_event_t ) * maxevents ); 00283 cur_wev = start_wev; 00284 00285 int cnt; 00286 for ( cnt = 0; cnt < maxevents; cnt++, cur_wev++ ) { 00287 cur_wev->event_num = events[cnt].event_num; 00288 strcpy( cur_wev->symbol, events[cnt].symbol ); 00289 cur_wev->short_description = 00290 ( char * ) malloc( strlen( events[cnt].short_description ) ); 00291 strcpy( cur_wev->short_description, events[cnt].short_description ); 00292 cur_wev->description = 00293 ( char * ) malloc( strlen( events[cnt].description ) ); 00294 strcpy( cur_wev->description, events[cnt].description ); 00295 } 00296 return start_wev; 00297 } 00298 00299 static ntv_event_info_t * 00300 parse_eventfile( FILE * evfile ) 00301 { 00302 int counter = 0, num_events = 0; 00303 int i, len, cc; 00304 int event; 00305 int line_counter_flag = 0; 00306 char line_data[1024]; 00307 ntv_event_t events[PAPI_MAX_NATIVE_EVENTS]; 00308 ntv_event_info_t *ntv_evt_info = 00309 ( ntv_event_info_t * ) malloc( sizeof ( ntv_event_info_t ) ); 00310 ntv_evt_info->maxpmcs = 0; 00311 char data[1024]; 00312 while ( fgets( data, 1022, evfile ) ) { 00313 if ( feof( evfile ) ) 00314 continue; 00315 if ( strlen( data ) < 2 ) 00316 continue; 00317 00318 if ( strncmp( data, "$$$$", 4 ) == 0 ) { 00319 line_counter_flag = 0; 00320 ntv_evt_info->maxevents[counter - 1] = num_events; 00321 ntv_evt_info->wev[counter - 1] = copy_buffer( events, num_events ); 00322 ntv_event_t *temp = ntv_evt_info->wev[counter - 1]; 00323 temp++; 00324 } 00325 switch ( line_counter_flag ) { 00326 case 0: 00327 if ( sscanf( data, "{ counter %u", &counter ) == 1 ) { 00328 line_counter_flag = 1; 00329 num_events = 0; 00330 ntv_evt_info->maxpmcs++; 00331 } 00332 break; 00333 case 1: 00334 if ( sscanf( data, "#%u", &event ) != 1 ) { 00335 fprintf( stderr, "EVS file format error 1 (%s)\n", data ); 00336 return NULL; 00337 } 00338 if ( event >= PAPI_MAX_NATIVE_EVENTS ) { 00339 fprintf( stderr, "EVS file format error 1 (%s)\n", data ); 00340 return NULL; 00341 } 00342 events[num_events].event_num = event; 00343 len = strlen( data ); 00344 int symb_found = 0; 00345 for ( i = cc = 0; i < len; i++ ) { 00346 if ( data[i] == ',' ) 00347 cc++; 00348 if ( cc == 5 && !symb_found ) { 00349 strcpy( line_data, &data[i + 1] ); 00350 int j = 0; 00351 while ( line_data[j] != ',' ) 00352 j++; 00353 strncpy( events[num_events].symbol, line_data, j ); 00354 events[num_events].symbol[j] = 0; 00355 symb_found = 1; 00356 i += j; 00357 } else if ( cc == 6 ) { 00358 len = strlen( &data[i + 1] ); 00359 events[num_events].short_description = 00360 ( char * ) malloc( len ); 00361 strcpy( events[num_events].short_description, 00362 &data[i + 1] ); 00363 events[num_events].short_description[len - 1] = 0; 00364 break; 00365 } 00366 } 00367 line_counter_flag = 2; 00368 break; 00369 case 2: 00370 line_counter_flag = 3; 00371 break; 00372 case 3: 00373 len = strlen( data ); 00374 events[num_events].description = ( char * ) malloc( len ); 00375 strcpy( events[num_events].description, data ); 00376 events[num_events].description[len - 1] = 0; 00377 line_counter_flag = 1; 00378 num_events++; 00379 break; 00380 } 00381 } 00382 if ( counter == 0 ) { 00383 free( ntv_evt_info ); 00384 ntv_evt_info = NULL; 00385 } 00386 if ( counter == MAX_COUNTERS ) { 00387 ntv_evt_info->maxevents[counter - 1] = num_events; 00388 ntv_evt_info->wev[counter - 1] = copy_buffer( events, num_events ); 00389 } 00390 fclose( evfile ); 00391 return ntv_evt_info; 00392 } 00393 00394 static int 00395 any_counter_invalid( int event_id[], int size ) 00396 { 00397 int j; 00398 for ( j = 0; j < size; j++ ) { 00399 if ( event_id[j] >= PAPI_MAX_NATIVE_EVENTS ) 00400 return 1; 00401 } 00402 return 0; 00403 } 00404 00405 static ntv_event_group_info_t * 00406 parse_groupfile( FILE * grp_file ) 00407 { 00408 char data[1024]; 00409 unsigned int mmcr0, mmcr1H, mmcr1L, mmcra; 00410 int g, state = 0; 00411 ntv_event_group_info_t *group_info = 00412 ( ntv_event_group_info_t * ) 00413 malloc( sizeof ( ntv_event_group_info_t ) ); 00414 group_info->maxgroups = 0; 00415 int event_num[MAX_COUNTERS]; 00416 while ( fgets( data, 1022, grp_file ) ) { 00417 if ( feof( grp_file ) || ( strlen( data ) < 2 ) ) 00418 continue; 00419 00420 switch ( state ) { 00421 case 0: 00422 #if defined(_POWER5) || defined(_POWER5p) 00423 if ( sscanf 00424 ( data, "#%u,%u,%u,%u,%u,%u,%u", &g, &event_num[0], 00425 &event_num[1], &event_num[2], &event_num[3], &event_num[4], 00426 &event_num[5] ) == 7 ) { 00427 state = 1; 00428 if ( any_counter_invalid( event_num, 6 ) ) { 00429 fprintf( stderr, "ERROR: Maximum events exceeded\n" ); 00430 return NULL; 00431 } 00432 } 00433 #else 00434 if ( sscanf 00435 ( data, "#%u,%u,%u,%u,%u,%u,%u,%u,%u", &g, &event_num[0], 00436 &event_num[1], &event_num[2], &event_num[3], &event_num[4], 00437 &event_num[5], &event_num[6], &event_num[7] ) == 9 ) { 00438 state = 1; 00439 if ( any_counter_invalid( event_num, 8 ) ) { 00440 fprintf( stderr, "ERROR: Maximum events exceeded\n" ); 00441 return NULL; 00442 } 00443 } 00444 #endif 00445 if ( state == 1 ) { 00446 group_info->event_groups[group_info->maxgroups] = 00447 ( event_group_t * ) malloc( sizeof ( event_group_t ) ); 00448 group_info->event_groups[group_info->maxgroups]->group_id = g; 00449 int j = 0; 00450 for ( ; j < MAX_COUNTERS; j++ ) 00451 group_info->event_groups[group_info->maxgroups]->events[j] = 00452 event_num[j]; 00453 } 00454 break; 00455 case 1: 00456 // unused hex event codes 00457 state = 2; 00458 break; 00459 case 2: 00460 /* get mmcr values */ 00461 if ( sscanf( data, "%x,%x,%x,%x", &mmcr0, &mmcr1H, &mmcr1L, &mmcra ) 00462 != 4 ) { 00463 fprintf( stderr, "GPS file format error 1 (%s)\n", data ); 00464 return NULL; 00465 } 00466 state = 3; 00467 group_info->event_groups[group_info->maxgroups]->mmcr0 = mmcr0; 00468 group_info->event_groups[group_info->maxgroups]->mmcr1L = mmcr1L; 00469 group_info->event_groups[group_info->maxgroups]->mmcr1U = mmcr1H; 00470 group_info->event_groups[group_info->maxgroups]->mmcra = mmcra; 00471 group_info->maxgroups++; 00472 break; 00473 case 3: 00474 // unused group name 00475 state = 0; 00476 } 00477 } 00478 fclose( grp_file ); 00479 return group_info; 00480 } 00481 00482 ntv_event_info_t * 00483 perfctr_get_native_evt_info( void ) 00484 { 00485 ntv_event_info_t *evt_info = NULL; 00486 FILE *evt_file = open_file( "events" ); 00487 if ( evt_file != NULL ) { 00488 evt_info = parse_eventfile( evt_file ); 00489 } 00490 return evt_info; 00491 00492 } 00493 00494 ntv_event_group_info_t * 00495 perfctr_get_native_group_info( void ) 00496 { 00497 ntv_event_group_info_t *groups = NULL; 00498 FILE *grp_file = NULL; 00499 if ( ( grp_file = open_file( "groups" ) ) != NULL ) { 00500 groups = parse_groupfile( grp_file ); 00501 } 00502 return groups; 00503 }