|
PAPI
5.0.1.0
|
00001 /* 00002 * File: papi_preset.c 00003 * Author: Haihang You 00004 * you@cs.utk.edu 00005 * Mods: Brian Sheely 00006 * bsheely@eecs.utk.edu 00007 * Author: Vince Weaver 00008 * vweaver1 @ eecs.utk.edu 00009 * Merge of the libpfm3/libpfm4/pmapi-ppc64_events preset code 00010 */ 00011 00012 00013 #include <string.h> 00014 #include <ctype.h> 00015 #include <errno.h> 00016 00017 #include "papi.h" 00018 #include "papi_internal.h" 00019 #include "papi_vector.h" 00020 #include "papi_memory.h" 00021 #include "papi_preset.h" 00022 #include "extras.h" 00023 00024 00025 /* This routine copies values from a dense 'findem' array of events 00026 into the sparse global _papi_hwi_presets array, which is assumed 00027 to be empty at initialization. 00028 00029 Multiple dense arrays can be copied into the sparse array, allowing 00030 event overloading at run-time, or allowing a baseline table to be 00031 augmented by a model specific table at init time. 00032 00033 This method supports adding new events; overriding existing events, or 00034 deleting deprecated events. 00035 */ 00036 int 00037 _papi_hwi_setup_all_presets( hwi_search_t * findem, int cidx ) 00038 { 00039 int i, pnum, did_something = 0; 00040 unsigned int preset_index, j, k; 00041 00042 /* dense array of events is terminated with a 0 preset. 00043 don't do anything if NULL pointer. This allows just notes to be loaded. 00044 It's also good defensive programming. 00045 */ 00046 if ( findem != NULL ) { 00047 for ( pnum = 0; ( pnum < PAPI_MAX_PRESET_EVENTS ) && 00048 ( findem[pnum].event_code != 0 ); pnum++ ) { 00049 /* find the index for the event to be initialized */ 00050 preset_index = ( findem[pnum].event_code & PAPI_PRESET_AND_MASK ); 00051 /* count and set the number of native terms in this event, 00052 these items are contiguous. 00053 00054 PAPI_EVENTS_IN_DERIVED_EVENT is arbitrarily defined in the high 00055 level to be a reasonable number of terms to use in a derived 00056 event linear expression, currently 8. 00057 00058 This wastes space for components with less than 8 counters, 00059 but keeps the framework independent of the components. 00060 00061 The 'native' field below is an arbitrary opaque identifier 00062 that points to information on an actual native event. 00063 It is not an event code itself (whatever that might mean). 00064 By definition, this value can never == PAPI_NULL. 00065 - dkt */ 00066 00067 INTDBG( "Counting number of terms for preset index %d, " 00068 "search map index %d.\n", preset_index, pnum ); 00069 i = 0; 00070 j = 0; 00071 while ( i < PAPI_EVENTS_IN_DERIVED_EVENT ) { 00072 if ( findem[pnum].native[i] != PAPI_NULL ) { 00073 j++; 00074 } 00075 else if ( j ) { 00076 break; 00077 } 00078 i++; 00079 } 00080 00081 INTDBG( "This preset has %d terms.\n", j ); 00082 _papi_hwi_presets[preset_index].count = j; 00083 00084 _papi_hwi_presets[preset_index].derived_int = findem[pnum].derived; 00085 for(k=0;k<j;k++) { 00086 _papi_hwi_presets[preset_index].code[k] = 00087 findem[pnum].native[k]; 00088 } 00089 /* preset code list must be PAPI_NULL terminated */ 00090 if (k<PAPI_EVENTS_IN_DERIVED_EVENT) { 00091 _papi_hwi_presets[preset_index].code[k] = PAPI_NULL; 00092 } 00093 00094 _papi_hwi_presets[preset_index].postfix= 00095 strdup(findem[pnum].operation); 00096 00097 did_something++; 00098 } 00099 } 00100 00101 _papi_hwd[cidx]->cmp_info.num_preset_events += did_something; 00102 00103 return ( did_something ? PAPI_OK : PAPI_ENOEVNT ); 00104 } 00105 00106 int 00107 _papi_hwi_cleanup_all_presets( void ) 00108 { 00109 int preset_index,cidx; 00110 unsigned int j; 00111 00112 for ( preset_index = 0; preset_index < PAPI_MAX_PRESET_EVENTS; 00113 preset_index++ ) { 00114 if ( _papi_hwi_presets[preset_index].postfix != NULL ) { 00115 free( _papi_hwi_presets[preset_index].postfix ); 00116 _papi_hwi_presets[preset_index].postfix = NULL; 00117 } 00118 if ( _papi_hwi_presets[preset_index].note != NULL ) { 00119 free( _papi_hwi_presets[preset_index].note ); 00120 _papi_hwi_presets[preset_index].note = NULL; 00121 } 00122 for(j=0; j<_papi_hwi_presets[preset_index].count;j++) { 00123 free(_papi_hwi_presets[preset_index].name[j]); 00124 } 00125 } 00126 00127 for(cidx=0;cidx<papi_num_components;cidx++) { 00128 _papi_hwd[cidx]->cmp_info.num_preset_events = 0; 00129 } 00130 00131 #if defined(ITANIUM2) || defined(ITANIUM3) 00132 /* NOTE: This memory may need to be freed for BG/P builds as well */ 00133 if ( preset_search_map != NULL ) { 00134 papi_free( preset_search_map ); 00135 preset_search_map = NULL; 00136 } 00137 #endif 00138 00139 return PAPI_OK; 00140 } 00141 00142 00143 00144 #define PAPI_EVENT_FILE "papi_events.csv" 00145 00146 00147 /* Trims blank space from both ends of a string (in place). 00148 Returns pointer to new start address */ 00149 static inline char * 00150 trim_string( char *in ) 00151 { 00152 int len, i = 0; 00153 char *start = in; 00154 00155 if ( in == NULL ) 00156 return ( in ); 00157 len = ( int ) strlen( in ); 00158 if ( len == 0 ) 00159 return ( in ); 00160 00161 /* Trim left */ 00162 while ( i < len ) { 00163 if ( isblank( in[i] ) ) { 00164 in[i] = '\0'; 00165 start++; 00166 } else 00167 break; 00168 i++; 00169 } 00170 00171 /* Trim right */ 00172 i = ( int ) strlen( start ) - 1; 00173 while ( i >= 0 ) { 00174 if ( isblank( start[i] ) ) 00175 start[i] = '\0'; 00176 else 00177 break; 00178 i--; 00179 } 00180 return ( start ); 00181 } 00182 00183 00184 /* Calls trim_string to remove blank space; 00185 Removes paired punctuation delimiters from 00186 beginning and end of string. If the same punctuation 00187 appears first and last (quotes, slashes) they are trimmed; 00188 Also checks for the following pairs: () <> {} [] */ 00189 static inline char * 00190 trim_note( char *in ) 00191 { 00192 int len; 00193 char *note, start, end; 00194 00195 note = trim_string( in ); 00196 if ( note != NULL ) { 00197 len = ( int ) strlen( note ); 00198 if ( len > 0 ) { 00199 if ( ispunct( *note ) ) { 00200 start = *note; 00201 end = note[len - 1]; 00202 if ( ( start == end ) 00203 || ( ( start == '(' ) && ( end == ')' ) ) 00204 || ( ( start == '<' ) && ( end == '>' ) ) 00205 || ( ( start == '{' ) && ( end == '}' ) ) 00206 || ( ( start == '[' ) && ( end == ']' ) ) ) { 00207 note[len - 1] = '\0'; 00208 *note = '\0'; 00209 note++; 00210 } 00211 } 00212 } 00213 } 00214 return note; 00215 } 00216 00217 static inline int 00218 find_preset_code( char *tmp, int *code ) 00219 { 00220 int i = 0; 00221 00222 while ( _papi_hwi_presets[i].symbol != NULL ) { 00223 if ( strcasecmp( tmp, _papi_hwi_presets[i].symbol ) == 0 ) { 00224 *code = ( int ) ( i | PAPI_PRESET_MASK ); 00225 return PAPI_OK; 00226 } 00227 i++; 00228 } 00229 return PAPI_EINVAL; 00230 } 00231 00232 /* Look for an event file 'name' in a couple common locations. 00233 Return a valid file handle if found */ 00234 static FILE * 00235 open_event_table( char *name ) 00236 { 00237 FILE *table; 00238 00239 SUBDBG( "Opening %s\n", name ); 00240 table = fopen( name, "r" ); 00241 if ( table == NULL ) { 00242 SUBDBG( "Open %s failed, trying ./%s.\n", 00243 name, PAPI_EVENT_FILE ); 00244 sprintf( name, "%s", PAPI_EVENT_FILE ); 00245 table = fopen( name, "r" ); 00246 } 00247 if ( table == NULL ) { 00248 SUBDBG( "Open ./%s failed, trying ../%s.\n", 00249 name, PAPI_EVENT_FILE ); 00250 sprintf( name, "../%s", PAPI_EVENT_FILE ); 00251 table = fopen( name, "r" ); 00252 } 00253 if ( table ) { 00254 SUBDBG( "Open %s succeeded.\n", name ); 00255 } 00256 return table; 00257 } 00258 00259 /* parse a single line from either a file or character table 00260 Strip trailing <cr>; return 0 if empty */ 00261 static int 00262 get_event_line( char *line, FILE * table, char **tmp_perfmon_events_table ) 00263 { 00264 int ret; 00265 int i; 00266 00267 if ( table ) { 00268 if ( fgets( line, LINE_MAX, table ) ) { 00269 ret = 1; 00270 i = ( int ) strlen( line ); 00271 if ( line[i - 1] == '\n' ) 00272 line[i - 1] = '\0'; 00273 } else 00274 ret = 0; 00275 } else { 00276 for ( i = 0; 00277 **tmp_perfmon_events_table && **tmp_perfmon_events_table != '\n'; 00278 i++ ) { 00279 line[i] = **tmp_perfmon_events_table; 00280 ( *tmp_perfmon_events_table )++; 00281 } 00282 if ( **tmp_perfmon_events_table == '\n' ) { 00283 ( *tmp_perfmon_events_table )++; 00284 } 00285 line[i] = '\0'; 00286 ret = **tmp_perfmon_events_table; 00287 } 00288 return ret; 00289 } 00290 00291 /* Static version of the events file. */ 00292 #if defined(STATIC_PAPI_EVENTS_TABLE) 00293 #include "papi_events_table.h" 00294 #else 00295 static char *papi_events_table = NULL; 00296 #endif 00297 00298 int 00299 _papi_load_preset_table( char *pmu_str, int pmu_type, int cidx) 00300 { 00301 00302 (void) cidx; /* We'll use this later */ 00303 00304 char pmu_name[PAPI_MIN_STR_LEN]; 00305 char line[LINE_MAX]; 00306 char name[PATH_MAX] = "builtin papi_events_table"; 00307 char *tmp_papi_events_table = NULL; 00308 char *tmpn; 00309 FILE *table; 00310 int ret; 00311 unsigned int event_idx; 00312 int invalid_event; 00313 int line_no = 1, derived = 0, insert = 0, preset = 0; 00314 int get_presets = 0; /* only get PRESETS after CPU is identified */ 00315 int found_presets = 0; /* only terminate search after PRESETS are found */ 00316 /* this allows support for synonyms for CPU names*/ 00317 00318 SUBDBG("ENTER\n"); 00319 00320 /* copy the pmu identifier, stripping commas if found */ 00321 tmpn = pmu_name; 00322 while ( *pmu_str ) { 00323 if ( *pmu_str != ',' ) *tmpn++ = *pmu_str; 00324 pmu_str++; 00325 } 00326 *tmpn = '\0'; 00327 00328 /* try the environment variable first */ 00329 if ( ( tmpn = getenv( "PAPI_CSV_EVENT_FILE" ) ) && 00330 ( strlen( tmpn ) != 0 ) ) { 00331 sprintf( name, "%s", tmpn ); 00332 table = fopen( name, "r" ); 00333 } 00334 /* if no valid environment variable, look for built-in table */ 00335 else if ( papi_events_table ) { 00336 tmp_papi_events_table = papi_events_table; 00337 table = NULL; 00338 } 00339 /* if no env var and no built-in, search for default file */ 00340 else { 00341 #ifdef PAPI_DATADIR 00342 sprintf( name, "%s/%s", PAPI_DATADIR, PAPI_EVENT_FILE ); 00343 #else 00344 sprintf( name, "%s", PAPI_EVENT_FILE ); 00345 #endif 00346 table = open_event_table( name ); 00347 } 00348 00349 /* if no valid file or built-in table, bail */ 00350 if ( table == NULL && tmp_papi_events_table == NULL ) { 00351 PAPIERROR( "fopen(%s): %s, please set the PAPI_CSV_EVENT_FILE " 00352 "env. variable", name, strerror( errno ) ); 00353 return PAPI_ESYS; 00354 } 00355 00356 /* at this point either a valid file pointer or built-in table pointer */ 00357 while ( get_event_line( line, table, &tmp_papi_events_table ) ) { 00358 char *t; 00359 int i; 00360 00361 t = trim_string( strtok( line, "," ) ); 00362 00363 /* Skip blank lines */ 00364 if ( ( t == NULL ) || ( strlen( t ) == 0 ) ) continue; 00365 00366 /* Skip comments */ 00367 if ( t[0] == '#' ) { 00368 goto nextline; 00369 } 00370 00371 if ( strcasecmp( t, "CPU" ) == 0 ) { 00372 00373 if ( get_presets != 0 && found_presets != 0 ) { 00374 SUBDBG( "Ending preset scanning at line %d of %s.\n", 00375 line_no, name ); 00376 00377 get_presets=0; found_presets=0; 00378 00379 } 00380 00381 t = trim_string( strtok( NULL, "," ) ); 00382 if ( ( t == NULL ) || ( strlen( t ) == 0 ) ) { 00383 PAPIERROR( "Expected name after CPU token at line %d of %s " 00384 "-- ignoring", line_no, name ); 00385 goto nextline; 00386 } 00387 00388 SUBDBG( "Examining CPU (%s) vs. (%s)\n", t, pmu_name ); 00389 00390 if ( strcasecmp( t, pmu_name ) == 0 ) { 00391 int type; 00392 00393 SUBDBG( "Found CPU %s at line %d of %s.\n", t, line_no, name ); 00394 00395 t = trim_string( strtok( NULL, "," ) ); 00396 if ( ( t == NULL ) || ( strlen( t ) == 0 ) ) { 00397 SUBDBG("No additional qualifier found, matching on string.\n"); 00398 00399 get_presets = 1; 00400 } else if ( ( sscanf( t,"%d",&type )==1) && (type==pmu_type) ) { 00401 SUBDBG( "Found CPU %s type %d at line %d of %s.\n", 00402 pmu_name, type, line_no, name ); 00403 get_presets = 1; 00404 } else { 00405 SUBDBG( "Additional qualifier match failed %d vs %d.\n", 00406 pmu_type, type ); 00407 00408 } 00409 } 00410 } else if ( strcasecmp( t, "PRESET" ) == 0 ) { 00411 00412 if ( get_presets == 0 ) goto nextline; 00413 00414 found_presets = 1; 00415 t = trim_string( strtok( NULL, "," ) ); 00416 00417 if ( ( t == NULL ) || ( strlen( t ) == 0 ) ) { 00418 00419 PAPIERROR( "Expected name after PRESET token at line %d of %s " 00420 "-- ignoring", line_no, name ); 00421 goto nextline; 00422 } 00423 00424 SUBDBG( "Examining preset %s\n", t ); 00425 00426 if ( find_preset_code( t, &preset ) != PAPI_OK ) { 00427 PAPIERROR ( "Invalid preset name %s after PRESET token " 00428 "at line %d of %s -- ignoring", 00429 t, line_no, name ); 00430 goto nextline; 00431 } 00432 00433 SUBDBG( "Found 0x%08x for %s\n", preset, t ); 00434 00435 t = trim_string( strtok( NULL, "," ) ); 00436 if ( ( t == NULL ) || ( strlen( t ) == 0 ) ) { 00437 PAPIERROR( "Expected derived type after PRESET token at " 00438 "line %d of %s -- ignoring", line_no, name ); 00439 goto nextline; 00440 } 00441 00442 if ( _papi_hwi_derived_type( t, &derived ) != PAPI_OK ) { 00443 PAPIERROR( "Invalid derived name %s after PRESET token at " 00444 "line %d of %s -- ignoring", 00445 t, line_no, name ); 00446 goto nextline; 00447 } 00448 00449 /****************************************/ 00450 /* Have a preset, let's start assigning */ 00451 /****************************************/ 00452 00453 SUBDBG( "Found %d for %s\n", derived, t ); 00454 SUBDBG( "Adding 0x%x,%d to preset search table.\n", 00455 preset, derived ); 00456 00457 insert=preset&PAPI_PRESET_AND_MASK; 00458 00459 /* _papi_hwi_presets[insert].event_code = preset; */ 00460 _papi_hwi_presets[insert].derived_int = derived; 00461 00462 /* Derived support starts here */ 00463 /* Special handling for postfix */ 00464 if ( derived == DERIVED_POSTFIX ) { 00465 t = trim_string( strtok( NULL, "," ) ); 00466 if ( ( t == NULL ) || ( strlen( t ) == 0 ) ) { 00467 PAPIERROR( "Expected Operation string after derived type " 00468 "DERIVED_POSTFIX at line %d of %s -- ignoring", 00469 line_no, name ); 00470 goto nextline; 00471 } 00472 00473 SUBDBG( "Saving PostFix operations %s\n", t ); 00474 00475 _papi_hwi_presets[insert].postfix=strdup(t); 00476 } 00477 00478 /* All derived terms collected here */ 00479 i = 0; 00480 invalid_event=0; 00481 do { 00482 t = trim_string( strtok( NULL, "," ) ); 00483 if ( ( t == NULL ) || ( strlen( t ) == 0 ) ) break; 00484 if ( strcasecmp( t, "NOTE" ) == 0 ) break; 00485 _papi_hwi_presets[insert].name[i]=strdup(t); 00486 00487 SUBDBG( "Adding term (%d) %s to preset event 0x%x.\n", 00488 i, t, preset ); 00489 00490 SUBDBG("Looking up: %s\n",t); 00491 00492 ret=_papi_hwd[cidx]->ntv_name_to_code(t, &event_idx); 00493 00494 if (ret==PAPI_OK) { 00495 _papi_hwi_presets[insert].code[i]= 00496 _papi_hwi_native_to_eventcode(cidx,event_idx); 00497 SUBDBG("Found: %s %x c%d e%d\n",t, 00498 _papi_hwi_presets[insert].code[i], 00499 cidx,event_idx); 00500 } 00501 else { 00502 PAPIERROR("papi_preset: Error finding event %s",t); 00503 invalid_event=1; 00504 } 00505 00506 } while ( ++i < PAPI_EVENTS_IN_DERIVED_EVENT ); 00507 00508 /* preset code list must be PAPI_NULL terminated */ 00509 if (i<PAPI_EVENTS_IN_DERIVED_EVENT) { 00510 _papi_hwi_presets[insert].code[i] = PAPI_NULL; 00511 } 00512 00513 if (invalid_event) { 00514 /* We signify a valid preset if count > 0 */ 00515 _papi_hwi_presets[insert].count=0; 00516 } else { 00517 _papi_hwi_presets[insert].count=i; 00518 } 00519 00520 /* End of derived support */ 00521 00522 if ( i == 0 ) { 00523 PAPIERROR( "Expected PFM event after DERIVED token at " 00524 "line %d of %s -- ignoring", line_no, name ); 00525 goto nextline; 00526 } 00527 if ( i == PAPI_EVENTS_IN_DERIVED_EVENT ) { 00528 t = trim_string( strtok( NULL, "," ) ); 00529 } 00530 00531 /* Handle optional NOTEs */ 00532 if ( t && ( strcasecmp( t, "NOTE" ) == 0 ) ) { 00533 SUBDBG( "%s found on line %d\n", t, line_no ); 00534 00535 /* read the rest of the line */ 00536 t = trim_note( strtok( NULL, "" ) ); 00537 00538 if ( ( t == NULL ) || ( strlen( t ) == 0 ) ) { 00539 PAPIERROR( "Expected Note string at line %d of %s\n", 00540 line_no, name ); 00541 } 00542 else { 00543 _papi_hwi_presets[insert].note = strdup( t ); 00544 SUBDBG( "NOTE: --%s-- found on line %d\n", t, line_no ); 00545 } 00546 } 00547 _papi_hwd[cidx]->cmp_info.num_preset_events++; 00548 00549 } else { 00550 PAPIERROR( "Unrecognized token %s at line %d of %s -- ignoring", 00551 t, line_no, name ); 00552 goto nextline; 00553 } 00554 nextline: 00555 line_no++; 00556 } 00557 00558 if ( table ) { 00559 fclose( table ); 00560 } 00561 00562 SUBDBG("Done parsing preset table\n"); 00563 00564 return PAPI_OK; 00565 } 00566 00567 00568 00569 00570 /* The following code is proof of principle for reading preset events from an 00571 xml file. It has been tested and works for pentium3. It relys on the expat 00572 library and is invoked by adding 00573 XMLFLAG = -DXML 00574 to the Makefile. It is presently hardcoded to look for "./papi_events.xml" 00575 */ 00576 #ifdef XML 00577 00578 #define BUFFSIZE 8192 00579 #define SPARSE_BEGIN 0 00580 #define SPARSE_EVENT_SEARCH 1 00581 #define SPARSE_EVENT 2 00582 #define SPARSE_DESC 3 00583 #define ARCH_SEARCH 4 00584 #define DENSE_EVENT_SEARCH 5 00585 #define DENSE_NATIVE_SEARCH 6 00586 #define DENSE_NATIVE_DESC 7 00587 #define FINISHED 8 00588 00589 char buffer[BUFFSIZE], *xml_arch; 00590 int location = SPARSE_BEGIN, sparse_index = 0, native_index, error = 0; 00591 00592 /* The function below, _xml_start(), is a hook into expat's XML 00593 * parser. _xml_start() defines how the parser handles the 00594 * opening tags in PAPI's XML file. This function can be understood 00595 * more easily if you follow along with its logic while looking at 00596 * papi_events.xml. The location variable is a global telling us 00597 * where we are in the XML file. Have we found our architecture's 00598 * events yet? Are we looking at an event definition?...etc. 00599 */ 00600 static void 00601 _xml_start( void *data, const char *el, const char **attr ) 00602 { 00603 int native_encoding; 00604 00605 if ( location == SPARSE_BEGIN && !strcmp( "papistdevents", el ) ) { 00606 location = SPARSE_EVENT_SEARCH; 00607 } else if ( location == SPARSE_EVENT_SEARCH && !strcmp( "papievent", el ) ) { 00608 _papi_hwi_presets[sparse_index].info.symbol = papi_strdup( attr[1] ); 00609 // strcpy(_papi_hwi_presets.info[sparse_index].symbol, attr[1]); 00610 location = SPARSE_EVENT; 00611 } else if ( location == SPARSE_EVENT && !strcmp( "desc", el ) ) { 00612 location = SPARSE_DESC; 00613 } else if ( location == ARCH_SEARCH && !strcmp( "availevents", el ) && 00614 !strcmp( xml_arch, attr[1] ) ) { 00615 location = DENSE_EVENT_SEARCH; 00616 } else if ( location == DENSE_EVENT_SEARCH && !strcmp( "papievent", el ) ) { 00617 if ( !strcmp( "PAPI_NULL", attr[1] ) ) { 00618 location = FINISHED; 00619 return; 00620 } else if ( PAPI_event_name_to_code( ( char * ) attr[1], &sparse_index ) 00621 != PAPI_OK ) { 00622 PAPIERROR( "Improper Preset name given in XML file for %s.", 00623 attr[1] ); 00624 error = 1; 00625 } 00626 sparse_index &= PAPI_PRESET_AND_MASK; 00627 00628 /* allocate and initialize data space for this event */ 00629 papi_valid_free( _papi_hwi_presets[sparse_index].data ); 00630 _papi_hwi_presets[sparse_index].data = 00631 papi_malloc( sizeof ( hwi_preset_data_t ) ); 00632 native_index = 0; 00633 _papi_hwi_presets[sparse_index].data->native[native_index] = PAPI_NULL; 00634 _papi_hwi_presets[sparse_index].data->operation[0] = '\0'; 00635 00636 00637 if ( attr[2] ) { /* derived event */ 00638 _papi_hwi_presets[sparse_index].data->derived = 00639 _papi_hwi_derived_type( ( char * ) attr[3] ); 00640 /* where does DERIVED POSTSCRIPT get encoded?? */ 00641 if ( _papi_hwi_presets[sparse_index].data->derived == -1 ) { 00642 PAPIERROR( "No derived type match for %s in Preset XML file.", 00643 attr[3] ); 00644 error = 1; 00645 } 00646 00647 if ( attr[5] ) { 00648 _papi_hwi_presets[sparse_index].count = atoi( attr[5] ); 00649 } else { 00650 PAPIERROR( "No count given for %s in Preset XML file.", 00651 attr[1] ); 00652 error = 1; 00653 } 00654 } else { 00655 _papi_hwi_presets[sparse_index].data->derived = NOT_DERIVED; 00656 _papi_hwi_presets[sparse_index].count = 1; 00657 } 00658 location = DENSE_NATIVE_SEARCH; 00659 } else if ( location == DENSE_NATIVE_SEARCH && !strcmp( "native", el ) ) { 00660 location = DENSE_NATIVE_DESC; 00661 } else if ( location == DENSE_NATIVE_DESC && !strcmp( "event", el ) ) { 00662 if ( _papi_hwi_native_name_to_code( attr[1], &native_encoding ) != 00663 PAPI_OK ) { 00664 printf( "Improper Native name given in XML file for %s\n", 00665 attr[1] ); 00666 PAPIERROR( "Improper Native name given in XML file for %s\n", 00667 attr[1] ); 00668 error = 1; 00669 } 00670 _papi_hwi_presets[sparse_index].data->native[native_index] = 00671 native_encoding; 00672 native_index++; 00673 _papi_hwi_presets[sparse_index].data->native[native_index] = PAPI_NULL; 00674 } else if ( location && location != ARCH_SEARCH && location != FINISHED ) { 00675 PAPIERROR( "Poorly-formed Preset XML document." ); 00676 error = 1; 00677 } 00678 } 00679 00680 /* The function below, _xml_end(), is a hook into expat's XML 00681 * parser. _xml_end() defines how the parser handles the 00682 * end tags in PAPI's XML file. 00683 */ 00684 static void 00685 _xml_end( void *data, const char *el ) 00686 { 00687 int i; 00688 00689 if ( location == SPARSE_EVENT_SEARCH && !strcmp( "papistdevents", el ) ) { 00690 for ( i = sparse_index; i < PAPI_MAX_PRESET_EVENTS; i++ ) { 00691 _papi_hwi_presets[i].info.symbol = NULL; 00692 _papi_hwi_presets[i].info.long_descr = NULL; 00693 _papi_hwi_presets[i].info.short_descr = NULL; 00694 } 00695 location = ARCH_SEARCH; 00696 } else if ( location == DENSE_NATIVE_DESC && !strcmp( "native", el ) ) { 00697 location = DENSE_EVENT_SEARCH; 00698 } else if ( location == DENSE_EVENT_SEARCH && !strcmp( "availevents", el ) ) { 00699 location = FINISHED; 00700 } 00701 } 00702 00703 /* The function below, _xml_content(), is a hook into expat's XML 00704 * parser. _xml_content() defines how the parser handles the 00705 * text between tags in PAPI's XML file. The information between 00706 * tags is usally text for event descriptions. 00707 */ 00708 static void 00709 _xml_content( void *data, const char *el, const int len ) 00710 { 00711 int i; 00712 if ( location == SPARSE_DESC ) { 00713 _papi_hwi_presets[sparse_index].info.long_descr = 00714 papi_malloc( len + 1 ); 00715 for ( i = 0; i < len; i++ ) 00716 _papi_hwi_presets[sparse_index].info.long_descr[i] = el[i]; 00717 _papi_hwi_presets[sparse_index].info.long_descr[len] = '\0'; 00718 /* the XML data currently doesn't contain a short description */ 00719 _papi_hwi_presets[sparse_index].info.short_descr = NULL; 00720 sparse_index++; 00721 _papi_hwi_presets[sparse_index].data = NULL; 00722 location = SPARSE_EVENT_SEARCH; 00723 } 00724 } 00725 00726 int 00727 _xml_papi_hwi_setup_all_presets( char *arch, hwi_dev_notes_t * notes ) 00728 { 00729 int done = 0; 00730 FILE *fp = fopen( "./papi_events.xml", "r" ); 00731 XML_Parser p = XML_ParserCreate( NULL ); 00732 00733 if ( !p ) { 00734 PAPIERROR( "Couldn't allocate memory for XML parser." ); 00735 return ( PAPI_ESYS ); 00736 } 00737 XML_SetElementHandler( p, _xml_start, _xml_end ); 00738 XML_SetCharacterDataHandler( p, _xml_content ); 00739 if ( fp == NULL ) { 00740 PAPIERROR( "Error opening Preset XML file." ); 00741 return ( PAPI_ESYS ); 00742 } 00743 00744 xml_arch = arch; 00745 00746 do { 00747 int len; 00748 void *buffer = XML_GetBuffer( p, BUFFSIZE ); 00749 00750 if ( buffer == NULL ) { 00751 PAPIERROR( "Couldn't allocate memory for XML buffer." ); 00752 return ( PAPI_ESYS ); 00753 } 00754 len = fread( buffer, 1, BUFFSIZE, fp ); 00755 if ( ferror( fp ) ) { 00756 PAPIERROR( "XML read error." ); 00757 return ( PAPI_ESYS ); 00758 } 00759 done = feof( fp ); 00760 if ( !XML_ParseBuffer( p, len, len == 0 ) ) { 00761 PAPIERROR( "Parse error at line %d:\n%s\n", 00762 XML_GetCurrentLineNumber( p ), 00763 XML_ErrorString( XML_GetErrorCode( p ) ) ); 00764 return ( PAPI_ESYS ); 00765 } 00766 if ( error ) 00767 return ( PAPI_ESYS ); 00768 } while ( !done ); 00769 XML_ParserFree( p ); 00770 fclose( fp ); 00771 return ( PAPI_OK ); 00772 } 00773 #endif