PAPI  5.3.0.0
native_avail.c
Go to the documentation of this file.
00001 /* This file utility reports hardware info and native event availability */
00045 #include "papi_test.h"
00046 
00047 #define EVT_LINE 80
00048 
00049 typedef struct command_flags
00050 {
00051     int help;
00052     int details;
00053     int named;
00054     int include;
00055     int xclude;
00056     char *name, *istr, *xstr;
00057     int darr;
00058     int dear;
00059     int iarr;
00060     int iear;
00061     int opcm;
00062     int umask;
00063     int groups;
00064 } command_flags_t;
00065 
00066 static void
00067 print_help( char **argv )
00068 {
00069     printf( "This is the PAPI native avail program.\n" );
00070     printf( "It provides availability and detail information for PAPI native events.\n" );
00071     printf( "Usage: %s [options]\n", argv[0] );
00072     printf( "\nOptions:\n" );
00073     printf( "   --help, -h   print this help message\n" );
00074     printf( "   -d           display detailed information about native events\n" );
00075     printf( "   -e EVENTNAME display detailed information about named native event\n" );
00076     printf( "   -i EVENTSTR  include only event names that contain EVENTSTR\n" );
00077     printf( "   -x EVENTSTR  exclude any event names that contain EVENTSTR\n" );
00078     printf( "   --noumasks   suppress display of Unit Mask information\n" );
00079     printf( "\nProcessor-specific options\n");
00080     printf( "  --darr        display events supporting Data Address Range Restriction\n" );
00081     printf( "  --dear        display Data Event Address Register events only\n" );
00082     printf( "  --iarr        display events supporting Instruction Address Range Restriction\n" );
00083     printf( "  --iear        display Instruction Event Address Register events only\n" );
00084     printf( "  --opcm        display events supporting OpCode Matching\n" );
00085     printf( "  --nogroups    suppress display of Event grouping information\n" );
00086     printf( "\n" );
00087 }
00088 
00089 static int
00090 no_str_arg( char *arg )
00091 {
00092     return ( ( arg == NULL ) || ( strlen( arg ) == 0 ) || ( arg[0] == '-' ) );
00093 }
00094 
00095 static void
00096 parse_args( int argc, char **argv, command_flags_t * f )
00097 {
00098 
00099     int i;
00100 
00101     /* Look for all currently defined commands */
00102     memset( f, 0, sizeof ( command_flags_t ) );
00103     f->umask = 1;
00104     f->groups = 1;
00105 
00106     for ( i = 1; i < argc; i++ ) {
00107         if ( !strcmp( argv[i], "--darr" ) )
00108             f->darr = 1;
00109         else if ( !strcmp( argv[i], "--dear" ) )
00110             f->dear = 1;
00111         else if ( !strcmp( argv[i], "--iarr" ) )
00112             f->iarr = 1;
00113         else if ( !strcmp( argv[i], "--iear" ) )
00114             f->iear = 1;
00115         else if ( !strcmp( argv[i], "--opcm" ) )
00116             f->opcm = 1;
00117         else if ( !strcmp( argv[i], "--noumasks" ) )
00118             f->umask = 0;
00119         else if ( !strcmp( argv[i], "--nogroups" ) )
00120             f->groups = 0;
00121         else if ( !strcmp( argv[i], "-d" ) )
00122             f->details = 1;
00123         else if ( !strcmp( argv[i], "-e" ) ) {
00124             f->named = 1;
00125             i++;
00126             f->name = argv[i];
00127             if ( i >= argc || no_str_arg( f->name ) ) {
00128                 printf( "Invalid argument for -e\n");
00129                 exit(1);
00130             }
00131         } else if ( !strcmp( argv[i], "-i" ) ) {
00132             f->include = 1;
00133             i++;
00134             f->istr = argv[i];
00135             if ( i >= argc || no_str_arg( f->istr ) ) {
00136                 printf( "Invalid argument for -i\n");
00137                 exit(1);
00138             }
00139         } else if ( !strcmp( argv[i], "-x" ) ) {
00140             f->xclude = 1;
00141             i++;
00142             f->xstr = argv[i];
00143             if ( i >= argc || no_str_arg( f->xstr ) ) {
00144                 printf( "Invalid argument for -x\n");
00145                 exit(1);
00146             }
00147         } else if ( !strcmp( argv[i], "-h" ) || !strcmp( argv[i], "--help" ) )
00148             f->help = 1;
00149         else {
00150             printf( "%s is not supported\n", argv[i] );
00151             exit(1);
00152         }
00153     }
00154 
00155     /* if help requested, print and bail */
00156     if ( f->help ) {
00157         print_help( argv);
00158         exit( 1 );
00159     }
00160 }
00161 
00162 static void
00163 space_pad( char *str, int spaces )
00164 {
00165     while ( spaces-- > 0 )
00166         strcat( str, " " );
00167 }
00168 
00169 static void
00170 print_event( PAPI_event_info_t * info, int offset )
00171 {
00172     unsigned int i, j = 0;
00173     char str[EVT_LINE + EVT_LINE];
00174 
00175     /* indent by offset */
00176     if ( offset ) {
00177        printf( "|     %-73s|\n", info->symbol );
00178     }
00179     else {
00180        printf( "| %-77s|\n", info->symbol );
00181     }
00182 
00183     while ( j <= strlen( info->long_descr ) ) {
00184        i = EVT_LINE - 12 - 2;
00185        if ( i > 0 ) {
00186           str[0] = 0;
00187           strcat(str,"| " );
00188           space_pad( str, 11 );
00189           strncat( str, &info->long_descr[j], i );
00190           j += i;
00191           i = ( unsigned int ) strlen( str );
00192           space_pad( str, EVT_LINE - ( int ) i - 1 );
00193           strcat( str, "|" );
00194        }
00195        printf( "%s\n", str );
00196     }
00197 }
00198 
00199 static int
00200 parse_unit_masks( PAPI_event_info_t * info )
00201 {
00202   char *pmask,*ptr;
00203 
00204   /* handle the PAPI component-style events which have a component:::event type */
00205   if ((ptr=strstr(info->symbol, ":::"))) {
00206     ptr+=3;
00207   /* handle libpfm4-style events which have a pmu::event type event name */
00208   } else if ((ptr=strstr(info->symbol, "::"))) {
00209     ptr+=2;
00210   }
00211   else {
00212     ptr=info->symbol;
00213   }
00214 
00215     if ( ( pmask = strchr( ptr, ':' ) ) == NULL ) {
00216         return ( 0 );
00217     }
00218     memmove( info->symbol, pmask, ( strlen( pmask ) + 1 ) * sizeof ( char ) );
00219     pmask = strchr( info->long_descr, ':' );
00220     if ( pmask == NULL )
00221         info->long_descr[0] = 0;
00222     else
00223         memmove( info->long_descr, pmask + sizeof ( char ),
00224                  ( strlen( pmask ) + 1 ) * sizeof ( char ) );
00225     return ( 1 );
00226 }
00227 
00228 int
00229 main( int argc, char **argv )
00230 {
00231     int i, j = 0, k;
00232     int retval;
00233     PAPI_event_info_t info;
00234     const PAPI_hw_info_t *hwinfo = NULL;
00235     command_flags_t flags;
00236     int enum_modifier;
00237     int numcmp, cid;
00238 
00239     /* Set TESTS_QUIET variable */
00240     tests_quiet( argc, argv );
00241 
00242     /* Initialize before parsing the input arguments */
00243     retval = PAPI_library_init( PAPI_VER_CURRENT );
00244     if ( retval != PAPI_VER_CURRENT ) {
00245         test_fail( __FILE__, __LINE__, "PAPI_library_init", retval );
00246     }
00247 
00248     /* Parse the command-line arguments */
00249     parse_args( argc, argv, &flags );
00250 
00251     /* Set enum modifier mask */
00252     if ( flags.dear )
00253         enum_modifier = PAPI_NTV_ENUM_DEAR;
00254     else if ( flags.darr )
00255         enum_modifier = PAPI_NTV_ENUM_DARR;
00256     else if ( flags.iear )
00257         enum_modifier = PAPI_NTV_ENUM_IEAR;
00258     else if ( flags.iarr )
00259         enum_modifier = PAPI_NTV_ENUM_IARR;
00260     else if ( flags.opcm )
00261         enum_modifier = PAPI_NTV_ENUM_OPCM;
00262     else
00263         enum_modifier = PAPI_ENUM_EVENTS;
00264 
00265 
00266     if ( !TESTS_QUIET ) {
00267        retval = PAPI_set_debug( PAPI_VERB_ECONT );
00268        if ( retval != PAPI_OK ) {
00269           test_fail( __FILE__, __LINE__, "PAPI_set_debug", retval );
00270        }
00271     }
00272 
00273     retval = papi_print_header( "Available native events and hardware information.\n", &hwinfo );
00274     if ( retval != PAPI_OK ) {
00275         test_fail( __FILE__, __LINE__, "PAPI_get_hardware_info", 2 );
00276     }
00277 
00278 
00279     /* Do this code if the event name option was specified on the commandline */
00280     if ( flags.named ) {
00281        if ( PAPI_event_name_to_code( flags.name, &i ) == PAPI_OK ) {
00282           if ( PAPI_get_event_info( i, &info ) == PAPI_OK ) {
00283          printf( "%-30s%s\n",
00284              "Event name:", info.symbol);
00285          printf( "%-29s|%s|\n", "Description:", info.long_descr );
00286 
00287              /* if unit masks exist but none specified, process all */
00288              if ( !strchr( flags.name, ':' ) ) {
00289             if ( PAPI_enum_event( &i, PAPI_NTV_ENUM_UMASKS ) == PAPI_OK ) {
00290                printf( "\nUnit Masks:\n" );
00291                do {
00292                   retval = PAPI_get_event_info( i, &info );
00293                   if ( retval == PAPI_OK ) {
00294                  if ( parse_unit_masks( &info ) ) {
00295                     printf( "%-29s|%s|%s|\n", " Mask Info:",
00296                         info.symbol, info.long_descr );
00297                  }
00298                   }
00299                } while ( PAPI_enum_event( &i, PAPI_NTV_ENUM_UMASKS ) == PAPI_OK );
00300             }
00301              }
00302           }
00303        } else {
00304          printf("Sorry, an event by the name '%s' could not be found.\n",
00305             flags.name);
00306          printf("Is it typed correctly?\n\n");
00307          exit( 1 );
00308        }
00309     }
00310     else {
00311 
00312        /* Print *ALL* available events */
00313 
00314        numcmp = PAPI_num_components(  );
00315 
00316        j = 0;
00317 
00318        for ( cid = 0; cid < numcmp; cid++ ) {
00319 
00320            const PAPI_component_info_t *component;
00321            component=PAPI_get_component_info(cid);
00322 
00323            /* Skip disabled components */
00324            if (component->disabled) continue;
00325 
00326            printf( "===============================================================================\n" );
00327            printf( " Native Events in Component: %s\n",component->name);
00328            printf( "===============================================================================\n" );
00329          
00330            /* Always ASK FOR the first event */
00331            /* Don't just assume it'll be the first numeric value */
00332            i = 0 | PAPI_NATIVE_MASK;
00333 
00334            retval=PAPI_enum_cmp_event( &i, PAPI_ENUM_FIRST, cid );
00335 
00336            if (retval==PAPI_OK) 
00337 
00338            do {
00339               memset( &info, 0, sizeof ( info ) );
00340               retval = PAPI_get_event_info( i, &info );
00341 
00342               /* This event may not exist */
00343               if ( retval != PAPI_OK )
00344                  continue;
00345 
00346               /* Bail if event name doesn't contain include string */
00347               if ( flags.include ) {
00348                  if ( !strstr( info.symbol, flags.istr ) ) {
00349                     continue;
00350                  }
00351               }
00352 
00353               /* Bail if event name does contain exclude string */
00354               if ( flags.xclude ) {
00355                  if ( strstr( info.symbol, flags.xstr ) )
00356                     continue;
00357               }
00358               
00359               /* count only events that are actually processed */
00360               j++;
00361 
00362               print_event( &info, 0 );
00363 
00364               if (flags.details) {
00365                 if (info.units[0]) printf( "|     Units: %-67s|\n", 
00366                                info.units );
00367               }
00368 
00369 /*      modifier = PAPI_NTV_ENUM_GROUPS returns event codes with a
00370             groups id for each group in which this
00371             native event lives, in bits 16 - 23 of event code
00372             terminating with PAPI_ENOEVNT at the end of the list.
00373 */
00374 
00375               /* This is an IBM Power issue */
00376               if ( flags.groups ) {
00377                  k = i;
00378                  if ( PAPI_enum_cmp_event( &k, PAPI_NTV_ENUM_GROUPS, cid ) == PAPI_OK ) {
00379                 printf( "Groups: " );
00380                 do {
00381                   printf( "%4d", ( ( k & PAPI_NTV_GROUP_AND_MASK ) >>
00382                              PAPI_NTV_GROUP_SHIFT ) - 1 );
00383                 } while ( PAPI_enum_cmp_event( &k, PAPI_NTV_ENUM_GROUPS, cid ) ==PAPI_OK );
00384                 printf( "\n" );
00385                  }
00386               }
00387 
00388               /* Print umasks */
00389               /* components that don't have them can just ignore */
00390 
00391                   if ( flags.umask ) { 
00392                  k = i;
00393                  if ( PAPI_enum_cmp_event( &k, PAPI_NTV_ENUM_UMASKS, cid ) == PAPI_OK ) {
00394                     do {
00395                    retval = PAPI_get_event_info( k, &info );
00396                    if ( retval == PAPI_OK ) {
00397                       if ( parse_unit_masks( &info ) )
00398                          print_event( &info, 2 );
00399                    }
00400                     } while ( PAPI_enum_cmp_event( &k, PAPI_NTV_ENUM_UMASKS, cid ) == PAPI_OK );
00401                  }
00402 
00403               }
00404               printf( "--------------------------------------------------------------------------------\n" );
00405 
00406            } while (PAPI_enum_cmp_event( &i, enum_modifier, cid ) == PAPI_OK );
00407        }
00408             
00409     
00410        printf("\n");
00411        printf( "Total events reported: %d\n", j );
00412     }
00413 
00414     test_pass( __FILE__, NULL, 0 );
00415     exit( 0 );
00416 }
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines