/** file papi_xml_event_info.c * @page papi_xml_event_info * @brief papi_xml_event_info utility. * @section NAME * papi_xml_event_info - provides detailed information for PAPI events in XML format * * @section Synopsis * * @section Description * papi_native_avail is a PAPI utility program that reports information * about the events available on the current platform in an XML format. * * It will attempt to create an EventSet with each event in it, which * can be slow. * * @section Options * * * @section Bugs * There are no known bugs in this utility. * If you find a bug, it should be reported to the * PAPI Mailing List at . */ #include #include #include "papi.h" static int EventSet; static int preset = 1; static int native = 1; static int cidx = -1; /**********************************************************************/ /* Take a string and print a version with properly escaped XML */ /**********************************************************************/ static int xmlize( const char *msg, FILE *f ) { const char *op; if ( !msg ) return PAPI_OK; for ( op = msg; *op != '\0'; op++ ) { switch ( *op ) { case '"': fprintf( f, """ ); break; case '&': fprintf( f, "&" ); break; case '\'': fprintf( f, "'" ); break; case '<': fprintf( f, "<" ); break; case '>': fprintf( f, ">" ); break; default: fprintf( f, "%c", *op); } } return PAPI_OK; } /*************************************/ /* print hardware info in XML format */ /*************************************/ static int papi_xml_hwinfo( FILE * f ) { const PAPI_hw_info_t *hwinfo; if ( ( hwinfo = PAPI_get_hardware_info( ) ) == NULL ) return PAPI_ESYS; fprintf( f, "\n" ); fprintf( f, " vendor_string, f ); fprintf( f,"\"/>\n"); fprintf( f, " \n", hwinfo->vendor ); fprintf( f, " model_string, f ); fprintf( f, "\"/>\n"); fprintf( f, " \n", hwinfo->model ); fprintf( f, " \n", hwinfo->revision ); fprintf( f, " \n" ); fprintf( f, " \n", hwinfo->cpuid_family ); fprintf( f, " \n", hwinfo->cpuid_model ); fprintf( f, " \n", hwinfo->cpuid_stepping ); fprintf( f, " \n" ); fprintf( f, " \n", hwinfo->cpu_max_mhz ); fprintf( f, " \n", hwinfo->cpu_min_mhz ); fprintf( f, " \n", hwinfo->threads ); fprintf( f, " \n", hwinfo->cores ); fprintf( f, " \n", hwinfo->sockets ); fprintf( f, " \n", hwinfo->nnodes ); fprintf( f, " \n", hwinfo->ncpu ); fprintf( f, " \n", hwinfo->totalcpus ); fprintf( f, "\n" ); return PAPI_OK; } /****************************************************************/ /* Test if event can be added to an eventset */ /* (there might be existing events if specified on command line */ /****************************************************************/ static int test_event( int evt ) { int retval; retval = PAPI_add_event( EventSet, evt ); if ( retval != PAPI_OK ) { return retval; } if ( ( retval = PAPI_remove_event( EventSet, evt ) ) != PAPI_OK ) { fprintf( stderr, "Error removing event from eventset\n" ); exit( 1 ); } return PAPI_OK; } /***************************************/ /* Convert an event to XML */ /***************************************/ static void xmlize_event( FILE * f, PAPI_event_info_t * info, int num ) { if ( num >= 0 ) { fprintf( f, " symbol, f ); fprintf( f, "\" desc=\""); xmlize( info->long_descr, f ); fprintf( f, "\">\n"); } else { fprintf( f," symbol, f ); fprintf( f,"\" desc=\""); xmlize( info->long_descr, f ); fprintf( f,"\"> \n"); } } /****************************************/ /* Print all preset events */ /****************************************/ static void enum_preset_events( FILE * f, int cidx) { int i, num; int retval; PAPI_event_info_t info; i = PAPI_PRESET_MASK; fprintf( f, " \n" ); num = -1; retval = PAPI_enum_cmp_event( &i, PAPI_ENUM_FIRST, cidx ); while ( retval == PAPI_OK ) { num++; retval = PAPI_get_event_info( i, &info ); if ( retval != PAPI_OK ) { retval = PAPI_enum_cmp_event( &i, PAPI_ENUM_EVENTS, cidx ); continue; } if ( test_event( i ) == PAPI_OK ) { xmlize_event( f, &info, num ); fprintf( f, " \n" ); } retval = PAPI_enum_cmp_event( &i, PAPI_ENUM_EVENTS, cidx ); } fprintf( f, " \n" ); } /****************************************/ /* Print all native events */ /****************************************/ static void enum_native_events( FILE * f, int cidx) { int i, k, num; int retval; PAPI_event_info_t info; i = PAPI_NATIVE_MASK; fprintf( f, " \n" ); num = -1; retval = PAPI_enum_cmp_event( &i, PAPI_ENUM_FIRST, cidx ); while ( retval == PAPI_OK ) { num++; retval = PAPI_get_event_info( i, &info ); if ( retval != PAPI_OK ) { retval = PAPI_enum_cmp_event( &i, PAPI_ENUM_EVENTS, cidx ); continue; } /* enumerate any umasks */ k = i; if ( PAPI_enum_cmp_event( &k, PAPI_NTV_ENUM_UMASKS, cidx ) == PAPI_OK ) { /* Test if event can be added */ if ( test_event( k ) == PAPI_OK ) { /* add the event */ xmlize_event( f, &info, num ); /* add the event's unit masks */ do { retval = PAPI_get_event_info( k, &info ); if ( retval == PAPI_OK ) { if ( test_event( k )!=PAPI_OK ) { break; } xmlize_event( f, &info, -1 ); } } while ( PAPI_enum_cmp_event( &k, PAPI_NTV_ENUM_UMASKS, cidx ) == PAPI_OK); fprintf( f, " \n" ); } } else { /* this event has no unit masks; test & write the event */ if ( test_event( i ) == PAPI_OK ) { xmlize_event( f, &info, num ); fprintf( f, " \n" ); } } retval = PAPI_enum_cmp_event( &i, PAPI_ENUM_EVENTS, cidx ); } fprintf( f, " \n" ); } /****************************************/ /* Print usage information */ /****************************************/ static void usage( char *argv[] ) { fprintf( stderr, "Usage: %s [options] [[event1] event2 ...]\n", argv[0] ); fprintf( stderr, " options: -h print help message\n" ); fprintf( stderr, " -p print only preset events\n" ); fprintf( stderr, " -n print only native events\n" ); fprintf( stderr," -c n print only events for component index n\n" ); fprintf( stderr, "If event1, event2, etc., are specified, then only events\n"); fprintf( stderr, "that can be run in addition to these events will be printed\n\n"); } static void parse_command_line (int argc, char **argv, int numc) { int i,retval; for( i = 1; i < argc; i++ ) { if ( argv[i][0] == '-' ) { switch ( argv[i][1] ) { case 'c': /* only events for specified component */ /* UGH, what is this, the IOCCC? */ cidx = (i+1) < argc ? atoi( argv[(i++)+1] ) : -1; if ( cidx < 0 || cidx >= numc ) { fprintf( stderr,"Error: component index %d out of bounds (0..%d)\n", cidx, numc - 1 ); usage( argv ); exit(1); } break; case 'p': /* only preset events */ preset = 1; native = 0; break; case 'n': /* only native events */ native = 1; preset = 0; break; case 'h': /* print help */ usage( argv ); exit(0); break; default: fprintf( stderr, "Error: unknown option: %s\n", argv[i] ); usage( argv ); exit(1); } } else { /* If event names are specified, add them to the */ /* EventSet and test if other events can be run with them */ int code = -1; retval = PAPI_event_name_to_code( argv[i], &code ); retval = PAPI_query_event( code ); if ( retval != PAPI_OK ) { fprintf( stderr, "Error: unknown event: %s\n", argv[i] ); usage( argv ); exit(1); } retval = PAPI_add_event( EventSet, code ); if ( retval != PAPI_OK ) { fprintf( stderr, "Error: event %s cannot be counted with others\n", argv[i] ); usage( argv ); exit(1); } } } } int main( int argc, char **argv) { int retval; const PAPI_component_info_t *comp; int numc = 0; retval = PAPI_library_init( PAPI_VER_CURRENT ); if ( retval != PAPI_VER_CURRENT ) { fprintf(stderr,"Error! PAPI_library_init\n"); return retval; } /* report any return codes less than 0? */ /* Why? */ #if 0 retval = PAPI_set_debug( PAPI_VERB_ECONT ); if ( retval != PAPI_OK ) { test_fail( __FILE__, __LINE__, "PAPI_set_debug", retval ); } #endif /* Create EventSet to use */ EventSet = PAPI_NULL; retval = PAPI_create_eventset( &EventSet ); if ( retval != PAPI_OK ) { fprintf(stderr,"Error! PAPI_create_eventset\n"); return retval; } /* Get number of components */ numc = PAPI_num_components( ); /* parse command line arguments */ parse_command_line(argc,argv,numc); /* print XML header */ fprintf( stdout, "\n" ); fprintf( stdout, "\n" ); /* print hardware info */ papi_xml_hwinfo( stdout ); /* If a specific component specified, only print events from there */ if ( cidx >= 0 ) { comp = PAPI_get_component_info( cidx ); fprintf( stdout, "\n", cidx, cidx ? "Unknown" : "CPU", comp->name ); if ( native ) enum_native_events( stdout, cidx); if ( preset ) enum_preset_events( stdout, cidx); fprintf( stdout, "\n" ); } else { /* Otherwise, print info for all components */ for ( cidx = 0; cidx < numc; cidx++ ) { comp = PAPI_get_component_info( cidx ); fprintf( stdout, "\n", cidx, cidx ? "Unknown" : "CPU", comp->name ); if ( native ) enum_native_events( stdout, cidx ); if ( preset ) enum_preset_events( stdout, cidx ); fprintf( stdout, "\n" ); /* clean out eventset */ retval = PAPI_cleanup_eventset( EventSet ); if ( retval != PAPI_OK ) { fprintf(stderr,"Error! PAPI_cleanup_eventset\n"); return retval; } retval = PAPI_destroy_eventset( &EventSet ); if ( retval != PAPI_OK ) { fprintf(stderr,"Error! PAPI_destroy_eventset\n"); return retval; } EventSet = PAPI_NULL; retval = PAPI_create_eventset( &EventSet ); if ( retval != PAPI_OK ) { fprintf(stderr,"Error! PAPI_create_eventset\n"); return retval; } /* re-parse command line to set up any events specified */ parse_command_line (argc, argv, numc); } } fprintf( stdout, "\n" ); return 0; }