[project @ 2003-08-01 14:50:48 by panne]
[ghc-hetmet.git] / ghc / utils / prof / cgprof / cgprof.c
1 /* ------------------------------------------------------------------------
2  * $Id: cgprof.c,v 1.3 2003/08/01 14:50:48 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 #if HAVE_STRING_H
22 #include <string.h>
23 #endif
24
25 #include "daVinci.h"
26 #include "symbol.h"
27 #include "cgprof.h"
28 #include "matrix.h"
29
30 /* -----------------------------------------------------------------------------
31  * Data structures
32  * -------------------------------------------------------------------------- */
33
34 int                 raw_profile_next=0;
35 int                 raw_profile_size=0;
36 parsed_cost_object *raw_profile=NULL;
37
38 /* -----------------------------------------------------------------------------
39  * Create/grow data sequence of raw profile data
40  * -------------------------------------------------------------------------- */
41
42 void enlargeRawProfile() {
43
44   if (raw_profile_size==0) {
45     raw_profile_next = 0;
46     raw_profile_size = RAW_PROFILE_INIT_SIZE;
47     raw_profile      = calloc(raw_profile_size,sizeof(parsed_cost_object));
48   } else {
49     raw_profile_size += RAW_PROFILE_INIT_SIZE;
50     raw_profile       = realloc(raw_profile,
51                                  raw_profile_size*sizeof(parsed_cost_object));
52   }
53   if (raw_profile==NULL) {
54     fprintf(stderr,"{enlargeRawProfile} unable to allocate %d elements",
55             raw_profile_size);
56     exit(1);
57   }
58 }
59
60 /* -----------------------------------------------------------------------------
61  * Function that adds two cost centers together
62  *
63  * This will be used to generate the inheretance profile.
64  * -------------------------------------------------------------------------- */
65
66 void add_costs(object_cost *left, object_cost right) {
67   int i;
68
69   left->syncs         += right.syncs;
70   left->comp_max      += right.comp_max;
71   left->comp_avg      += right.comp_avg;
72   left->comp_min      += right.comp_min;
73   left->comm_max      += right.comm_max;
74   left->comm_avg      += right.comm_avg;
75   left->comm_min      += right.comm_min;
76   left->comp_idle_max += right.comp_idle_max;
77   left->comp_idle_avg += right.comp_idle_avg;
78   left->comp_idle_min += right.comp_idle_min;
79   left->hrel_max      += right.hrel_max;
80   left->hrel_avg      += right.hrel_avg;
81   left->hrel_min      += right.hrel_min;
82   if ((left->proc==NULL) || (right.proc==NULL)) {
83     fprintf(stderr,"Cost is null");
84     exit(0);
85   }
86 }
87
88
89 int ignore_function(char *fname) {
90   return 0;
91 }
92
93 /* -----------------------------------------------------------------------------
94  * GHC specific data structures
95  * -------------------------------------------------------------------------- */
96
97 /* Globals */
98 /* You will need to update these when you increase the number of */
99 /*   cost centres, cost centre stacks, heap objects              */
100
101    #define MAX_IDENTIFIERS 2000 /* maximum number of identifiers */
102                                 /* or size of matrix structure   */
103
104   /* make this dynamic */
105
106    #define MAX_TIME    100      /* Maximum serial time for heap profile */
107    #define MAX_SAMPLES 50       /* Maximum heap samples */
108
109                                 /* To do: modify this to be dynamic */
110
111    #define MAX_STRING_SIZE 70
112    #define MAX_LINE_LENGTH 80
113    #define EOF (-1)
114
115 /* Cost centre data structure */
116
117    struct cost_centre { char *name;
118                         char *module;
119                         char *group;
120    } _cc_;
121
122    typedef struct cost_centre cc_matrix[MAX_IDENTIFIERS];
123
124    //typedef struct cost_centre *cc_matrix;
125
126    typedef cc_matrix* p_cc_matrix;
127    typedef char* MY_STRING;
128
129 /* Heap sample structure */
130
131    struct heap_sample { 
132                         int count; /* heap_sample */
133    };
134
135    typedef struct heap_sample heap_sample_matrix[MAX_IDENTIFIERS];
136    typedef heap_sample_matrix* p_heap_sample_matrix;
137
138 /* Cost centre stack data structure */
139
140    struct cost_centre_stack { 
141                       int cc;
142                       int ccs;
143                       int scc;   /* scc_sample  */
144                       int ticks; /* scc_sample  */
145                       int bytes; /* scc_sample  */
146                       p_heap_sample_matrix hsm; /* heap_sample */
147    };
148
149    typedef struct cost_centre_stack ccs_matrix[MAX_IDENTIFIERS];
150    typedef ccs_matrix* p_ccs_matrix;
151
152 /* Heap object data structure */
153
154    struct heap_object { int   type;            /* type of heap object */
155                         char* descriptor; 
156                         int   type_constr_ref; /* if present */
157                       };
158
159    typedef struct heap_object heap_object_matrix[MAX_IDENTIFIERS];
160    typedef heap_object_matrix* p_heap_object_matrix;
161
162 /* Type constructor structure */
163
164    struct type_constr { char* module;
165                         char* name;
166                       };
167
168    typedef struct type_constr type_constr_matrix[MAX_IDENTIFIERS];
169    typedef type_constr_matrix* p_type_constr_matrix;
170
171 /* Heap update structure */
172
173    struct heap_update_sample { int ccs;   /* associated cost centre stack */
174                                int ho;    /* associated heap object */
175                                int count; 
176                               };
177
178    typedef struct heap_update_sample heap_update_list[MAX_SAMPLES];
179    typedef heap_update_list* p_heap_update_list;
180
181    struct heap_update_record { int no_samples; /* Number of samples */
182                                p_heap_update_list acc_samples;
183                              };
184
185    typedef struct heap_update_record TheHeap[MAX_TIME];
186    typedef TheHeap* p_TheHeap;
187
188
189 /* -----------------------------------------------------------------------------
190  * GHC specific functions
191  * -------------------------------------------------------------------------- */
192
193 // Initialisation routines
194
195 void initialise_heap_update_list(heap_update_list *m)
196 {
197   int i;
198   for (i=0; i<MAX_SAMPLES;i++)
199   {
200     (*m)[i].ccs   = -1;
201     (*m)[i].ho    = -1;
202     (*m)[i].count    = -1;
203   }
204 }
205
206 void add_to_heap_update_list(heap_update_list *m, int ccs, int ho, int count, int pos)
207 {
208   (*m)[pos].ccs    = ccs;
209   (*m)[pos].ho     = ho;
210   (*m)[pos].count    = count;
211 }
212
213 void initialise_TheHeap(TheHeap *h)
214 {
215   int i;
216   for (i=0; i<MAX_TIME;i++)
217   {
218     heap_update_list *h_u_l;
219     h_u_l = (p_heap_update_list) malloc (sizeof(heap_update_list));
220     initialise_heap_update_list(h_u_l);
221     (*h)[i].acc_samples = h_u_l;
222     (*h)[i].no_samples   = 0;
223   }
224 }
225
226 void add_to_TheHeap(TheHeap *h, int time, int ccs, int ho, int count)
227 {
228   add_to_heap_update_list((*h)[time].acc_samples,ccs,ho,count,(*h)[time].no_samples);
229   (*h)[time].no_samples++;
230 }
231
232 void initialise_cc_matrix(cc_matrix *m)
233
234   int i;
235   char *blank="blank"; /* To do: Modify this terminator string */
236   for (i=0; i<MAX_IDENTIFIERS; i++)
237     { 
238       (*m)[i].name =  (MY_STRING) malloc ((MAX_STRING_SIZE));
239       (*m)[i].module = (MY_STRING) malloc ((MAX_STRING_SIZE));
240       (*m)[i].group = (MY_STRING) malloc ((MAX_STRING_SIZE));
241
242       strcpy((*m)[i].name,blank); 
243       strcpy((*m)[i].module,blank);
244       strcpy((*m)[i].group,blank);  
245     }
246 }
247
248 void free_cc_matrix(cc_matrix *m)
249 {
250   int i;
251   for (i=0; i<MAX_IDENTIFIERS; i++)
252     {
253       free((*m)[i].name);
254       free((*m)[i].module);
255       free((*m)[i].group);
256     }
257     free(m);
258 }
259
260 void initialise_heap_object_matrix(heap_object_matrix *m)
261 {
262   int i;
263   char *blank="blank"; /* To do: ditto */
264   for (i=0; i<MAX_IDENTIFIERS; i++)
265   {
266     (*m)[i].type = -1;
267     (*m)[i].descriptor = (MY_STRING) malloc ((MAX_STRING_SIZE));
268     strcpy((*m)[i].descriptor,blank);
269     (*m)[i].type_constr_ref = -1; 
270   }
271 }
272
273 void initialise_type_constr_matrix(type_constr_matrix *m)
274 {
275   int i;
276   char *blank="blank";
277   for (i=0; i<MAX_IDENTIFIERS; i++)
278   {
279     (*m)[i].module = (MY_STRING) malloc ((MAX_STRING_SIZE));
280     (*m)[i].name   = (MY_STRING) malloc ((MAX_STRING_SIZE));
281     strcpy((*m)[i].module,blank);
282     strcpy((*m)[i].name,blank);
283   }
284 }
285
286 void initialise_heap_sample_matrix(heap_sample_matrix *m)
287 {
288   int i;
289   for (i=0; i<MAX_IDENTIFIERS; i++)
290   { (*m)[i].count = -1; }
291 }
292
293 void initialise_ccs_matrix(ccs_matrix *m)
294
295   int i;
296   for (i=0; i<MAX_IDENTIFIERS; i++)
297     { 
298       /* Stack heap samples */
299       heap_sample_matrix *hs_m;
300       hs_m = (p_heap_sample_matrix) malloc (sizeof(heap_sample_matrix));
301       initialise_heap_sample_matrix(hs_m);
302       (*m)[i].hsm = hs_m;
303       /* Stack scc samples */
304       (*m)[i].cc    = 0; 
305       (*m)[i].ccs   = 0;
306       (*m)[i].scc   = 0;
307       (*m)[i].ticks = 0; 
308       (*m)[i].bytes = 0; 
309     }
310 }
311
312
313 // Filling matrix routines
314
315 char* StripDoubleQuotes(char* s) /* For fussy daVinci! */
316 {
317   char *p = s;
318   char *tempchar;
319   char *empty="";
320   char *tempstring = (MY_STRING) malloc ((MAX_STRING_SIZE));
321   strcpy(tempstring,empty);
322   while (*p)
323   { if (*p!='"')
324     { tempchar = p; strncat(tempstring,p,1);
325      }
326     p++; 
327   }
328   return tempstring;
329 }
330
331 void fill_cc_matrix(cc_matrix *m,char* name,char* module,char* group,int i)
332
333   if (i>MAX_IDENTIFIERS) 
334   {  fprintf(logFile,"Cost centre MAX_IDENTIFIERS exceeded: %i \n",i); exit(1); }
335   name = StripDoubleQuotes(name);
336   strcpy((*m)[i].name,name); 
337   module = StripDoubleQuotes(module);
338   strcpy((*m)[i].module,module);
339   group = StripDoubleQuotes(group);
340   strcpy((*m)[i].group,group);
341 }
342
343 void fill_ccs_matrix(ccs_matrix *m,int cc, int ccs, int scc, int ticks, int bytes, int h_o, int count, int i)
344 {
345   heap_sample_matrix *hsm;
346
347   if ((*m)[i].cc == 0)  /* added for type 2 stack semantics, but should not */
348                         /* change behaviour of type 1 (apart from CAF:REP.  */
349   {
350     if (i>MAX_IDENTIFIERS) 
351     {  fprintf(logFile,"Cost centre stack MAX_IDENTIFIERS exceeded: %i \n",i); exit(1); }
352     hsm = (*m)[i].hsm;
353     (*m)[i].cc = cc; (*m)[i].ccs = ccs; 
354     (*m)[i].ticks = ticks; (*m)[i].bytes = bytes; (*m)[i].scc = scc;
355     (*hsm)[h_o].count = count;
356   }
357   else fprintf(logFile,"Ignoring redeclaration of stack %i\n",i);
358 }
359
360 void add_ccs_costs(ccs_matrix *m, int b,int c,int d,int x,int y,int h_o, int co)
361 {
362   (*m)[c].scc    = (*m)[c].scc + d;
363   (*m)[c].ticks  = (*m)[c].ticks + x;
364   (*m)[c].bytes  = (*m)[c].bytes + y;
365 }
366
367 void add_heap_sample_costs(ccs_matrix *m, int b,int c,int d,int x,int y,int h_o, int co)
368
369   heap_sample_matrix *hsm = (*m)[c].hsm;
370   if (((*hsm)[h_o].count)==-1)
371      (*hsm)[h_o].count = (*hsm)[h_o].count + co + 1; /* as init is -1 */
372   else 
373      (*hsm)[h_o].count = (*hsm)[h_o].count + co;
374 }
375
376 void add_heap_object(heap_object_matrix *m, int pos, int t, char* des, int tr)
377 {
378   if (pos>MAX_IDENTIFIERS) 
379   {  fprintf(logFile,"Heap object MAX_IDENTIFIERS exceeded: %i \n",pos); exit(1); }
380   (*m)[pos].type = t;
381   strcpy((*m)[pos].descriptor,des);
382   (*m)[pos].type_constr_ref = tr;
383
384
385 void add_type_constr_object(type_constr_matrix *m, int pos, char* mod, char* n)
386 {
387   if (pos>MAX_IDENTIFIERS) 
388   {  fprintf(logFile,"Type constructor MAX_IDENTIFIERS exceeded: %i \n",pos); exit(1); }
389   strcpy((*m)[pos].module,mod);
390   strcpy((*m)[pos].name,n);
391 }
392
393
394 // Printing routines
395
396 void print_heap_update_list(heap_update_list *m, int number)
397 {
398   int i;
399   fprintf(logFile,"[");
400   for (i=0; i<number;i++)
401   {
402     fprintf(logFile," (%i,%i,%i) ",(*m)[i].ccs,(*m)[i].ho,(*m)[i].count);
403   }
404   fprintf(logFile,"]\n");
405 }
406
407 void print_TheHeap(TheHeap *h)
408 {
409   int i;
410   fprintf(logFile,"The Heap\n========\n");
411   for (i=0; i<MAX_TIME;i++)
412   {
413     if ((*h)[i].no_samples>0)
414     {
415       fprintf(logFile,"Sample time %i, number of samples %i actual samples "
416                  ,i,(*h)[i].no_samples);
417       print_heap_update_list((*h)[i].acc_samples,(*h)[i].no_samples);
418     }
419   }
420 }
421
422 void PrintXaxis(FILE *HEAP_PROFILE, TheHeap *h)
423 {
424   int i;
425   fprintf(HEAP_PROFILE," ");
426   for (i=0; i<MAX_TIME;i++)
427   {
428     if ((*h)[i].no_samples>0)
429        fprintf(HEAP_PROFILE,"%i ",i);
430   }
431 }
432
433 int FindSample(heap_update_list *m, int number, int element)
434 {
435   int i;
436   for (i=0; i<number;i++)
437   {
438     if ((*m)[i].ho==element)
439         return ((*m)[i].count);
440   }
441   return 0;
442 }
443
444 void PrintSampleCosts(FILE *hfp, TheHeap *h, int element)
445 {
446   int i;
447   int total = 0;
448   for (i=0; i<MAX_TIME;i++)
449   {
450     if ((*h)[i].no_samples>0)
451     {
452       total = total + FindSample((*h)[i].acc_samples,(*h)[i].no_samples,element);
453       fprintf(hfp," %i ",total);
454     }
455   }
456 }
457
458 void print_cc_matrix(cc_matrix *m)
459
460   int i;
461   char *blank="blank";
462   fprintf(logFile,"Cost centre matrix\n");
463   fprintf(logFile,"==================\n");
464   for (i=0; i<MAX_IDENTIFIERS; i++)
465     { if (strcmp((*m)[i].name,blank)!=0) 
466          fprintf(logFile,"%s %s %s\n",(*m)[i].name,(*m)[i].module,(*m)[i].group); }
467   fprintf(logFile,"\n");
468 }
469
470 void print_heap_object_matrix(FILE* hfp, TheHeap *h, heap_object_matrix *m)
471 {
472   int i;
473   for (i=0; i<MAX_IDENTIFIERS; i++)
474   { 
475     if (((*m)[i].type)!=-1)
476     {
477       fprintf(hfp,"Y%i set {",i);
478       /* if ((*m)[i].type==1) fprintf(hfp,"data_contr ");
479       if ((*m)[i].type==2) fprintf(hfp,"PAP ");
480       if ((*m)[i].type==3) fprintf(hfp,"thunk ");
481       if ((*m)[i].type==4) fprintf(hfp,"function ");
482       if ((*m)[i].type==5) fprintf(hfp,"dictionary ");
483       if ((*m)[i].type==1) 
484          fprintf(hfp,"%s %i ",(*m)[i].descriptor,(*m)[i].type_constr_ref);
485       else
486          fprintf(hfp,"%s ",(*m)[i].descriptor); */
487       PrintSampleCosts(hfp,h,i);
488       fprintf(hfp,"}\n");
489     }
490   }         
491 }
492
493 int number_of_heap_objects(heap_object_matrix *m)
494 {
495   int i;
496   int count = 0;
497   for (i=0; i<MAX_IDENTIFIERS; i++)
498   {
499     if (((*m)[i].type)!=-1) count++;
500   }
501   return count;
502 }
503
504 void names_of_heap_objects(FILE *hfp, heap_object_matrix *m)
505 {
506   int i;
507   for (i=0; i<MAX_IDENTIFIERS; i++)
508   {
509     if (((*m)[i].type)!=-1) 
510       fprintf(hfp,"Y%i ",i);
511   }
512   fprintf(hfp,"\n");
513 }
514
515 void names_and_colour_assignment(FILE *hfp, heap_object_matrix *m)
516 {
517   int i;
518   int colour=0;
519   for (i=0; i<MAX_IDENTIFIERS; i++)
520   {
521     if (((*m)[i].type)!=-1) 
522     {
523       switch(colour)
524       {
525         case 0 : fprintf(hfp,"%s \t Y%i \t red \t fdiagonal1\n",(*m)[i].descriptor,i); 
526                  colour++; break;
527         case 1 : fprintf(hfp,"%s \t Y%i \t blue \t fdiagonal1\n",(*m)[i].descriptor,i);
528                  colour++; break;
529         case 2 : fprintf(hfp,"%s \t Y%i \t green \t fdiagonal1\n",(*m)[i].descriptor,i);
530                  colour++; break;
531         case 3 : fprintf(hfp,"%s \t Y%i \t yellow \t fdiagonal1\n",(*m)[i].descriptor,i);
532                  colour++; break;
533         case 4 : fprintf(hfp,"%s \t Y%i \t pink \t fdiagonal1\n",(*m)[i].descriptor,i);
534                  colour++; break;
535         case 5 : fprintf(hfp,"%s \t Y%i \t goldenrod \t fdiagonal1\n",(*m)[i].descriptor,i);
536                  colour++; break;
537         case 6 : fprintf(hfp,"%s \t Y%i \t orange \t fdiagonal1\n",(*m)[i].descriptor,i);
538                  colour++; break;
539         default: fprintf(hfp,"%s \t Y%i \t purple \t fdiagonal1\n",(*m)[i].descriptor,i);
540                  colour=0; break;
541       }
542     }
543   }
544 }
545
546 void print_type_constr_matrix(type_constr_matrix *m)
547 {
548   int i;
549   char *blank="blank";
550   fprintf(logFile,"Type constructor matrix\n");
551   fprintf(logFile,"=======================\n");
552   for (i=0; i<MAX_IDENTIFIERS; i++)
553   {
554     if (strcmp((*m)[i].name,blank)!=0)
555          fprintf(logFile,"%i %s %s\n",i,(*m)[i].module,(*m)[i].name);
556   }
557 }
558
559 void print_heap_sample_matrix(heap_sample_matrix *m)
560 {
561   int i;
562   fprintf(logFile,"HeapSamples[");
563   for (i=0; i<MAX_IDENTIFIERS; i++)
564   {
565     if ((*m)[i].count!=-1) fprintf(logFile,"(%i,%i),",i,(*m)[i].count);
566   }
567   fprintf(logFile,"]\n");
568 }
569
570 void print_ccs_matrix(ccs_matrix *m)
571
572   int i;
573   fprintf(logFile,"Cost centre stack matrix\n");
574   fprintf(logFile,"========================\n");
575   for (i=0; i<MAX_IDENTIFIERS; i++)
576   {  if ((*m)[i].cc!=0)
577      {
578        fprintf(logFile,"%i %i %i %i %i \n",(*m)[i].cc,(*m)[i].ccs,(*m)[i].scc,
579                                (*m)[i].ticks,(*m)[i].bytes); 
580      } 
581   }
582   fprintf(logFile,"\n");
583 }
584
585
586 /* No longer used */
587
588 void FormStack(ccs_matrix *m, cc_matrix *n, int i, char s[])
589 {
590   int j = i;
591   if ((*m)[j].cc != 0)
592   {
593     strcat(s,(*n)[(*m)[j].cc].name);
594     strcat(s," ");
595     while ((*m)[j].ccs != (-1))
596     {
597       strcat(s,(*n)[(*m)[(*m)[j].ccs].cc].name);
598       strcat(s,",");
599       j = (*m)[j].ccs;
600     }
601   }
602   else fprintf(logFile,"ERROR: Form Stack %i\n",i);
603 }
604
605 /* This version, which is used, adds the module and group name to the cost centre name*/
606 /* This means the cost centre name remains unique when it is textualised and fed into */
607 /* daVinci. It also allows the module and group name to be extracted at the display   */
608 /* level */
609
610 void FormStack2(ccs_matrix *m, cc_matrix *n, int i, char s[])
611 {
612   int j = i;
613   if ((*m)[j].cc != 0)
614   {
615     strcat(s,(*n)[(*m)[j].cc].name);
616     strcat(s,"&");
617     strcat(s,(*n)[(*m)[j].cc].module);
618     strcat(s,"&");
619     strcat(s,(*n)[(*m)[j].cc].group);
620     strcat(s," ");
621     while ((*m)[j].ccs != (-1))
622     {
623       strcat(s,(*n)[(*m)[(*m)[j].ccs].cc].name);
624       strcat(s,"&");
625       strcat(s,(*n)[(*m)[(*m)[j].ccs].cc].module);
626       strcat(s,"&");
627       strcat(s,(*n)[(*m)[(*m)[j].ccs].cc].group);
628       strcat(s,",");
629       j = (*m)[j].ccs;
630     }
631   }
632   else fprintf(logFile,"ERROR: Form Stack %i\n",i);
633 }
634
635 void PrintStack(ccs_matrix *m, cc_matrix *n, int i)
636 {
637   char    stack[MAX_PROFILE_LINE_LENGTH];
638   int j = i;
639   if ((*m)[j].cc != 0)
640   {
641     fprintf(logFile,"<"); 
642     fprintf(logFile,"%s,",(*n)[(*m)[j].cc].name);
643     while ((*m)[j].ccs != (-1))
644     {
645       fprintf(logFile,"%s,",(*n)[(*m)[(*m)[j].ccs].cc].name);
646       j = (*m)[j].ccs;
647     }
648     fprintf(logFile,"> ");
649     fprintf(logFile,"%i scc %i ticks %i bytes  ",
650             (*m)[i].scc,(*m)[i].ticks,(*m)[i].bytes);
651     print_heap_sample_matrix((*m)[i].hsm);
652   }
653   else
654   { /* fprintf(logFile,"empty stack\n"); */ }
655 }
656
657 int CountStacks(ccs_matrix *m)
658 {
659   int j;
660   int count = 0;
661   for (j=0; j<MAX_IDENTIFIERS;j++) if ((*m)[j].cc != 0) count++;
662   return count;
663 }
664
665 void PrintAllStacks(ccs_matrix *m, cc_matrix *n)
666 {
667   int i;
668   fprintf(logFile,"Stacks\n======\n");
669   for (i=0;i<MAX_IDENTIFIERS;i++) { PrintStack(m,n,i); }
670 }
671
672
673 /* -----------------------------------------------------------------------------
674  * TCL Heap profile generator
675  * -------------------------------------------------------------------------- */
676
677 void produce_HEAP_PROFILE(FILE *HEAP_PROFILE, TheHeap *th, heap_object_matrix *ho_m)
678 {
679   // First the header information 
680   fprintf(HEAP_PROFILE,"#!/home/sj/blt2.4o/src/bltwish\n");
681   fprintf(HEAP_PROFILE,"package require BLT\n");
682   fprintf(HEAP_PROFILE,"if { $tcl_version >= 8.0 } {\n");
683   fprintf(HEAP_PROFILE,"\t \t namespace import blt::*\n");
684   fprintf(HEAP_PROFILE,"namespace import -force blt::tile::*\n");
685   fprintf(HEAP_PROFILE,"}\n");
686   fprintf(HEAP_PROFILE,"source scripts/demo.tcl\n");
687   fprintf(HEAP_PROFILE,"proc FormatXTicks { w value } {\n");
688   fprintf(HEAP_PROFILE,"\t \t set index [expr round($value)]\n");
689   fprintf(HEAP_PROFILE,"\t \t if { $index != $value } {\n");
690   fprintf(HEAP_PROFILE,"\t \t \t return $value\n");
691   fprintf(HEAP_PROFILE,"\t \t}\n");
692   fprintf(HEAP_PROFILE,"incr index -1\n");
693
694   // Now the code to generate the units in the X axis
695
696   fprintf(HEAP_PROFILE,"set name [lindex { ");
697   PrintXaxis(HEAP_PROFILE,th);
698   fprintf(HEAP_PROFILE," } $index]\n");
699
700   fprintf(HEAP_PROFILE,"return $name\n");
701   fprintf(HEAP_PROFILE,"}\n");
702   
703   // more general graph stuff 
704
705   fprintf(HEAP_PROFILE,"source scripts/stipples.tcl\n");
706   fprintf(HEAP_PROFILE,"image create photo bgTexture -file ./images/chalk.gif\n");
707   fprintf(HEAP_PROFILE,"option add *Button.padX                 5\n");
708   fprintf(HEAP_PROFILE,"option add *tile                        bgTexture\n");
709   fprintf(HEAP_PROFILE,"option add *Radiobutton.font            -*-courier*-medium-r-*-*-14-*-*\n");
710   fprintf(HEAP_PROFILE,"option add *Radiobutton.relief          flat\n");
711   fprintf(HEAP_PROFILE,"option add *Radiobutton.borderWidth     2\n");
712   fprintf(HEAP_PROFILE,"option add *Radiobutton.highlightThickness 0\n");
713   fprintf(HEAP_PROFILE,"option add *Htext.font                  -*-times*-bold-r-*-*-14-*-*\n");
714   fprintf(HEAP_PROFILE,"option add *Htext.tileOffset            no\n");
715   fprintf(HEAP_PROFILE,"option add *header.font                 -*-times*-medium-r-*-*-14-*-*\n");
716   fprintf(HEAP_PROFILE,"option add *Barchart.font                -*-helvetica-bold-r-*-*-14-*-*\n");
717
718   fprintf(HEAP_PROFILE,"option add *Barchart.title              \"Heap profile of program ");
719   // TO DO: Add program name in here
720   fprintf(HEAP_PROFILE,"\"\n");
721
722   fprintf(HEAP_PROFILE,"option add *Axis.tickFont               -*-helvetica-medium-r-*-*-12-*-*\n");
723   fprintf(HEAP_PROFILE,"option add *Axis.titleFont              -*-helvetica-bold-r-*-*-12-*-*\n");
724   fprintf(HEAP_PROFILE,"option add *x.Command                   FormatXTicks\n");
725   fprintf(HEAP_PROFILE,"option add *x.Title                     \"Time (seconds)\"\n");
726   fprintf(HEAP_PROFILE,"option add *y.Title                     \"Heap usage (000 bytes)\"\n");
727   fprintf(HEAP_PROFILE,"option add *activeBar.Foreground        pink\noption add *activeBar.stipple             dot3\noption add *Element.Background            red\noption add *Element.Relief         raised\n");
728   fprintf(HEAP_PROFILE,"option add *Grid.dashes                 { 2 4 }\noption add *Grid.hide                  no\noption add *Grid.mapX                       \"\"\n");
729   fprintf(HEAP_PROFILE,"option add *Legend.Font                 \"-*-helvetica*-bold-r-*-*-12-*-*\"\noption add *Legend.activeBorderWidth       2\noption add *Legend.activeRelief              raised \noption add *Legend.anchor              ne \noption add *Legend.borderWidth             0\noption add *Legend.position          right\n");
730   fprintf(HEAP_PROFILE,"option add *TextMarker.Font             *Helvetica-Bold-R*14*\n");
731   fprintf(HEAP_PROFILE,"set visual [winfo screenvisual .] \nif { $visual != \"staticgray\" && $visual != \"grayscale\" } {\n    option add *print.background    yellow\n    option add *quit.background         red\n    option add *quit.activeBackground      red2\n}\n");
732   fprintf(HEAP_PROFILE,"htext .title -text {\n    Heap profile\n}\n");
733   fprintf(HEAP_PROFILE,"htext .header -text {\n    \%%\% \n");
734   fprintf(HEAP_PROFILE,"      radiobutton .header.stacked -text stacked -variable barMode \\\n            -anchor w -value \"stacked\" -selectcolor red -command {\n            .graph configure -barmode $barMode\n        } \n        .header append .header.stacked -width 1.5i -anchor w\n");
735   fprintf(HEAP_PROFILE,"    \%%\%      Heap usage stacked: overall height is the sum of the heap used. \n    \%%\% \n");
736   fprintf(HEAP_PROFILE,"        radiobutton .header.aligned -text aligned -variable barMode \\\n          -anchor w -value \"aligned\" -selectcolor yellow -command {\n            .graph configure -barmode $barMode        }\n        .header append .header.aligned -width 1.5i -fill x\n");
737   fprintf(HEAP_PROFILE,"    \%%\%      Heap usage components displayed side-by-side.\n    \%%\%\n");
738   fprintf(HEAP_PROFILE,"        radiobutton .header.overlap -text \"overlap\" -variable barMode \\\n            -anchor w -value \"overlap\" -selectcolor green -command {\n            .graph configure -barmode $barMode\n        }\n         .header append .header.overlap -width 1.5i -fill x\n");
739   fprintf(HEAP_PROFILE,"    \%%\%      Heap  usage shown as an overlapped histogram.\n    \%%\%\n");
740   fprintf(HEAP_PROFILE,"        radiobutton .header.normal -text \"normal\" -variable barMode \\\n            -anchor w -value \"normal\" -selectcolor blue -command {\n            .graph configure -barmode $barMode\n        }\n         .header append .header.normal -width 1.5i -fill x\n");
741   fprintf(HEAP_PROFILE,"    \%%\%      Heap components overlayed one on top of the next. \n}\n");
742   fprintf(HEAP_PROFILE,"htext .footer -text { To create a postscript file \"heap_profile.ps\", press the \%%\%\n  button $htext(widget).print -text print -command {\n        puts stderr [time {.graph postscript output heap_profile.ps}]\n  }\n  $htext(widget) append $htext(widget).print\n\%%\% button.}\n");
743   fprintf(HEAP_PROFILE,"barchart .graph -tile bgTexture\n");
744
745   // This is where the actual data comes in
746
747   fprintf(HEAP_PROFILE,"vector X ");
748   names_of_heap_objects(HEAP_PROFILE,ho_m);
749   fprintf(HEAP_PROFILE,"\nX set { ");
750   PrintXaxis(HEAP_PROFILE,th);
751   fprintf(HEAP_PROFILE," }\n");
752
753   print_heap_object_matrix(HEAP_PROFILE,th, ho_m);
754
755   // NAMES FOR THE ATTRIBUTES 
756   fprintf(HEAP_PROFILE,"set attributes {\n");
757   names_and_colour_assignment(HEAP_PROFILE,ho_m);
758   fprintf(HEAP_PROFILE,"}\n");
759   
760   fprintf(HEAP_PROFILE,"foreach {label yData color stipple} $attributes {\n    .graph element create $yData -label $label -bd 1 \\\n    -ydata $yData -xdata X -fg ${color}3 -bg ${color}1 -stipple $stipple\n}\n");
761   fprintf(HEAP_PROFILE,".header.stacked invoke\n");
762   fprintf(HEAP_PROFILE,"scrollbar .xbar -command { .graph axis view x } -orient horizontal\nscrollbar .ybar -command { .graph axis view y } -orient vertical\n.graph axis configure x -scrollcommand { .xbar set } -logscale no -loose no\n.graph axis configure y -scrollcommand { .ybar set } -logscale no -loose no\n");
763   fprintf(HEAP_PROFILE,"table . \\\n    0,0 .title -fill x \\\n    1,0 .header -fill x  \\\n    2,0 .graph -fill both \\\n    3,0 .xbar -fill x \\\n    5,0 .footer -fill x\n");
764   fprintf(HEAP_PROFILE,"table configure . r0 r1 r3 r4 r5 -resize none\n");
765   fprintf(HEAP_PROFILE,"Blt_ZoomStack .graph\nBlt_Crosshairs .graph\nBlt_ActiveLegend .graph\nBlt_ClosestPoint .graph\n");
766   fprintf(HEAP_PROFILE,".graph marker bind all <B2-Motion> {\n    set coords [\%W invtransform \%%x \%y]\n    catch { \%W marker configure [\%W marker get current] -coords $coords }\n}\n.graph marker bind all <Enter> {\n    set marker [\%W marker get current]\n    catch { %W marker configure $marker -bg green}\n}\n.graph marker bind all <Leave> {\n    set marker [\%W marker get current]\n    catch { %W marker configure $marker -bg \"\"}\n}\n");
767
768 }
769
770
771 /* -----------------------------------------------------------------------------
772  * Read and create the raw profile data structure
773  * -------------------------------------------------------------------------- */
774
775 /* void readRawProfile(FILE *fptr,int *nonodes) { */
776
777 void readRawProfile(FILE *fp,int *nonodes, int MaxNoNodes) {
778   char    line[MAX_PROFILE_LINE_LENGTH];
779   char    stack[MAX_PROFILE_LINE_LENGTH];
780   char    rest[MAX_PROFILE_LINE_LENGTH];
781   int     i,nolines,sstepline,syncs;
782   char   *ptr,*drag;
783
784   float   comp_max,      comp_avg,      comp_min,          /* SYNCS    */
785           comm_max,      comm_avg,      comm_min,          /* COMP     */
786           comp_idle_max, comp_idle_avg, comp_idle_min;     /* COMM     */
787
788   /* Cost  relationships are comp=scc, comm=ticks, comp_idle=bytes */
789
790   long int hmax,havg,hmin;                                 /* COMPIDLE */
791
792   /* set to zero for now. Might use these later for heap costs. */
793
794   int     *result; /* Something to do with daVinci? */
795
796   /* GHC specific variables */
797
798   int a,b,c,d,x,y,z,count, next, throw;
799   int newloop;
800   char *ignore;
801   char e[MAX_STRING_SIZE];
802   char f[MAX_STRING_SIZE];
803   char g[MAX_STRING_SIZE];
804   char lline[MAX_PROFILE_LINE_LENGTH];
805
806   /* identifiers generated by the XML handler */
807   char *ccentre=">>cost_centre";
808   char *ccstack=">>cost_centre_stack";
809   char *sccsample=">>scc_sample";
810   char *heapsample=">>heap_sample";
811   char *heapupdate=">>heap_update";
812   char *heapobject=">>heap_object";
813   char *typeconstr=">>type_constr";
814   char *ending=">>";
815
816   char *blank="blank";
817   /* FILE *fp; */
818
819   cc_matrix *cc_m;
820   ccs_matrix *ccs_m;
821   heap_object_matrix *ho_m;
822   type_constr_matrix *tc_m;
823   TheHeap *th;
824
825   FILE *HEAP_PROFILE;
826
827   HEAP_PROFILE = fopen("GHCbarchart.tcl", "w");
828   if (HEAP_PROFILE == NULL){
829    fprintf(stderr,"tcl script generator: ERROR- GHCbarchart.tcl cannot be created\a\n");
830     exit(1);
831   }
832
833   th = (p_TheHeap) malloc (sizeof(TheHeap));
834   cc_m = (p_cc_matrix) malloc (sizeof(cc_matrix));
835   //cc_m = (p_cc_matrix) calloc(MAX_IDENTIFIERS,sizeof(_cc_));
836   ccs_m = (p_ccs_matrix) malloc (sizeof(ccs_matrix));
837   ho_m  = (p_heap_object_matrix) malloc (sizeof(heap_object_matrix));
838   tc_m  = (p_type_constr_matrix) malloc (sizeof(type_constr_matrix));
839
840   /* End of GHC specific variables */
841
842   //fprintf(logFile,"Number 1 %i \n",MAX_IDENTIFIERS*sizeof(_cc_));
843   //fprintf(logFile,"Number 2 %i \n",sizeof(cc_matrix));
844
845   nolines=0; /* Number of lines read in from profile log file */
846
847   /* GHC specific */
848   count = 0;
849   next = 0;
850
851   initialise_cc_matrix(cc_m);
852   initialise_ccs_matrix(ccs_m);
853   initialise_heap_object_matrix(ho_m);
854   initialise_type_constr_matrix(tc_m);
855   initialise_TheHeap(th);
856
857   fprintf(logFile,"MAX_IDENTIFIERS = %i \n",MAX_IDENTIFIERS);
858   
859   /* end GHC specific */
860
861   /* CAF fixing */
862   fill_cc_matrix(cc_m,"CAF:REPOSITORY","PROFILER","PROFILER",MAX_IDENTIFIERS-1);
863   fill_ccs_matrix(ccs_m,MAX_IDENTIFIERS-1,1,0.0,0.0,0.0,0,-1,MAX_IDENTIFIERS-1);
864
865   /* 
866
867   This builds a node in the graph called CAF:REPOSITORY, which can be 
868   found off the root node. All CAFs are subsequently hung from this node
869   which means the node node can be hidden using the abstraction 
870   mechanisms provided by daVinci.
871
872   */
873
874
875   /* This is the GHC file handler which reads the lines from the profile log file and */
876   /* puts the stack and cost information in the raw profile data structure */
877
878    while (fscanf(fp,"%s",lline))
879    { 
880     /* Kill the end of the logfile with the ">>" string */
881     if (strcmp(lline,ending)==0) break;
882
883     /* Deal with the cost centres */
884     if (strcmp(ccentre,lline)==0)
885     {
886       next = fgetc(fp);
887       //while (fscanf(fp," %i %[^ ] %[^ ] %s", &z, e, f, g)!=0)
888       while (fscanf(fp," %i %[^ ] %s", &z, e, f)!=0)
889       {
890         fprintf(logFile,"Declaring cost centre `%i %s %s %s' \n",z,e,f,f);
891         fflush(logFile);
892         fill_cc_matrix(cc_m,e,f,f,z);
893         next = fgetc(fp);
894       }
895     }
896     else 
897     {
898
899       /* Deal with the cost centre stacks */
900       if (strcmp(ccstack,lline)==0)
901       { 
902         next = fgetc(fp);
903         while (fscanf(fp,"%i %i %i",&a,&d,&b)!=0)
904         {
905           if (d==1) /* of size one */
906           {  
907             fprintf(logFile,"Declaring cost centre stack `%i %i %i'\n",a,d,b);
908             fill_ccs_matrix(ccs_m,b,-1,(*ccs_m)[a].scc,(*ccs_m)[a].ticks,(*ccs_m)[a].bytes,0,-1,a);
909           }
910           if (d==2) /* of size > 1 */
911           { 
912             fscanf(fp," %i",&c);
913
914             /* CAF fixing */
915             fprintf(logFile,"Declaring cost centre stack `%i %i %i %i'\n",a,d,b,c);
916             if ((c==1)&&!(strncmp((*cc_m)[b].name,"CAF",2)))
917                // fill_ccs_matrix(ccs_m,b,MAX_IDENTIFIERS-1,(*ccs_m)[a].scc,(*ccs_m)[a].ticks,(*ccs_m)[a].bytes,0,-1,a);
918                /* The line above hangs all CAFs off the CAF:REPOSITORY node
919                   in the daVinci graph. For programs which have a small 
920                   number of CAFs this works nicely. However, when the 
921                   number of CAFs become very large (eg +200) then the 
922                   daVinci graph begins to look horid and, after (say)
923                   +500 CAF nodes, becomes very slow to load. So to 
924                   fix this we replace the code with the line below.
925                */
926                  if (!(strncmp((*cc_m)[b].name,"CAF:main",7)))
927                     /* Treat CAF:main as a normal node */ 
928                     fill_ccs_matrix(ccs_m,b,c,(*ccs_m)[a].scc,(*ccs_m)[a].ticks,(*ccs_m)[a].bytes,0,-1,a); 
929                     /* merge the rest */
930                  else
931                     //add_ccs_costs(ccs_m,0,MAX_IDENTIFIERS-1,(*ccs_m)[a].scc,(*ccs_m)[a].ticks,(*ccs_m)[a].bytes,0,0);
932                     fill_ccs_matrix(ccs_m,MAX_IDENTIFIERS-1,1,(*ccs_m)[a].scc,(*ccs_m)[a].ticks,(*ccs_m)[a].bytes,0,-1,a);
933                 /* This does not even bother registering the new CAFs
934                    as daVinci nodes, but instead just merges the CAF
935                    with the CAF:REPOSITORY node. This greatly reduces
936                    the number of CAFs daVinci has to deal with, though
937                    may make the graph look a little different!
938
939                    Also note that now Simon has changed the semantics,
940                    you will want to treat adding CAF nodes in a 
941                    different way to adding normal program nodes
942                  */
943             else 
944                /* Normal mode */
945                fill_ccs_matrix(ccs_m,b,c,(*ccs_m)[a].scc,(*ccs_m)[a].ticks,(*ccs_m)[a].bytes,0,-1,a);
946           }
947           next = fgetc(fp);
948         }
949       } 
950       else
951       {
952
953         /* Deal with the scc_samples */
954         if (strcmp(sccsample,lline)==0)
955         {
956           next = fgetc(fp);
957           while (fscanf(fp,"%i %i %i %i",&a,&d,&b,&c))
958           {
959             fprintf(logFile,"Loading scc_samples `%i %i %i %i'\n",a,d,b,c);
960             add_ccs_costs(ccs_m,0,a,d,b,c,0,0);
961             next = fgetc(fp);
962           }
963         } /* end sccsample if */
964         else 
965         {
966         
967           /* Deal with the heap samples */
968           if (strcmp(heapsample,lline)==0)
969           {
970             next = fgetc(fp);
971             while (fscanf(fp,"%i %i %i",&a,&d,&b))
972             {
973               fprintf(logFile,"Loading heap_samples `%i %i %i'\n",a,d,b);
974               add_heap_sample_costs(ccs_m,0,a,0,0,0,d,b);
975               next = fgetc(fp);
976             }
977           } /* end heapsample if */
978           else 
979           {
980
981             /* Deal with the heap objects */
982             if (strcmp(heapobject,lline)==0)
983             {
984               next = fgetc(fp);
985               while (fscanf(fp,"%i %i",&a,&d)) 
986               {
987                 if (d==1) 
988                 {
989                   fscanf(fp," %s %i",e,&b);
990                   add_heap_object(ho_m,a,d,e,b);
991                 }
992                 else 
993                 {
994                   fscanf(fp," %s",e);
995                   add_heap_object(ho_m,a,d,e,-1);
996                 }
997                 next = fgetc(fp);
998               }
999             } /* end heapobject if */
1000             else
1001             {
1002
1003               /* Deal with the type constructors */ 
1004               if (strcmp(typeconstr,lline)==0)
1005               {
1006                 next = fgetc(fp);
1007                 while (fscanf(fp,"%i %s %s",&a,e,f))
1008                 {
1009                   add_type_constr_object(tc_m,a,e,f);
1010                   next = fgetc(fp);
1011                 }
1012               } /* end type constructor if */
1013               else
1014               {
1015                 
1016                 /* Deal with the heap_updates */ 
1017                 if (strcmp(heapupdate,lline)==0)
1018                 {
1019                   next = fgetc(fp);
1020                   while (fscanf(fp,"%i %i %i %i %i %i",&a,&d,&b,&c,&z,&x))
1021                   {
1022                     add_to_TheHeap(th,a,b,c,z);
1023                     fprintf(logFile,"Adding heap sample %i %i %i %i\n",a,b,c,z);
1024                     while (x) /* more than one sample */
1025                     {
1026                       fscanf(fp," %i %i %i %i",&b,&c,&z,&x);
1027                       add_to_TheHeap(th,a,b,c,z);
1028                       fprintf(logFile,"Adding heap sample %i %i %i %i\n",a,b,c,z);
1029                     }  
1030                     next = fgetc(fp);
1031                   }
1032
1033                 } /* end heap update if */
1034
1035               }  /* end type constructor else */
1036
1037              } /* end heapobject else */
1038
1039            } /* end heapsample else */
1040          } /* end sccsample else */
1041        } /* end ccstack else */
1042      } /* end ccstack if */
1043    } /* end while */
1044
1045    print_cc_matrix(cc_m);
1046    print_ccs_matrix(ccs_m);
1047    fprintf(logFile,"There are %i stacks\n",CountStacks(ccs_m));
1048    print_type_constr_matrix(tc_m);
1049
1050    /* Functions for heap profile */
1051    print_TheHeap(th);
1052    fprintf(logFile,"The units for the x axis are \n");
1053    PrintXaxis(logFile,th);
1054    fprintf(logFile,"\n");
1055    fprintf(logFile,"There are %i distinct heap objects\n",number_of_heap_objects(ho_m));
1056    names_of_heap_objects(logFile,ho_m);
1057    names_and_colour_assignment(logFile,ho_m);
1058    print_heap_object_matrix(logFile,th,ho_m);
1059
1060    PrintAllStacks(ccs_m,cc_m);
1061    /* comment out line below to remove the heap profile generator */
1062    produce_HEAP_PROFILE(HEAP_PROFILE,th,ho_m);
1063    fclose(HEAP_PROFILE);
1064
1065    /* End of GHC file handler */
1066   
1067
1068   /* Now process the stack matrix */ 
1069
1070   for (newloop=0;newloop<MAX_IDENTIFIERS;newloop++) 
1071   { if ((*ccs_m)[newloop].cc != 0)
1072     {
1073          
1074     sstepline = 0;
1075     FormStack2(ccs_m,cc_m,newloop,stack);
1076
1077     syncs = 0;     
1078     comp_max = (float)(*ccs_m)[newloop].scc; 
1079     comp_avg = (float)(*ccs_m)[newloop].scc; 
1080     comp_min = (float)(*ccs_m)[newloop].scc; 
1081     comm_max = (float)(*ccs_m)[newloop].ticks; 
1082     comm_avg = (float)(*ccs_m)[newloop].ticks; 
1083     comm_min = (float)(*ccs_m)[newloop].ticks; 
1084     comp_idle_max = (float)(*ccs_m)[newloop].bytes; 
1085     comp_idle_avg = (float)(*ccs_m)[newloop].bytes; 
1086     comp_idle_min = (float)(*ccs_m)[newloop].bytes; 
1087     hmax = 0.0; havg = 0.0; hmin = 0.0; 
1088
1089       /* Dynamic memory allocation for raw_profile data structure */ 
1090
1091       if (raw_profile_next==raw_profile_size) enlargeRawProfile();
1092
1093       /* Assign data from single logfile entry to raw_profile data structure */
1094       /* this deals with the cost metrics */
1095
1096       raw_profile[raw_profile_next].active            = 1;
1097       raw_profile[raw_profile_next].cost.syncs        = syncs;
1098       raw_profile[raw_profile_next].cost.comp_max     = comp_max;
1099       raw_profile[raw_profile_next].cost.comp_avg     = comp_avg;
1100       raw_profile[raw_profile_next].cost.comp_min     = comp_min;
1101       raw_profile[raw_profile_next].cost.comm_max     = comm_max;
1102       raw_profile[raw_profile_next].cost.comm_avg     = comm_avg;
1103       raw_profile[raw_profile_next].cost.comm_min     = comm_min;
1104       raw_profile[raw_profile_next].cost.comp_idle_max= comp_idle_max;
1105       raw_profile[raw_profile_next].cost.comp_idle_avg= comp_idle_avg;
1106       raw_profile[raw_profile_next].cost.comp_idle_min= comp_idle_min;
1107       raw_profile[raw_profile_next].cost.hrel_max     = hmax;
1108       raw_profile[raw_profile_next].cost.hrel_avg     = havg;
1109       raw_profile[raw_profile_next].cost.hrel_min     = hmin;
1110
1111       /* this deals with the stack itself */
1112
1113       raw_profile[raw_profile_next].stack=calloc(MAX_STACK_DEPTH,
1114                                                  sizeof(int));
1115       if (raw_profile[raw_profile_next].stack==NULL) {
1116         fprintf(stderr,"{readRawProfile} unable to allocate stack entry");
1117         exit(1);
1118       }
1119
1120       fprintf(logFile,"STACK=\"%s\"\n",stack);
1121       raw_profile[raw_profile_next].stack_size=1;
1122       /* move the stack read frame to the first space (or comma) in the stack string */ 
1123       for(ptr=stack; ((*ptr)!=' ') && (*ptr!=',');ptr++) {}
1124       fprintf(logFile,"TOS=%d at line %d\n",*ptr,sstepline);
1125      
1126       /* to distinguish the head of the stack from the rest */
1127       /* if read frame points to space you are at the head of the stack */
1128       if (*ptr==' ') 
1129         /* raw_profile[raw_profile_next].stack[0]
1130           =lookupSymbolTable(CG_SSTEP,sstepline,(*ptr='\0',stack)); */
1131         /* This line has changed as GHC treats its cost-centres in a different     */
1132         /* way to BSP. There is no distinction between 'a cost centre at line x'   */
1133         /* and a normal cost centre. The fix is easy, just treat all cost centres, */
1134         /* even those at the head of the stack in the same way.                    */
1135            raw_profile[raw_profile_next].stack[0]
1136           =lookupSymbolTable(CG_STACK,sstepline,(*ptr='\0',stack));
1137       else
1138       /* otherwise you are looking at just another stack element */
1139         raw_profile[raw_profile_next].stack[0]
1140           =lookupSymbolTable(CG_STACK,sstepline,(*ptr='\0',stack));
1141
1142       ptr++; /* move the read frame on one */
1143       drag=ptr;
1144       for(;*ptr;ptr++) { /* find the next element in the stack */
1145         if (*ptr==',') {
1146           *ptr='\0';
1147           if (Verbose) fprintf(logFile,"NAME=\"%s\"\n",drag); /* name of the next element */
1148           if (!ignore_function(drag)) {
1149             raw_profile[raw_profile_next].stack[
1150               raw_profile[raw_profile_next].stack_size++]
1151               = lookupSymbolTable(CG_STACK,0,drag); /* add element to the raw_profile */
1152           }
1153           drag = ptr+1;
1154         }
1155       }
1156
1157       /* create cost object */
1158
1159       raw_profile[raw_profile_next].cost.proc
1160         =calloc(bsp_p,sizeof(object_cost_proc));
1161       if (raw_profile[raw_profile_next].cost.proc==NULL) {
1162         fprintf(stderr,"Unable to allocate storage");
1163         exit(0);
1164       }
1165   
1166       /* process the HREL information - one set for every BSP process */
1167
1168       for(i=0;i<bsp_p;i++) {
1169
1170          raw_profile[raw_profile_next].cost.proc[i].proc_comp     = 0.0; 
1171          raw_profile[raw_profile_next].cost.proc[i].proc_comm     = 0.0; 
1172          raw_profile[raw_profile_next].cost.proc[i].proc_comp_idle= 0.0; 
1173          raw_profile[raw_profile_next].cost.proc[i].proc_hrel_in  = 0; 
1174          raw_profile[raw_profile_next].cost.proc[i].proc_hrel_out = 0; 
1175
1176       }
1177
1178       raw_profile_next++;    /* Increase the raw profile data structure counter */
1179       nolines++;             /* Increase the number of lines read               */
1180
1181        strcpy(stack,""); /* reset the stack */
1182     } /* end of new if statement */
1183   } /* end of new for loop */
1184
1185   *nonodes = symbol_table_next;
1186   fprintf(logFile,"%s: read %d lines from profile.Graph contains %i nodes.\n",
1187           Pgm,nolines,symbol_table_next);
1188
1189   free_cc_matrix(cc_m); /* be nice and clean up the cost centre matrix */
1190 }
1191
1192 /* -----------------------------------------------------------------------------
1193  * Pretty print the raw profile data
1194  * -------------------------------------------------------------------------- */
1195
1196 void printRawProfile() {
1197   int i,j;
1198   object_cost *cost;
1199   int         *stack;
1200   
1201   fprintf(logFile,"\n\nRAW DATA:\n");
1202   for(i=0;i<raw_profile_next;i++) {
1203     cost  = &raw_profile[i].cost;
1204     stack = raw_profile[i].stack;
1205     fprintf(logFile,"Stack=[");
1206     for(j=0;j<raw_profile[i].stack_size;j++) 
1207       printSymbolTable_entry(stack[j]);
1208     fprintf(logFile,"] %d Syncs %f Comp %f Comm %f Wait\n\n",
1209             cost->syncs,cost->comp_max,cost->comm_max,cost->comp_idle_max);
1210   }
1211 }
1212
1213 /* -----------------------------------------------------------------------------
1214  * Create connectivity matrix
1215  * -------------------------------------------------------------------------- */
1216
1217 void createConnectivityMatrix(int NoNodes,Matrix *graph,
1218                               Matrix *costs,int *root, int inherit) {
1219   object_cost zero_cost,*update;
1220   int i,j,this,next;
1221
1222
1223   zero_cost.comp_max     =0.0;
1224   zero_cost.comp_avg     =0.0;
1225   zero_cost.comp_min     =0.0;
1226   zero_cost.comm_max     =0.0;
1227   zero_cost.comm_avg     =0.0;
1228   zero_cost.comm_min     =0.0;
1229   zero_cost.comp_idle_max=0.0;
1230   zero_cost.comp_idle_avg=0.0;
1231   zero_cost.comp_idle_min=0.0;
1232   zero_cost.hrel_max     =0;
1233   zero_cost.hrel_avg     =0;
1234   zero_cost.hrel_min     =0;
1235   zero_cost.syncs=0;
1236   zero_cost.proc = NULL;
1237   *graph = newMat(NoNodes,NoNodes,sizeof(int),(i=0,&i));
1238   *costs = newMat(NoNodes,1,sizeof(object_cost),&zero_cost);
1239   for(i=0;i<NoNodes;i++) {
1240     update=&Mat(object_cost,*costs,i,0);
1241     update->proc=calloc(bsp_p,sizeof(object_cost_proc));
1242     if (update->proc==NULL){
1243       fprintf(stderr,"Unable to allocate storage");
1244       exit(0);
1245     }
1246     for(j=0;j<bsp_p;j++) {
1247       update->proc[j].proc_comp      =0.0;
1248       update->proc[j].proc_comm      =0.0;
1249       update->proc[j].proc_comp_idle =0.0;
1250       update->proc[j].proc_hrel_in   =0;
1251       update->proc[j].proc_hrel_out  =0;
1252     }
1253   }
1254       
1255   for(i=0;i<raw_profile_next;i++) {
1256     if (raw_profile[i].active) {
1257       this = raw_profile[i].stack[0];
1258       next = this;
1259       Mat(int,*graph,this,next) = 1;
1260       update = &Mat(object_cost,*costs,next,0);
1261       add_costs(update,raw_profile[i].cost);
1262       for(j=1;j<raw_profile[i].stack_size;j++) {
1263         this = next;
1264         next = raw_profile[i].stack[j];
1265         Mat(int,*graph,next,this)=1;
1266         update = &Mat(object_cost,*costs,next,0);
1267         /* include this line for INHERITANCE; remove it for not! */
1268         if (inherit) add_costs(update,raw_profile[i].cost);
1269       }
1270     }
1271   }
1272   *root =  raw_profile[0].stack[raw_profile[0].stack_size-1];
1273
1274   /* Check graph isn't empty */
1275   if (!Mat_dense(*costs,*root,0)) *root=-1;
1276 }
1277
1278 void printConnectivityMatrix(Matrix graph,Matrix costs,int root) { 
1279   int i,j;
1280   object_cost cost;
1281
1282   fprintf(logFile,"Root node is %d\n",root);
1283   for(i=0;i<graph.rows;i++) {
1284     fprintf(logFile,"%4d)",i);
1285     printSymbolTable_entry(i);
1286     cost = Mat(object_cost,costs,i,0);
1287     fprintf(logFile,"%d %f %f %f\n\tBranch=[",
1288             cost.syncs,cost.comp_max,cost.comm_max,cost.comp_idle_max);
1289     for(j=0;j<graph.cols;j++) 
1290       if (Mat_dense(graph,i,j)) fprintf(logFile,"%d ",j);
1291     fprintf(logFile,"]\n\n");
1292   }
1293 }