ce3c0dea7f141aeadf47864063286de35158fdb8
[ghc-hetmet.git] / ghc / utils / prof / cgprof / main.c
1 /* ------------------------------------------------------------------------
2  * $Id: main.c,v 1.2 2003/08/01 14:50:50 panne Exp $
3  *                                                                      
4  *      Copyright (C) 1995-2000 University of Oxford
5  *                                                                      
6  * Permission to use, copy, modify, and distribute this software,
7  * and to incorporate it, in whole or in part, into other software,
8  * is hereby granted without fee, provided that
9  *   (1) the above copyright notice and this permission notice appear in
10  *       all copies of the source code, and the above copyright notice
11  *       appear in clearly visible form on all supporting documentation
12  *       and distribution media;
13  *   (2) modified versions of this software be accompanied by a complete
14  *       change history describing author, date, and modifications made;
15  *       and
16  *   (3) any redistribution of the software, in original or modified
17  *       form, be without fee and subject to these same conditions.
18  * --------------------------------------------------------------------- */
19
20 #include "config.h"
21
22 #include <stdio.h>
23
24 #if HAVE_UNISTD_H
25 #include <unistd.h>
26 #endif
27 #if HAVE_STRING_H
28 #include <string.h>
29 #endif
30
31 #include "symbol.h"
32 #include "cgprof.h"
33 #include "matrix.h"
34 #include "daVinci.h"
35
36 #define NoDeletes 80
37
38 int     CriticalPath=CRITICAL_SYNCS;
39 int     CriticalType=CRITTYPE_ABSOLUTE;
40 int     Verbose=1;
41 int     NodeviewTime=1;
42 int     NodeviewCompress=1;
43 int     PrintLogo=1;
44 int     Colour=1;
45 int     DeltaNormalise=1;
46 int     PieView=TCL_COMP;
47 int     PieCombine=0;
48 char   *Pgm;
49 char   *ProfileData;
50 int     NoNodes,root;
51 char    usage[]="usage:  cgprof profile-data [See man 1 cgprof]";
52 char    helpUrl[]="http://www.dcs.warwick.ac.uk/people/academic/Stephen.Jarvis/profiler/";
53 Matrix  graph; /* NoNodes x NoNodes matrix of integers */
54 Matrix  costs; /* NoNodes x 1       matrix of costs    */
55
56 double   TotalComp, TotalComm, TotalCompIdle;
57 int      TotalSyncs;
58 long int TotalH;
59
60 char    *dateProfiled, *machineName;
61 double minNodeSize = 0.01;   /* i.e, don't show nodes with _combined_
62                                     comp and comm % less than this */
63 double bsp_s = 74.0;
64 double bsp_l = 1902;
65 double bsp_g = 9.3;
66 int    bsp_p;
67
68 FILE *logFile;
69
70
71 extern void printDaVinci(int);
72
73 int 
74 main(int argc, char *argv[]) {
75   char davinci_stdin[MAX_PROFILE_LINE_LENGTH];
76   FILE   *fptr;
77   int i,j,k,going=1,*select_nodes, select_nodes_next,MaxNoNodes;
78   davinciCmd cmd;
79   int *undo_stack, undo_stack_next;
80   float temp_f;
81   char *ptr;
82   int mode = 0;
83   char *tempstring = malloc (80);
84   char *tempstring2 = malloc (80);
85   
86
87   /* printf("Starting main routine of browser script\n"); */
88   /* fflush(stderr); */
89
90   if (argc!=14) {
91     fprintf(stderr,"The perl script bspsgprof is buggered\n");
92     exit(1);
93   }
94
95   /* Most (if not all) of these BSP specific arguments can be removed */
96
97   Pgm         = argv[0];
98   ProfileData = argv[1];
99   bsp_p       = atoi(argv[2]);
100   machineName = argv[3];
101   dateProfiled= argv[4];
102   sscanf(argv[5],"%f",&temp_f);
103   bsp_s = temp_f;
104   sscanf(argv[6],"%f",&temp_f);
105   bsp_l = temp_f;
106   sscanf(argv[7],"%f",&temp_f);
107   bsp_g = temp_f;
108   sscanf(argv[8],"%f",&temp_f);
109   minNodeSize=temp_f;
110   Verbose = atoi(argv[9]);
111   PrintLogo=atoi(argv[10]);
112   Colour=atoi(argv[11]);
113   DeltaNormalise=atoi(argv[12]);
114   MaxNoNodes=atoi(argv[13]);
115
116   /* printf("Initialisation done\n"); */
117
118   if (Verbose) sleep(10);  
119   if (!(fptr=fopen(ProfileData,"r"))) {
120     fprintf(stderr,"%s: unable to open profile data in \"%s\".\n%s\n",
121             Pgm,ProfileData,usage);
122     exit(1);
123   }
124   if (!(logFile=fopen("ghcprof.log","w"))) {
125     fprintf(stderr,"%s: unable to open log file for writing\n",Pgm);
126     exit(1);
127   }
128
129   /* printf("Files opened OK\n"); */
130
131   if (!fgets(davinci_stdin, MAX_PROFILE_LINE_LENGTH, stdin) || 
132        strcmp(davinci_stdin,"ok\n")) {
133     fprintf(stderr,"%s{%s}: failed to receive ok from daVinci.\n",
134             davinci_stdin,Pgm);
135     exit(1);
136   }
137
138   /* printf("Initialising daVinci\n"); */
139
140   initDaVinci();
141   
142   /* printf("Ending initialisation of daVinci\n"); */
143  
144   if (Verbose) fprintf(logFile,"%s: opened profile file \"%s\".\n",Pgm,ProfileData);
145   readRawProfile(fptr,&NoNodes,MaxNoNodes);
146   fclose(fptr);
147   if (Verbose) fprintf(logFile,"%s: %d nodes in profile.\n",Pgm,NoNodes);
148
149   if (NoNodes<=0) {
150     fprintf(logFile,"%s: no call-graph profile data in \"%s\".\n"
151             "Re-run your program using the appropriate profiling flags\n",
152             Pgm,ProfileData);
153     exit(1);
154   }
155   if (Verbose) printRawProfile();
156
157   /* Do we want INHERITANCE to begin with or not? Set to yes. */
158   createConnectivityMatrix(NoNodes,&graph,&costs,&root,1);
159
160   TotalComp     = Mat(object_cost,costs,root,0).comp_max;
161   TotalComm     = Mat(object_cost,costs,root,0).comm_max;
162   TotalCompIdle = Mat(object_cost,costs,root,0).comp_idle_max;
163   TotalH        = Mat(object_cost,costs,root,0).hrel_max;
164   TotalSyncs    = Mat(object_cost,costs,root,0).syncs;
165   if (Verbose) printConnectivityMatrix(graph,costs,root);
166   fflush(logFile);
167   graphToDaVinci(root,&graph,&costs,0);
168   fflush(stdout);
169   undo_stack   = calloc(NoDeletes,sizeof(int));
170   select_nodes = calloc(NoNodes,sizeof(int));
171   if (undo_stack==NULL || select_nodes==NULL) {
172     fprintf(stderr,"Unable to allocate storage for undo stack\n");
173     exit(1);
174   }
175   undo_stack_next=0;
176   select_nodes_next=0;
177   // Pie chart stuff not wanted for GHC
178   // tclPieInit();
179   // tclPieUpdate(&Mat(object_cost,costs,root,0),root,PieView);
180   select_nodes_next=1;
181   select_nodes[0]=root;
182   while (fgets(davinci_stdin, MAX_PROFILE_LINE_LENGTH, stdin) && going) {
183     cmd = parseDaVinciCmd(davinci_stdin);
184     if (Verbose) fprintf(logFile,"From davinci=\"%s\"\n",davinci_stdin);
185     switch (cmd.type) {
186     case DAVINCI_OK:
187       continue;
188
189     case DAVINCI_QUIT:
190       going=0;
191       break;
192
193     case DAVINCI_NODE:
194       select_nodes_next=cmd.size;
195       for(i=0;((i<cmd.size) && (i<NoNodes));i++)
196         select_nodes[i]=atoi(cmd.list[i]);
197       if (select_nodes_next>0)
198         //Pie chart stuff not wanted for GHC
199         //tclPieUpdate(&Mat(object_cost,costs,select_nodes[0],0),
200         //                   select_nodes[0],
201         //                   PieView);
202       if (mode==3) 
203       {
204          mode = atoi(cmd.list[0]);
205          getNameFromSymbolTable(mode,tempstring);
206          for(ptr=tempstring;*ptr!='\0';ptr++)
207             if (*ptr=='&') *ptr=' ';
208          mode = 3;
209          strcpy(tempstring2,"window(show_status(\"");
210          strcat(tempstring2,tempstring);
211          strcat(tempstring2,"\"))");
212          cmdDaVinci(tempstring2);
213          strcpy(tempstring,"");
214          strcpy(tempstring2,"");
215       }
216       break;
217
218     case DAVINCI_MENU:
219       if (cmd.size>0) {
220         if (strcmp(cmd.list[0], "jump")==0)  {
221           if ((select_nodes_next>=0)      && 
222               (select_nodes[0]>0)         &&
223               (select_nodes[0] < NoNodes) &&
224               (Mat_dense(graph,select_nodes[0],select_nodes[0]))) {
225             cmdDaVinci("special(focus_node(\"%d\"))\n",select_nodes[0]);
226           }
227         }
228       }
229       break;
230
231     case DAVINCI_ICON:
232       if (cmd.size>0) {
233         if (strcmp(cmd.list[0], "sync")==0) {
234           CriticalPath=CRITICAL_SYNCS;
235           activateDaVinciMenu(cmd.list[0]);
236           cmdDaVinci("window(show_status(\"Graph view\"))");
237           updateColours(root,&graph,&costs);
238
239         } else if (strcmp(cmd.list[0], "comp")==0) {
240           CriticalPath=CRITICAL_COMP;
241           activateDaVinciMenu(cmd.list[0]);
242           cmdDaVinci("window(show_status(\"SCCs critical path\"))");
243           updateColours(root,&graph,&costs);
244           
245         } else if (strcmp(cmd.list[0], "comm")==0) {
246           CriticalPath=CRITICAL_COMM;
247           activateDaVinciMenu(cmd.list[0]);
248           cmdDaVinci("window(show_status(\"Computation time critical path\"))");
249           updateColours(root,&graph,&costs);
250           
251         } else if (strcmp(cmd.list[0], "wait")==0) {
252           CriticalPath=CRITICAL_WAIT;
253           activateDaVinciMenu(cmd.list[0]);
254           cmdDaVinci("window(show_status(\"Heap usage critical path\"))"); 
255           updateColours(root,&graph,&costs);
256           
257         } else if (strcmp(cmd.list[0], "hrel")==0) {
258
259           if (mode != 3)
260           {
261             cmdDaVinci("window(show_status(\"Node spy on\"))");
262             mode = 3;
263           }
264           else 
265           {
266             mode = 0;
267             cmdDaVinci("window(show_status(\"Node spy off\"))");
268           }
269
270         } else if (strcmp(cmd.list[0], "absolute")==0) {
271           /* Now deals with inheritance profile */
272           CriticalType=CRITTYPE_ABSOLUTE;
273           activateDaVinciMenu(cmd.list[0]);
274           cmdDaVinci("window(show_status(\"Inheritance profile\"))");
275           freeMat(&graph); 
276           freeMat(&costs); 
277           createConnectivityMatrix(NoNodes,&graph,&costs,&root,1);
278           graphToDaVinci(root,&graph,&costs,0);
279           cmdDaVinci("window(show_status(\"Inheritance profile\"))");
280           updateColours(root,&graph,&costs);
281
282         } else if (strcmp(cmd.list[0], "absdelta")==0) {
283           /* Now deals with flat profile */
284           CriticalType=CRITTYPE_ABSDELTA;
285           activateDaVinciMenu(cmd.list[0]);
286           cmdDaVinci("window(show_status(\"Flat profile\"))");
287           freeMat(&graph); 
288           freeMat(&costs); 
289           createConnectivityMatrix(NoNodes,&graph,&costs,&root,0);
290           graphToDaVinci(root,&graph,&costs,0);
291           cmdDaVinci("window(show_status(\"Flat profile\"))");
292           updateColours(root,&graph,&costs);
293
294         } else if (strcmp(cmd.list[0], "reldelta")==0) {
295           CriticalType=CRITTYPE_ABSOLUTE;
296           activateDaVinciMenu(cmd.list[0]);
297           cmdDaVinci("window(show_status(\"Trimmed zero-cost sub-trees\"))");
298           strcpy(cmd.list[0], "absolute");
299           activateDaVinciMenu(cmd.list[0]);
300           graphToDaVinci(root,&graph,&costs,2);
301           updateColours(root,&graph,&costs);
302           
303         } else if (strcmp(cmd.list[0], "weightdelta")==0) {
304           CriticalType=CRITTYPE_ABSOLUTE;
305           activateDaVinciMenu(cmd.list[0]);
306           cmdDaVinci("window(show_status(\"Marked zero-cost nodes ready for deletion\"))");
307           strcpy(cmd.list[0], "absolute");
308           activateDaVinciMenu(cmd.list[0]);
309           graphToDaVinci(root,&graph,&costs,1);
310           updateColours(root,&graph,&costs);
311           
312         } else if (strcmp(cmd.list[0],"help")==0) {
313           cmdDaVinci("special(show_url(\"%s\"))",helpUrl);
314
315         } else if (strcmp(cmd.list[0],"time")==0) {
316           NodeviewTime=1;
317           activateDaVinciMenu(cmd.list[0]);
318           cmdDaVinci("window(show_status(\"Cost metric view\"))");
319           graphToDaVinci(root,&graph,&costs,0);
320
321         } else if (strcmp(cmd.list[0],"percent")==0) {
322           NodeviewTime=0;
323           activateDaVinciMenu(cmd.list[0]);
324           cmdDaVinci("window(show_status(\"Percentage view\"))");
325           graphToDaVinci(root,&graph,&costs,0);
326
327         } else if (strcmp(cmd.list[0],"compress")==0) {
328           NodeviewCompress=1;
329           activateDaVinciMenu(cmd.list[0]);
330           cmdDaVinci("window(show_status(\"Compressed node view\"))");
331           cmdDaVinci("menu(layout(compact_all))");
332           graphToDaVinci(root,&graph,&costs,0);
333
334         } else if (strcmp(cmd.list[0],"uncompress")==0) {
335           NodeviewCompress=0;
336           activateDaVinciMenu(cmd.list[0]);
337           cmdDaVinci("window(show_status(\"Uncompressed node view\"))");
338           graphToDaVinci(root,&graph,&costs,0);
339
340         } else if ((strcmp(cmd.list[0],"delete")==0) ||
341                    (strcmp(cmd.list[0],"undo")==0)) {
342           if (strcmp(cmd.list[0],"delete")==0) {
343             if (undo_stack_next==0) 
344               activateDaVinciMenu("undo");
345             for(i=0;(i<select_nodes_next) && (undo_stack_next<NoNodes);i++) 
346               undo_stack[undo_stack_next++] = select_nodes[i];
347             if (undo_stack_next==NoDeletes) 
348               activateDaVinciMenu("delete");
349             cmdDaVinci("window(show_status(\"Deleted node (s)\"))");
350             select_nodes_next=0;
351           } else {
352             if (undo_stack_next==NoDeletes) 
353               activateDaVinciMenu("delete");
354             undo_stack_next--;
355             if (undo_stack_next==0) 
356               activateDaVinciMenu("undo");
357             cmdDaVinci("window(show_status(\"Undone deletion\"))");
358             select_nodes_next=1;
359             select_nodes[0]=undo_stack[undo_stack_next];
360             
361             for(i=0;i<raw_profile_next;i++)
362               raw_profile[i].active=1;
363           }
364           activateDaVinciMenu("default");
365           for(i=0;i<undo_stack_next;i++) {
366             for(j=0;j<raw_profile_next;j++) {
367               for(k=0;k<raw_profile[j].stack_size;k++) {
368                 if (raw_profile[j].stack[k]==undo_stack[i])
369                   raw_profile[j].active=0;
370               }
371             }
372           }
373           cmdDaVinci("window(show_message(\"Deleting node...\"))");
374           freeMat(&graph);
375           freeMat(&costs);
376           createConnectivityMatrix(NoNodes,&graph,&costs,&root,1);
377           graphToDaVinci(root,&graph,&costs,0);
378           if (strcmp(cmd.list[0],"undo")==0) {
379             if ((select_nodes[0]>0)         &&
380                 (select_nodes[0] < NoNodes) &&
381                 (Mat_dense(graph,select_nodes[0],select_nodes[0]))) {
382             cmdDaVinci("special(focus_node(\"%d\"))\n",select_nodes[0]);
383             cmdDaVinci("special(select_nodes([\"%d\"]))",select_nodes[0]);
384             //Pie chart stuff not wanted for GHC
385             //tclPieUpdate(&Mat(object_cost,costs,select_nodes[0],0),
386             //         select_nodes[0],
387             //         PieView);
388             }
389           }
390         }    
391       }
392       break;
393     case DAVINCI_TCL: 
394     // This stuff can go as it is related to the input for the Pie chart tool
395       if (cmd.size>0) {
396         if        (strcmp(cmd.list[0], "comm")==0)  {
397           PieView=TCL_COMM;
398         } else if (strcmp(cmd.list[0], "comp")==0)  {
399           PieView=TCL_COMP;
400         } else if (strcmp(cmd.list[0], "hrel")==0)  {
401           PieView=TCL_HREL;
402         } else if (strcmp(cmd.list[0], "wait")==0)  {
403           PieView=TCL_WAIT;
404         } else if (strcmp(cmd.list[0], "combine")==0)  {
405           PieCombine=!PieCombine;
406         } else if (strlen(cmd.list[0])==0) {
407           break;
408         }
409         if (select_nodes_next>0) break;
410           //Added a break for compiliation above since it does not compile if 
411           //we just remove the Pie chart code 
412           //tclPieUpdate(&Mat(object_cost,costs,select_nodes[0],0),
413           //           select_nodes[0],
414           //           PieView);
415       }
416       break;
417     case DAVINCI_ERROR:  
418     default:
419       fprintf(stderr,"CGPROF error:\n"
420                      "\tCommand = %s\n"
421                      "\tError   = %s\n",lastDavinciCmd,davinci_stdin);
422       exit(1); 
423       break;
424     }
425     fflush(stdout);
426     fflush(logFile);
427   }  
428
429   return 0;
430 }