PAPI  5.0.1.0
papi_preset.c
Go to the documentation of this file.
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
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines