|
PAPI
5.0.1.0
|
00001 00032 #include <stdio.h> 00033 #include <stdlib.h> 00034 #include "papi.h" 00035 #include "papi_test.h" 00036 00037 static int EventSet; 00038 static int preset = 1; 00039 static int native = 1; 00040 static int cidx = -1; 00041 00042 /**********************************************************************/ 00043 /* Take a string and print a version with properly escaped XML */ 00044 /**********************************************************************/ 00045 static int 00046 xmlize( const char *msg, FILE *f ) 00047 { 00048 const char *op; 00049 00050 if ( !msg ) 00051 return PAPI_OK; 00052 00053 for ( op = msg; *op != '\0'; op++ ) { 00054 switch ( *op ) { 00055 case '"': 00056 fprintf( f, """ ); 00057 break; 00058 case '&': 00059 fprintf( f, "&" ); 00060 break; 00061 case '\'': 00062 fprintf( f, "'" ); 00063 break; 00064 case '<': 00065 fprintf( f, "<" ); 00066 break; 00067 case '>': 00068 fprintf( f, ">" ); 00069 break; 00070 default: 00071 fprintf( f, "%c", *op); 00072 } 00073 } 00074 00075 return PAPI_OK; 00076 } 00077 00078 /*************************************/ 00079 /* print hardware info in XML format */ 00080 /*************************************/ 00081 static int 00082 papi_xml_hwinfo( FILE * f ) 00083 { 00084 const PAPI_hw_info_t *hwinfo; 00085 00086 if ( ( hwinfo = PAPI_get_hardware_info( ) ) == NULL ) 00087 return PAPI_ESYS; 00088 00089 fprintf( f, "<hardware>\n" ); 00090 00091 fprintf( f, " <vendor string=\""); 00092 xmlize( hwinfo->vendor_string, f ); 00093 fprintf( f,"\"/>\n"); 00094 fprintf( f, " <vendorCode value=\"%d\"/>\n", hwinfo->vendor ); 00095 fprintf( f, " <model string=\""); 00096 xmlize( hwinfo->model_string, f ); 00097 fprintf( f, "\"/>\n"); 00098 fprintf( f, " <modelCode value=\"%d\"/>\n", hwinfo->model ); 00099 fprintf( f, " <cpuRevision value=\"%f\"/>\n", hwinfo->revision ); 00100 fprintf( f, " <cpuID>\n" ); 00101 fprintf( f, " <family value=\"%d\"/>\n", hwinfo->cpuid_family ); 00102 fprintf( f, " <model value=\"%d\"/>\n", hwinfo->cpuid_model ); 00103 fprintf( f, " <stepping value=\"%d\"/>\n", hwinfo->cpuid_stepping ); 00104 fprintf( f, " </cpuID>\n" ); 00105 fprintf( f, " <cpuMaxMegahertz value=\"%d\"/>\n", hwinfo->cpu_max_mhz ); 00106 fprintf( f, " <cpuMinMegahertz value=\"%d\"/>\n", hwinfo->cpu_min_mhz ); 00107 fprintf( f, " <threads value=\"%d\"/>\n", hwinfo->threads ); 00108 fprintf( f, " <cores value=\"%d\"/>\n", hwinfo->cores ); 00109 fprintf( f, " <sockets value=\"%d\"/>\n", hwinfo->sockets ); 00110 fprintf( f, " <nodes value=\"%d\"/>\n", hwinfo->nnodes ); 00111 fprintf( f, " <cpuPerNode value=\"%d\"/>\n", hwinfo->ncpu ); 00112 fprintf( f, " <totalCPUs value=\"%d\"/>\n", hwinfo->totalcpus ); 00113 fprintf( f, "</hardware>\n" ); 00114 00115 return PAPI_OK; 00116 } 00117 00118 00119 00120 /****************************************************************/ 00121 /* Test if event can be added to an eventset */ 00122 /* (there might be existing events if specified on command line */ 00123 /****************************************************************/ 00124 00125 static int 00126 test_event( int evt ) 00127 { 00128 int retval; 00129 00130 retval = PAPI_add_event( EventSet, evt ); 00131 if ( retval != PAPI_OK ) { 00132 return retval; 00133 } 00134 00135 if ( ( retval = PAPI_remove_event( EventSet, evt ) ) != PAPI_OK ) { 00136 fprintf( stderr, "Error removing event from eventset\n" ); 00137 exit( 1 ); 00138 } 00139 return PAPI_OK; 00140 } 00141 00142 /***************************************/ 00143 /* Convert an event to XML */ 00144 /***************************************/ 00145 00146 static void 00147 xmlize_event( FILE * f, PAPI_event_info_t * info, int num ) 00148 { 00149 00150 if ( num >= 0 ) { 00151 fprintf( f, " <event index=\"%d\" name=\"",num); 00152 xmlize( info->symbol, f ); 00153 fprintf( f, "\" desc=\""); 00154 xmlize( info->long_descr, f ); 00155 fprintf( f, "\">\n"); 00156 } 00157 else { 00158 fprintf( f," <modifier name=\""); 00159 xmlize( info->symbol, f ); 00160 fprintf( f,"\" desc=\""); 00161 xmlize( info->long_descr, f ); 00162 fprintf( f,"\"> </modifier>\n"); 00163 } 00164 00165 } 00166 00167 00168 /****************************************/ 00169 /* Print all preset events */ 00170 /****************************************/ 00171 00172 static void 00173 enum_preset_events( FILE * f, int cidx) 00174 { 00175 int i, num; 00176 int retval; 00177 PAPI_event_info_t info; 00178 00179 i = PAPI_PRESET_MASK; 00180 fprintf( f, " <eventset type=\"PRESET\">\n" ); 00181 num = -1; 00182 retval = PAPI_enum_cmp_event( &i, PAPI_ENUM_FIRST, cidx ); 00183 00184 while ( retval == PAPI_OK ) { 00185 num++; 00186 retval = PAPI_get_event_info( i, &info ); 00187 if ( retval != PAPI_OK ) { 00188 retval = PAPI_enum_cmp_event( &i, PAPI_ENUM_EVENTS, cidx ); 00189 continue; 00190 } 00191 if ( test_event( i ) == PAPI_OK ) { 00192 xmlize_event( f, &info, num ); 00193 fprintf( f, " </event>\n" ); 00194 } 00195 retval = PAPI_enum_cmp_event( &i, PAPI_ENUM_EVENTS, cidx ); 00196 } 00197 fprintf( f, " </eventset>\n" ); 00198 } 00199 00200 /****************************************/ 00201 /* Print all native events */ 00202 /****************************************/ 00203 00204 static void 00205 enum_native_events( FILE * f, int cidx) 00206 { 00207 int i, k, num; 00208 int retval; 00209 PAPI_event_info_t info; 00210 00211 i = PAPI_NATIVE_MASK; 00212 fprintf( f, " <eventset type=\"NATIVE\">\n" ); 00213 num = -1; 00214 retval = PAPI_enum_cmp_event( &i, PAPI_ENUM_FIRST, cidx ); 00215 00216 while ( retval == PAPI_OK ) { 00217 00218 num++; 00219 retval = PAPI_get_event_info( i, &info ); 00220 if ( retval != PAPI_OK ) { 00221 retval = PAPI_enum_cmp_event( &i, PAPI_ENUM_EVENTS, cidx ); 00222 continue; 00223 } 00224 00225 /* enumerate any umasks */ 00226 k = i; 00227 if ( PAPI_enum_cmp_event( &k, PAPI_NTV_ENUM_UMASKS, cidx ) == PAPI_OK ) { 00228 00229 /* Test if event can be added */ 00230 if ( test_event( k ) == PAPI_OK ) { 00231 00232 /* add the event */ 00233 xmlize_event( f, &info, num ); 00234 00235 /* add the event's unit masks */ 00236 do { 00237 retval = PAPI_get_event_info( k, &info ); 00238 if ( retval == PAPI_OK ) { 00239 if ( test_event( k )!=PAPI_OK ) { 00240 retval = PAPI_enum_cmp_event( &i, PAPI_ENUM_EVENTS, cidx ); 00241 continue; 00242 } 00243 xmlize_event( f, &info, -1 ); 00244 } 00245 } while ( PAPI_enum_cmp_event( &k, PAPI_NTV_ENUM_UMASKS, cidx ) == PAPI_OK); 00246 fprintf( f, " </event>\n" ); 00247 } 00248 } else { 00249 /* this event has no unit masks; test & write the event */ 00250 if ( test_event( i ) == PAPI_OK ) { 00251 xmlize_event( f, &info, num ); 00252 fprintf( f, " </event>\n" ); 00253 } 00254 } 00255 retval = PAPI_enum_cmp_event( &i, PAPI_ENUM_EVENTS, cidx ); 00256 } 00257 fprintf( f, " </eventset>\n" ); 00258 } 00259 00260 /****************************************/ 00261 /* Print usage information */ 00262 /****************************************/ 00263 00264 static void 00265 usage( char *argv[] ) 00266 { 00267 fprintf( stderr, "Usage: %s [options] [[event1] event2 ...]\n", argv[0] ); 00268 fprintf( stderr, " options: -h print help message\n" ); 00269 fprintf( stderr, " -p print only preset events\n" ); 00270 fprintf( stderr, " -n print only native events\n" ); 00271 fprintf( stderr," -c n print only events for component index n\n" ); 00272 fprintf( stderr, "If event1, event2, etc., are specified, then only events\n"); 00273 fprintf( stderr, "that can be run in addition to these events will be printed\n\n"); 00274 } 00275 00276 static void 00277 parse_command_line (int argc, char **argv, int numc) { 00278 00279 int i,retval; 00280 00281 for( i = 1; i < argc; i++ ) { 00282 if ( argv[i][0] == '-' ) { 00283 switch ( argv[i][1] ) { 00284 case 'c': 00285 /* only events for specified component */ 00286 00287 /* UGH, what is this, the IOCCC? */ 00288 cidx = (i+1) < argc ? atoi( argv[(i++)+1] ) : -1; 00289 if ( cidx < 0 || cidx >= numc ) { 00290 fprintf( stderr,"Error: component index %d out of bounds (0..%d)\n", 00291 cidx, numc - 1 ); 00292 usage( argv ); 00293 exit(1); 00294 } 00295 break; 00296 00297 case 'p': 00298 /* only preset events */ 00299 preset = 1; 00300 native = 0; 00301 break; 00302 00303 case 'n': 00304 /* only native events */ 00305 native = 1; 00306 preset = 0; 00307 break; 00308 00309 case 'h': 00310 /* print help */ 00311 usage( argv ); 00312 exit(0); 00313 break; 00314 00315 default: 00316 fprintf( stderr, 00317 "Error: unknown option: %s\n", argv[i] ); 00318 usage( argv ); 00319 exit(1); 00320 } 00321 } else { 00322 00323 /* If event names are specified, add them to the */ 00324 /* EventSet and test if other events can be run with them */ 00325 00326 int code = -1; 00327 00328 retval = PAPI_event_name_to_code( argv[i], &code ); 00329 retval = PAPI_query_event( code ); 00330 if ( retval != PAPI_OK ) { 00331 fprintf( stderr, "Error: unknown event: %s\n", argv[i] ); 00332 usage( argv ); 00333 exit(1); 00334 } 00335 00336 retval = PAPI_add_event( EventSet, code ); 00337 if ( retval != PAPI_OK ) { 00338 fprintf( stderr, 00339 "Error: event %s cannot be counted with others\n", 00340 argv[i] ); 00341 usage( argv ); 00342 exit(1); 00343 } 00344 } 00345 } 00346 00347 } 00348 00349 00350 int 00351 main( int argc, char **argv) 00352 { 00353 int retval; 00354 const PAPI_component_info_t *comp; 00355 00356 int numc = 0; 00357 00358 /* Set TESTS_QUIET variable */ 00359 tests_quiet( argc, argv ); 00360 00361 retval = PAPI_library_init( PAPI_VER_CURRENT ); 00362 if ( retval != PAPI_VER_CURRENT ) { 00363 test_fail( __FILE__, __LINE__, "PAPI_library_init", retval ); 00364 } 00365 00366 /* report any return codes less than 0? */ 00367 /* Why? */ 00368 #if 0 00369 retval = PAPI_set_debug( PAPI_VERB_ECONT ); 00370 if ( retval != PAPI_OK ) { 00371 test_fail( __FILE__, __LINE__, "PAPI_set_debug", retval ); 00372 } 00373 #endif 00374 00375 /* Create EventSet to use */ 00376 EventSet = PAPI_NULL; 00377 00378 retval = PAPI_create_eventset( &EventSet ); 00379 if ( retval != PAPI_OK ) { 00380 test_fail( __FILE__, __LINE__, "PAPI_create_eventset", retval ); 00381 return 1; 00382 } 00383 00384 /* Get number of components */ 00385 numc = PAPI_num_components( ); 00386 00387 /* parse command line arguments */ 00388 parse_command_line(argc,argv,numc); 00389 00390 /* print XML header */ 00391 fprintf( stdout, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" ); 00392 fprintf( stdout, "<eventinfo>\n" ); 00393 00394 00395 /* print hardware info */ 00396 papi_xml_hwinfo( stdout ); 00397 00398 /* If a specific component specified, only print events from there */ 00399 if ( cidx >= 0 ) { 00400 comp = PAPI_get_component_info( cidx ); 00401 00402 fprintf( stdout, "<component index=\"%d\" type=\"%s\" id=\"%s\">\n", 00403 cidx, cidx ? "Unknown" : "CPU", comp->name ); 00404 00405 if ( native ) 00406 enum_native_events( stdout, cidx); 00407 if ( preset ) 00408 enum_preset_events( stdout, cidx); 00409 00410 fprintf( stdout, "</component>\n" ); 00411 } 00412 else { 00413 /* Otherwise, print info for all components */ 00414 for ( cidx = 0; cidx < numc; cidx++ ) { 00415 comp = PAPI_get_component_info( cidx ); 00416 00417 fprintf( stdout, "<component index=\"%d\" type=\"%s\" id=\"%s\">\n", 00418 cidx, cidx ? "Unknown" : "CPU", comp->name ); 00419 00420 if ( native ) 00421 enum_native_events( stdout, cidx ); 00422 if ( preset ) 00423 enum_preset_events( stdout, cidx ); 00424 00425 fprintf( stdout, "</component>\n" ); 00426 00427 /* clean out eventset */ 00428 retval = PAPI_cleanup_eventset( EventSet ); 00429 if ( retval != PAPI_OK ) 00430 test_fail( __FILE__, __LINE__, "PAPI_cleanup_eventset", retval ); 00431 retval = PAPI_destroy_eventset( &EventSet ); 00432 if ( retval != PAPI_OK ) 00433 test_fail( __FILE__, __LINE__, "PAPI_destroy_eventset", retval ); 00434 EventSet = PAPI_NULL; 00435 00436 retval = PAPI_create_eventset( &EventSet ); 00437 if ( retval != PAPI_OK ) { 00438 test_fail( __FILE__, __LINE__, "PAPI_create_eventset", retval ); } 00439 00440 /* re-parse command line to set up any events specified */ 00441 parse_command_line (argc, argv, numc); 00442 00443 00444 } 00445 } 00446 fprintf( stdout, "</eventinfo>\n" ); 00447 00448 return 0; 00449 }