|
PAPI
5.3.0.0
|
00001 /* This file utility reports hardware info and native event availability on either the host 00002 * CPU or on one of the attached MIC devices. It is based on the papi_native_avail utility, 00003 * but uses offloading to run either on the host CPU or on a target device. */ 00050 #pragma offload_attribute (push,target(mic)) 00051 #include "papi_test.h" 00052 #pragma offload_attribute (pop) 00053 00054 #include <stdlib.h> 00055 #include <offload.h> 00056 00057 #define EVT_LINE 80 00058 00059 typedef struct command_flags 00060 { 00061 int help; 00062 int details; 00063 int named; 00064 int include; 00065 int xclude; 00066 char *name, *istr, *xstr; 00067 int darr; 00068 int dear; 00069 int iarr; 00070 int iear; 00071 int opcm; 00072 int umask; 00073 int groups; 00074 int mic; 00075 int devidx; 00076 } command_flags_t; 00077 00078 static void 00079 print_help( char **argv ) 00080 { 00081 printf( "This is the PAPI native avail program.\n" ); 00082 printf( "It provides availability and detail information for PAPI native events.\n" ); 00083 printf( "Usage: %s [options]\n", argv[0] ); 00084 printf( "\nOptions:\n" ); 00085 printf( " --help, -h print this help message\n" ); 00086 printf( " -d display detailed information about native events\n" ); 00087 printf( " -e EVENTNAME display detailed information about named native event\n" ); 00088 printf( " -i EVENTSTR include only event names that contain EVENTSTR\n" ); 00089 printf( " -x EVENTSTR exclude any event names that contain EVENTSTR\n" ); 00090 printf( " --noumasks suppress display of Unit Mask information\n" ); 00091 printf( "\nProcessor-specific options\n"); 00092 printf( " --darr display events supporting Data Address Range Restriction\n" ); 00093 printf( " --dear display Data Event Address Register events only\n" ); 00094 printf( " --iarr display events supporting Instruction Address Range Restriction\n" ); 00095 printf( " --iear display Instruction Event Address Register events only\n" ); 00096 printf( " --opcm display events supporting OpCode Matching\n" ); 00097 printf( " --nogroups suppress display of Event grouping information\n" ); 00098 printf( " --mic <index> display events on the specified Xeon Phi device\n" ); 00099 printf( "\n" ); 00100 } 00101 00102 static int 00103 no_str_arg( char *arg ) 00104 { 00105 return ( ( arg == NULL ) || ( strlen( arg ) == 0 ) || ( arg[0] == '-' ) ); 00106 } 00107 00108 static void 00109 parse_args( int argc, char **argv, command_flags_t * f ) 00110 { 00111 00112 int i; 00113 00114 /* Look for all currently defined commands */ 00115 memset( f, 0, sizeof ( command_flags_t ) ); 00116 f->umask = 1; 00117 f->groups = 1; 00118 00119 for ( i = 1; i < argc; i++ ) { 00120 if ( !strcmp( argv[i], "--darr" ) ) 00121 f->darr = 1; 00122 else if ( !strcmp( argv[i], "--dear" ) ) 00123 f->dear = 1; 00124 else if ( !strcmp( argv[i], "--iarr" ) ) 00125 f->iarr = 1; 00126 else if ( !strcmp( argv[i], "--iear" ) ) 00127 f->iear = 1; 00128 else if ( !strcmp( argv[i], "--opcm" ) ) 00129 f->opcm = 1; 00130 else if ( !strcmp( argv[i], "--noumasks" ) ) 00131 f->umask = 0; 00132 else if ( !strcmp( argv[i], "--nogroups" ) ) 00133 f->groups = 0; 00134 else if ( !strcmp( argv[i], "-d" ) ) 00135 f->details = 1; 00136 else if ( !strcmp( argv[i], "--mic" ) ) 00137 { 00138 f->mic = 1; 00139 i++; 00140 if ( i >= argc || no_str_arg( argv[i] ) ) { 00141 printf( "Specify a device index for --mic\n"); 00142 exit(1); 00143 } 00144 f->devidx = strtol(argv[i], 0, 10); 00145 } else if ( !strcmp( argv[i], "-e" ) ) { 00146 f->named = 1; 00147 i++; 00148 f->name = argv[i]; 00149 if ( i >= argc || no_str_arg( f->name ) ) { 00150 printf( "Invalid argument for -e\n"); 00151 exit(1); 00152 } 00153 } else if ( !strcmp( argv[i], "-i" ) ) { 00154 f->include = 1; 00155 i++; 00156 f->istr = argv[i]; 00157 if ( i >= argc || no_str_arg( f->istr ) ) { 00158 printf( "Invalid argument for -i\n"); 00159 exit(1); 00160 } 00161 } else if ( !strcmp( argv[i], "-x" ) ) { 00162 f->xclude = 1; 00163 i++; 00164 f->xstr = argv[i]; 00165 if ( i >= argc || no_str_arg( f->xstr ) ) { 00166 printf( "Invalid argument for -x\n"); 00167 exit(1); 00168 } 00169 } else if ( !strcmp( argv[i], "-h" ) || !strcmp( argv[i], "--help" ) ) 00170 f->help = 1; 00171 else { 00172 printf( "%s is not supported\n", argv[i] ); 00173 exit(1); 00174 } 00175 } 00176 00177 /* if help requested, print and bail */ 00178 if ( f->help ) { 00179 print_help( argv); 00180 exit( 1 ); 00181 } 00182 } 00183 00184 static void 00185 space_pad( char *str, int spaces ) 00186 { 00187 while ( spaces-- > 0 ) 00188 strcat( str, " " ); 00189 } 00190 00191 static void 00192 print_event( PAPI_event_info_t * info, int offset ) 00193 { 00194 unsigned int i, j = 0; 00195 char str[EVT_LINE + EVT_LINE]; 00196 00197 /* indent by offset */ 00198 if ( offset ) { 00199 printf( "| %-73s|\n", info->symbol ); 00200 } 00201 else { 00202 printf( "| %-77s|\n", info->symbol ); 00203 } 00204 00205 while ( j <= strlen( info->long_descr ) ) { 00206 i = EVT_LINE - 12 - 2; 00207 if ( i > 0 ) { 00208 str[0] = 0; 00209 strcat(str,"| " ); 00210 space_pad( str, 11 ); 00211 strncat( str, &info->long_descr[j], i ); 00212 j += i; 00213 i = ( unsigned int ) strlen( str ); 00214 space_pad( str, EVT_LINE - ( int ) i - 1 ); 00215 strcat( str, "|" ); 00216 } 00217 printf( "%s\n", str ); 00218 } 00219 } 00220 00221 static int 00222 parse_unit_masks( PAPI_event_info_t * info ) 00223 { 00224 char *pmask,*ptr; 00225 00226 /* handle the PAPI component-style events which have a component:::event type */ 00227 if ((ptr=strstr(info->symbol, ":::"))) { 00228 ptr+=3; 00229 /* handle libpfm4-style events which have a pmu::event type event name */ 00230 } else if ((ptr=strstr(info->symbol, "::"))) { 00231 ptr+=2; 00232 } 00233 else { 00234 ptr=info->symbol; 00235 } 00236 00237 if ( ( pmask = strchr( ptr, ':' ) ) == NULL ) { 00238 return ( 0 ); 00239 } 00240 memmove( info->symbol, pmask, ( strlen( pmask ) + 1 ) * sizeof ( char ) ); 00241 pmask = strchr( info->long_descr, ':' ); 00242 if ( pmask == NULL ) 00243 info->long_descr[0] = 0; 00244 else 00245 memmove( info->long_descr, pmask + sizeof ( char ), 00246 ( strlen( pmask ) + 1 ) * sizeof ( char ) ); 00247 return ( 1 ); 00248 } 00249 00250 00251 int 00252 main( int argc, char **argv ) 00253 { 00254 int i, j = 0, k; 00255 int retval; 00256 PAPI_event_info_t info; 00257 const PAPI_hw_info_t *hwinfo = NULL; 00258 command_flags_t flags; 00259 int enum_modifier; 00260 int numcmp, cid; 00261 00262 int num_devices = 0; 00263 int target_idx = 0; 00264 int offload_mode = 0; 00265 int target_ok = 0; 00266 00267 /* Parse the command-line arguments */ 00268 parse_args( argc, argv, &flags ); 00269 00270 if (flags.mic) 00271 { 00272 printf("Checking for Intel(R) Xeon Phi(TM) (Target CPU) devices...\n\n"); 00273 00274 #ifdef __INTEL_OFFLOAD 00275 num_devices = _Offload_number_of_devices(); 00276 #endif 00277 printf("Number of Target devices installed: %d\n\n",num_devices); 00278 00279 if (flags.devidx >= num_devices) { 00280 // Run in fallback-mode 00281 printf("Requested device index %d is not available. Specify a device between 0 and %d\n\n", 00282 flags.devidx, num_devices-1); 00283 exit(1); 00284 } 00285 else { 00286 offload_mode = 1; 00287 target_idx = flags.devidx; 00288 printf("PAPI will list the native events available on device mic%d\n\n", target_idx); 00289 } 00290 } 00291 00292 /* Set enum modifier mask */ 00293 if ( flags.dear ) 00294 enum_modifier = PAPI_NTV_ENUM_DEAR; 00295 else if ( flags.darr ) 00296 enum_modifier = PAPI_NTV_ENUM_DARR; 00297 else if ( flags.iear ) 00298 enum_modifier = PAPI_NTV_ENUM_IEAR; 00299 else if ( flags.iarr ) 00300 enum_modifier = PAPI_NTV_ENUM_IARR; 00301 else if ( flags.opcm ) 00302 enum_modifier = PAPI_NTV_ENUM_OPCM; 00303 else 00304 enum_modifier = PAPI_ENUM_EVENTS; 00305 00306 /* Set TESTS_QUIET variable */ 00308 tests_quiet( argc, argv ); 00309 00310 /* Initialize before parsing the input arguments */ 00311 #ifdef __INTEL_OFFLOAD 00312 __Offload_report(1); 00313 #endif 00314 #pragma offload target(mic: target_idx) if(offload_mode) 00315 retval = PAPI_library_init(PAPI_VER_CURRENT); 00316 if ( retval != PAPI_VER_CURRENT ) { 00317 test_fail( __FILE__, __LINE__, "PAPI_library_init", retval ); 00318 } 00319 00320 00321 if ( !TESTS_QUIET ) { 00322 #ifdef __INTEL_OFFLOAD 00323 __Offload_report(1); 00324 #endif 00325 #pragma offload target(mic: target_idx) if(offload_mode) 00326 retval = PAPI_set_debug( PAPI_VERB_ECONT ); 00327 if ( retval != PAPI_OK ) { 00328 test_fail( __FILE__, __LINE__, "PAPI_set_debug", retval ); 00329 } 00330 } 00331 00332 #ifdef __INTEL_OFFLOAD 00333 __Offload_report(1); 00334 #endif 00335 #pragma offload target(mic: target_idx) if(offload_mode) nocopy(hwinfo) 00336 { 00337 retval = papi_print_header( "Available native events and hardware information.\n", &hwinfo ); 00338 fflush(stdout); 00339 } 00340 if ( retval != PAPI_OK ) { 00341 test_fail( __FILE__, __LINE__, "PAPI_get_hardware_info", 2 ); 00342 } 00343 00344 00345 /* Do this code if the event name option was specified on the commandline */ 00346 if ( flags.named ) 00347 { 00348 int papi_ok = 0; 00349 char *ename = flags.name; 00350 int elen = 0; 00351 if (ename) 00352 elen = strlen(ename) + 1; 00353 #ifdef __INTEL_OFFLOAD 00354 __Offload_report(1); 00355 #endif 00356 #pragma offload target(mic: target_idx) if(offload_mode) in(ename:length(elen)) out(i) 00357 papi_ok = PAPI_event_name_to_code(ename, &i); 00358 00359 if (papi_ok == PAPI_OK) 00360 { 00361 #ifdef __INTEL_OFFLOAD 00362 __Offload_report(1); 00363 #endif 00364 #pragma offload target(mic: target_idx) if(offload_mode) out(info) 00365 papi_ok = PAPI_get_event_info(i, &info); 00366 } 00367 00368 if (papi_ok == PAPI_OK) 00369 { 00370 printf( "%-30s%s\n", 00371 "Event name:", info.symbol); 00372 printf( "%-29s|%s|\n", "Description:", info.long_descr ); 00373 00374 /* if unit masks exist but none specified, process all */ 00375 if ( !strchr( flags.name, ':' ) ) 00376 { 00377 #ifdef __INTEL_OFFLOAD 00378 __Offload_report(1); 00379 #endif 00380 #pragma offload target(mic: target_idx) if(offload_mode) inout(i) 00381 papi_ok = PAPI_enum_event( &i, PAPI_NTV_ENUM_UMASKS); 00382 if (papi_ok == PAPI_OK ) 00383 { 00384 printf( "\nUnit Masks:\n" ); 00385 do 00386 { 00387 #ifdef __INTEL_OFFLOAD 00388 __Offload_report(1); 00389 #endif 00390 #pragma offload target(mic: target_idx) if(offload_mode) inout(i, info) 00391 retval = PAPI_get_event_info( i, &info ); 00392 if ( retval == PAPI_OK ) { 00393 if ( parse_unit_masks( &info ) ) { 00394 printf( "%-29s|%s|%s|\n", " Mask Info:", 00395 info.symbol, info.long_descr ); 00396 } 00397 } 00398 #ifdef __INTEL_OFFLOAD 00399 __Offload_report(1); 00400 #endif 00401 #pragma offload target(mic: target_idx) if(offload_mode) inout(i, info) 00402 papi_ok = PAPI_enum_event(&i, PAPI_NTV_ENUM_UMASKS); 00403 } while (papi_ok == PAPI_OK); 00404 } 00405 } 00406 } else { 00407 printf("Sorry, an event by the name '%s' could not be found.\n", 00408 flags.name); 00409 printf("Is it typed correctly?\n\n"); 00410 exit( 1 ); 00411 } 00412 } 00413 else { 00414 00415 /* Print *ALL* available events */ 00416 00417 #ifdef __INTEL_OFFLOAD 00418 __Offload_report(1); 00419 #endif 00420 #pragma offload target(mic: target_idx) if(offload_mode) 00421 numcmp = PAPI_num_components( ); 00422 00423 j = 0; 00424 00425 for ( cid = 0; cid < numcmp; cid++ ) { 00426 00427 PAPI_component_info_t component; 00428 // if (offload_mode) // I must allocate local memory to receive the result 00429 // component = (PAPI_component_info_t*)malloc(sizeof(PAPI_component_info_t)); 00430 // #pragma offload target(mic: target_idx) if(offload_mode) out(*component:length(sizeof(PAPI_component_info_t)) alloc_if(0) free_if(0)) 00431 #ifdef __INTEL_OFFLOAD 00432 __Offload_report(1); 00433 #endif 00434 #pragma offload target(mic: target_idx) if(offload_mode) out(component) 00435 { 00436 memcpy(&component, PAPI_get_component_info(cid), sizeof(PAPI_component_info_t)); 00437 } 00438 00439 /* Skip disabled components */ 00440 if (component.disabled) continue; 00441 00442 printf( "===============================================================================\n" ); 00443 printf( " Native Events in Component: %s\n",component.name); 00444 printf( "===============================================================================\n" ); 00445 00446 /* Always ASK FOR the first event */ 00447 /* Don't just assume it'll be the first numeric value */ 00448 i = 0 | PAPI_NATIVE_MASK; 00449 00450 #ifdef __INTEL_OFFLOAD 00451 __Offload_report(1); 00452 #endif 00453 #pragma offload target(mic: target_idx) if(offload_mode) inout(i) 00454 retval=PAPI_enum_cmp_event( &i, PAPI_ENUM_FIRST, cid ); 00455 00456 do 00457 { 00458 memset( &info, 0, sizeof ( info ) ); 00459 #ifdef __INTEL_OFFLOAD 00460 __Offload_report(1); 00461 #endif 00462 #pragma offload target(mic: target_idx) if(offload_mode) inout(info) 00463 retval = PAPI_get_event_info( i, &info ); 00464 00465 /* This event may not exist */ 00466 if ( retval != PAPI_OK ) 00467 goto endloop; 00468 00469 /* Bail if event name doesn't contain include string */ 00470 if ( flags.include ) { 00471 if ( !strstr( info.symbol, flags.istr ) ) { 00472 goto endloop; 00473 } 00474 } 00475 00476 /* Bail if event name does contain exclude string */ 00477 if ( flags.xclude ) { 00478 if ( strstr( info.symbol, flags.xstr ) ) 00479 goto endloop; 00480 } 00481 00482 /* count only events that are actually processed */ 00483 j++; 00484 00485 print_event( &info, 0 ); 00486 00487 if (flags.details) { 00488 if (info.units[0]) printf( "| Units: %-67s|\n", 00489 info.units ); 00490 } 00491 00492 /* modifier = PAPI_NTV_ENUM_GROUPS returns event codes with a 00493 groups id for each group in which this 00494 native event lives, in bits 16 - 23 of event code 00495 terminating with PAPI_ENOEVNT at the end of the list. 00496 */ 00497 00498 /* This is an IBM Power issue */ 00499 if ( flags.groups ) { 00500 int papi_ok = 0; 00501 k = i; 00502 #ifdef __INTEL_OFFLOAD 00503 __Offload_report(1); 00504 #endif 00505 #pragma offload target(mic: target_idx) if(offload_mode) inout(k) 00506 papi_ok = PAPI_enum_cmp_event(&k, PAPI_NTV_ENUM_GROUPS, cid); 00507 if (papi_ok == PAPI_OK ) 00508 { 00509 printf("Groups: "); 00510 do { 00511 printf( "%4d", ( ( k & PAPI_NTV_GROUP_AND_MASK ) >> 00512 PAPI_NTV_GROUP_SHIFT ) - 1 ); 00513 #ifdef __INTEL_OFFLOAD 00514 __Offload_report(1); 00515 #endif 00516 #pragma offload target(mic: target_idx) if(offload_mode) inout(k) 00517 papi_ok = PAPI_enum_cmp_event(&k, PAPI_NTV_ENUM_GROUPS, cid); 00518 } while (papi_ok==PAPI_OK ); 00519 printf( "\n" ); 00520 } 00521 } 00522 00523 /* Print umasks */ 00524 /* components that don't have them can just ignore */ 00525 00526 if ( flags.umask ) 00527 { 00528 int papi_ok = 0; 00529 k = i; 00530 #ifdef __INTEL_OFFLOAD 00531 __Offload_report(1); 00532 #endif 00533 #pragma offload target(mic: target_idx) if(offload_mode) inout(k) 00534 papi_ok = PAPI_enum_cmp_event(&k, PAPI_NTV_ENUM_UMASKS, cid); 00535 if (papi_ok == PAPI_OK ) 00536 { 00537 do { 00538 #ifdef __INTEL_OFFLOAD 00539 __Offload_report(1); 00540 #endif 00541 #pragma offload target(mic: target_idx) if(offload_mode) inout(info) 00542 retval = PAPI_get_event_info(k, &info); 00543 if ( retval == PAPI_OK ) { 00544 if (parse_unit_masks( &info )) 00545 print_event(&info, 2); 00546 } 00547 #ifdef __INTEL_OFFLOAD 00548 __Offload_report(1); 00549 #endif 00550 #pragma offload target(mic: target_idx) if(offload_mode) inout(k) 00551 papi_ok = PAPI_enum_cmp_event(&k, PAPI_NTV_ENUM_UMASKS, cid); 00552 } while (papi_ok == PAPI_OK); 00553 } 00554 } 00555 printf( "--------------------------------------------------------------------------------\n" ); 00556 00557 endloop: 00558 #ifdef __INTEL_OFFLOAD 00559 __Offload_report(1); 00560 #endif 00561 #pragma offload target(mic: target_idx) if(offload_mode) inout(i) 00562 retval=PAPI_enum_cmp_event(&i, enum_modifier, cid); 00563 } while (retval == PAPI_OK ); 00564 } 00565 00566 00567 printf("\n"); 00568 printf( "Total events reported: %d\n", j ); 00569 } 00570 00571 test_pass( __FILE__, NULL, 0 ); 00572 exit( 0 ); 00573 }