1 #ifdef USE_PAPI /* ugly */
10 /* These constants specify which events to keep track of.
11 * Probably it is better to count one set of events at a time.
12 * The reason is that processors have limited counters and
13 * multiplexing is not enabled (yet).
15 #define PAPI_COUNT_BRANCHES 0
16 /* The one below is Opteron specific.
18 #define PAPI_COUNT_STALLS 0
19 #define PAPI_COUNT_DCACHE1_MISSES 1
20 #define PAPI_COUNT_DCACHE2_MISSES 0
27 #define PAPI_ADD_EVENT(EVENT) \
29 ASSERT(n_papi_events<MAX_PAPI_EVENTS); \
30 papi_events[n_papi_events].event_code = EVENT; \
31 papi_events[n_papi_events].event_name = #EVENT; \
35 /* Beware, these counters are Opteron specific */
36 #define FR_BR 0x40000040
37 #define FR_BR_MIS 0x40000041
38 #define FR_BR_MISCOMPARE 0x40000048
39 #define DC_ACCESS 0x40000019
40 #define DC_MISS 0x4000001a
41 #define FR_DISPATCH_STALLS_BR 0x40000055
42 #define FR_DISPATCH_STALLS_FULL_LS 0x4000005b
44 /* Report the value of a counter */
45 #define PAPI_REPORT(EVENTSET,EVENT) \
47 ullong_format_string(papi_counter(EVENTSET,EVENT),temp,rtsTrue/*commas*/); \
48 statsPrintf(" (" #EVENT ") : %s\n",temp); \
51 /* Report the value of a counter as a percentage of another counter */
52 #define PAPI_REPORT_PCT(EVENTSET,EVENT,EVENTTOT) \
53 statsPrintf(" (" #EVENT ") %% of (" #EVENTTOT ") : %.1f%%\n", \
54 papi_counter(EVENTSET,EVENT)*100.0/papi_counter(EVENTSET,EVENTTOT))
56 /* Number of counted events, computed from size of papi_events */
57 #define N_PAPI_EVENTS n_papi_events
59 /* This is bad, it should be in a header */
60 #define BIG_STRING_LEN 512
62 /* While PAPI reporting is going on this flag is on */
63 int papi_is_reporting;
65 /* Event sets and counter arrays for GC and mutator */
67 int MutatorEvents = PAPI_NULL;
68 int GCEvents = PAPI_NULL;
72 /* Arbitrary, to avoid using malloc */
73 #define MAX_PAPI_EVENTS 10
75 int n_papi_events = 0;
77 /* If you want to add events to count, extend the
78 * papi_events array and the papi_report function.
81 /* Events counted during GC and Mutator execution */
82 /* There's a trailing comma, do all C compilers accept that? */
83 static struct _papi_events papi_events[MAX_PAPI_EVENTS];
86 init_countable_events(void)
88 PAPI_ADD_EVENT(PAPI_TOT_CYC);
89 if(RtsFlags.PapiFlags.eventType==PAPI_FLAG_BRANCH) {
90 PAPI_ADD_EVENT(FR_BR);
91 PAPI_ADD_EVENT(FR_BR_MIS);
92 /* Docs are wrong? Opteron does not count indirect branch misses exclusively */
93 PAPI_ADD_EVENT(FR_BR_MISCOMPARE);
95 if(RtsFlags.PapiFlags.eventType==PAPI_FLAG_STALLS) {
96 PAPI_ADD_EVENT(FR_DISPATCH_STALLS_BR);
97 PAPI_ADD_EVENT(FR_DISPATCH_STALLS_FULL_LS);
99 if(RtsFlags.PapiFlags.eventType==PAPI_FLAG_CACHE_L1) {
100 PAPI_ADD_EVENT(PAPI_L1_DCA);
101 PAPI_ADD_EVENT(PAPI_L1_DCM);
103 if(RtsFlags.PapiFlags.eventType==PAPI_FLAG_CACHE_L2) {
104 PAPI_ADD_EVENT(PAPI_L2_DCA);
105 PAPI_ADD_EVENT(PAPI_L2_DCM);
109 long_long MutatorCounters[MAX_PAPI_EVENTS];
110 long_long GCCounters[MAX_PAPI_EVENTS];
113 /* Extract the value corresponding to an event */
115 papi_counter(long_long values[],int event)
118 for(i=0;i<N_PAPI_EVENTS;i++) {
119 if(papi_events[i].event_code==event) {
123 /* Passed a wrong event? */
124 debugBelch("Event %d is not part of event set\n",event);
128 /* This function reports counters for GC and mutator */
130 papi_report(long_long PapiCounters[])
132 char temp[BIG_STRING_LEN];
134 /* I need to improve formatting aesthetics */
135 PAPI_REPORT(PapiCounters,PAPI_TOT_CYC);
136 if(RtsFlags.PapiFlags.eventType==PAPI_FLAG_BRANCH) {
137 PAPI_REPORT(PapiCounters,FR_BR);
138 PAPI_REPORT(PapiCounters,FR_BR_MIS);
139 PAPI_REPORT_PCT(PapiCounters,FR_BR_MIS,FR_BR);
140 PAPI_REPORT_PCT(PapiCounters,FR_BR_MISCOMPARE,FR_BR);
143 if(RtsFlags.PapiFlags.eventType==PAPI_FLAG_STALLS) {
144 PAPI_REPORT(PapiCounters,FR_DISPATCH_STALLS_BR);
145 PAPI_REPORT_PCT(PapiCounters,FR_DISPATCH_STALLS_BR,PAPI_TOT_CYC);
146 PAPI_REPORT(PapiCounters,FR_DISPATCH_STALLS_FULL_LS);
147 PAPI_REPORT_PCT(PapiCounters,FR_DISPATCH_STALLS_FULL_LS,PAPI_TOT_CYC);
150 if(RtsFlags.PapiFlags.eventType==PAPI_FLAG_CACHE_L1) {
151 PAPI_REPORT(PapiCounters,PAPI_L1_DCA);
152 PAPI_REPORT(PapiCounters,PAPI_L1_DCM);
153 PAPI_REPORT_PCT(PapiCounters,PAPI_L1_DCM,PAPI_L1_DCA);
156 if(RtsFlags.PapiFlags.eventType==PAPI_FLAG_CACHE_L2) {
157 PAPI_REPORT(PapiCounters,PAPI_L2_DCA);
158 PAPI_REPORT(PapiCounters,PAPI_L2_DCM);
159 PAPI_REPORT_PCT(PapiCounters,PAPI_L2_DCM,PAPI_L2_DCA);
164 /* Add the events of papi_events into an event set */
166 papi_add_events(int EventSet)
169 for(i=0;i<N_PAPI_EVENTS;i++) {
170 if((papi_error=PAPI_add_event(EventSet,
171 papi_events[i].event_code))
173 debugBelch("Failed adding %s to event set with error code %d\n",
174 papi_events[i].event_name,papi_error);
179 papi_init_eventsets(void)
182 init_countable_events();
184 /* One event set for the mutator and another for the GC */
185 PAPI_CHECK( PAPI_create_eventset(&MutatorEvents));
186 PAPI_CHECK( PAPI_create_eventset(&GCEvents));
188 /* Both sets contain the same events */
189 papi_add_events(MutatorEvents);
190 papi_add_events(GCEvents);
195 papi_start_mutator_count(void)
197 PAPI_CHECK( PAPI_start(MutatorEvents));
201 papi_stop_mutator_count(void)
203 PAPI_CHECK( PAPI_accum(MutatorEvents,MutatorCounters));
204 PAPI_CHECK( PAPI_stop(MutatorEvents,NULL));
208 papi_start_gc_count(void)
210 PAPI_CHECK( PAPI_start(GCEvents));
214 papi_stop_gc_count(void)
216 PAPI_CHECK( PAPI_accum(GCEvents,GCCounters));
217 PAPI_CHECK( PAPI_stop(GCEvents,NULL));
221 #endif /* USE_PAPI */