Addition of PAPI to RTS
[ghc-hetmet.git] / rts / Papi.c
1
2
3 #include "Papi.h"
4 #include "Rts.h"
5 #include "RtsUtils.h"
6 #include "Stats.h"
7
8
9 /* These constants specify which events to keep track of.
10  * Probably it is better to count one set of events at a time.
11  * The reason is that processors have limited counters and
12  * multiplexing is not enabled (yet).
13  */
14 #define PAPI_COUNT_BRANCHES 0
15 /* The one below is Opteron specific.
16  */
17 #define PAPI_COUNT_STALLS 0
18 #define PAPI_COUNT_DCACHE1_MISSES 1
19 #define PAPI_COUNT_DCACHE2_MISSES 0
20
21 struct _papi_events {
22   int event_code;
23   char * event_name;
24 };
25
26 #define PAPI_ADD_EVENT(EVENT) { EVENT, #EVENT }
27
28 /* Beware, these counters are Opteron specific */
29 #define FR_BR 0x40000040
30 #define FR_BR_MIS 0x40000041
31 #define FR_BR_MISCOMPARE 0x40000048
32 #define DC_ACCESS 0x40000019
33 #define DC_MISS 0x4000001a
34 #define FR_DISPATCH_STALLS_BR 0x40000055
35 #define FR_DISPATCH_STALLS_FULL_LS 0x4000005b
36
37 /* Report the value of a counter */
38 #define PAPI_REPORT(EVENTSET,EVENT) \
39   { \
40     ullong_format_string(papi_counter(EVENTSET,EVENT),temp,rtsTrue/*commas*/); \
41     statsPrintf("  (" #EVENT ")  : %s\n",temp);                         \
42   }
43
44 /* Report the value of a counter as a percentage of another counter */
45 #define PAPI_REPORT_PCT(EVENTSET,EVENT,EVENTTOT) \
46   statsPrintf("  (" #EVENT ") %% of (" #EVENTTOT ") : %.1f%%\n", \
47               papi_counter(EVENTSET,EVENT)*100.0/papi_counter(EVENTSET,EVENTTOT))
48
49 /* Number of counted events, computed from size of papi_events */
50 #define N_PAPI_EVENTS ((int)(sizeof(papi_events)/sizeof(struct _papi_events)))
51
52 /* This is bad, it should be in a header */
53 #define BIG_STRING_LEN 512
54
55 /* While PAPI reporting is going on this flag is on */
56 int papi_is_reporting;
57
58 /* Event sets and counter arrays for GC and mutator */
59
60 int MutatorEvents = PAPI_NULL;
61 int GCEvents = PAPI_NULL;
62
63 int papi_error;
64
65
66 /* If you want to add events to count, extend the
67  * papi_events array and the papi_report function.
68  */
69
70 /* Events counted during GC and Mutator execution */
71 /* There's a trailing comma, do all C compilers accept that? */
72 static struct _papi_events papi_events[] = {
73   PAPI_ADD_EVENT(PAPI_TOT_CYC),
74 #if PAPI_COUNT_BRANCHES
75   PAPI_ADD_EVENT(FR_BR),
76   PAPI_ADD_EVENT(FR_BR_MIS),
77   /* Docs are wrong? Opteron does not count indirect branch misses apparently */
78   PAPI_ADD_EVENT(FR_BR_MISCOMPARE),
79 #endif
80 #if PAPI_COUNT_STALLS
81   PAPI_ADD_EVENT(FR_DISPATCH_STALLS_BR),
82   PAPI_ADD_EVENT(FR_DISPATCH_STALLS_FULL_LS),
83 #endif
84 #if PAPI_COUNT_DCACHE1_MISSES
85   PAPI_ADD_EVENT(PAPI_L1_DCA),
86   PAPI_ADD_EVENT(PAPI_L1_DCM),
87 #endif
88 #if PAPI_COUNT_DCACHE2_MISSES
89   PAPI_ADD_EVENT(PAPI_L2_DCA),
90   PAPI_ADD_EVENT(PAPI_L2_DCM),
91 #endif
92 };
93
94 long_long MutatorCounters[N_PAPI_EVENTS];
95 long_long GCCounters[N_PAPI_EVENTS];
96
97
98 /* Extract the value corresponding to an event */
99 long_long
100 papi_counter(long_long values[],int event)
101 {
102   int i;
103   for(i=0;i<N_PAPI_EVENTS;i++) {
104     if(papi_events[i].event_code==event) {
105       return values[i];
106     }
107   }
108   /* Passed a wrong event? */
109   debugBelch("Event %d is not part of event set\n",event);
110   return 0;
111 }
112
113 /* This function reports counters for GC and mutator */
114 void
115 papi_report(long_long PapiCounters[])
116 {
117     char temp[BIG_STRING_LEN];
118
119     /* I need to improve formatting aesthetics */
120     PAPI_REPORT(PapiCounters,PAPI_TOT_CYC);
121 #if PAPI_COUNT_BRANCHES
122     PAPI_REPORT(PapiCounters,FR_BR);
123     PAPI_REPORT(PapiCounters,FR_BR_MIS);
124     PAPI_REPORT_PCT(PapiCounters,FR_BR_MIS,FR_BR);
125     PAPI_REPORT_PCT(PapiCounters,FR_BR_MISCOMPARE,FR_BR);
126 #endif
127 #if PAPI_COUNT_STALLS
128     PAPI_REPORT(PapiCounters,FR_DISPATCH_STALLS_BR);
129     PAPI_REPORT_PCT(PapiCounters,FR_DISPATCH_STALLS_BR,PAPI_TOT_CYC);
130     PAPI_REPORT(PapiCounters,FR_DISPATCH_STALLS_FULL_LS);
131     PAPI_REPORT_PCT(PapiCounters,FR_DISPATCH_STALLS_FULL_LS,PAPI_TOT_CYC);
132 #endif
133 #if PAPI_COUNT_DCACHE1_MISSES
134     PAPI_REPORT(PapiCounters,PAPI_L1_DCA);
135     PAPI_REPORT(PapiCounters,PAPI_L1_DCM);
136     PAPI_REPORT_PCT(PapiCounters,PAPI_L1_DCM,PAPI_L1_DCA);
137 #endif
138 #if PAPI_COUNT_DCACHE2_MISSES
139     PAPI_REPORT(PapiCounters,PAPI_L2_DCA);
140     PAPI_REPORT(PapiCounters,PAPI_L2_DCM);
141     PAPI_REPORT_PCT(PapiCounters,PAPI_L2_DCM,PAPI_L2_DCA);
142 #endif
143 }
144
145 /* Add the events of papi_events into an event set */
146 void
147 papi_add_events(int EventSet)
148 {
149   int i;
150   for(i=0;i<N_PAPI_EVENTS;i++) {
151     if((papi_error=PAPI_add_event(EventSet,
152                                   papi_events[i].event_code))
153        != PAPI_OK)
154       debugBelch("Failed adding %s to event set with error code %d\n",
155                  papi_events[i].event_name,papi_error);
156   }
157 }
158
159 void
160 papi_init_eventsets(void)
161 {
162
163     /* One event set for the mutator and another for the GC */
164     PAPI_CHECK( PAPI_create_eventset(&MutatorEvents));
165     PAPI_CHECK( PAPI_create_eventset(&GCEvents));
166
167     /* Both sets contain the same events */
168     papi_add_events(MutatorEvents);
169     papi_add_events(GCEvents);
170
171 }
172
173 void
174 papi_start_mutator_count(void)
175 {
176     PAPI_CHECK( PAPI_start(MutatorEvents));
177 }
178
179 void
180 papi_stop_mutator_count(void)
181 {
182     PAPI_CHECK( PAPI_accum(MutatorEvents,MutatorCounters));
183     PAPI_CHECK( PAPI_stop(MutatorEvents,NULL));
184 }
185
186 void
187 papi_start_gc_count(void)
188 {
189       PAPI_CHECK( PAPI_start(GCEvents));
190 }
191
192 void
193 papi_stop_gc_count(void)
194 {
195       PAPI_CHECK( PAPI_accum(GCEvents,GCCounters));
196       PAPI_CHECK( PAPI_stop(GCEvents,NULL));
197 }