papi_preset.c File Reference

Include dependency graph for papi_preset.c:

Go to the source code of this file.

Defines

#define PAPI_EVENT_FILE   "papi_events.csv"

Functions

static int papi_load_derived_events (char *pmu_str, int pmu_type, int cidx, int preset_flag)
int _papi_hwi_setup_all_presets (hwi_search_t *findem, int cidx)
int _papi_hwi_cleanup_all_presets (void)
static char * trim_string (char *in)
static char * trim_note (char *in)
static int find_event_index (hwi_presets_t *array, int size, char *tmp)
static FILE * open_event_table (char *name)
static int get_event_line (char *line, FILE *table, char **tmp_perfmon_events_table)
static void update_ops_string (char **formula, int old_index, int new_index)
static void ops_string_append (hwi_presets_t *results, hwi_presets_t *depends_on, int addition)
static void ops_string_merge (char **original, char *insertion, int replaces, int start_index)
static int check_derived_events (char *target, int derived_type, hwi_presets_t *results, hwi_presets_t *search, int search_size, int token_index)
static int check_native_events (char *target, hwi_presets_t *results)
static int is_event (char *event_name, int derived_type, hwi_presets_t *results, int token_index)
int _papi_load_preset_table (char *pmu_str, int pmu_type, int cidx)
static int priority (char symbol)
static int push (char symbol)
static char pop ()
static char * infix_to_postfix (char *infix)

Variables

hwi_presets_t user_defined_events []
int user_defined_events_count
static char * papi_events_table = NULL
static char stack [PAPI_HUGE_STR_LEN]
static int stacktop = -1

Define Documentation

#define PAPI_EVENT_FILE   "papi_events.csv"

Definition at line 151 of file papi_preset.c.


Function Documentation

int _papi_hwi_cleanup_all_presets ( void   ) 

Definition at line 114 of file papi_preset.c.

00115 {
00116         int preset_index,cidx;
00117     unsigned int j;
00118 
00119     for ( preset_index = 0; preset_index < PAPI_MAX_PRESET_EVENTS;
00120           preset_index++ ) {
00121         if ( _papi_hwi_presets[preset_index].postfix != NULL ) {
00122            papi_free( _papi_hwi_presets[preset_index].postfix );
00123            _papi_hwi_presets[preset_index].postfix = NULL;
00124         }
00125         if ( _papi_hwi_presets[preset_index].note != NULL ) {
00126            papi_free( _papi_hwi_presets[preset_index].note );
00127            _papi_hwi_presets[preset_index].note = NULL;
00128         }
00129         for(j=0; j<_papi_hwi_presets[preset_index].count;j++) {
00130            papi_free(_papi_hwi_presets[preset_index].name[j]);
00131         }
00132     }
00133     
00134     for(cidx=0;cidx<papi_num_components;cidx++) {
00135        _papi_hwd[cidx]->cmp_info.num_preset_events = 0;
00136     }
00137 
00138 #if defined(ITANIUM2) || defined(ITANIUM3)
00139     /* NOTE: This memory may need to be freed for BG/P builds as well */
00140     if ( preset_search_map != NULL ) {
00141         papi_free( preset_search_map );
00142         preset_search_map = NULL;
00143     }
00144 #endif
00145 
00146     return PAPI_OK;
00147 }

Here is the caller graph for this function:

int _papi_hwi_setup_all_presets ( hwi_search_t findem,
int  cidx 
)

Definition at line 44 of file papi_preset.c.

00045 {
00046     int i, pnum, did_something = 0;
00047     unsigned int preset_index, j, k;
00048 
00049     /* dense array of events is terminated with a 0 preset.
00050        don't do anything if NULL pointer. This allows just notes to be loaded.
00051        It's also good defensive programming. 
00052      */
00053     if ( findem != NULL ) {
00054        for ( pnum = 0; ( pnum < PAPI_MAX_PRESET_EVENTS ) &&
00055               ( findem[pnum].event_code != 0 ); pnum++ ) {
00056        /* find the index for the event to be initialized */
00057        preset_index = ( findem[pnum].event_code & PAPI_PRESET_AND_MASK );
00058        /* count and set the number of native terms in this event, 
00059               these items are contiguous.
00060 
00061           PAPI_EVENTS_IN_DERIVED_EVENT is arbitrarily defined in the high 
00062               level to be a reasonable number of terms to use in a derived 
00063               event linear expression, currently 8.
00064 
00065           This wastes space for components with less than 8 counters, 
00066               but keeps the framework independent of the components.
00067 
00068           The 'native' field below is an arbitrary opaque identifier 
00069               that points to information on an actual native event. 
00070               It is not an event code itself (whatever that might mean).
00071           By definition, this value can never == PAPI_NULL.
00072           - dkt */
00073 
00074        INTDBG( "Counting number of terms for preset index %d, "
00075                    "search map index %d.\n", preset_index, pnum );
00076        i = 0;
00077        j = 0;
00078        while ( i < PAPI_EVENTS_IN_DERIVED_EVENT ) {
00079           if ( findem[pnum].native[i] != PAPI_NULL ) {
00080          j++;
00081           }
00082           else if ( j ) {
00083          break;
00084           }
00085           i++;
00086        }
00087 
00088        INTDBG( "This preset has %d terms.\n", j );
00089        _papi_hwi_presets[preset_index].count = j;
00090  
00091            _papi_hwi_presets[preset_index].derived_int = findem[pnum].derived;
00092        for(k=0;k<j;k++) {
00093               _papi_hwi_presets[preset_index].code[k] = 
00094                      findem[pnum].native[k];
00095        }
00096        /* preset code list must be PAPI_NULL terminated */
00097        if (k<PAPI_EVENTS_IN_DERIVED_EVENT) {
00098               _papi_hwi_presets[preset_index].code[k] = PAPI_NULL;
00099        }
00100 
00101        _papi_hwi_presets[preset_index].postfix=
00102                                        papi_strdup(findem[pnum].operation);
00103 
00104        did_something++;
00105        }
00106     }
00107 
00108     _papi_hwd[cidx]->cmp_info.num_preset_events += did_something;
00109 
00110     return ( did_something ? PAPI_OK : PAPI_ENOEVNT );
00111 }

Here is the caller graph for this function:

int _papi_load_preset_table ( char *  pmu_str,
int  pmu_type,
int  cidx 
)

Definition at line 771 of file papi_preset.c.

00771                                                                    {
00772     SUBDBG("ENTER: pmu_str: %s, pmu_type: %d, cidx: %d\n", pmu_str, pmu_type, cidx);
00773 
00774     int retval;
00775 
00776     // go load papi preset events (last argument tells function if we are loading presets or user events)
00777     retval = papi_load_derived_events(pmu_str, pmu_type, cidx, 1);
00778     if (retval != PAPI_OK) {
00779         SUBDBG("EXIT: retval: %d\n", retval);
00780         return retval;
00781     }
00782 
00783     // go load the user defined event definitions if any are defined
00784     retval = papi_load_derived_events(pmu_str, pmu_type, cidx, 0);
00785 
00786     SUBDBG("EXIT: retval: %d\n", retval);
00787     return retval;
00788 }

Here is the call graph for this function:

Here is the caller graph for this function:

static int check_derived_events ( char *  target,
int  derived_type,
hwi_presets_t results,
hwi_presets_t search,
int  search_size,
int  token_index 
) [static]

Definition at line 617 of file papi_preset.c.

00618 {
00619     INTDBG("ENTER: target: %p (%s), results: %p, search: %p, search_size: %d, token_index: %d\n", target, target, results, search, search_size, token_index);
00620     unsigned int i;
00621     int j;
00622     int k;
00623     int found = 0;
00624 
00625     for (j=0; j < search_size; j++) {
00626         //  INTDBG("search[%d].symbol: %s, looking for: %s\n", j, search[j].symbol, target);
00627         if (search[j].symbol == NULL) {
00628             INTDBG("EXIT: returned: 0\n");
00629             return 0;
00630         }
00631 
00632         // if not the event we depend on, just look at next
00633         if ( strcasecmp( target, search[j].symbol) != 0 ) {
00634             continue;
00635         }
00636 
00637         INTDBG("Found a match\n");
00638 
00639         // derived formulas need to be adjusted based on what kind of derived event we are processing
00640         // the derived type passed to this function is the type of the new event being defined (not the events it is based on)
00641         // when we get here the formula must be in reverse polish notation (RPN) format
00642         switch (derived_type) {
00643             case DERIVED_POSTFIX: {
00644                 // go create a formula to merge the second formula into a spot identified by one of the tokens in
00645                 // the first formula.
00646                 ops_string_merge(&(results->postfix), search[j].postfix, token_index, results->count);
00647                 break;
00648             }
00649             case DERIVED_ADD: {
00650                 // the new derived event adds two things together, go handle this target events role in the add
00651                 ops_string_append(results, &search[j], 1);
00652                 break;
00653             }
00654             case DERIVED_SUB: {
00655                 // go create a formula to subtract the value generated by the second formula from the value generated by the first formula.
00656                 ops_string_append(results, &search[j], 0);
00657                 break;
00658             }
00659                 default: {
00660                 INTDBG("Derived type: %d, not currently handled\n", derived_type);
00661                 break;
00662             }
00663         }
00664 
00665         // copy event name and code used by the derived event into the results table (place where new derived event is getting created)
00666         for ( k = 0; k < (int)search[j].count; k++ ) {
00667 //          INTDBG("search[%d]: %p, name[%d]: %s, code[%d]: %#x\n", j, &search[j], k, search[j].name[k], k, search[j].code[k]);
00668             // if this event is already in the list, just update the formula so that references to this event point to the existing one
00669             for (i=0 ; i < results->count ; i++) {
00670                 if (results->code[i] == search[j].code[k]) {
00671                     INTDBG("event: %s, code: %#x, already in results at index: %d\n", search[j].name[k], search[j].code[k], i);
00672                     // replace all tokens in the formula that refer to index "results->count + found" with a token that refers to index "i".
00673                     // the index "results->count + found" identifies the index used in the formula for the event we just determined is a duplicate
00674                     update_ops_string(&(results->postfix), results->count + found, i);
00675                     found++;
00676                     break;
00677                 }
00678             }
00679 
00680             // if we did not find a match, copy native event info into results array
00681             if (found == 0) {
00682                 // not a duplicate, go ahead and copy into results and bump number of native events in results
00683                 if (search[j].name[k]) {
00684                     results->name[results->count] = papi_strdup(search[j].name[k]);
00685                 } else {
00686                     results->name[results->count] = papi_strdup(target);
00687                 }
00688                 results->code[results->count] = search[j].code[k];
00689                 INTDBG("results: %p, name[%d]: %s, code[%d]: %#x\n", results, results->count, results->name[results->count], results->count, results->code[results->count]);
00690 
00691                 results->count++;
00692             }
00693         }
00694 
00695         INTDBG("EXIT: returned: 1\n");
00696         return 1;
00697     }
00698 
00699     INTDBG("EXIT: returned: 0\n");
00700     return 0;
00701 }

Here is the call graph for this function:

Here is the caller graph for this function:

static int check_native_events ( char *  target,
hwi_presets_t results 
) [static]

Definition at line 704 of file papi_preset.c.

00705 {
00706     INTDBG("ENTER: target: %p (%s), results: %p\n", target, target, results);
00707     int ret;
00708 
00709     // find this native events code
00710     if ( ( ret = _papi_hwi_native_name_to_code( target, (int *)(&results->code[results->count])) ) != PAPI_OK ) {
00711         INTDBG("EXIT: returned: 0, call to convert name to event code failed with ret: %d\n", ret);
00712         return 0;
00713     }
00714 
00715     // if the code returned was 0, return to show it is not a valid native event
00716     if ( results->code[results->count] == 0 ) {
00717         INTDBG( "EXIT: returned: 0, event code not found\n");
00718         return 0;
00719     }
00720 
00721     // if this native event is not for component 0, return to show it can not be used in derived events
00722     // it should be possible to create derived events for other components as long as all events in the derived event are associated with the same component
00723     if ( _papi_hwi_component_index(results->code[results->count]) != 0 ) {
00724         INTDBG( "EXIT: returned: 0, new event not associated with component 0 (current limitation with derived events)\n");
00725         return 0;
00726     }
00727 
00728     //    found = 1;
00729     INTDBG("\tFound a native event %s\n", target);
00730     results->name[results->count++] = papi_strdup(target);
00731 
00732     INTDBG( "EXIT: returned: 1\n");
00733     return 1;
00734 }

Here is the call graph for this function:

Here is the caller graph for this function:

static int find_event_index ( hwi_presets_t array,
int  size,
char *  tmp 
) [inline, static]

Definition at line 225 of file papi_preset.c.

00225                                                             {
00226     SUBDBG("ENTER: array: %p, size: %d, tmp: %s\n", array, size, tmp);
00227     int i;
00228     for (i = 0; i < size; i++) {
00229         if (array[i].symbol == NULL) {
00230             array[i].symbol = papi_strdup(tmp);
00231             SUBDBG("EXIT: i: %d\n", i);
00232             return i;
00233         }
00234         if (strcasecmp(tmp, array[i].symbol) == 0) {
00235             SUBDBG("EXIT: i: %d\n", i);
00236             return i;
00237         }
00238     }
00239     SUBDBG("EXIT: PAPI_EINVAL\n");
00240     return PAPI_EINVAL;
00241 }

Here is the caller graph for this function:

static int get_event_line ( char *  line,
FILE *  table,
char **  tmp_perfmon_events_table 
) [static]

Definition at line 273 of file papi_preset.c.

00274 {
00275     int i;
00276 
00277     if ( table ) {
00278         if ( fgets( line, LINE_MAX, table ) == NULL)
00279         return 0;
00280 
00281         i = ( int ) strlen( line );
00282         if (i == 0)
00283         return 0;
00284         if ( line[i-1] == '\n' )
00285         line[i-1] = '\0';
00286         return 1;
00287     } else {
00288         for ( i = 0;
00289               **tmp_perfmon_events_table && **tmp_perfmon_events_table != '\n';
00290               i++, ( *tmp_perfmon_events_table )++ ) 
00291             line[i] = **tmp_perfmon_events_table;
00292         if (i == 0)
00293             return 0;
00294         if ( **tmp_perfmon_events_table && **tmp_perfmon_events_table == '\n' ) {
00295             ( *tmp_perfmon_events_table )++;
00296         }
00297         line[i] = '\0';
00298         return 1;
00299     }
00300 }

Here is the caller graph for this function:

static char* infix_to_postfix ( char *  infix  )  [static]

Definition at line 839 of file papi_preset.c.

00839                                 {
00840     INTDBG("ENTER: in: %s, size: %zu\n", infix, strlen(infix));
00841     static char postfix[2*PAPI_HUGE_STR_LEN];   // output
00842         unsigned int index;
00843         int postfixlen;
00844         char token;
00845         if ( strlen(infix) > PAPI_HUGE_STR_LEN ) 
00846             PAPIERROR("A infix string (probably in user-defined presets) is too big (max allowed %d): %s", PAPI_HUGE_STR_LEN, infix );
00847 
00848         // initialize stack
00849     memset( &stack, 0, 2*PAPI_HUGE_STR_LEN );
00850     stacktop = -1; 
00851     push('#');
00852         /* initialize output string */
00853     memset(&postfix,0,2*PAPI_HUGE_STR_LEN);
00854         postfixlen = 0;
00855 
00856     for( index=0; index<strlen(infix); index++ ) {
00857                 token = infix[index];
00858                 INTDBG("INTDBG: in: %s, length: %zu, index: %d token %c\n", infix, strlen( infix ), index, token);
00859         switch( token ) {
00860         case '(':
00861             push( token );
00862             break;
00863         case ')':
00864                         if (postfix[postfixlen-1]!='|') postfix[postfixlen++] = '|';
00865                         while ( stack[stacktop] != '(' ) {
00866                                 postfix[postfixlen++] = pop();
00867                                 postfix[postfixlen++] = '|';
00868                         }
00869                         token = pop();  /* pop the '(' character */
00870             break;
00871         case '+':
00872         case '-':
00873         case '*':
00874         case '/':
00875         case '%':
00876         case '^':       /* if an operator */
00877                         if (postfix[postfixlen-1]!='|') postfix[postfixlen++] = '|';
00878                         while ( priority(stack[stacktop]) > priority(token) ) {
00879                                 postfix[postfixlen++] = pop();
00880                                 postfix[postfixlen++] = '|';
00881                         }
00882                         push( token ); /* save current operator */
00883                         break;
00884         default: // if alphanumeric character which is not parenthesis or an operator
00885                         postfix[postfixlen++] = token;
00886             break;
00887         } // end switch symbol
00888     } // end while
00889 
00890         /* Write any remaining operators */
00891         if (postfix[postfixlen-1]!='|') postfix[postfixlen++] = '|';
00892         while ( stacktop>0 ) {
00893                 postfix[postfixlen++] = pop();
00894                 postfix[postfixlen++] = '|';
00895         }
00896         postfix[postfixlen++] = '\0';
00897     stacktop = -1; 
00898 
00899     INTDBG("EXIT: postfix: %s, size: %zu\n", postfix, strlen(postfix));
00900     return (postfix);
00901 } // end infix_to_postfix

Here is the call graph for this function:

Here is the caller graph for this function:

static int is_event ( char *  event_name,
int  derived_type,
hwi_presets_t results,
int  token_index 
) [static]

Definition at line 739 of file papi_preset.c.

00739                                                                                       {
00740     INTDBG("ENTER: event_name: %p (%s), derived_type: %d, results: %p, token_index: %d\n", event_name, event_name, derived_type, results, token_index);
00741 
00742     /* check if its a preset event */
00743     if ( check_derived_events(event_name, derived_type, results, &_papi_hwi_presets[0], PAPI_MAX_PRESET_EVENTS, token_index) ) {
00744         INTDBG("EXIT: found preset event\n");
00745         return 1;
00746     }
00747 
00748     /* check if its a user defined event */
00749     if ( check_derived_events(event_name, derived_type, results, user_defined_events, user_defined_events_count, token_index) ) {
00750         INTDBG("EXIT: found user event\n");
00751         return 1;
00752     }
00753 
00754     /* check if its a native event */
00755     if ( check_native_events(event_name, results) ) {
00756         INTDBG("EXIT: found native event\n");
00757         return 1;
00758     }
00759 
00760     INTDBG("EXIT: event not found\n");
00761     return 0;
00762 }

Here is the call graph for this function:

Here is the caller graph for this function:

static FILE* open_event_table ( char *  name  )  [static]

Definition at line 246 of file papi_preset.c.

00247 {
00248     FILE *table;
00249 
00250     SUBDBG( "Opening %s\n", name );
00251     table = fopen( name, "r" );
00252     if ( table == NULL ) {
00253         SUBDBG( "Open %s failed, trying ./%s.\n", 
00254             name, PAPI_EVENT_FILE );
00255         sprintf( name, "%s", PAPI_EVENT_FILE );
00256         table = fopen( name, "r" );
00257     }
00258     if ( table == NULL ) {
00259         SUBDBG( "Open ./%s failed, trying ../%s.\n", 
00260             name, PAPI_EVENT_FILE );
00261         sprintf( name, "../%s", PAPI_EVENT_FILE );
00262         table = fopen( name, "r" );
00263     }
00264     if ( table ) {
00265         SUBDBG( "Open %s succeeded.\n", name );
00266     }
00267     return table;
00268 }

Here is the caller graph for this function:

static void ops_string_append ( hwi_presets_t results,
hwi_presets_t depends_on,
int  addition 
) [static]

Definition at line 363 of file papi_preset.c.

00363                                                                                    {
00364     INTDBG("ENTER: results: %p, depends_on: %p, addition %d\n", results, depends_on, addition);
00365 
00366     int i;
00367     int second_event = 0;
00368     char newFormula[PAPI_MIN_STR_LEN] = "";
00369     char work[20];
00370 
00371     // if our results already have a formula, start with what was collected so far
00372     // this should only happens when processing the second event of a new derived add
00373     if (results->postfix != NULL) {
00374         INTDBG("Event %s has existing formula %s\n", results->symbol, results->postfix);
00375         // get the existing formula
00376         strncat(newFormula, results->postfix, sizeof(newFormula)-1);
00377         newFormula[sizeof(newFormula)-1] = '\0';
00378         second_event = 1;
00379     }
00380 
00381     // process based on what kind of event the one we depend on is
00382     switch (depends_on->derived_int) {
00383         case DERIVED_POSTFIX: {
00384             // the event we depend on has a formula, append it our new events formula
00385 
00386             // if event we depend on does not have a formula, report error
00387             if (depends_on->postfix == NULL) {
00388                 INTDBG("Event %s is of type DERIVED_POSTFIX but is missing operation string\n", depends_on->symbol);
00389                 return;
00390             }
00391 
00392             // may need to renumber the native event index values in the depends on event formula before putting it into new derived event
00393             char *temp = papi_strdup(depends_on->postfix);
00394 
00395             // If this is not the first event of the new derived add, need to adjust native event index values in formula.
00396             // At this time we assume that all the native events in the second events formula are unique for the new event
00397             // and just bump the indexes by the number of events already known to the new event.  Later when we add the events
00398             // to the native event list for this new derived event, we will check to see if the native events are already known
00399             // to the new derived event and if so adjust the indexes again.
00400             if (second_event) {
00401                 for ( i=depends_on->count-1 ; i>=0 ; i--) {
00402                     update_ops_string(&temp, i, results->count + i);
00403                 }
00404             }
00405 
00406             // append the existing formula from the event we depend on (but get rid of last '|' character)
00407             strncat(newFormula, temp, sizeof(newFormula)-1);
00408             newFormula[sizeof(newFormula)-1] = '\0';
00409             papi_free (temp);
00410             break;
00411         }
00412         case DERIVED_ADD: {
00413             // the event we depend on has no formula, create a formula for our new event to add together the depends_on native event values
00414 
00415             // build a formula for this add event
00416             sprintf(work, "N%d|N%d|+|", results->count, results->count + 1);
00417             strcat(newFormula, work);
00418             break;
00419         }
00420         case DERIVED_SUB: {
00421             // the event we depend on has no formula, create a formula for our new event to subtract the depends_on native event values
00422 
00423             // build a formula for this subtract event
00424             sprintf(work, "N%d|N%d|-|", results->count, results->count + 1);
00425             strcat(newFormula, work);
00426             break;
00427         }
00428         case NOT_DERIVED: {
00429             // the event we depend on has no formula and is itself only based on one native event, create a formula for our new event to include this native event
00430 
00431             // build a formula for this subtract event
00432             sprintf(work, "N%d|", results->count);
00433             strcat(newFormula, work);
00434             break;
00435         }
00436         default: {
00437             // the event we depend on has unsupported derived type, put out some debug and give up
00438             INTDBG("Event %s depends on event %s which has an unsupported derived type of %d\n", results->symbol, depends_on->symbol, depends_on->derived_int);
00439             return;
00440         }
00441     }
00442 
00443     // if this was the second event, append to the formula an operation to add or subtract the results of the two events
00444     if (second_event) {
00445         if (addition != 0) {
00446             strcat(newFormula, "+|");
00447         } else {
00448             strcat(newFormula, "-|");
00449         }
00450         // also change the new derived events type to show it has a formula now
00451         results->derived_int = DERIVED_POSTFIX;
00452     }
00453 
00454     // we need to free the existing space (created by malloc and we need to create a new one)
00455     papi_free (results->postfix);
00456     results->postfix = papi_strdup(newFormula);
00457     INTDBG("EXIT: newFormula: %s\n", newFormula);
00458     return;
00459 }

Here is the call graph for this function:

Here is the caller graph for this function:

static void ops_string_merge ( char **  original,
char *  insertion,
int  replaces,
int  start_index 
) [static]

Definition at line 464 of file papi_preset.c.

00464                                                                                   {
00465     INTDBG("ENTER: original: %p, *original: %s, insertion: %s, replaces: %d, start_index: %d\n", original, *original, insertion, replaces, start_index);
00466 
00467     int orig_len=0;
00468     int ins_len=0;
00469     char *subtoken;
00470     char *workBuf;
00471     char *workPtr;
00472     char *tok_save_ptr=NULL;
00473     char *newOriginal;
00474     char *newInsertion;
00475     char *newFormula;
00476     int insert_events;
00477 
00478     if (*original != NULL) {
00479         orig_len = strlen(*original);
00480     }
00481     if (insertion != NULL) {
00482         ins_len = strlen(insertion);
00483     }
00484     newFormula = papi_calloc (orig_len + ins_len + 40, 1);
00485 
00486     // if insertion formula is not provided, then the original formula remains basically unchanged.
00487     if (insertion == NULL) {
00488         // if the original formula has a leading '|' then get rid of it
00489         workPtr = *original;
00490         if (workPtr[0] == '|') {
00491             strcpy(newFormula, &workPtr[1]);
00492         } else {
00493             strcpy(newFormula, workPtr);
00494         }
00495         // formula fields are always malloced space so free the previous one
00496         papi_free (*original);
00497         *original = newFormula;
00498         INTDBG("EXIT: newFormula: %s\n", *original);
00499         return;
00500     }
00501 
00502     // renumber the token numbers in the insertion formula
00503     // also count how many native events are used in this formula
00504     insert_events = 0;
00505     newInsertion = papi_calloc(ins_len+20, 1);
00506     workBuf = papi_calloc(ins_len+10, 1);
00507     workPtr = papi_strdup(insertion);
00508     subtoken = strtok_r(workPtr, "|", &tok_save_ptr);
00509     while ( subtoken != NULL) {
00510 //      INTDBG("subtoken: %s, newInsertion: %s\n", subtoken, newInsertion);
00511         if ((subtoken[0] == 'N')  &&  (isdigit(subtoken[1]))) {
00512             insert_events++;
00513             int val = atoi(&subtoken[1]);
00514             val += start_index;
00515             subtoken[1] = '\0';
00516             sprintf (workBuf, "N%d", val);
00517         } else {
00518             strcpy(workBuf, subtoken);
00519         }
00520         strcat (newInsertion, workBuf);
00521         strcat (newInsertion, "|");
00522         subtoken = strtok_r(NULL, "|", &tok_save_ptr);
00523     }
00524     papi_free (workBuf);
00525     papi_free (workPtr);
00526     INTDBG("newInsertion: %s\n", newInsertion);
00527 
00528     // if original formula is not provided, then the updated insertion formula becomes the new formula
00529     // but we still had to renumber the native event tokens in case another native event was put into the list first
00530     if (*original == NULL) {
00531         *original = papi_strdup(newInsertion);
00532         INTDBG("EXIT: newFormula: %s\n", newInsertion);
00533         papi_free (newInsertion);
00534         papi_free (newFormula);
00535         return;
00536     }
00537 
00538     // if token to replace not valid, return null  (do we also need to check an upper bound ???)
00539     if ((replaces < 0)) {
00540         papi_free (newInsertion);
00541         papi_free (newFormula);
00542         INTDBG("EXIT: Invalid value for token in original formula to be replaced\n");
00543         return;
00544     }
00545 
00546     // renumber the token numbers in the original formula
00547     // tokens with an index greater than the replaces token need to be incremented by number of events in insertion formula-1
00548     newOriginal = papi_calloc (orig_len+20, 1);
00549     workBuf = papi_calloc(orig_len+10, 1);
00550     workPtr = papi_strdup(*original);
00551 
00552     subtoken = strtok_r(workPtr, "|", &tok_save_ptr);
00553     while ( subtoken != NULL) {
00554 //      INTDBG("subtoken: %s, newOriginal: %s\n", subtoken, newOriginal);
00555         // prime the work area with the next token, then see if we need to change it
00556         strcpy(workBuf, subtoken);
00557         if ((subtoken[0] == 'N')  &&  (isdigit(subtoken[1]))) {
00558             int val = atoi(&subtoken[1]);
00559             if (val > replaces) {
00560                 val += insert_events-1;
00561                 subtoken[1] = '\0';
00562                 sprintf (workBuf, "N%d", val);
00563             }
00564         }
00565         // put the work buffer into the new original formula
00566         strcat (newOriginal, workBuf);
00567         strcat (newOriginal, "|");
00568         subtoken = strtok_r(NULL, "|", &tok_save_ptr);
00569     }
00570     papi_free (workBuf);
00571     papi_free (workPtr);
00572     INTDBG("newOriginal: %s\n", newOriginal);
00573 
00574     // replace the specified "replace" tokens in the new original formula with the new insertion formula
00575     newFormula[0] = '\0';
00576     workPtr = newOriginal;
00577     subtoken = strtok_r(workPtr, "|", &tok_save_ptr);
00578     while ( subtoken != NULL) {
00579 //      INTDBG("subtoken: %s, newFormula: %s\n", subtoken, newFormula);
00580         // if this is the token we want to replace with the insertion string, do it now
00581         if ((subtoken[0] == 'N')  &&  (isdigit(subtoken[1]))  &&  (replaces == atoi(&subtoken[1]))) {
00582             // copy updated insertion string into the original string (replacing this token)
00583             strcat(newFormula, newInsertion);
00584         } else {
00585             // copy this part of the original formula into the new formula
00586             strcat(newFormula, subtoken);
00587             strcat(newFormula, "|");
00588         }
00589         subtoken = strtok_r(NULL, "|", &tok_save_ptr);
00590     }
00591     papi_free (newInsertion);
00592     papi_free (workPtr);
00593 
00594     // formula fields are always malloced space so free the previous one
00595     papi_free (*original);
00596     *original = newFormula;
00597     INTDBG("EXIT: newFormula: %s\n", newFormula);
00598     return;
00599 }

Here is the call graph for this function:

Here is the caller graph for this function:

static int papi_load_derived_events ( char *  pmu_str,
int  pmu_type,
int  cidx,
int  preset_flag 
) [static]

Definition at line 946 of file papi_preset.c.

00946                                                                                   {
00947     SUBDBG( "ENTER: pmu_str: %s, pmu_type: %d, cidx: %d, preset_flag: %d\n", pmu_str, pmu_type, cidx, preset_flag);
00948 
00949     char pmu_name[PAPI_MIN_STR_LEN];
00950     char line[LINE_MAX];
00951     char name[PATH_MAX] = "builtin papi_events_table";
00952     char *event_file_path=NULL;
00953     char *event_table_ptr=NULL;
00954     int event_type_bits = 0;
00955     char *tmpn;
00956     char *tok_save_ptr=NULL;
00957     FILE *event_file = NULL;
00958     hwi_presets_t *results=NULL;
00959     int result_size = 0;
00960     int *event_count = NULL;
00961     int invalid_event;
00962     int line_no = 0;  /* count of lines read from event definition input */
00963     int derived = 0;
00964     int res_idx = 0;  /* index into results array for where to store next event */
00965     int preset = 0;
00966     int get_events = 0; /* only process derived events after CPU type they apply to is identified      */
00967     int found_events = 0; /* flag to track if event definitions (PRESETS) are found since last CPU declaration */
00968 #ifdef PAPI_DATADIR
00969         char path[PATH_MAX];
00970 #endif
00971 
00972 
00973     if (preset_flag) {
00974         /* try the environment variable first */
00975         if ((tmpn = getenv("PAPI_CSV_EVENT_FILE")) && (strlen(tmpn) > 0)) {
00976             event_file_path = tmpn;
00977         }
00978         /* if no valid environment variable, look for built-in table */
00979         else if (papi_events_table) {
00980             event_table_ptr = papi_events_table;
00981         }
00982         /* if no env var and no built-in, search for default file */
00983         else {
00984 #ifdef PAPI_DATADIR
00985             sprintf( path, "%s/%s", PAPI_DATADIR, PAPI_EVENT_FILE );
00986             event_file_path = path;
00987 #else
00988             event_file_path = PAPI_EVENT_FILE;
00989 #endif
00990         }
00991         event_type_bits = PAPI_PRESET_MASK;
00992         results = &_papi_hwi_presets[0];
00993         result_size = PAPI_MAX_PRESET_EVENTS;
00994         event_count = &_papi_hwd[cidx]->cmp_info.num_preset_events;
00995     } else {
00996         if ((event_file_path = getenv( "PAPI_USER_EVENTS_FILE" )) == NULL ) {
00997             SUBDBG("EXIT: User event definition file not provided.\n");
00998             return PAPI_OK;
00999         }
01000 
01001         event_type_bits = PAPI_UE_MASK;
01002         results = &user_defined_events[0];
01003         result_size = PAPI_MAX_USER_EVENTS;
01004         event_count = &user_defined_events_count;
01005     }
01006 
01007     // if we have an event file pathname, open it and read event definitions from the file
01008     if (event_file_path != NULL) {
01009         if ((event_file = open_event_table(event_file_path)) == NULL) {
01010             // if file open fails, return an error
01011             SUBDBG("EXIT: Event file open failed.\n");
01012             return PAPI_ESYS;
01013         }
01014         strncpy(name, event_file_path, sizeof(name)-1);
01015         name[sizeof(name)-1] = '\0';
01016     } else if (event_table_ptr == NULL) {
01017         // if we do not have a path name or table pointer, return an error
01018         SUBDBG("EXIT: Both event_file_path and event_table_ptr are NULL.\n");
01019         return PAPI_ESYS;
01020     }
01021 
01022     /* copy the pmu identifier, stripping commas if found */
01023     tmpn = pmu_name;
01024     while (*pmu_str) {
01025         if (*pmu_str != ',')
01026             *tmpn++ = *pmu_str;
01027         pmu_str++;
01028     }
01029     *tmpn = '\0';
01030 
01031     /* at this point we have either a valid file pointer or built-in table pointer */
01032     while (get_event_line(line, event_file, &event_table_ptr)) {
01033         char *t;
01034         int i;
01035 
01036         // increment number of lines we have read
01037         line_no++;
01038 
01039         t = trim_string(strtok_r(line, ",", &tok_save_ptr));
01040 
01041         /* Skip blank lines */
01042         if ((t == NULL) || (strlen(t) == 0))
01043             continue;
01044 
01045         /* Skip comments */
01046         if (t[0] == '#') {
01047             continue;
01048         }
01049 
01050         if (strcasecmp(t, "CPU") == 0) {
01051             if (get_events != 0 && found_events != 0) {
01052                 SUBDBG( "Ending event scanning at line %d of %s.\n", line_no, name);
01053                 get_events = 0;
01054                 found_events = 0;
01055             }
01056 
01057             t = trim_string(strtok_r(NULL, ",", &tok_save_ptr));
01058             if ((t == NULL) || (strlen(t) == 0)) {
01059                 PAPIERROR("Expected name after CPU token at line %d of %s -- ignoring", line_no, name);
01060                 continue;
01061             }
01062 
01063             if (strcasecmp(t, pmu_name) == 0) {
01064                 int type;
01065 
01066                 SUBDBG( "Process events for PMU %s found at line %d of %s.\n", t, line_no, name);
01067 
01068                 t = trim_string(strtok_r(NULL, ",", &tok_save_ptr));
01069                 if ((t == NULL) || (strlen(t) == 0)) {
01070                     SUBDBG("No additional qualifier found, matching on string.\n");
01071                     get_events = 1;
01072                 } else if ((sscanf(t, "%d", &type) == 1) && (type == pmu_type)) {
01073                     SUBDBG( "Found CPU %s type %d at line %d of %s.\n", pmu_name, type, line_no, name);
01074                     get_events = 1;
01075                 } else {
01076                     SUBDBG( "Additional qualifier match failed %d vs %d.\n", pmu_type, type);
01077                 }
01078             }
01079             continue;
01080         }
01081 
01082         if ((strcasecmp(t, "PRESET") == 0)  || (strcasecmp(t, "EVENT") == 0)) {
01083 
01084             if (get_events == 0)
01085                 continue;
01086 
01087             found_events = 1;
01088             t = trim_string(strtok_r(NULL, ",", &tok_save_ptr));
01089 
01090             if ((t == NULL) || (strlen(t) == 0)) {
01091                 PAPIERROR("Expected name after PRESET token at line %d of %s -- ignoring", line_no, name);
01092                 continue;
01093             }
01094 
01095             SUBDBG( "Examining event %s\n", t);
01096 
01097             // see if this event already exists in the results array, if not already known it sets up event in unused entry
01098             if ((res_idx = find_event_index (results, result_size, t)) < 0) {
01099                 PAPIERROR("No room left for event %s -- ignoring", t);
01100                 continue;
01101             }
01102 
01103             // add the proper event bits (preset or user defined bits)
01104             preset = res_idx | event_type_bits;
01105 
01106             SUBDBG( "Use event code: %#x for %s\n", preset, t);
01107 
01108             t = trim_string(strtok_r(NULL, ",", &tok_save_ptr));
01109             if ((t == NULL) || (strlen(t) == 0)) {
01110                 // got an error, make this entry unused
01111                 papi_free (results[res_idx].symbol);
01112                 results[res_idx].symbol = NULL;
01113                 PAPIERROR("Expected derived type after PRESET token at line %d of %s -- ignoring", line_no, name);
01114                 continue;
01115             }
01116 
01117             if (_papi_hwi_derived_type(t, &derived) != PAPI_OK) {
01118                 // got an error, make this entry unused
01119                 papi_free (results[res_idx].symbol);
01120                 results[res_idx].symbol = NULL;
01121                 PAPIERROR("Invalid derived name %s after PRESET token at line %d of %s -- ignoring", t, line_no, name);
01122                 continue;
01123             }
01124 
01125             /****************************************/
01126             /* Have an event, let's start assigning */
01127             /****************************************/
01128 
01129             SUBDBG( "Adding event: %s, code: %#x, derived: %d results[%d]: %p.\n", t, preset, derived, res_idx, &results[res_idx]);
01130 
01131             /* results[res_idx].event_code = preset; */
01132             results[res_idx].derived_int = derived;
01133 
01134             /* Derived support starts here */
01135             /* Special handling for postfix and infix */
01136             if ((derived == DERIVED_POSTFIX)  || (derived == DERIVED_INFIX)) {
01137                 t = trim_string(strtok_r(NULL, ",", &tok_save_ptr));
01138                 if ((t == NULL) || (strlen(t) == 0)) {
01139                     // got an error, make this entry unused
01140                     papi_free (results[res_idx].symbol);
01141                     results[res_idx].symbol = NULL;
01142                     PAPIERROR("Expected Operation string after derived type DERIVED_POSTFIX or DERIVED_INFIX at line %d of %s -- ignoring", line_no, name);
01143                     continue;
01144                 }
01145 
01146                 // if it is an algebraic formula, we need to convert it to postfix
01147                 if (derived == DERIVED_INFIX) {
01148                     SUBDBG( "Converting InFix operations %s\n", t);
01149                     t = infix_to_postfix( t );
01150                     results[res_idx].derived_int = DERIVED_POSTFIX;
01151                 }
01152 
01153                 SUBDBG( "Saving PostFix operations %s\n", t);
01154                 results[res_idx].postfix = papi_strdup(t);
01155             }
01156 
01157             /* All derived terms collected here */
01158             i = 0;
01159             invalid_event = 0;
01160             results[res_idx].count = 0;
01161             do {
01162                 t = trim_string(strtok_r(NULL, ",", &tok_save_ptr));
01163                 if ((t == NULL) || (strlen(t) == 0))
01164                     break;
01165                 if (strcasecmp(t, "NOTE") == 0)
01166                     break;
01167                 if (strcasecmp(t, "LDESC") == 0)
01168                     break;
01169                 if (strcasecmp(t, "SDESC") == 0)
01170                     break;
01171 
01172                 SUBDBG( "Adding term (%d) %s to derived event %#x, current native event count: %d.\n", i, t, preset, results[res_idx].count);
01173 
01174                 // show that we do not have an event code yet (the component may create one and update this info)
01175                 // this also clears any values left over from a previous call
01176                 _papi_hwi_set_papi_event_code(-1, -1);
01177 
01178                 // make sure that this term in the derived event is a valid event name
01179                 // this call replaces preset and user event names with the equivalent native events in our results table
01180                 // it also updates formulas for derived events so that they refer to the correct native event index
01181                 if (is_event(t, results[res_idx].derived_int, &results[res_idx], i) == 0) {
01182                     invalid_event = 1;
01183                     PAPIERROR("Error finding event %s, it is used in derived event %s", t, results[res_idx].symbol);
01184                     break;
01185                 }
01186 
01187                 i++;
01188             } while (results[res_idx].count < PAPI_EVENTS_IN_DERIVED_EVENT);
01189 
01190             /* preset code list must be PAPI_NULL terminated */
01191             if (i < PAPI_EVENTS_IN_DERIVED_EVENT) {
01192                 results[res_idx].code[results[res_idx].count] = PAPI_NULL;
01193             }
01194 
01195             if (invalid_event) {
01196                 // got an error, make this entry unused
01197                 papi_free (results[res_idx].symbol);
01198                 results[res_idx].symbol = NULL;
01199                 continue;
01200             }
01201 
01202             /* End of derived support */
01203 
01204             // if we did not find any terms to base this derived event on, report error
01205             if (i == 0) {
01206                 // got an error, make this entry unused
01207                 papi_free (results[res_idx].symbol);
01208                 results[res_idx].symbol = NULL;
01209                 PAPIERROR("Expected PFM event after DERIVED token at line %d of %s -- ignoring", line_no, name);
01210                 continue;
01211             }
01212 
01213             if (i == PAPI_EVENTS_IN_DERIVED_EVENT) {
01214                 t = trim_string(strtok_r(NULL, ",", &tok_save_ptr));
01215             }
01216 
01217             // if something was provided following the list of events to be used by the operation, process it
01218             if ( t!= NULL  && strlen(t) > 0 ) {
01219                 do {
01220                     // save the field name
01221                     char *fptr = papi_strdup(t);
01222 
01223                     // get the value to be used with this field
01224                     t = trim_note(strtok_r(NULL, ",", &tok_save_ptr));
01225                     if ( t== NULL  || strlen(t) == 0 ) {
01226                         papi_free(fptr);
01227                         break;
01228                     }
01229 
01230                     // Handle optional short descriptions, long descriptions and notes
01231                     if (strcasecmp(fptr, "SDESC") == 0) {
01232                         results[res_idx].short_descr = papi_strdup(t);
01233                     }
01234                     if (strcasecmp(fptr, "LDESC") == 0) {
01235                         results[res_idx].long_descr = papi_strdup(t);
01236                     }
01237                     if (strcasecmp(fptr, "NOTE") == 0) {
01238                         results[res_idx].note = papi_strdup(t);
01239                     }
01240 
01241                     SUBDBG( "Found %s (%s) on line %d\n", fptr, t, line_no);
01242                     papi_free (fptr);
01243 
01244                     // look for another field name
01245                     t = trim_string(strtok_r(NULL, ",", &tok_save_ptr));
01246                     if ( t== NULL  || strlen(t) == 0 ) {
01247                         break;
01248                     }
01249                 } while (t != NULL);
01250             }
01251             (*event_count)++;
01252             continue;
01253         }
01254 
01255         PAPIERROR("Unrecognized token %s at line %d of %s -- ignoring", t, line_no, name);
01256     }
01257 
01258     if (event_file) {
01259         fclose(event_file);
01260     }
01261 
01262     SUBDBG("EXIT: Done processing derived event file.\n");
01263     return PAPI_OK;
01264 }

Here is the call graph for this function:

Here is the caller graph for this function:

static char pop (  )  [static]

Definition at line 826 of file papi_preset.c.

00826            {
00827         if( stacktop < 0 ) {
00828                 INTDBG("EXIT: Stack Underflow converting Algebraic Expression:%d\n", stacktop );
00829                 return '\0';  //***TODO: Figure out how to exit gracefully
00830         } // end if empty
00831         return( stack[stacktop--] );
00832 } // end pop

Here is the caller graph for this function:

static int priority ( char  symbol  )  [static]

Definition at line 796 of file papi_preset.c.

00796                             {
00797         switch( symbol ) {
00798         case '@':
00799                 return -1;
00800         case '(':
00801                 return 0;
00802     case '+':
00803     case '-':
00804                 return 1;
00805     case '*':
00806     case '/':
00807     case '%':
00808         return 2;
00809     default :
00810         return 0;
00811     } // end switch symbol
00812 } // end priority

Here is the caller graph for this function:

static int push ( char  symbol  )  [static]

Definition at line 815 of file papi_preset.c.

00815                         {
00816         if( stacktop >= (PAPI_HUGE_STR_LEN - 1) ) {
00817                 INTDBG("EXIT: Stack Overflow converting Algebraic Expression:%d\n", stacktop );
00818                 return -1;  //***TODO: Figure out how to exit gracefully
00819   } // end if stacktop>MAX
00820         stack[++stacktop] = symbol;
00821         return 0;
00822 } // end push

Here is the caller graph for this function:

static char* trim_note ( char *  in  )  [inline, static]

Definition at line 197 of file papi_preset.c.

00198 {
00199     int len;
00200     char *note, start, end;
00201 
00202     note = trim_string( in );
00203     if ( note != NULL ) {
00204                 len = ( int ) strlen( note );
00205         if ( len > 0 ) {
00206             if ( ispunct( *note ) ) {
00207                 start = *note;
00208                 end = note[len - 1];
00209                 if ( ( start == end )
00210                      || ( ( start == '(' ) && ( end == ')' ) )
00211                      || ( ( start == '<' ) && ( end == '>' ) )
00212                      || ( ( start == '{' ) && ( end == '}' ) )
00213                      || ( ( start == '[' ) && ( end == ']' ) ) ) {
00214                     note[len - 1] = '\0';
00215                     *note = '\0';
00216                     note++;
00217                 }
00218             }
00219         }
00220     }
00221     return note;
00222 }

Here is the call graph for this function:

Here is the caller graph for this function:

static char* trim_string ( char *  in  )  [inline, static]

Definition at line 157 of file papi_preset.c.

00158 {
00159     int len, i = 0;
00160     char *start = in;
00161 
00162     if ( in == NULL )
00163         return ( in );
00164     len = ( int ) strlen( in );
00165     if ( len == 0 )
00166         return ( in );
00167 
00168     /* Trim left */
00169     while ( i < len ) {
00170         if ( isblank( in[i] ) ) {
00171             in[i] = '\0';
00172             start++;
00173         } else
00174             break;
00175         i++;
00176     }
00177 
00178     /* Trim right */
00179     i = ( int ) strlen( start ) - 1;
00180     while ( i >= 0 ) {
00181         if ( isblank( start[i] ) )
00182             start[i] = '\0';
00183         else
00184             break;
00185         i--;
00186     }
00187     return ( start );
00188 }

Here is the caller graph for this function:

static void update_ops_string ( char **  formula,
int  old_index,
int  new_index 
) [static]

Definition at line 304 of file papi_preset.c.

00304                                                                 {
00305     INTDBG("ENTER:   *formula: %s, old_index: %d, new_index: %d\n", *formula?*formula:"NULL", old_index, new_index);
00306 
00307     int cur_index;
00308     char *newFormula;
00309     char *subtoken;
00310     char *tok_save_ptr=NULL;
00311 
00312     // if formula is null just return
00313     if (*formula == NULL) {
00314         INTDBG("EXIT: Null pointer to formula passed in\n");
00315         return;
00316     }
00317 
00318     // get some space for the new formula we are going to create
00319     newFormula = papi_calloc(strlen(*formula) + 20, 1);
00320 
00321     // replace the specified "replace" tokens in the new original formula with the new insertion formula
00322     newFormula[0] = '\0';
00323     subtoken = strtok_r(*formula, "|", &tok_save_ptr);
00324     while ( subtoken != NULL) {
00325 //      INTDBG("subtoken: %s, newFormula: %s\n", subtoken, newFormula);
00326         char work[10];
00327         // if this is the token we want to replace with the new token index, do it now
00328         if ((subtoken[0] == 'N')  &&  (isdigit(subtoken[1]))) {
00329             cur_index = atoi(&subtoken[1]);
00330             // if matches old index, use the new one
00331             if (cur_index == old_index) {
00332                 sprintf (work, "N%d", new_index);
00333                 strcat (newFormula, work);
00334             } else if (cur_index > old_index) {
00335                 // current token greater than old index, make it one less than what it was
00336                 sprintf (work, "N%d", cur_index-1);
00337                 strcat (newFormula, work);
00338             } else {
00339                 // current token less than old index, copy this part of the original formula into the new formula
00340                 strcat(newFormula, subtoken);
00341             }
00342         } else {
00343             // copy this part of the original formula into the new formula
00344             strcat(newFormula, subtoken);
00345         }
00346         strcat (newFormula, "|");
00347         subtoken = strtok_r(NULL, "|", &tok_save_ptr);
00348     }
00349     papi_free (*formula);
00350     *formula = newFormula;
00351 
00352     INTDBG("EXIT: newFormula: %s\n", newFormula);
00353     return;
00354 }

Here is the call graph for this function:

Here is the caller graph for this function:


Variable Documentation

char* papi_events_table = NULL [static]

Definition at line 768 of file papi_preset.c.

char stack[PAPI_HUGE_STR_LEN] [static]

Definition at line 791 of file papi_preset.c.

int stacktop = -1 [static]

Definition at line 792 of file papi_preset.c.

Definition at line 58 of file papi_internal.c.

Definition at line 59 of file papi_internal.c.


Generated on 26 Jan 2016 for PAPI by  doxygen 1.6.1