Performance-Monitoring Counters Library, for Intel/AMD Processors and Linux
This example introduces
   pmc_events.h        -- symbolic names of event codes
   pmc_event_set_t     -- events for concurrent measurement
   pmc_event_label_t   -- textual description of an event set
   pmc_event_counters  -- number of event counters in a set
   pmc_event_valid()
   pmc_event_name()
   pmc_event_description()

Previous example       -- pmc_getargs()
Download this example
Next example           -- Pentium Pro/II/III events
Return to Main Menu


For a Pentium Pro/II/III, compile with gcc -o menu3 -O `pmc_options` menu3.c -lpmc Try these examples: menu3 rabbit -l | tr a-z A-Z
#include <pmc_lib.h> int main(int argc, char * argv[]) { int i, j; pmc_control_t Ctl = pmc_control_null; pmc_event_set_t Event[3] = { /* initialize event sets */ {DATA_MEM_REFS, BUS_TRAN_MEM}, /* symbols defined in pmc_events.a */ {INST_RETIRED, UOPS_RETIRED}, {MUL, DIV} }; pmc_event_label_t Label[3] = { /* initialize event set labels */ "Fraction of memory references that cause bus transactions", "Micro-operations per instruction", "Floating-point operations" }; /* required, to initialize internal event tables */ if (pmc_getargs(stderr, argv[0], NULL, NULL, &Ctl) == FALSE) { exit(1); } Event[0][0] = DATA_MEM_REFS; /* assign event sets */ Event[0][1] = BUS_TRAN_MEM; Event[1][0] = INST_RETIRED; Event[1][1] = UOPS_RETIRED; Event[2][0] = MUL; Event[2][1] = DIV; /* pmc_control_t components used by pmc_counter_init() */ Ctl.event[0] = Event[0][0]; Ctl.event[1] = Event[0][1]; #if 0 Ctl.event = Event[0]; /* gcc: "incompatible types in assignment" */ #endif /* pmc_control_t list of event sets used by pmc_print_results() */ Ctl.event_pairs = 3; Ctl.events = Event; Ctl.labels = Label; for (i = 0; i < 3; i++) /* event set i */ for (j = 0; j < pmc_event_counters; j++) /* event j in set i */ { int event = Event[i][j]; if (pmc_event_valid(event,j)) /* valid for counter j? */ { printf("0x%2x %3d %s\n" " %s\n", event, event, pmc_event_name(event,j), pmc_event_description(event,j) ); } else { printf("0x%2x %3d not valid for counter %d\n", event, event, j); } } exit(0); }
Synopsis #include <pmc_events.h> #define pmc_event_counters 2 /* 2 with Intel; 4 with AMD Athlon */ typedef int pmc_event_set_t[pmc_event_counters]; typedef char pmc_event_label_t[PMC_STRING]; int pmc_event_valid(const int code, const int counter); const char * pmc_event_name(const int code, const int counter); const char * pmc_event_description(const int code, const int counter);
The processor allows pmc_event_counters events to be counted concurrently. In the pmc_control_t data structure, each pmc_event_set_t has a corresponding pmc_event_label_t used by pmc_print_results(). Each event that can be counted by the hardware has a processor-dependent numeric code, that is most easily obtained from 'rabbit -c'. The symbolic names of the events are given in pmc_events.h, which is included by pmc_lib.h. The functions pmc_event_name() and pmc_event_description() return pointers to the [mostly lower case] symbolic name and description strings. Some events are only valid in one counter, such as the MUL and DIV events above. This is indicated by the description, and checked by pmc_getargs(). If you are uncertain whether event code n is valid, try 'rabbit --e n -c'. pmc_event_valid() returns FALSE if the event code is not valid for the indicated counter.
The output for this example is 0x43 67 data_mem_refs L1 d-cache, all memory references, both cacheable and non-cacheable 0x6f 111 bus_tran_mem external bus, memory transactions (--bus_agent) 0xc0 192 inst_retired instruction decode and retire unit, instructions retired 0xc2 194 uops_retired instruction decode and retire unit, micro-operations retired 0x12 18 not valid for counter 0 0x13 19 div floating-point unit, FP divides (counter 1 only)
Forward References pmc_counter_init() pmc_print_results()

Performance-Monitoring Counters Library, for Intel/AMD Processors and Linux
Author: Don Heller, dheller@scl.ameslab.gov
Last revised: 2 August 2000