summaryrefslogtreecommitdiff
path: root/utils/prof/cgprof
diff options
context:
space:
mode:
authorSimon Marlow <simonmar@microsoft.com>2006-04-07 02:05:11 +0000
committerSimon Marlow <simonmar@microsoft.com>2006-04-07 02:05:11 +0000
commit0065d5ab628975892cea1ec7303f968c3338cbe1 (patch)
tree8e2afe0ab48ee33cf95009809d67c9649573ef92 /utils/prof/cgprof
parent28a464a75e14cece5db40f2765a29348273ff2d2 (diff)
downloadhaskell-0065d5ab628975892cea1ec7303f968c3338cbe1.tar.gz
Reorganisation of the source tree
Most of the other users of the fptools build system have migrated to Cabal, and with the move to darcs we can now flatten the source tree without losing history, so here goes. The main change is that the ghc/ subdir is gone, and most of what it contained is now at the top level. The build system now makes no pretense at being multi-project, it is just the GHC build system. No doubt this will break many things, and there will be a period of instability while we fix the dependencies. A straightforward build should work, but I haven't yet fixed binary/source distributions. Changes to the Building Guide will follow, too.
Diffstat (limited to 'utils/prof/cgprof')
-rw-r--r--utils/prof/cgprof/Makefile9
-rw-r--r--utils/prof/cgprof/README7
-rw-r--r--utils/prof/cgprof/cgprof.c1284
-rw-r--r--utils/prof/cgprof/cgprof.h82
-rw-r--r--utils/prof/cgprof/daVinci.c760
-rw-r--r--utils/prof/cgprof/daVinci.h95
-rw-r--r--utils/prof/cgprof/main.c436
-rw-r--r--utils/prof/cgprof/matrix.c98
-rw-r--r--utils/prof/cgprof/matrix.h42
-rw-r--r--utils/prof/cgprof/symbol.c115
-rw-r--r--utils/prof/cgprof/symbol.h58
11 files changed, 2986 insertions, 0 deletions
diff --git a/utils/prof/cgprof/Makefile b/utils/prof/cgprof/Makefile
new file mode 100644
index 0000000000..17c567537a
--- /dev/null
+++ b/utils/prof/cgprof/Makefile
@@ -0,0 +1,9 @@
+TOP=../../..
+include $(TOP)/mk/boilerplate.mk
+
+C_PROG = cgprof
+INSTALL_LIBEXECS=$(C_PROG)
+
+SRC_CC_OPTS += -Wall -I$(GHC_INCLUDE_DIR)
+
+include $(TOP)/mk/target.mk
diff --git a/utils/prof/cgprof/README b/utils/prof/cgprof/README
new file mode 100644
index 0000000000..2c4ca16bc9
--- /dev/null
+++ b/utils/prof/cgprof/README
@@ -0,0 +1,7 @@
+
+Please read the instructions in the section `Introduction - Using the
+profiling tool' before you begin:
+
+http://www.dcs.warwick.ac.uk/people/academic/Stephen.Jarvis/profiler/index.html
+
+This contains all the necessary compilation instructions etc.
diff --git a/utils/prof/cgprof/cgprof.c b/utils/prof/cgprof/cgprof.c
new file mode 100644
index 0000000000..8ee66e1f52
--- /dev/null
+++ b/utils/prof/cgprof/cgprof.c
@@ -0,0 +1,1284 @@
+/* ------------------------------------------------------------------------
+ * $Id: cgprof.c,v 1.6 2004/08/13 13:11:22 simonmar Exp $
+ *
+ * Copyright (C) 1995-2000 University of Oxford
+ *
+ * Permission to use, copy, modify, and distribute this software,
+ * and to incorporate it, in whole or in part, into other software,
+ * is hereby granted without fee, provided that
+ * (1) the above copyright notice and this permission notice appear in
+ * all copies of the source code, and the above copyright notice
+ * appear in clearly visible form on all supporting documentation
+ * and distribution media;
+ * (2) modified versions of this software be accompanied by a complete
+ * change history describing author, date, and modifications made;
+ * and
+ * (3) any redistribution of the software, in original or modified
+ * form, be without fee and subject to these same conditions.
+ * --------------------------------------------------------------------- */
+
+#include "ghcconfig.h"
+#if HAVE_STRING_H
+#include <string.h>
+#endif
+
+#include "daVinci.h"
+#include "symbol.h"
+#include "cgprof.h"
+#include "matrix.h"
+
+/* -----------------------------------------------------------------------------
+ * Data structures
+ * -------------------------------------------------------------------------- */
+
+int raw_profile_next=0;
+int raw_profile_size=0;
+parsed_cost_object *raw_profile=NULL;
+
+/* -----------------------------------------------------------------------------
+ * Create/grow data sequence of raw profile data
+ * -------------------------------------------------------------------------- */
+
+void enlargeRawProfile() {
+
+ if (raw_profile_size==0) {
+ raw_profile_next = 0;
+ raw_profile_size = RAW_PROFILE_INIT_SIZE;
+ raw_profile = calloc(raw_profile_size,sizeof(parsed_cost_object));
+ } else {
+ raw_profile_size += RAW_PROFILE_INIT_SIZE;
+ raw_profile = realloc(raw_profile,
+ raw_profile_size*sizeof(parsed_cost_object));
+ }
+ if (raw_profile==NULL) {
+ fprintf(stderr,"{enlargeRawProfile} unable to allocate %d elements",
+ raw_profile_size);
+ exit(1);
+ }
+}
+
+/* -----------------------------------------------------------------------------
+ * Function that adds two cost centers together
+ *
+ * This will be used to generate the inheretance profile.
+ * -------------------------------------------------------------------------- */
+
+void add_costs(object_cost *left, object_cost right) {
+
+ left->syncs += right.syncs;
+ left->comp_max += right.comp_max;
+ left->comp_avg += right.comp_avg;
+ left->comp_min += right.comp_min;
+ left->comm_max += right.comm_max;
+ left->comm_avg += right.comm_avg;
+ left->comm_min += right.comm_min;
+ left->comp_idle_max += right.comp_idle_max;
+ left->comp_idle_avg += right.comp_idle_avg;
+ left->comp_idle_min += right.comp_idle_min;
+ left->hrel_max += right.hrel_max;
+ left->hrel_avg += right.hrel_avg;
+ left->hrel_min += right.hrel_min;
+ if ((left->proc==NULL) || (right.proc==NULL)) {
+ fprintf(stderr,"Cost is null");
+ exit(0);
+ }
+}
+
+
+int ignore_function(char *fname) {
+ return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * GHC specific data structures
+ * -------------------------------------------------------------------------- */
+
+/* Globals */
+/* You will need to update these when you increase the number of */
+/* cost centres, cost centre stacks, heap objects */
+
+ #define MAX_IDENTIFIERS 2000 /* maximum number of identifiers */
+ /* or size of matrix structure */
+
+ /* make this dynamic */
+
+ #define MAX_TIME 100 /* Maximum serial time for heap profile */
+ #define MAX_SAMPLES 50 /* Maximum heap samples */
+
+ /* To do: modify this to be dynamic */
+
+ #define MAX_STRING_SIZE 70
+ #define MAX_LINE_LENGTH 80
+ #define EOF (-1)
+
+/* Cost centre data structure */
+
+ struct cost_centre { char *name;
+ char *module;
+ char *group;
+ } _cc_;
+
+ typedef struct cost_centre cc_matrix[MAX_IDENTIFIERS];
+
+ //typedef struct cost_centre *cc_matrix;
+
+ typedef cc_matrix* p_cc_matrix;
+ typedef char* MY_STRING;
+
+/* Heap sample structure */
+
+ struct heap_sample {
+ int count; /* heap_sample */
+ };
+
+ typedef struct heap_sample heap_sample_matrix[MAX_IDENTIFIERS];
+ typedef heap_sample_matrix* p_heap_sample_matrix;
+
+/* Cost centre stack data structure */
+
+ struct cost_centre_stack {
+ int cc;
+ int ccs;
+ int scc; /* scc_sample */
+ int ticks; /* scc_sample */
+ int bytes; /* scc_sample */
+ p_heap_sample_matrix hsm; /* heap_sample */
+ };
+
+ typedef struct cost_centre_stack ccs_matrix[MAX_IDENTIFIERS];
+ typedef ccs_matrix* p_ccs_matrix;
+
+/* Heap object data structure */
+
+ struct heap_object { int type; /* type of heap object */
+ char* descriptor;
+ int type_constr_ref; /* if present */
+ };
+
+ typedef struct heap_object heap_object_matrix[MAX_IDENTIFIERS];
+ typedef heap_object_matrix* p_heap_object_matrix;
+
+/* Type constructor structure */
+
+ struct type_constr { char* module;
+ char* name;
+ };
+
+ typedef struct type_constr type_constr_matrix[MAX_IDENTIFIERS];
+ typedef type_constr_matrix* p_type_constr_matrix;
+
+/* Heap update structure */
+
+ struct heap_update_sample { int ccs; /* associated cost centre stack */
+ int ho; /* associated heap object */
+ int count;
+ };
+
+ typedef struct heap_update_sample heap_update_list[MAX_SAMPLES];
+ typedef heap_update_list* p_heap_update_list;
+
+ struct heap_update_record { int no_samples; /* Number of samples */
+ p_heap_update_list acc_samples;
+ };
+
+ typedef struct heap_update_record TheHeap[MAX_TIME];
+ typedef TheHeap* p_TheHeap;
+
+
+/* -----------------------------------------------------------------------------
+ * GHC specific functions
+ * -------------------------------------------------------------------------- */
+
+// Initialisation routines
+
+void initialise_heap_update_list(heap_update_list *m)
+{
+ int i;
+ for (i=0; i<MAX_SAMPLES;i++)
+ {
+ (*m)[i].ccs = -1;
+ (*m)[i].ho = -1;
+ (*m)[i].count = -1;
+ }
+}
+
+void add_to_heap_update_list(heap_update_list *m, int ccs, int ho, int count, int pos)
+{
+ (*m)[pos].ccs = ccs;
+ (*m)[pos].ho = ho;
+ (*m)[pos].count = count;
+}
+
+void initialise_TheHeap(TheHeap *h)
+{
+ int i;
+ for (i=0; i<MAX_TIME;i++)
+ {
+ heap_update_list *h_u_l;
+ h_u_l = (p_heap_update_list) malloc (sizeof(heap_update_list));
+ initialise_heap_update_list(h_u_l);
+ (*h)[i].acc_samples = h_u_l;
+ (*h)[i].no_samples = 0;
+ }
+}
+
+void add_to_TheHeap(TheHeap *h, int time, int ccs, int ho, int count)
+{
+ add_to_heap_update_list((*h)[time].acc_samples,ccs,ho,count,(*h)[time].no_samples);
+ (*h)[time].no_samples++;
+}
+
+void initialise_cc_matrix(cc_matrix *m)
+{
+ int i;
+ char *blank="blank"; /* To do: Modify this terminator string */
+ for (i=0; i<MAX_IDENTIFIERS; i++)
+ {
+ (*m)[i].name = (MY_STRING) malloc ((MAX_STRING_SIZE));
+ (*m)[i].module = (MY_STRING) malloc ((MAX_STRING_SIZE));
+ (*m)[i].group = (MY_STRING) malloc ((MAX_STRING_SIZE));
+
+ strcpy((*m)[i].name,blank);
+ strcpy((*m)[i].module,blank);
+ strcpy((*m)[i].group,blank);
+ }
+}
+
+void free_cc_matrix(cc_matrix *m)
+{
+ int i;
+ for (i=0; i<MAX_IDENTIFIERS; i++)
+ {
+ free((*m)[i].name);
+ free((*m)[i].module);
+ free((*m)[i].group);
+ }
+ free(m);
+}
+
+void initialise_heap_object_matrix(heap_object_matrix *m)
+{
+ int i;
+ char *blank="blank"; /* To do: ditto */
+ for (i=0; i<MAX_IDENTIFIERS; i++)
+ {
+ (*m)[i].type = -1;
+ (*m)[i].descriptor = (MY_STRING) malloc ((MAX_STRING_SIZE));
+ strcpy((*m)[i].descriptor,blank);
+ (*m)[i].type_constr_ref = -1;
+ }
+}
+
+void initialise_type_constr_matrix(type_constr_matrix *m)
+{
+ int i;
+ char *blank="blank";
+ for (i=0; i<MAX_IDENTIFIERS; i++)
+ {
+ (*m)[i].module = (MY_STRING) malloc ((MAX_STRING_SIZE));
+ (*m)[i].name = (MY_STRING) malloc ((MAX_STRING_SIZE));
+ strcpy((*m)[i].module,blank);
+ strcpy((*m)[i].name,blank);
+ }
+}
+
+void initialise_heap_sample_matrix(heap_sample_matrix *m)
+{
+ int i;
+ for (i=0; i<MAX_IDENTIFIERS; i++)
+ { (*m)[i].count = -1; }
+}
+
+void initialise_ccs_matrix(ccs_matrix *m)
+{
+ int i;
+ for (i=0; i<MAX_IDENTIFIERS; i++)
+ {
+ /* Stack heap samples */
+ heap_sample_matrix *hs_m;
+ hs_m = (p_heap_sample_matrix) malloc (sizeof(heap_sample_matrix));
+ initialise_heap_sample_matrix(hs_m);
+ (*m)[i].hsm = hs_m;
+ /* Stack scc samples */
+ (*m)[i].cc = 0;
+ (*m)[i].ccs = 0;
+ (*m)[i].scc = 0;
+ (*m)[i].ticks = 0;
+ (*m)[i].bytes = 0;
+ }
+}
+
+
+// Filling matrix routines
+
+char* StripDoubleQuotes(char* s) /* For fussy daVinci! */
+{
+ char *p = s;
+ char *tempchar;
+ char *empty="";
+ char *tempstring = (MY_STRING) malloc ((MAX_STRING_SIZE));
+ strcpy(tempstring,empty);
+ while (*p)
+ { if (*p!='"')
+ { tempchar = p; strncat(tempstring,p,1);
+ }
+ p++;
+ }
+ return tempstring;
+}
+
+void fill_cc_matrix(cc_matrix *m,char* name,char* module,char* group,int i)
+{
+ if (i>MAX_IDENTIFIERS)
+ { fprintf(logFile,"Cost centre MAX_IDENTIFIERS exceeded: %i \n",i); exit(1); }
+ name = StripDoubleQuotes(name);
+ strcpy((*m)[i].name,name);
+ module = StripDoubleQuotes(module);
+ strcpy((*m)[i].module,module);
+ group = StripDoubleQuotes(group);
+ strcpy((*m)[i].group,group);
+}
+
+void fill_ccs_matrix(ccs_matrix *m,int cc, int ccs, int scc, int ticks, int bytes, int h_o, int count, int i)
+{
+ heap_sample_matrix *hsm;
+
+ if ((*m)[i].cc == 0) /* added for type 2 stack semantics, but should not */
+ /* change behaviour of type 1 (apart from CAF:REP. */
+ {
+ if (i>MAX_IDENTIFIERS)
+ { fprintf(logFile,"Cost centre stack MAX_IDENTIFIERS exceeded: %i \n",i); exit(1); }
+ hsm = (*m)[i].hsm;
+ (*m)[i].cc = cc; (*m)[i].ccs = ccs;
+ (*m)[i].ticks = ticks; (*m)[i].bytes = bytes; (*m)[i].scc = scc;
+ (*hsm)[h_o].count = count;
+ }
+ else fprintf(logFile,"Ignoring redeclaration of stack %i\n",i);
+}
+
+void add_ccs_costs(ccs_matrix *m, int b,int c,int d,int x,int y,int h_o, int co)
+{
+ (*m)[c].scc = (*m)[c].scc + d;
+ (*m)[c].ticks = (*m)[c].ticks + x;
+ (*m)[c].bytes = (*m)[c].bytes + y;
+}
+
+void add_heap_sample_costs(ccs_matrix *m, int b,int c,int d,int x,int y,int h_o, int co)
+{
+ heap_sample_matrix *hsm = (*m)[c].hsm;
+ if (((*hsm)[h_o].count)==-1)
+ (*hsm)[h_o].count = (*hsm)[h_o].count + co + 1; /* as init is -1 */
+ else
+ (*hsm)[h_o].count = (*hsm)[h_o].count + co;
+}
+
+void add_heap_object(heap_object_matrix *m, int pos, int t, char* des, int tr)
+{
+ if (pos>MAX_IDENTIFIERS)
+ { fprintf(logFile,"Heap object MAX_IDENTIFIERS exceeded: %i \n",pos); exit(1); }
+ (*m)[pos].type = t;
+ strcpy((*m)[pos].descriptor,des);
+ (*m)[pos].type_constr_ref = tr;
+}
+
+void add_type_constr_object(type_constr_matrix *m, int pos, char* mod, char* n)
+{
+ if (pos>MAX_IDENTIFIERS)
+ { fprintf(logFile,"Type constructor MAX_IDENTIFIERS exceeded: %i \n",pos); exit(1); }
+ strcpy((*m)[pos].module,mod);
+ strcpy((*m)[pos].name,n);
+}
+
+
+// Printing routines
+
+void print_heap_update_list(heap_update_list *m, int number)
+{
+ int i;
+ fprintf(logFile,"[");
+ for (i=0; i<number;i++)
+ {
+ fprintf(logFile," (%i,%i,%i) ",(*m)[i].ccs,(*m)[i].ho,(*m)[i].count);
+ }
+ fprintf(logFile,"]\n");
+}
+
+void print_TheHeap(TheHeap *h)
+{
+ int i;
+ fprintf(logFile,"The Heap\n========\n");
+ for (i=0; i<MAX_TIME;i++)
+ {
+ if ((*h)[i].no_samples>0)
+ {
+ fprintf(logFile,"Sample time %i, number of samples %i actual samples "
+ ,i,(*h)[i].no_samples);
+ print_heap_update_list((*h)[i].acc_samples,(*h)[i].no_samples);
+ }
+ }
+}
+
+void PrintXaxis(FILE *HEAP_PROFILE, TheHeap *h)
+{
+ int i;
+ fprintf(HEAP_PROFILE," ");
+ for (i=0; i<MAX_TIME;i++)
+ {
+ if ((*h)[i].no_samples>0)
+ fprintf(HEAP_PROFILE,"%i ",i);
+ }
+}
+
+int FindSample(heap_update_list *m, int number, int element)
+{
+ int i;
+ for (i=0; i<number;i++)
+ {
+ if ((*m)[i].ho==element)
+ return ((*m)[i].count);
+ }
+ return 0;
+}
+
+void PrintSampleCosts(FILE *hfp, TheHeap *h, int element)
+{
+ int i;
+ int total = 0;
+ for (i=0; i<MAX_TIME;i++)
+ {
+ if ((*h)[i].no_samples>0)
+ {
+ total = total + FindSample((*h)[i].acc_samples,(*h)[i].no_samples,element);
+ fprintf(hfp," %i ",total);
+ }
+ }
+}
+
+void print_cc_matrix(cc_matrix *m)
+{
+ int i;
+ char *blank="blank";
+ fprintf(logFile,"Cost centre matrix\n");
+ fprintf(logFile,"==================\n");
+ for (i=0; i<MAX_IDENTIFIERS; i++)
+ { if (strcmp((*m)[i].name,blank)!=0)
+ fprintf(logFile,"%s %s %s\n",(*m)[i].name,(*m)[i].module,(*m)[i].group); }
+ fprintf(logFile,"\n");
+}
+
+void print_heap_object_matrix(FILE* hfp, TheHeap *h, heap_object_matrix *m)
+{
+ int i;
+ for (i=0; i<MAX_IDENTIFIERS; i++)
+ {
+ if (((*m)[i].type)!=-1)
+ {
+ fprintf(hfp,"Y%i set {",i);
+ /* if ((*m)[i].type==1) fprintf(hfp,"data_contr ");
+ if ((*m)[i].type==2) fprintf(hfp,"PAP ");
+ if ((*m)[i].type==3) fprintf(hfp,"thunk ");
+ if ((*m)[i].type==4) fprintf(hfp,"function ");
+ if ((*m)[i].type==5) fprintf(hfp,"dictionary ");
+ if ((*m)[i].type==1)
+ fprintf(hfp,"%s %i ",(*m)[i].descriptor,(*m)[i].type_constr_ref);
+ else
+ fprintf(hfp,"%s ",(*m)[i].descriptor); */
+ PrintSampleCosts(hfp,h,i);
+ fprintf(hfp,"}\n");
+ }
+ }
+}
+
+int number_of_heap_objects(heap_object_matrix *m)
+{
+ int i;
+ int count = 0;
+ for (i=0; i<MAX_IDENTIFIERS; i++)
+ {
+ if (((*m)[i].type)!=-1) count++;
+ }
+ return count;
+}
+
+void names_of_heap_objects(FILE *hfp, heap_object_matrix *m)
+{
+ int i;
+ for (i=0; i<MAX_IDENTIFIERS; i++)
+ {
+ if (((*m)[i].type)!=-1)
+ fprintf(hfp,"Y%i ",i);
+ }
+ fprintf(hfp,"\n");
+}
+
+void names_and_colour_assignment(FILE *hfp, heap_object_matrix *m)
+{
+ int i;
+ int colour=0;
+ for (i=0; i<MAX_IDENTIFIERS; i++)
+ {
+ if (((*m)[i].type)!=-1)
+ {
+ switch(colour)
+ {
+ case 0 : fprintf(hfp,"%s \t Y%i \t red \t fdiagonal1\n",(*m)[i].descriptor,i);
+ colour++; break;
+ case 1 : fprintf(hfp,"%s \t Y%i \t blue \t fdiagonal1\n",(*m)[i].descriptor,i);
+ colour++; break;
+ case 2 : fprintf(hfp,"%s \t Y%i \t green \t fdiagonal1\n",(*m)[i].descriptor,i);
+ colour++; break;
+ case 3 : fprintf(hfp,"%s \t Y%i \t yellow \t fdiagonal1\n",(*m)[i].descriptor,i);
+ colour++; break;
+ case 4 : fprintf(hfp,"%s \t Y%i \t pink \t fdiagonal1\n",(*m)[i].descriptor,i);
+ colour++; break;
+ case 5 : fprintf(hfp,"%s \t Y%i \t goldenrod \t fdiagonal1\n",(*m)[i].descriptor,i);
+ colour++; break;
+ case 6 : fprintf(hfp,"%s \t Y%i \t orange \t fdiagonal1\n",(*m)[i].descriptor,i);
+ colour++; break;
+ default: fprintf(hfp,"%s \t Y%i \t purple \t fdiagonal1\n",(*m)[i].descriptor,i);
+ colour=0; break;
+ }
+ }
+ }
+}
+
+void print_type_constr_matrix(type_constr_matrix *m)
+{
+ int i;
+ char *blank="blank";
+ fprintf(logFile,"Type constructor matrix\n");
+ fprintf(logFile,"=======================\n");
+ for (i=0; i<MAX_IDENTIFIERS; i++)
+ {
+ if (strcmp((*m)[i].name,blank)!=0)
+ fprintf(logFile,"%i %s %s\n",i,(*m)[i].module,(*m)[i].name);
+ }
+}
+
+void print_heap_sample_matrix(heap_sample_matrix *m)
+{
+ int i;
+ fprintf(logFile,"HeapSamples[");
+ for (i=0; i<MAX_IDENTIFIERS; i++)
+ {
+ if ((*m)[i].count!=-1) fprintf(logFile,"(%i,%i),",i,(*m)[i].count);
+ }
+ fprintf(logFile,"]\n");
+}
+
+void print_ccs_matrix(ccs_matrix *m)
+{
+ int i;
+ fprintf(logFile,"Cost centre stack matrix\n");
+ fprintf(logFile,"========================\n");
+ for (i=0; i<MAX_IDENTIFIERS; i++)
+ { if ((*m)[i].cc!=0)
+ {
+ fprintf(logFile,"%i %i %i %i %i \n",(*m)[i].cc,(*m)[i].ccs,(*m)[i].scc,
+ (*m)[i].ticks,(*m)[i].bytes);
+ }
+ }
+ fprintf(logFile,"\n");
+}
+
+
+/* No longer used */
+
+void FormStack(ccs_matrix *m, cc_matrix *n, int i, char s[])
+{
+ int j = i;
+ if ((*m)[j].cc != 0)
+ {
+ strcat(s,(*n)[(*m)[j].cc].name);
+ strcat(s," ");
+ while ((*m)[j].ccs != (-1))
+ {
+ strcat(s,(*n)[(*m)[(*m)[j].ccs].cc].name);
+ strcat(s,",");
+ j = (*m)[j].ccs;
+ }
+ }
+ else fprintf(logFile,"ERROR: Form Stack %i\n",i);
+}
+
+/* This version, which is used, adds the module and group name to the cost centre name*/
+/* This means the cost centre name remains unique when it is textualised and fed into */
+/* daVinci. It also allows the module and group name to be extracted at the display */
+/* level */
+
+void FormStack2(ccs_matrix *m, cc_matrix *n, int i, char s[])
+{
+ int j = i;
+ if ((*m)[j].cc != 0)
+ {
+ strcat(s,(*n)[(*m)[j].cc].name);
+ strcat(s,"&");
+ strcat(s,(*n)[(*m)[j].cc].module);
+ strcat(s,"&");
+ strcat(s,(*n)[(*m)[j].cc].group);
+ strcat(s," ");
+ while ((*m)[j].ccs != (-1))
+ {
+ strcat(s,(*n)[(*m)[(*m)[j].ccs].cc].name);
+ strcat(s,"&");
+ strcat(s,(*n)[(*m)[(*m)[j].ccs].cc].module);
+ strcat(s,"&");
+ strcat(s,(*n)[(*m)[(*m)[j].ccs].cc].group);
+ strcat(s,",");
+ j = (*m)[j].ccs;
+ }
+ }
+ else fprintf(logFile,"ERROR: Form Stack %i\n",i);
+}
+
+void PrintStack(ccs_matrix *m, cc_matrix *n, int i)
+{
+ int j = i;
+ if ((*m)[j].cc != 0)
+ {
+ fprintf(logFile,"<");
+ fprintf(logFile,"%s,",(*n)[(*m)[j].cc].name);
+ while ((*m)[j].ccs != (-1))
+ {
+ fprintf(logFile,"%s,",(*n)[(*m)[(*m)[j].ccs].cc].name);
+ j = (*m)[j].ccs;
+ }
+ fprintf(logFile,"> ");
+ fprintf(logFile,"%i scc %i ticks %i bytes ",
+ (*m)[i].scc,(*m)[i].ticks,(*m)[i].bytes);
+ print_heap_sample_matrix((*m)[i].hsm);
+ }
+ else
+ { /* fprintf(logFile,"empty stack\n"); */ }
+}
+
+int CountStacks(ccs_matrix *m)
+{
+ int j;
+ int count = 0;
+ for (j=0; j<MAX_IDENTIFIERS;j++) if ((*m)[j].cc != 0) count++;
+ return count;
+}
+
+void PrintAllStacks(ccs_matrix *m, cc_matrix *n)
+{
+ int i;
+ fprintf(logFile,"Stacks\n======\n");
+ for (i=0;i<MAX_IDENTIFIERS;i++) { PrintStack(m,n,i); }
+}
+
+
+/* -----------------------------------------------------------------------------
+ * TCL Heap profile generator
+ * -------------------------------------------------------------------------- */
+
+void produce_HEAP_PROFILE(FILE *HEAP_PROFILE, TheHeap *th, heap_object_matrix *ho_m)
+{
+ // First the header information
+ fprintf(HEAP_PROFILE,"#!/home/sj/blt2.4o/src/bltwish\n");
+ fprintf(HEAP_PROFILE,"package require BLT\n");
+ fprintf(HEAP_PROFILE,"if { $tcl_version >= 8.0 } {\n");
+ fprintf(HEAP_PROFILE,"\t \t namespace import blt::*\n");
+ fprintf(HEAP_PROFILE,"namespace import -force blt::tile::*\n");
+ fprintf(HEAP_PROFILE,"}\n");
+ fprintf(HEAP_PROFILE,"source scripts/demo.tcl\n");
+ fprintf(HEAP_PROFILE,"proc FormatXTicks { w value } {\n");
+ fprintf(HEAP_PROFILE,"\t \t set index [expr round($value)]\n");
+ fprintf(HEAP_PROFILE,"\t \t if { $index != $value } {\n");
+ fprintf(HEAP_PROFILE,"\t \t \t return $value\n");
+ fprintf(HEAP_PROFILE,"\t \t}\n");
+ fprintf(HEAP_PROFILE,"incr index -1\n");
+
+ // Now the code to generate the units in the X axis
+
+ fprintf(HEAP_PROFILE,"set name [lindex { ");
+ PrintXaxis(HEAP_PROFILE,th);
+ fprintf(HEAP_PROFILE," } $index]\n");
+
+ fprintf(HEAP_PROFILE,"return $name\n");
+ fprintf(HEAP_PROFILE,"}\n");
+
+ // more general graph stuff
+
+ fprintf(HEAP_PROFILE,"source scripts/stipples.tcl\n");
+ fprintf(HEAP_PROFILE,"image create photo bgTexture -file ./images/chalk.gif\n");
+ fprintf(HEAP_PROFILE,"option add *Button.padX 5\n");
+ fprintf(HEAP_PROFILE,"option add *tile bgTexture\n");
+ fprintf(HEAP_PROFILE,"option add *Radiobutton.font -*-courier*-medium-r-*-*-14-*-*\n");
+ fprintf(HEAP_PROFILE,"option add *Radiobutton.relief flat\n");
+ fprintf(HEAP_PROFILE,"option add *Radiobutton.borderWidth 2\n");
+ fprintf(HEAP_PROFILE,"option add *Radiobutton.highlightThickness 0\n");
+ fprintf(HEAP_PROFILE,"option add *Htext.font -*-times*-bold-r-*-*-14-*-*\n");
+ fprintf(HEAP_PROFILE,"option add *Htext.tileOffset no\n");
+ fprintf(HEAP_PROFILE,"option add *header.font -*-times*-medium-r-*-*-14-*-*\n");
+ fprintf(HEAP_PROFILE,"option add *Barchart.font -*-helvetica-bold-r-*-*-14-*-*\n");
+
+ fprintf(HEAP_PROFILE,"option add *Barchart.title \"Heap profile of program ");
+ // TO DO: Add program name in here
+ fprintf(HEAP_PROFILE,"\"\n");
+
+ fprintf(HEAP_PROFILE,"option add *Axis.tickFont -*-helvetica-medium-r-*-*-12-*-*\n");
+ fprintf(HEAP_PROFILE,"option add *Axis.titleFont -*-helvetica-bold-r-*-*-12-*-*\n");
+ fprintf(HEAP_PROFILE,"option add *x.Command FormatXTicks\n");
+ fprintf(HEAP_PROFILE,"option add *x.Title \"Time (seconds)\"\n");
+ fprintf(HEAP_PROFILE,"option add *y.Title \"Heap usage (000 bytes)\"\n");
+ fprintf(HEAP_PROFILE,"option add *activeBar.Foreground pink\noption add *activeBar.stipple dot3\noption add *Element.Background red\noption add *Element.Relief raised\n");
+ fprintf(HEAP_PROFILE,"option add *Grid.dashes { 2 4 }\noption add *Grid.hide no\noption add *Grid.mapX \"\"\n");
+ 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");
+ fprintf(HEAP_PROFILE,"option add *TextMarker.Font *Helvetica-Bold-R*14*\n");
+ 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");
+ fprintf(HEAP_PROFILE,"htext .title -text {\n Heap profile\n}\n");
+ fprintf(HEAP_PROFILE,"htext .header -text {\n %%%% \n");
+ 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");
+ fprintf(HEAP_PROFILE," %%%% Heap usage stacked: overall height is the sum of the heap used. \n %%%% \n");
+ 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");
+ fprintf(HEAP_PROFILE," %%%% Heap usage components displayed side-by-side.\n %%%%\n");
+ 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");
+ fprintf(HEAP_PROFILE," %%%% Heap usage shown as an overlapped histogram.\n %%%%\n");
+ 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");
+ fprintf(HEAP_PROFILE," %%%% Heap components overlayed one on top of the next. \n}\n");
+ 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");
+ fprintf(HEAP_PROFILE,"barchart .graph -tile bgTexture\n");
+
+ // This is where the actual data comes in
+
+ fprintf(HEAP_PROFILE,"vector X ");
+ names_of_heap_objects(HEAP_PROFILE,ho_m);
+ fprintf(HEAP_PROFILE,"\nX set { ");
+ PrintXaxis(HEAP_PROFILE,th);
+ fprintf(HEAP_PROFILE," }\n");
+
+ print_heap_object_matrix(HEAP_PROFILE,th, ho_m);
+
+ // NAMES FOR THE ATTRIBUTES
+ fprintf(HEAP_PROFILE,"set attributes {\n");
+ names_and_colour_assignment(HEAP_PROFILE,ho_m);
+ fprintf(HEAP_PROFILE,"}\n");
+
+ 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");
+ fprintf(HEAP_PROFILE,".header.stacked invoke\n");
+ 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");
+ 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");
+ fprintf(HEAP_PROFILE,"table configure . r0 r1 r3 r4 r5 -resize none\n");
+ fprintf(HEAP_PROFILE,"Blt_ZoomStack .graph\nBlt_Crosshairs .graph\nBlt_ActiveLegend .graph\nBlt_ClosestPoint .graph\n");
+ 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");
+
+}
+
+
+/* -----------------------------------------------------------------------------
+ * Read and create the raw profile data structure
+ * -------------------------------------------------------------------------- */
+
+/* void readRawProfile(FILE *fptr,int *nonodes) { */
+
+void readRawProfile(FILE *fp,int *nonodes, int MaxNoNodes) {
+ char stack[MAX_PROFILE_LINE_LENGTH];
+ int i,nolines,sstepline,syncs;
+ char *ptr,*drag;
+
+ float comp_max, comp_avg, comp_min, /* SYNCS */
+ comm_max, comm_avg, comm_min, /* COMP */
+ comp_idle_max, comp_idle_avg, comp_idle_min; /* COMM */
+
+ /* Cost relationships are comp=scc, comm=ticks, comp_idle=bytes */
+
+ long int hmax,havg,hmin; /* COMPIDLE */
+
+ /* set to zero for now. Might use these later for heap costs. */
+
+ /* GHC specific variables */
+
+ int a,b,c,d,x,z,count, next;
+ int newloop;
+ char e[MAX_STRING_SIZE];
+ char f[MAX_STRING_SIZE];
+ char lline[MAX_PROFILE_LINE_LENGTH];
+
+ /* identifiers generated by the XML handler */
+ char *ccentre=">>cost_centre";
+ char *ccstack=">>cost_centre_stack";
+ char *sccsample=">>scc_sample";
+ char *heapsample=">>heap_sample";
+ char *heapupdate=">>heap_update";
+ char *heapobject=">>heap_object";
+ char *typeconstr=">>type_constr";
+ char *ending=">>";
+
+ /* FILE *fp; */
+
+ cc_matrix *cc_m;
+ ccs_matrix *ccs_m;
+ heap_object_matrix *ho_m;
+ type_constr_matrix *tc_m;
+ TheHeap *th;
+
+ FILE *HEAP_PROFILE;
+
+ HEAP_PROFILE = fopen("GHCbarchart.tcl", "w");
+ if (HEAP_PROFILE == NULL){
+ fprintf(stderr,"tcl script generator: ERROR- GHCbarchart.tcl cannot be created\a\n");
+ exit(1);
+ }
+
+ th = (p_TheHeap) malloc (sizeof(TheHeap));
+ cc_m = (p_cc_matrix) malloc (sizeof(cc_matrix));
+ //cc_m = (p_cc_matrix) calloc(MAX_IDENTIFIERS,sizeof(_cc_));
+ ccs_m = (p_ccs_matrix) malloc (sizeof(ccs_matrix));
+ ho_m = (p_heap_object_matrix) malloc (sizeof(heap_object_matrix));
+ tc_m = (p_type_constr_matrix) malloc (sizeof(type_constr_matrix));
+
+ /* End of GHC specific variables */
+
+ //fprintf(logFile,"Number 1 %i \n",MAX_IDENTIFIERS*sizeof(_cc_));
+ //fprintf(logFile,"Number 2 %i \n",sizeof(cc_matrix));
+
+ nolines=0; /* Number of lines read in from profile log file */
+
+ /* GHC specific */
+ count = 0;
+ next = 0;
+
+ initialise_cc_matrix(cc_m);
+ initialise_ccs_matrix(ccs_m);
+ initialise_heap_object_matrix(ho_m);
+ initialise_type_constr_matrix(tc_m);
+ initialise_TheHeap(th);
+
+ fprintf(logFile,"MAX_IDENTIFIERS = %i \n",MAX_IDENTIFIERS);
+
+ /* end GHC specific */
+
+ /* CAF fixing */
+ fill_cc_matrix(cc_m,"CAF:REPOSITORY","PROFILER","PROFILER",MAX_IDENTIFIERS-1);
+ fill_ccs_matrix(ccs_m,MAX_IDENTIFIERS-1,1,0.0,0.0,0.0,0,-1,MAX_IDENTIFIERS-1);
+
+ /*
+
+ This builds a node in the graph called CAF:REPOSITORY, which can be
+ found off the root node. All CAFs are subsequently hung from this node
+ which means the node node can be hidden using the abstraction
+ mechanisms provided by daVinci.
+
+ */
+
+
+ /* This is the GHC file handler which reads the lines from the profile log file and */
+ /* puts the stack and cost information in the raw profile data structure */
+
+ while (fscanf(fp,"%s",lline))
+ {
+ /* Kill the end of the logfile with the ">>" string */
+ if (strcmp(lline,ending)==0) break;
+
+ /* Deal with the cost centres */
+ if (strcmp(ccentre,lline)==0)
+ {
+ next = fgetc(fp);
+ //while (fscanf(fp," %i %[^ ] %[^ ] %s", &z, e, f, g)!=0)
+ while (fscanf(fp," %i %[^ ] %s", &z, e, f)!=0)
+ {
+ fprintf(logFile,"Declaring cost centre `%i %s %s %s' \n",z,e,f,f);
+ fflush(logFile);
+ fill_cc_matrix(cc_m,e,f,f,z);
+ next = fgetc(fp);
+ }
+ }
+ else
+ {
+
+ /* Deal with the cost centre stacks */
+ if (strcmp(ccstack,lline)==0)
+ {
+ next = fgetc(fp);
+ while (fscanf(fp,"%i %i %i",&a,&d,&b)!=0)
+ {
+ if (d==1) /* of size one */
+ {
+ fprintf(logFile,"Declaring cost centre stack `%i %i %i'\n",a,d,b);
+ fill_ccs_matrix(ccs_m,b,-1,(*ccs_m)[a].scc,(*ccs_m)[a].ticks,(*ccs_m)[a].bytes,0,-1,a);
+ }
+ if (d==2) /* of size > 1 */
+ {
+ fscanf(fp," %i",&c);
+
+ /* CAF fixing */
+ fprintf(logFile,"Declaring cost centre stack `%i %i %i %i'\n",a,d,b,c);
+ if ((c==1)&&!(strncmp((*cc_m)[b].name,"CAF",2)))
+ // fill_ccs_matrix(ccs_m,b,MAX_IDENTIFIERS-1,(*ccs_m)[a].scc,(*ccs_m)[a].ticks,(*ccs_m)[a].bytes,0,-1,a);
+ /* The line above hangs all CAFs off the CAF:REPOSITORY node
+ in the daVinci graph. For programs which have a small
+ number of CAFs this works nicely. However, when the
+ number of CAFs become very large (eg +200) then the
+ daVinci graph begins to look horid and, after (say)
+ +500 CAF nodes, becomes very slow to load. So to
+ fix this we replace the code with the line below.
+ */
+ if (!(strncmp((*cc_m)[b].name,"CAF:main",7)))
+ /* Treat CAF:main as a normal node */
+ fill_ccs_matrix(ccs_m,b,c,(*ccs_m)[a].scc,(*ccs_m)[a].ticks,(*ccs_m)[a].bytes,0,-1,a);
+ /* merge the rest */
+ else
+ //add_ccs_costs(ccs_m,0,MAX_IDENTIFIERS-1,(*ccs_m)[a].scc,(*ccs_m)[a].ticks,(*ccs_m)[a].bytes,0,0);
+ fill_ccs_matrix(ccs_m,MAX_IDENTIFIERS-1,1,(*ccs_m)[a].scc,(*ccs_m)[a].ticks,(*ccs_m)[a].bytes,0,-1,a);
+ /* This does not even bother registering the new CAFs
+ as daVinci nodes, but instead just merges the CAF
+ with the CAF:REPOSITORY node. This greatly reduces
+ the number of CAFs daVinci has to deal with, though
+ may make the graph look a little different!
+
+ Also note that now Simon has changed the semantics,
+ you will want to treat adding CAF nodes in a
+ different way to adding normal program nodes
+ */
+ else
+ /* Normal mode */
+ fill_ccs_matrix(ccs_m,b,c,(*ccs_m)[a].scc,(*ccs_m)[a].ticks,(*ccs_m)[a].bytes,0,-1,a);
+ }
+ next = fgetc(fp);
+ }
+ }
+ else
+ {
+
+ /* Deal with the scc_samples */
+ if (strcmp(sccsample,lline)==0)
+ {
+ next = fgetc(fp);
+ while (fscanf(fp,"%i %i %i %i",&a,&d,&b,&c))
+ {
+ fprintf(logFile,"Loading scc_samples `%i %i %i %i'\n",a,d,b,c);
+ add_ccs_costs(ccs_m,0,a,d,b,c,0,0);
+ next = fgetc(fp);
+ }
+ } /* end sccsample if */
+ else
+ {
+
+ /* Deal with the heap samples */
+ if (strcmp(heapsample,lline)==0)
+ {
+ next = fgetc(fp);
+ while (fscanf(fp,"%i %i %i",&a,&d,&b))
+ {
+ fprintf(logFile,"Loading heap_samples `%i %i %i'\n",a,d,b);
+ add_heap_sample_costs(ccs_m,0,a,0,0,0,d,b);
+ next = fgetc(fp);
+ }
+ } /* end heapsample if */
+ else
+ {
+
+ /* Deal with the heap objects */
+ if (strcmp(heapobject,lline)==0)
+ {
+ next = fgetc(fp);
+ while (fscanf(fp,"%i %i",&a,&d))
+ {
+ if (d==1)
+ {
+ fscanf(fp," %s %i",e,&b);
+ add_heap_object(ho_m,a,d,e,b);
+ }
+ else
+ {
+ fscanf(fp," %s",e);
+ add_heap_object(ho_m,a,d,e,-1);
+ }
+ next = fgetc(fp);
+ }
+ } /* end heapobject if */
+ else
+ {
+
+ /* Deal with the type constructors */
+ if (strcmp(typeconstr,lline)==0)
+ {
+ next = fgetc(fp);
+ while (fscanf(fp,"%i %s %s",&a,e,f))
+ {
+ add_type_constr_object(tc_m,a,e,f);
+ next = fgetc(fp);
+ }
+ } /* end type constructor if */
+ else
+ {
+
+ /* Deal with the heap_updates */
+ if (strcmp(heapupdate,lline)==0)
+ {
+ next = fgetc(fp);
+ while (fscanf(fp,"%i %i %i %i %i %i",&a,&d,&b,&c,&z,&x))
+ {
+ add_to_TheHeap(th,a,b,c,z);
+ fprintf(logFile,"Adding heap sample %i %i %i %i\n",a,b,c,z);
+ while (x) /* more than one sample */
+ {
+ fscanf(fp," %i %i %i %i",&b,&c,&z,&x);
+ add_to_TheHeap(th,a,b,c,z);
+ fprintf(logFile,"Adding heap sample %i %i %i %i\n",a,b,c,z);
+ }
+ next = fgetc(fp);
+ }
+
+ } /* end heap update if */
+
+ } /* end type constructor else */
+
+ } /* end heapobject else */
+
+ } /* end heapsample else */
+ } /* end sccsample else */
+ } /* end ccstack else */
+ } /* end ccstack if */
+ } /* end while */
+
+ print_cc_matrix(cc_m);
+ print_ccs_matrix(ccs_m);
+ fprintf(logFile,"There are %i stacks\n",CountStacks(ccs_m));
+ print_type_constr_matrix(tc_m);
+
+ /* Functions for heap profile */
+ print_TheHeap(th);
+ fprintf(logFile,"The units for the x axis are \n");
+ PrintXaxis(logFile,th);
+ fprintf(logFile,"\n");
+ fprintf(logFile,"There are %i distinct heap objects\n",number_of_heap_objects(ho_m));
+ names_of_heap_objects(logFile,ho_m);
+ names_and_colour_assignment(logFile,ho_m);
+ print_heap_object_matrix(logFile,th,ho_m);
+
+ PrintAllStacks(ccs_m,cc_m);
+ /* comment out line below to remove the heap profile generator */
+ produce_HEAP_PROFILE(HEAP_PROFILE,th,ho_m);
+ fclose(HEAP_PROFILE);
+
+ /* End of GHC file handler */
+
+
+ /* Now process the stack matrix */
+
+ for (newloop=0;newloop<MAX_IDENTIFIERS;newloop++)
+ { if ((*ccs_m)[newloop].cc != 0)
+ {
+
+ sstepline = 0;
+ FormStack2(ccs_m,cc_m,newloop,stack);
+
+ syncs = 0;
+ comp_max = (float)(*ccs_m)[newloop].scc;
+ comp_avg = (float)(*ccs_m)[newloop].scc;
+ comp_min = (float)(*ccs_m)[newloop].scc;
+ comm_max = (float)(*ccs_m)[newloop].ticks;
+ comm_avg = (float)(*ccs_m)[newloop].ticks;
+ comm_min = (float)(*ccs_m)[newloop].ticks;
+ comp_idle_max = (float)(*ccs_m)[newloop].bytes;
+ comp_idle_avg = (float)(*ccs_m)[newloop].bytes;
+ comp_idle_min = (float)(*ccs_m)[newloop].bytes;
+ hmax = 0.0; havg = 0.0; hmin = 0.0;
+
+ /* Dynamic memory allocation for raw_profile data structure */
+
+ if (raw_profile_next==raw_profile_size) enlargeRawProfile();
+
+ /* Assign data from single logfile entry to raw_profile data structure */
+ /* this deals with the cost metrics */
+
+ raw_profile[raw_profile_next].active = 1;
+ raw_profile[raw_profile_next].cost.syncs = syncs;
+ raw_profile[raw_profile_next].cost.comp_max = comp_max;
+ raw_profile[raw_profile_next].cost.comp_avg = comp_avg;
+ raw_profile[raw_profile_next].cost.comp_min = comp_min;
+ raw_profile[raw_profile_next].cost.comm_max = comm_max;
+ raw_profile[raw_profile_next].cost.comm_avg = comm_avg;
+ raw_profile[raw_profile_next].cost.comm_min = comm_min;
+ raw_profile[raw_profile_next].cost.comp_idle_max= comp_idle_max;
+ raw_profile[raw_profile_next].cost.comp_idle_avg= comp_idle_avg;
+ raw_profile[raw_profile_next].cost.comp_idle_min= comp_idle_min;
+ raw_profile[raw_profile_next].cost.hrel_max = hmax;
+ raw_profile[raw_profile_next].cost.hrel_avg = havg;
+ raw_profile[raw_profile_next].cost.hrel_min = hmin;
+
+ /* this deals with the stack itself */
+
+ raw_profile[raw_profile_next].stack=calloc(MAX_STACK_DEPTH,
+ sizeof(int));
+ if (raw_profile[raw_profile_next].stack==NULL) {
+ fprintf(stderr,"{readRawProfile} unable to allocate stack entry");
+ exit(1);
+ }
+
+ fprintf(logFile,"STACK=\"%s\"\n",stack);
+ raw_profile[raw_profile_next].stack_size=1;
+ /* move the stack read frame to the first space (or comma) in the stack string */
+ for(ptr=stack; ((*ptr)!=' ') && (*ptr!=',');ptr++) {}
+ fprintf(logFile,"TOS=%d at line %d\n",*ptr,sstepline);
+
+ /* to distinguish the head of the stack from the rest */
+ /* if read frame points to space you are at the head of the stack */
+ if (*ptr==' ')
+ /* raw_profile[raw_profile_next].stack[0]
+ =lookupSymbolTable(CG_SSTEP,sstepline,(*ptr='\0',stack)); */
+ /* This line has changed as GHC treats its cost-centres in a different */
+ /* way to BSP. There is no distinction between 'a cost centre at line x' */
+ /* and a normal cost centre. The fix is easy, just treat all cost centres, */
+ /* even those at the head of the stack in the same way. */
+ raw_profile[raw_profile_next].stack[0]
+ =lookupSymbolTable(CG_STACK,sstepline,(*ptr='\0',stack));
+ else
+ /* otherwise you are looking at just another stack element */
+ raw_profile[raw_profile_next].stack[0]
+ =lookupSymbolTable(CG_STACK,sstepline,(*ptr='\0',stack));
+
+ ptr++; /* move the read frame on one */
+ drag=ptr;
+ for(;*ptr;ptr++) { /* find the next element in the stack */
+ if (*ptr==',') {
+ *ptr='\0';
+ if (Verbose) fprintf(logFile,"NAME=\"%s\"\n",drag); /* name of the next element */
+ if (!ignore_function(drag)) {
+ raw_profile[raw_profile_next].stack[
+ raw_profile[raw_profile_next].stack_size++]
+ = lookupSymbolTable(CG_STACK,0,drag); /* add element to the raw_profile */
+ }
+ drag = ptr+1;
+ }
+ }
+
+ /* create cost object */
+
+ raw_profile[raw_profile_next].cost.proc
+ =calloc(bsp_p,sizeof(object_cost_proc));
+ if (raw_profile[raw_profile_next].cost.proc==NULL) {
+ fprintf(stderr,"Unable to allocate storage");
+ exit(0);
+ }
+
+ /* process the HREL information - one set for every BSP process */
+
+ for(i=0;i<bsp_p;i++) {
+
+ raw_profile[raw_profile_next].cost.proc[i].proc_comp = 0.0;
+ raw_profile[raw_profile_next].cost.proc[i].proc_comm = 0.0;
+ raw_profile[raw_profile_next].cost.proc[i].proc_comp_idle= 0.0;
+ raw_profile[raw_profile_next].cost.proc[i].proc_hrel_in = 0;
+ raw_profile[raw_profile_next].cost.proc[i].proc_hrel_out = 0;
+
+ }
+
+ raw_profile_next++; /* Increase the raw profile data structure counter */
+ nolines++; /* Increase the number of lines read */
+
+ strcpy(stack,""); /* reset the stack */
+ } /* end of new if statement */
+ } /* end of new for loop */
+
+ *nonodes = symbol_table_next;
+ fprintf(logFile,"%s: read %d lines from profile.Graph contains %i nodes.\n",
+ Pgm,nolines,symbol_table_next);
+
+ free_cc_matrix(cc_m); /* be nice and clean up the cost centre matrix */
+}
+
+/* -----------------------------------------------------------------------------
+ * Pretty print the raw profile data
+ * -------------------------------------------------------------------------- */
+
+void printRawProfile() {
+ int i,j;
+ object_cost *cost;
+ int *stack;
+
+ fprintf(logFile,"\n\nRAW DATA:\n");
+ for(i=0;i<raw_profile_next;i++) {
+ cost = &raw_profile[i].cost;
+ stack = raw_profile[i].stack;
+ fprintf(logFile,"Stack=[");
+ for(j=0;j<raw_profile[i].stack_size;j++)
+ printSymbolTable_entry(stack[j]);
+ fprintf(logFile,"] %d Syncs %f Comp %f Comm %f Wait\n\n",
+ cost->syncs,cost->comp_max,cost->comm_max,cost->comp_idle_max);
+ }
+}
+
+/* -----------------------------------------------------------------------------
+ * Create connectivity matrix
+ * -------------------------------------------------------------------------- */
+
+void createConnectivityMatrix(int NoNodes,Matrix *graph,
+ Matrix *costs,int *root, int inherit) {
+ object_cost zero_cost,*update;
+ int i,j,this,next;
+
+
+ zero_cost.comp_max =0.0;
+ zero_cost.comp_avg =0.0;
+ zero_cost.comp_min =0.0;
+ zero_cost.comm_max =0.0;
+ zero_cost.comm_avg =0.0;
+ zero_cost.comm_min =0.0;
+ zero_cost.comp_idle_max=0.0;
+ zero_cost.comp_idle_avg=0.0;
+ zero_cost.comp_idle_min=0.0;
+ zero_cost.hrel_max =0;
+ zero_cost.hrel_avg =0;
+ zero_cost.hrel_min =0;
+ zero_cost.syncs=0;
+ zero_cost.proc = NULL;
+ *graph = newMat(NoNodes,NoNodes,sizeof(int),(i=0,&i));
+ *costs = newMat(NoNodes,1,sizeof(object_cost),&zero_cost);
+ for(i=0;i<NoNodes;i++) {
+ update=&Mat(object_cost,*costs,i,0);
+ update->proc=calloc(bsp_p,sizeof(object_cost_proc));
+ if (update->proc==NULL){
+ fprintf(stderr,"Unable to allocate storage");
+ exit(0);
+ }
+ for(j=0;j<bsp_p;j++) {
+ update->proc[j].proc_comp =0.0;
+ update->proc[j].proc_comm =0.0;
+ update->proc[j].proc_comp_idle =0.0;
+ update->proc[j].proc_hrel_in =0;
+ update->proc[j].proc_hrel_out =0;
+ }
+ }
+
+ for(i=0;i<raw_profile_next;i++) {
+ if (raw_profile[i].active) {
+ this = raw_profile[i].stack[0];
+ next = this;
+ Mat(int,*graph,this,next) = 1;
+ update = &Mat(object_cost,*costs,next,0);
+ add_costs(update,raw_profile[i].cost);
+ for(j=1;j<raw_profile[i].stack_size;j++) {
+ this = next;
+ next = raw_profile[i].stack[j];
+ Mat(int,*graph,next,this)=1;
+ update = &Mat(object_cost,*costs,next,0);
+ /* include this line for INHERITANCE; remove it for not! */
+ if (inherit) add_costs(update,raw_profile[i].cost);
+ }
+ }
+ }
+ *root = raw_profile[0].stack[raw_profile[0].stack_size-1];
+
+ /* Check graph isn't empty */
+ if (!Mat_dense(*costs,*root,0)) *root=-1;
+}
+
+void printConnectivityMatrix(Matrix graph,Matrix costs,int root) {
+ int i,j;
+ object_cost cost;
+
+ fprintf(logFile,"Root node is %d\n",root);
+ for(i=0;i<graph.rows;i++) {
+ fprintf(logFile,"%4d)",i);
+ printSymbolTable_entry(i);
+ cost = Mat(object_cost,costs,i,0);
+ fprintf(logFile,"%d %f %f %f\n\tBranch=[",
+ cost.syncs,cost.comp_max,cost.comm_max,cost.comp_idle_max);
+ for(j=0;j<graph.cols;j++)
+ if (Mat_dense(graph,i,j)) fprintf(logFile,"%d ",j);
+ fprintf(logFile,"]\n\n");
+ }
+}
diff --git a/utils/prof/cgprof/cgprof.h b/utils/prof/cgprof/cgprof.h
new file mode 100644
index 0000000000..e93f02b53e
--- /dev/null
+++ b/utils/prof/cgprof/cgprof.h
@@ -0,0 +1,82 @@
+/* ------------------------------------------------------------------------
+ * $Id: cgprof.h,v 1.2 2003/08/01 14:50:50 panne Exp $
+ *
+ * Copyright (C) 1995-2000 University of Oxford
+ *
+ * Permission to use, copy, modify, and distribute this software,
+ * and to incorporate it, in whole or in part, into other software,
+ * is hereby granted without fee, provided that
+ * (1) the above copyright notice and this permission notice appear in
+ * all copies of the source code, and the above copyright notice
+ * appear in clearly visible form on all supporting documentation
+ * and distribution media;
+ * (2) modified versions of this software be accompanied by a complete
+ * change history describing author, date, and modifications made;
+ * and
+ * (3) any redistribution of the software, in original or modified
+ * form, be without fee and subject to these same conditions.
+ * --------------------------------------------------------------------- */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <limits.h>
+#include "symbol.h"
+#include "matrix.h"
+
+/* -----------------------------------------------------------------------------
+ * Data structures associated with parsed data
+ * -------------------------------------------------------------------------- */
+
+/* -----------------------------------------------------------------------------
+ * Cost attributes
+ * -------------------------------------------------------------------------- */
+
+#ifndef _CGPROF_H_
+#define _CGPROF_H_
+
+typedef struct {
+ double proc_comp;
+ double proc_comm;
+ double proc_comp_idle;
+ long int proc_hrel_in;
+ long int proc_hrel_out;
+} object_cost_proc;
+
+typedef struct {
+ double comp_max, comp_avg, comp_min;
+ double comm_max, comm_avg, comm_min;
+ double comp_idle_max, comp_idle_avg, comp_idle_min;
+ long int hrel_max, hrel_avg, hrel_min;
+ object_cost_proc *proc;
+ int syncs;
+} object_cost;
+
+/* -----------------------------------------------------------------------------
+ * Sequence of cost centres
+ * -------------------------------------------------------------------------- */
+
+typedef struct {
+ object_cost cost;
+ name_id *stack;
+ int stack_size;
+ int active;
+} parsed_cost_object;
+
+#define RAW_PROFILE_INIT_SIZE 100
+extern int raw_profile_next;
+extern int raw_profile_size;
+extern parsed_cost_object *raw_profile;
+
+/* -----------------------------------------------------------------------------
+ * Misc.
+ * -------------------------------------------------------------------------- */
+
+extern int Verbose;
+extern char *Pgm;
+extern void readRawProfile(FILE *,int*,int);
+extern void printRawProfile();
+extern void add_costs(object_cost *,object_cost);
+extern void createConnectivityMatrix(int,Matrix *,Matrix *,int *,int);
+extern void printConnectivityMatrix(Matrix,Matrix,int);
+extern FILE* logFile;
+#endif
diff --git a/utils/prof/cgprof/daVinci.c b/utils/prof/cgprof/daVinci.c
new file mode 100644
index 0000000000..0a59d1c89e
--- /dev/null
+++ b/utils/prof/cgprof/daVinci.c
@@ -0,0 +1,760 @@
+/* ------------------------------------------------------------------------
+ * $Id: daVinci.c,v 1.5 2006/01/09 14:38:01 simonmar Exp $
+ *
+ * Copyright (C) 1995-2000 University of Oxford
+ *
+ * Permission to use, copy, modify, and distribute this software,
+ * and to incorporate it, in whole or in part, into other software,
+ * is hereby granted without fee, provided that
+ * (1) the above copyright notice and this permission notice appear in
+ * all copies of the source code, and the above copyright notice
+ * appear in clearly visible form on all supporting documentation
+ * and distribution media;
+ * (2) modified versions of this software be accompanied by a complete
+ * change history describing author, date, and modifications made;
+ * and
+ * (3) any redistribution of the software, in original or modified
+ * form, be without fee and subject to these same conditions.
+ * --------------------------------------------------------------------- */
+
+#include "daVinci.h"
+#include <stdarg.h>
+#include <string.h>
+#include <ctype.h>
+
+static char* extra_space(int);
+static void recur_graphToDaVinci(int,Matrix *, Matrix *,char*,int);
+static char *parse_word(char**);
+static char *parse_quoted(char**);
+static char *dup_str(char*);
+double this_total_time,
+ this_total_comp_max, this_total_comp_avg,
+ this_total_comm_max, this_total_comm_avg,
+ this_total_comp_idle_max, this_total_comp_idle_avg;
+long int this_hrel_max, this_hrel_avg;
+int this_syncs;
+
+char *lastDavinciCmd;
+
+/* -----------------------------------------------------------------------------
+ * Send a command with ok return value daVinci
+ * -------------------------------------------------------------------------- */
+
+void cmdDaVinci(char* format,...) {
+ va_list args;
+
+ va_start(args, format);
+ vfprintf(stdout, format, args);
+ fprintf(stdout, "\n");
+ va_end(args);
+ fflush(stdout);
+ lastDavinciCmd = format;
+}
+
+/* -----------------------------------------------------------------------------
+ * Initialise daVinci
+ * -------------------------------------------------------------------------- */
+
+void initDaVinci() {
+ cmdDaVinci("window(title(\"GHC profiler: cost-centre-stack view\"))\n");
+ cmdDaVinci("set(font_size(8))");
+ cmdDaVinci("set(animation_speed(0))");
+ cmdDaVinci("set(scrolling_on_selection(false))");
+ /* SAJ */
+ /* cmdDaVinci("set(no_cache(true)))"); */
+ cmdDaVinci("app_menu(create_icons(["
+ "icon_entry(\"delete\","
+ "\"delete.xbm\","
+ "\"Delete node and its children\"),"
+ "icon_entry(\"undo\","
+ "\"undo.xbm\","
+ "\"Undo delete\"),"
+ "blank,"
+ "icon_entry(\"time\","
+ "\"time.xbm\","
+ "\"Cost metric view\"),"
+ "icon_entry(\"percent\","
+ "\"percent.xbm\","
+ "\"Percentage view\"),"
+ "blank,"
+ "icon_entry(\"compress\","
+ "\"compress.xbm\","
+ "\"Compressed node view\"),"
+ "icon_entry(\"uncompress\","
+ "\"uncompress.xbm\","
+ "\"Uncompressed node view\"),"
+ "blank,"
+ "icon_entry(\"absolute\","
+ "\"absolute.xbm\","
+ "\"Display inherited profile results\"),"
+ "icon_entry(\"absdelta\","
+ "\"absdelta.xbm\","
+ "\"Display flat profile results\"),"
+ "icon_entry(\"reldelta\","
+ "\"reldelta.xbm\","
+ "\"Trim zero-cost sub-trees\"),"
+ "icon_entry(\"weightdelta\","
+ "\"weightdelta.xbm\","
+ "\"Trim zero-cost nodes\"),"
+ "blank,"
+ "icon_entry(\"sync\","
+ "\"sync.xbm\","
+ "\"Graph view\"),"
+ "icon_entry(\"comp\","
+ "\"comp.xbm\","
+ "\"SCCs critical path\"),"
+ "icon_entry(\"comm\","
+ "\"comm.xbm\","
+ "\"Computation time critical path\"),"
+ "icon_entry(\"wait\","
+ "\"wait.xbm\","
+ "\"Heap usage critical path\"),"
+ "icon_entry(\"hrel\","
+ "\"hrel.xbm\","
+ "\"Node spy\"),"
+ "blank,"
+ "icon_entry(\"help\","
+ "\"help.xbm\","
+ "\"Help\"),"
+ "]))");
+
+ activateDaVinciMenu("default");
+ cmdDaVinci("app_menu(create_menus([menu_entry_mne(\"jump\",\"Goto a node\",\"G\",control,\"G\")]))\n");
+ /* SAJ */
+ // cmdDaVinci("app_menu(activate_menus([\"jump\"]))");
+}
+
+/* -----------------------------------------------------------------------------
+ * Menu FSM
+ * -------------------------------------------------------------------------- */
+
+void activateDaVinciMenu(char *pressed) {
+ static int compress=1,time=1,critical_type=0,critical=0,undo=1,delete=0;
+
+ if (strcmp(pressed,"absolute")==0) critical_type=0;
+ if (strcmp(pressed,"absdelta")==0) critical_type=1;
+ if (strcmp(pressed,"reldelta")==0) critical_type=2;
+ if (strcmp(pressed,"weightdelta")==0) critical_type=3;
+
+ if (strcmp(pressed,"sync")==0) critical=0;
+ if (strcmp(pressed,"comp")==0) critical=1;
+ if (strcmp(pressed,"comm")==0) critical=2;
+ if (strcmp(pressed,"wait")==0) critical=3;
+ if (strcmp(pressed,"hrel")==0) critical=4;
+
+ if (strcmp(pressed,"compress")==0 || strcmp(pressed,"uncompress")==0)
+ compress=!compress;
+
+ if (strcmp(pressed,"time")==0 || strcmp(pressed,"percent")==0)
+ time=!time;
+
+ if (strcmp(pressed,"undo")==0) {undo=!undo;}
+ if (strcmp(pressed,"delete")==0) {delete=!delete;}
+
+ printf("app_menu(activate_icons([");
+ if (critical_type!=0) printf("\"absolute\",");
+ if (critical_type!=1) printf("\"absdelta\",");
+ if (critical_type!=2) printf("\"reldelta\",");
+ if (critical_type!=3) printf("\"weightdelta\",");
+
+ if (critical!=0) printf("\"sync\",");
+ if (critical!=1) printf("\"comp\",");
+ if (critical!=2) printf("\"comm\",");
+ if (critical!=3) printf("\"wait\",");
+ if (critical!=4) printf("\"hrel\",");
+
+ if (!compress) printf("\"compress\",");
+ if (compress) printf("\"uncompress\",");
+ if (!time) printf("\"time\",");
+ if (time) printf("\"percent\",");
+ if (!delete) printf("\"delete\",");
+ if (!undo) printf("\"undo\",");
+
+ cmdDaVinci("\"help\"]))");
+}
+
+/* -----------------------------------------------------------------------------
+ * Graph to daVinci
+ * -------------------------------------------------------------------------- */
+
+void graphToDaVinci(int root,Matrix *graph, Matrix *costs, int removezerocosts) {
+ int i,j;
+ object_cost *ptr;
+ char zeronodes[MAX_PROFILE_LINE_LENGTH*2]; // is this a sen. MAX
+ char TEMPzeronodes[MAX_PROFILE_LINE_LENGTH*2];
+ char* p_zeronodes = zeronodes;
+ char* TEMPp_zeronodes = TEMPzeronodes;
+
+ printf("graph(new([");
+ if (PrintLogo) {
+ /* I have implemented some name changes here. They are purely for output and */
+ /* following the relation (comp = scc, comm = ticks, wait = bytes */
+ printf("l(\"info\",n(\"\",["
+ "a(\"COLOR\",\"gold\"),"
+ "a(\"FONTFAMILY\",\"courier\"),"
+ //"a(\"_GO\",\"icon\"),"
+ //"a(\"ICONFILE\",\"oxpara.xbm\"),"
+ "a(\"OBJECT\",\""
+ "Program statistics\\n\\n"
+ "Time elapsed = %6.2f ticks\\n"
+ "Heap usage = %6.2f bytes\\n"
+ "Total scc count = %6.2f (scc)\\n"
+ "\")],[])),",
+ TotalComm,TotalCompIdle,
+ TotalComp
+ );
+ }
+
+ if (root==-1) {
+ printf("]))\n");
+ } else {
+ ptr = &Mat(object_cost,*costs,root,0);
+ this_total_comp_max = ptr->comp_max;
+ this_total_comp_avg = ptr->comp_avg;
+ this_total_comm_max = ptr->comm_max;
+ this_total_comm_avg = ptr->comm_avg;
+ this_total_comp_idle_max= ptr->comp_idle_max;
+ this_total_comp_idle_avg= ptr->comp_idle_avg;
+ this_total_time = 0.00001 +
+ this_total_comp_max+ this_total_comm_max;
+ this_hrel_max = ptr->hrel_max;
+ this_hrel_avg = ptr->hrel_avg;
+ this_syncs = ptr->syncs;
+ recur_graphToDaVinci(root,graph,costs,p_zeronodes,removezerocosts);
+
+ printf("]))\n");
+ fflush(stdout);
+ cmdDaVinci("special(focus_node(\"%d\"))\n",root);
+
+ /* graph will have been altered so that visted elements are marked
+ by a negative value. These are reset */
+ for(i=0;i<graph->rows;i++) {
+ for(j=0;j<graph->cols;j++) {
+ if (Mat_dense(*graph,i,j))
+ if (Mat(int,*graph,i,j)<0) Mat(int,*graph,i,j)=1;
+ }
+ }
+
+ if (removezerocosts==1)
+ {
+ if (strlen(p_zeronodes)>0)
+ { strncpy(TEMPp_zeronodes,p_zeronodes,strlen(p_zeronodes)-1);
+ printf("select_nodes_labels([%s])\n",TEMPp_zeronodes);
+ }
+ strcpy(TEMPp_zeronodes,"");
+ strcpy(p_zeronodes,"");
+ }
+ }
+}
+
+static char *printCompressNode(int node, object_cost *ptr) {
+ char name[MAX_FUNNAME+20];
+ char comp[MAX_FUNNAME+20];
+ char comm[MAX_FUNNAME+20];
+ static char res[(MAX_FUNNAME+20)*4];
+ char tempstring[MAX_FUNNAME+20];
+ char *padding;
+ int x;
+ char delimiter[] = "&";
+
+ if (symbol_table[node].type==CG_SSTEP)
+ sprintf(name,"%d %s",
+ symbol_table[node].lineno,symbol_table[node].filename);
+ else
+ {
+ strcpy(tempstring,symbol_table[node].filename);
+ sprintf(name,"%s",strtok(tempstring,delimiter));
+ }
+
+ if (NodeviewTime) {
+ /* changed this for GHC stats */
+ sprintf(comp,"\\nTime %6.2fticks\\n",ptr->comm_max);
+ sprintf(comm,"Bytes %6.2funits",ptr->comp_idle_max);
+ } else {
+ sprintf(comp,"\\nTime %6.2f%%\\n",(ptr->comm_max/TotalComm)*100.0);
+ sprintf(comm,"Bytes %6.2f%%",(ptr->comp_idle_max/TotalCompIdle)*100.0);
+ }
+ /* Slightly arbitrary choice for max display length of CC string */
+ /* If it is larger than this the display nodes look bad */
+ if (strlen(name)>20) name[20]='\0';
+ x=strlen(name);
+ if (((20-(strlen(name)+3))/2)>19)
+ padding = extra_space(0);
+ else
+ padding = extra_space((20-(strlen(name)+3))/2); /* includes \\n */
+ strcpy(res,padding);
+ strcat(res,name);
+ strcat(res,comp);
+ strcat(res,comm);
+ return res;
+}
+
+static char *printUncompressNode(int node, object_cost *ptr) {
+ char name [MAX_FUNNAME+40];
+ char module [MAX_FUNNAME+40];
+ char group [MAX_FUNNAME+40];
+ char head [MAX_FUNNAME+40];
+ char comp [MAX_FUNNAME+40];
+ char comm [MAX_FUNNAME+40];
+ char wait [MAX_FUNNAME+40];
+ char hrel [MAX_FUNNAME+40];
+ char tempstring[MAX_FUNNAME+20];
+ char tempstring2[MAX_FUNNAME+20];
+ char *tempstring3;
+ char *tempstring5;
+ char tempstring4[MAX_FUNNAME+20];
+ char delimiter[] = "&";
+
+
+ static char res[(MAX_FUNNAME+40)*7];
+ char *padding;
+ int width=0,x;
+
+ if (symbol_table[node].type==CG_SSTEP)
+ sprintf(name,"%s line %d\\n",
+ symbol_table[node].filename,symbol_table[node].lineno);
+ else
+ {
+ strcpy(tempstring,symbol_table[node].filename);
+ strcpy(tempstring2,symbol_table[node].filename);
+ sprintf(name,"%s",strtok(tempstring,delimiter));
+ strcpy(tempstring4,tempstring2);
+ tempstring5 = strpbrk(tempstring4,delimiter);
+ sprintf(module,"%s",strtok(tempstring5+1,delimiter));
+ tempstring3 = strrchr(tempstring2,'&');
+ sprintf(group,"%s",tempstring3+1);
+ }
+
+ if (NodeviewTime) {
+
+ sprintf(head, "Metric Total \\n");
+ sprintf(comp, " Time %6.2ft \\n",ptr->comm_max);
+ sprintf(comm, " Bytes %6.2fu \\n",ptr->comp_idle_max);
+ sprintf(wait, " SCC %6.2fc \\n",ptr->comp_max);
+
+
+ } else {
+
+ sprintf(head, "Metric Total \\n");
+ sprintf(comp, " Time %5.1f%% \\n",100.0*SAFEDIV(ptr->comm_max,TotalComm));
+ sprintf(comm, " Bytes %5.1f%% \\n",100.0*SAFEDIV(ptr->comp_idle_max,TotalCompIdle));
+ sprintf(wait, " SCC %5.1f%% \\n",100.0*SAFEDIV(ptr->comp_max,TotalComp));
+
+ }
+
+ if ((x=strlen(name))>width) width=x;
+ if ((x=strlen(hrel))>width) width=x;
+ padding = extra_space((width-strlen(name)+3)/2); /* includes \\n */
+ /* strcpy(res,padding); */
+ strcpy(res,"Cost centre: ");
+ strcat(res,name);
+ strcat(res,"\\n");
+ strcat(res,"Module : ");
+ strcat(res,module);
+ strcat(res,"\\n");
+ strcat(res,"Group : ");
+ strcat(res,group);
+ strcat(res,"\\n\\n");
+
+ strcat(res,head);
+ strcat(res,comp);
+ strcat(res,comm);
+ strcat(res,wait);
+ /* strcat(res,hrel); */
+ return res;
+}
+
+
+double nodeColour(object_cost *cost) {
+
+ switch (CriticalPath + CriticalType) {
+ case CRITTYPE_ABSOLUTE+CRITICAL_SYNCS:
+ case CRITTYPE_ABSDELTA+CRITICAL_SYNCS:
+ case CRITTYPE_RELDELTA+CRITICAL_SYNCS:
+ case CRITTYPE_WEIGHTDELTA+CRITICAL_SYNCS:
+ return SAFEDIV(((double)cost->syncs),((double)this_syncs));
+
+ case CRITTYPE_ABSOLUTE+CRITICAL_COMP:
+ return SAFEDIV(cost->comp_max,this_total_comp_max);
+
+ case CRITTYPE_ABSOLUTE+CRITICAL_COMM:
+ return SAFEDIV(cost->comm_max,this_total_comm_max);
+
+ case CRITTYPE_ABSOLUTE+CRITICAL_WAIT:
+ return SAFEDIV(cost->comp_idle_max,this_total_comp_idle_max);
+
+ case CRITTYPE_ABSOLUTE+CRITICAL_HREL:
+ return SAFEDIV(((double) cost->hrel_max),((double)this_hrel_max));
+
+ case CRITTYPE_ABSDELTA+CRITICAL_COMP:
+ return SAFEDIV(cost->comp_max,TotalComp);
+
+ case CRITTYPE_ABSDELTA+CRITICAL_COMM:
+ return SAFEDIV(cost->comm_max,TotalComm);
+
+ case CRITTYPE_ABSDELTA+CRITICAL_WAIT:
+ return SAFEDIV(cost->comp_idle_max,TotalCompIdle);
+
+ case CRITTYPE_ABSDELTA+CRITICAL_HREL:
+ return SAFEDIV(((double) (cost->hrel_max - cost->hrel_avg)),
+ ((double) (this_hrel_max-this_hrel_avg)));
+
+ case CRITTYPE_RELDELTA+CRITICAL_COMP:
+ return SAFEDIV((cost->comp_max-cost->comp_avg),
+ (cost->comp_avg*DeltaNormalise));
+
+ case CRITTYPE_RELDELTA+CRITICAL_COMM:
+ return SAFEDIV((cost->comm_max-cost->comm_avg),
+ (cost->comm_avg*DeltaNormalise));
+
+ case CRITTYPE_RELDELTA+CRITICAL_WAIT:
+ return SAFEDIV((cost->comp_idle_max-cost->comp_idle_avg),
+ (cost->comp_idle_avg*DeltaNormalise));
+
+ case CRITTYPE_RELDELTA+CRITICAL_HREL:
+ return SAFEDIV(((double) (cost->hrel_max - cost->hrel_avg)),
+ ((double) (cost->hrel_avg*DeltaNormalise)));
+
+ case CRITTYPE_WEIGHTDELTA+CRITICAL_COMP:
+ return (SAFEDIV((cost->comp_max-cost->comp_avg),
+ (cost->comp_avg*DeltaNormalise))*
+ SAFEDIV(cost->comp_max,this_total_comp_max));
+
+ case CRITTYPE_WEIGHTDELTA+CRITICAL_COMM:
+ return (SAFEDIV((cost->comm_max-cost->comm_avg),
+ (cost->comm_avg*DeltaNormalise))*
+ SAFEDIV(cost->comm_max,this_total_comm_max));
+
+ case CRITTYPE_WEIGHTDELTA+CRITICAL_WAIT:
+ return (SAFEDIV((cost->comp_idle_max-cost->comp_idle_avg),
+ (cost->comp_idle_avg*DeltaNormalise))*
+ SAFEDIV(cost->comp_idle_max,this_total_comp_idle_max));
+
+ case CRITTYPE_WEIGHTDELTA+CRITICAL_HREL:
+ return (SAFEDIV(((double) (cost->hrel_max - cost->hrel_avg)),
+ ((double) (cost->hrel_avg*DeltaNormalise)))*
+ SAFEDIV(((double) cost->hrel_max),((double)this_hrel_max)));
+
+ }
+ return 0.0;
+}
+
+int percentToColour(double colour) {
+ int range=255,base=0;
+
+ if (!Colour) {
+ base =100;
+ range=155;
+ }
+ if (colour>1.0) return (base+range);
+ else if (colour<0.0) return base;
+ else return (((int) (((double)range)*colour))+base);
+}
+
+/* -----------------------------------------------------------------------------
+ * Recursively draw the graph
+ * -------------------------------------------------------------------------- */
+
+static void recur_graphToDaVinci(int node,Matrix *graph,Matrix *costs,char* p_zeronodes, int mode){
+ object_cost *ptr;
+ int i,j,no_children=0,*children=NULL,colour;
+ char *node_str;
+ char tempnode[MAX_FUNNAME];
+ if (Mat(int,*graph,node,node)<0) {
+ printf("r(\"%d\") ",node);
+ } else {
+ for(i=0;i<graph->cols;i++)
+ if (node!=i && Mat_dense(*graph,node,i)) no_children++;
+
+ if (no_children>0) {
+ children = calloc(no_children,sizeof(int));
+ if (children==NULL) {
+ fprintf(stderr,"{printDaVinci} unable to allocate %d ",no_children);
+ exit(1);
+ }
+ for((i=0,j=0);i<graph->cols;i++)
+ if (node!=i && Mat_dense(*graph,node,i)) children[j++]=i;
+
+ qsort(children,no_children,sizeof(int),
+ (int (*)(const void *,const void *)) cmp_symbol_entry);
+ }
+ ptr = &Mat(object_cost,*costs,node,0);
+ node_str=(NodeviewCompress)?
+ printCompressNode(node,ptr):
+ printUncompressNode(node,ptr);
+ printf("l(\"%d\",n(\"\",[a(\"OBJECT\",\"%s\"),",node,node_str);
+ printf("a(\"FONTFAMILY\",\"courier\"),");
+
+
+ // hide the CAF:REPOSITORY as default
+ if (!strncmp(node_str,"Cost centre: CAF:REPOSITORY",26))
+ printf("a(\"HIDDEN\",\"true\"),"); // when uncompressed
+ if (!strncmp(node_str," CAF:REPOSITORY",12))
+ printf("a(\"HIDDEN\",\"true\"),"); // when compressed
+
+
+ if (mode==2)
+ {
+ if ((ptr->comm_max+ptr->comp_idle_max+ptr->comp_max) <= 0.0)
+ printf("a(\"HIDDEN\",\"true\"),");
+ }
+ //for pruning all zero-cost nodes
+ if (mode==1)
+ {
+ if ((ptr->comm_max+ptr->comp_idle_max+ptr->comp_max) <= 0.0)
+ { fprintf(logFile,"Node %d %s is a candidate for deletion\n",node, node_str);
+ sprintf(tempnode,"\"%d\",",node);
+ strcat(p_zeronodes,tempnode);
+ }
+ }
+
+ colour=percentToColour(1.0-nodeColour(ptr));
+ printf("a(\"COLOR\",\"#ff%.2x%.2x\")",colour,colour);
+ printf("],[");
+ Mat(int,*graph,node,node)=-1;
+ for(i=0;i<no_children;i++) {
+
+ printf("e(\"%d->%d\",[],",node,children[i]);
+
+ recur_graphToDaVinci(children[i],graph,costs,p_zeronodes,mode);
+ printf(")");
+ if (i<(no_children-1)) {printf(",");}
+ }
+ printf("]))");
+ }
+}
+
+
+
+static void recur_graphToDaVinci_old(int node,Matrix *graph, Matrix *costs) {
+ object_cost *ptr;
+ int i,j,no_children=0,*children=NULL,colour;
+ char *node_str;
+ if (Mat(int,*graph,node,node)<0) {
+ fprintf(logFile,"r(\"%d\") ",node);
+ printf("r(\"%d\") ",node);
+ } else {
+ for(i=0;i<graph->cols;i++)
+ if (node!=i && Mat_dense(*graph,node,i)) no_children++;
+
+ if (no_children>0) {
+ children = calloc(no_children,sizeof(int));
+ if (children==NULL) {
+ fprintf(stderr,"{printDaVinci} unable to allocate %d ",no_children);
+ exit(1);
+ }
+ for((i=0,j=0);i<graph->cols;i++)
+ if (node!=i && Mat_dense(*graph,node,i)) children[j++]=i;
+
+ qsort(children,no_children,sizeof(int),
+ (int (*)(const void *,const void *)) cmp_symbol_entry);
+ }
+ ptr = &Mat(object_cost,*costs,node,0);
+ node_str=(NodeviewCompress)?
+ printCompressNode(node,ptr):
+ printUncompressNode(node,ptr);
+ fprintf(logFile,"l(\"%d\",n(\"\",[a(\"OBJECT\",\"%s\"),",node,node_str);
+ printf("l(\"%d\",n(\"\",[a(\"OBJECT\",\"%s\"),",node,node_str);
+ fprintf(logFile,"a(\"FONTFAMILY\",\"courier\"),");
+ printf("a(\"FONTFAMILY\",\"courier\"),");
+ if (symbol_table[node].type==CG_SSTEP)
+ printf("a(\"BORDER\",\"double\"),");
+ else
+ //if (prune subgraphs of zero cost node)
+ // minNodeSize hardwired
+ if ((ptr->comm_max+ptr->comp_idle_max+ptr->comp_max) < minNodeSize)
+ printf("a(\"HIDDEN\",\"true\"),");
+
+ //if ((ptr->comm_max+ptr->comp_idle_max+ptr->comp_max) < 0.01)
+ // small=1;
+ //else small=0;
+
+
+ colour=percentToColour(1.0-nodeColour(ptr));
+ //if (!small)
+ fprintf(logFile,"a(\"COLOR\",\"#ff%.2x%.2x\")",colour,colour);
+ printf("a(\"COLOR\",\"#ff%.2x%.2x\")",colour,colour);
+ //else
+ // printf("a(\"COLOR\",\"yellow\"),");
+ fprintf(logFile,"],[");
+ printf("],[");
+ Mat(int,*graph,node,node)=-1;
+ for(i=0;i<no_children;i++) {
+
+ //if (!small)
+ fprintf(logFile,"e(\"%d->%d\",[],",node,children[i]);
+ printf("e(\"%d->%d\",[],",node,children[i]);
+ //else
+ // printf("e(\"%d->%d\",[a(\"EDGECOLOR\",\"yellow\")],",node,children[i]);
+
+ recur_graphToDaVinci_old(children[i],graph,costs);
+ fprintf(logFile,")");
+ printf(")");
+ if (i<(no_children-1)) {fprintf(logFile,","); printf(",");}
+ }
+ fprintf(logFile,"]))");
+ printf("]))");
+ }
+}
+
+
+/* -----------------------------------------------------------------------------
+ * Update colour
+ * -------------------------------------------------------------------------- */
+
+void updateColours(int root, Matrix *graph, Matrix *costs) {
+ int i,colour,last;
+
+ printf("graph(change_attr([");
+ for(last=costs->rows-1;last>=0;last--)
+ if (Mat_dense(*graph,last,last)) break;
+
+ for(i=0;i<costs->rows;i++) {
+ if (Mat_dense(*graph,i,i)) {
+ colour = percentToColour(1.0-nodeColour(&Mat(object_cost,*costs,i,0)));
+ printf("node(\"%d\",[a(\"COLOR\",\"#ff%.2x%.2x\")])",
+ i,colour,colour);
+ if (i<last) printf(",");
+ }
+ }
+ printf("]))\n");
+}
+
+/* -----------------------------------------------------------------------------
+ * Parse answer from daVinci
+ * -------------------------------------------------------------------------- */
+
+davinciCmd parseDaVinciCmd(char *input) {
+ davinciCmd result;
+ char *crp;
+ char *word;
+ int i;
+
+ result.size=1;
+ result.list=NULL;
+ for(crp=input;*crp;crp++)
+ if (*crp==',') result.size++;
+
+ crp=input;
+ word = parse_word(&crp);
+ if (Verbose) fprintf(logFile,"{parseDaVinciCmd}=%s size=%d\n",word,result.size);
+ if (strcmp(word,"node_selections_labels")==0) {
+ result.type=DAVINCI_NODE;
+ result.list =calloc(result.size,sizeof(char*));
+ if (result.list==NULL) {
+ fprintf(stderr,"{parseDaVinciCmd} failed to allocate storage");
+ exit(1);
+ }
+ crp+=2;
+ i=0;
+ word = parse_quoted(&crp);
+ result.list[i++] = dup_str(word);
+ while (*crp++==',') {
+ word = parse_quoted(&crp);
+ result.list[i++] = dup_str(word);
+ }
+ } else if (strcmp(word,"icon_selection")==0) {
+ result.type=DAVINCI_ICON;
+ result.list =calloc(result.size,sizeof(char*));
+ if (result.list==NULL) {
+ fprintf(stderr,"{parseDaVinciCmd} failed to allocate storage");
+ exit(1);
+ }
+ crp++;
+ i=0;
+ word = parse_quoted(&crp);
+ result.list[i++] = dup_str(word);
+ } else if (strcmp(word,"tcl_answer")==0) {
+ result.type=DAVINCI_TCL;
+ result.list =calloc(result.size,sizeof(char*));
+ if (result.list==NULL) {
+ fprintf(stderr,"{parseDaVinciCmd} failed to allocate storage");
+ exit(1);
+ }
+ crp++;
+ i=0;
+ word = parse_quoted(&crp);
+ result.list[i++] = dup_str(word);
+ } else if (strcmp(word,"menu_selection")==0) {
+ result.type=DAVINCI_MENU;
+ result.list =calloc(result.size,sizeof(char*));
+ if (result.list==NULL) {
+ fprintf(stderr,"{parseDaVinciCmd} failed to allocate storage");
+ exit(1);
+ }
+ crp++;
+ i=0;
+ word = parse_quoted(&crp);
+ result.list[i++] = dup_str(word);
+ }else if (strcmp(word,"node_double_click")==0) {
+ result.type=DAVINCI_OK;
+ } else if (strcmp(word,"edge_selection_labels")==0) {
+ result.type=DAVINCI_OK;
+ } else if (strcmp(word,"ok")==0) {
+ result.type=DAVINCI_OK;
+ } else if (strcmp(word,"quit")==0) {
+ result.type=DAVINCI_QUIT;
+ } else {
+ result.type=DAVINCI_ERROR;
+ }
+ return result;
+}
+
+/* -----------------------------------------------------------------------------
+ * Misc.
+ * -------------------------------------------------------------------------- */
+
+
+/* Function that returns a string containing \texttt{x} spaces. */
+static char* extra_space(int x) {
+ static char space[MAX_FUNNAME+1];
+ int i;
+
+ if (Verbose) fprintf(logFile,"Padding is %d\n",x);
+ for(i=0;(i<x)&&(i<MAX_FUNNAME);i++) space[i]=' ';
+ space[i]='\0';
+ return space;
+}
+
+
+static char *parse_word(char **crp) {
+ static char result[MAX_FUNNAME];
+ int i=0;
+
+ while(islower(**crp) || **crp=='_') {
+ result[i++]=**crp;
+ (*crp)++;
+ }
+ result[i]='\0';
+ return result;
+}
+
+static char *parse_quoted(char **crp) {
+ static char result[MAX_FUNNAME];
+ int i=0;
+ if (**crp=='\"') {
+ (*crp)++;
+ while (**crp != '\"') {
+ result[i++]=**crp;
+ (*crp)++;
+ }
+ (*crp)++;
+ }
+ result[i]='\0';
+ return result;
+}
+
+static char *dup_str(char *xs) {
+ char *result;
+
+ if (xs==NULL) return NULL;
+ else {
+ result = malloc(strlen(xs)+1);
+ if (result==NULL) {
+ fprintf(stderr,"{dup_str}: unable to allocate bytes");
+ exit(1);
+ }
+ strcpy(result,xs);
+ return result;
+ }
+}
diff --git a/utils/prof/cgprof/daVinci.h b/utils/prof/cgprof/daVinci.h
new file mode 100644
index 0000000000..3f6106983d
--- /dev/null
+++ b/utils/prof/cgprof/daVinci.h
@@ -0,0 +1,95 @@
+/* ------------------------------------------------------------------------
+ * $Id: daVinci.h,v 1.1 2000/04/05 10:06:36 simonmar Exp $
+ *
+ * Copyright (C) 1995-2000 University of Oxford
+ *
+ * Permission to use, copy, modify, and distribute this software,
+ * and to incorporate it, in whole or in part, into other software,
+ * is hereby granted without fee, provided that
+ * (1) the above copyright notice and this permission notice appear in
+ * all copies of the source code, and the above copyright notice
+ * appear in clearly visible form on all supporting documentation
+ * and distribution media;
+ * (2) modified versions of this software be accompanied by a complete
+ * change history describing author, date, and modifications made;
+ * and
+ * (3) any redistribution of the software, in original or modified
+ * form, be without fee and subject to these same conditions.
+ * --------------------------------------------------------------------- */
+
+#ifndef _DAVINCI_H_
+#define _DAVINCI_H_
+#include "symbol.h"
+#include "matrix.h"
+#include "cgprof.h"
+
+#define PAIRMAX(x,y) (((x)>(y))?(x):(y))
+
+#define SAFEDIV(x,y) (((y)==0.0)?0.0:((x)/(y)))
+
+#define DAVINCI_ERROR 0
+#define DAVINCI_OK 1
+#define DAVINCI_NODE 2
+#define DAVINCI_MENU 3
+#define DAVINCI_ICON 4
+#define DAVINCI_DOUBLE_CLICK 5
+#define DAVINCI_QUIT 6
+#define DAVINCI_TCL 7
+
+#define TCL_HREL 0
+#define TCL_COMP 1
+#define TCL_COMM 2
+#define TCL_WAIT 3
+#define TCL_EXIT 4
+
+#define INCLUDEDIR "@includedir@"
+
+typedef struct {
+ int type;
+ char **list;
+ int size;
+} davinciCmd;
+
+
+#define CRITICAL_COMP 0
+#define CRITICAL_COMM 1
+#define CRITICAL_WAIT 2
+#define CRITICAL_HREL 3
+#define CRITICAL_SYNCS 4
+
+#define CRITTYPE_ABSOLUTE 0
+#define CRITTYPE_ABSDELTA 100
+#define CRITTYPE_RELDELTA 200
+#define CRITTYPE_WEIGHTDELTA 300
+
+extern void graphToDaVinci(int,Matrix*,Matrix *,int);
+davinciCmd parseDaVinciCmd(char*);
+extern void cmdDaVinci(char*,...);
+extern void initDaVinci();
+extern void activateDaVinciMenu(char *);
+extern void updateColours(int,Matrix*,Matrix*);
+extern void tclPieUpdate(object_cost *,int,int);
+extern void tclPieInit();
+
+
+extern char* lastDavinciCmd;
+extern int NodeviewTime;
+extern int NodeviewCompress;
+extern double TotalComp;
+extern double TotalComm;
+extern double TotalCompIdle;
+extern int TotalSyncs;
+extern long int TotalH;
+extern char *dateProfiled;
+extern char *machineName;
+extern int bsp_p;
+extern double bsp_s,bsp_l,bsp_g;
+extern int CriticalPath;
+extern int CriticalType;
+extern double minNodeSize;
+extern int bsp_p;
+extern int PrintLogo;
+extern int Colour;
+extern int DeltaNormalise;
+extern int PieCombine;
+#endif
diff --git a/utils/prof/cgprof/main.c b/utils/prof/cgprof/main.c
new file mode 100644
index 0000000000..afa8fbee19
--- /dev/null
+++ b/utils/prof/cgprof/main.c
@@ -0,0 +1,436 @@
+/* ------------------------------------------------------------------------
+ * $Id: main.c,v 1.4 2005/12/02 12:45:16 simonmar Exp $
+ *
+ * Copyright (C) 1995-2000 University of Oxford
+ *
+ * Permission to use, copy, modify, and distribute this software,
+ * and to incorporate it, in whole or in part, into other software,
+ * is hereby granted without fee, provided that
+ * (1) the above copyright notice and this permission notice appear in
+ * all copies of the source code, and the above copyright notice
+ * appear in clearly visible form on all supporting documentation
+ * and distribution media;
+ * (2) modified versions of this software be accompanied by a complete
+ * change history describing author, date, and modifications made;
+ * and
+ * (3) any redistribution of the software, in original or modified
+ * form, be without fee and subject to these same conditions.
+ * --------------------------------------------------------------------- */
+
+#include "ghcconfig.h"
+
+#include <stdio.h>
+
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#if HAVE_STRING_H
+#include <string.h>
+#endif
+
+#include "symbol.h"
+#include "cgprof.h"
+#include "matrix.h"
+#include "daVinci.h"
+
+#if HAVE_WINDOWS_H
+#include <windows.h>
+#define sleep(x) Sleep((x)*1000)
+#endif
+
+
+#define NoDeletes 80
+
+int CriticalPath=CRITICAL_SYNCS;
+int CriticalType=CRITTYPE_ABSOLUTE;
+int Verbose=1;
+int NodeviewTime=1;
+int NodeviewCompress=1;
+int PrintLogo=1;
+int Colour=1;
+int DeltaNormalise=1;
+int PieView=TCL_COMP;
+int PieCombine=0;
+char *Pgm;
+char *ProfileData;
+int NoNodes,root;
+char usage[]="usage: cgprof profile-data [See man 1 cgprof]";
+char helpUrl[]="http://www.dcs.warwick.ac.uk/people/academic/Stephen.Jarvis/profiler/";
+Matrix graph; /* NoNodes x NoNodes matrix of integers */
+Matrix costs; /* NoNodes x 1 matrix of costs */
+
+double TotalComp, TotalComm, TotalCompIdle;
+int TotalSyncs;
+long int TotalH;
+
+char *dateProfiled, *machineName;
+double minNodeSize = 0.01; /* i.e, don't show nodes with _combined_
+ comp and comm % less than this */
+double bsp_s = 74.0;
+double bsp_l = 1902;
+double bsp_g = 9.3;
+int bsp_p;
+
+FILE *logFile;
+
+
+extern void printDaVinci(int);
+
+int
+main(int argc, char *argv[]) {
+ char davinci_stdin[MAX_PROFILE_LINE_LENGTH];
+ FILE *fptr;
+ int i,j,k,going=1,*select_nodes, select_nodes_next,MaxNoNodes;
+ davinciCmd cmd;
+ int *undo_stack, undo_stack_next;
+ float temp_f;
+ char *ptr;
+ int mode = 0;
+ char *tempstring = malloc (80);
+ char *tempstring2 = malloc (80);
+
+
+ /* printf("Starting main routine of browser script\n"); */
+ /* fflush(stderr); */
+
+ if (argc!=14) {
+ fprintf(stderr,"The perl script bspsgprof is buggered\n");
+ exit(1);
+ }
+
+ /* Most (if not all) of these BSP specific arguments can be removed */
+
+ Pgm = argv[0];
+ ProfileData = argv[1];
+ bsp_p = atoi(argv[2]);
+ machineName = argv[3];
+ dateProfiled= argv[4];
+ sscanf(argv[5],"%f",&temp_f);
+ bsp_s = temp_f;
+ sscanf(argv[6],"%f",&temp_f);
+ bsp_l = temp_f;
+ sscanf(argv[7],"%f",&temp_f);
+ bsp_g = temp_f;
+ sscanf(argv[8],"%f",&temp_f);
+ minNodeSize=temp_f;
+ Verbose = atoi(argv[9]);
+ PrintLogo=atoi(argv[10]);
+ Colour=atoi(argv[11]);
+ DeltaNormalise=atoi(argv[12]);
+ MaxNoNodes=atoi(argv[13]);
+
+ /* printf("Initialisation done\n"); */
+
+ if (Verbose) sleep(10);
+ if (!(fptr=fopen(ProfileData,"r"))) {
+ fprintf(stderr,"%s: unable to open profile data in \"%s\".\n%s\n",
+ Pgm,ProfileData,usage);
+ exit(1);
+ }
+ if (!(logFile=fopen("ghcprof.log","w"))) {
+ fprintf(stderr,"%s: unable to open log file for writing\n",Pgm);
+ exit(1);
+ }
+
+ /* printf("Files opened OK\n"); */
+
+ if (!fgets(davinci_stdin, MAX_PROFILE_LINE_LENGTH, stdin) ||
+ strcmp(davinci_stdin,"ok\n")) {
+ fprintf(stderr,"%s{%s}: failed to receive ok from daVinci.\n",
+ davinci_stdin,Pgm);
+ exit(1);
+ }
+
+ /* printf("Initialising daVinci\n"); */
+
+ initDaVinci();
+
+ /* printf("Ending initialisation of daVinci\n"); */
+
+ if (Verbose) fprintf(logFile,"%s: opened profile file \"%s\".\n",Pgm,ProfileData);
+ readRawProfile(fptr,&NoNodes,MaxNoNodes);
+ fclose(fptr);
+ if (Verbose) fprintf(logFile,"%s: %d nodes in profile.\n",Pgm,NoNodes);
+
+ if (NoNodes<=0) {
+ fprintf(logFile,"%s: no call-graph profile data in \"%s\".\n"
+ "Re-run your program using the appropriate profiling flags\n",
+ Pgm,ProfileData);
+ exit(1);
+ }
+ if (Verbose) printRawProfile();
+
+ /* Do we want INHERITANCE to begin with or not? Set to yes. */
+ createConnectivityMatrix(NoNodes,&graph,&costs,&root,1);
+
+ TotalComp = Mat(object_cost,costs,root,0).comp_max;
+ TotalComm = Mat(object_cost,costs,root,0).comm_max;
+ TotalCompIdle = Mat(object_cost,costs,root,0).comp_idle_max;
+ TotalH = Mat(object_cost,costs,root,0).hrel_max;
+ TotalSyncs = Mat(object_cost,costs,root,0).syncs;
+ if (Verbose) printConnectivityMatrix(graph,costs,root);
+ fflush(logFile);
+ graphToDaVinci(root,&graph,&costs,0);
+ fflush(stdout);
+ undo_stack = calloc(NoDeletes,sizeof(int));
+ select_nodes = calloc(NoNodes,sizeof(int));
+ if (undo_stack==NULL || select_nodes==NULL) {
+ fprintf(stderr,"Unable to allocate storage for undo stack\n");
+ exit(1);
+ }
+ undo_stack_next=0;
+ select_nodes_next=0;
+ // Pie chart stuff not wanted for GHC
+ // tclPieInit();
+ // tclPieUpdate(&Mat(object_cost,costs,root,0),root,PieView);
+ select_nodes_next=1;
+ select_nodes[0]=root;
+ while (fgets(davinci_stdin, MAX_PROFILE_LINE_LENGTH, stdin) && going) {
+ cmd = parseDaVinciCmd(davinci_stdin);
+ if (Verbose) fprintf(logFile,"From davinci=\"%s\"\n",davinci_stdin);
+ switch (cmd.type) {
+ case DAVINCI_OK:
+ continue;
+
+ case DAVINCI_QUIT:
+ going=0;
+ break;
+
+ case DAVINCI_NODE:
+ select_nodes_next=cmd.size;
+ for(i=0;((i<cmd.size) && (i<NoNodes));i++)
+ select_nodes[i]=atoi(cmd.list[i]);
+ if (select_nodes_next>0)
+ //Pie chart stuff not wanted for GHC
+ //tclPieUpdate(&Mat(object_cost,costs,select_nodes[0],0),
+ // select_nodes[0],
+ // PieView);
+ if (mode==3)
+ {
+ mode = atoi(cmd.list[0]);
+ getNameFromSymbolTable(mode,tempstring);
+ for(ptr=tempstring;*ptr!='\0';ptr++)
+ if (*ptr=='&') *ptr=' ';
+ mode = 3;
+ strcpy(tempstring2,"window(show_status(\"");
+ strcat(tempstring2,tempstring);
+ strcat(tempstring2,"\"))");
+ cmdDaVinci(tempstring2);
+ strcpy(tempstring,"");
+ strcpy(tempstring2,"");
+ }
+ break;
+
+ case DAVINCI_MENU:
+ if (cmd.size>0) {
+ if (strcmp(cmd.list[0], "jump")==0) {
+ if ((select_nodes_next>=0) &&
+ (select_nodes[0]>0) &&
+ (select_nodes[0] < NoNodes) &&
+ (Mat_dense(graph,select_nodes[0],select_nodes[0]))) {
+ cmdDaVinci("special(focus_node(\"%d\"))\n",select_nodes[0]);
+ }
+ }
+ }
+ break;
+
+ case DAVINCI_ICON:
+ if (cmd.size>0) {
+ if (strcmp(cmd.list[0], "sync")==0) {
+ CriticalPath=CRITICAL_SYNCS;
+ activateDaVinciMenu(cmd.list[0]);
+ cmdDaVinci("window(show_status(\"Graph view\"))");
+ updateColours(root,&graph,&costs);
+
+ } else if (strcmp(cmd.list[0], "comp")==0) {
+ CriticalPath=CRITICAL_COMP;
+ activateDaVinciMenu(cmd.list[0]);
+ cmdDaVinci("window(show_status(\"SCCs critical path\"))");
+ updateColours(root,&graph,&costs);
+
+ } else if (strcmp(cmd.list[0], "comm")==0) {
+ CriticalPath=CRITICAL_COMM;
+ activateDaVinciMenu(cmd.list[0]);
+ cmdDaVinci("window(show_status(\"Computation time critical path\"))");
+ updateColours(root,&graph,&costs);
+
+ } else if (strcmp(cmd.list[0], "wait")==0) {
+ CriticalPath=CRITICAL_WAIT;
+ activateDaVinciMenu(cmd.list[0]);
+ cmdDaVinci("window(show_status(\"Heap usage critical path\"))");
+ updateColours(root,&graph,&costs);
+
+ } else if (strcmp(cmd.list[0], "hrel")==0) {
+
+ if (mode != 3)
+ {
+ cmdDaVinci("window(show_status(\"Node spy on\"))");
+ mode = 3;
+ }
+ else
+ {
+ mode = 0;
+ cmdDaVinci("window(show_status(\"Node spy off\"))");
+ }
+
+ } else if (strcmp(cmd.list[0], "absolute")==0) {
+ /* Now deals with inheritance profile */
+ CriticalType=CRITTYPE_ABSOLUTE;
+ activateDaVinciMenu(cmd.list[0]);
+ cmdDaVinci("window(show_status(\"Inheritance profile\"))");
+ freeMat(&graph);
+ freeMat(&costs);
+ createConnectivityMatrix(NoNodes,&graph,&costs,&root,1);
+ graphToDaVinci(root,&graph,&costs,0);
+ cmdDaVinci("window(show_status(\"Inheritance profile\"))");
+ updateColours(root,&graph,&costs);
+
+ } else if (strcmp(cmd.list[0], "absdelta")==0) {
+ /* Now deals with flat profile */
+ CriticalType=CRITTYPE_ABSDELTA;
+ activateDaVinciMenu(cmd.list[0]);
+ cmdDaVinci("window(show_status(\"Flat profile\"))");
+ freeMat(&graph);
+ freeMat(&costs);
+ createConnectivityMatrix(NoNodes,&graph,&costs,&root,0);
+ graphToDaVinci(root,&graph,&costs,0);
+ cmdDaVinci("window(show_status(\"Flat profile\"))");
+ updateColours(root,&graph,&costs);
+
+ } else if (strcmp(cmd.list[0], "reldelta")==0) {
+ CriticalType=CRITTYPE_ABSOLUTE;
+ activateDaVinciMenu(cmd.list[0]);
+ cmdDaVinci("window(show_status(\"Trimmed zero-cost sub-trees\"))");
+ strcpy(cmd.list[0], "absolute");
+ activateDaVinciMenu(cmd.list[0]);
+ graphToDaVinci(root,&graph,&costs,2);
+ updateColours(root,&graph,&costs);
+
+ } else if (strcmp(cmd.list[0], "weightdelta")==0) {
+ CriticalType=CRITTYPE_ABSOLUTE;
+ activateDaVinciMenu(cmd.list[0]);
+ cmdDaVinci("window(show_status(\"Marked zero-cost nodes ready for deletion\"))");
+ strcpy(cmd.list[0], "absolute");
+ activateDaVinciMenu(cmd.list[0]);
+ graphToDaVinci(root,&graph,&costs,1);
+ updateColours(root,&graph,&costs);
+
+ } else if (strcmp(cmd.list[0],"help")==0) {
+ cmdDaVinci("special(show_url(\"%s\"))",helpUrl);
+
+ } else if (strcmp(cmd.list[0],"time")==0) {
+ NodeviewTime=1;
+ activateDaVinciMenu(cmd.list[0]);
+ cmdDaVinci("window(show_status(\"Cost metric view\"))");
+ graphToDaVinci(root,&graph,&costs,0);
+
+ } else if (strcmp(cmd.list[0],"percent")==0) {
+ NodeviewTime=0;
+ activateDaVinciMenu(cmd.list[0]);
+ cmdDaVinci("window(show_status(\"Percentage view\"))");
+ graphToDaVinci(root,&graph,&costs,0);
+
+ } else if (strcmp(cmd.list[0],"compress")==0) {
+ NodeviewCompress=1;
+ activateDaVinciMenu(cmd.list[0]);
+ cmdDaVinci("window(show_status(\"Compressed node view\"))");
+ cmdDaVinci("menu(layout(compact_all))");
+ graphToDaVinci(root,&graph,&costs,0);
+
+ } else if (strcmp(cmd.list[0],"uncompress")==0) {
+ NodeviewCompress=0;
+ activateDaVinciMenu(cmd.list[0]);
+ cmdDaVinci("window(show_status(\"Uncompressed node view\"))");
+ graphToDaVinci(root,&graph,&costs,0);
+
+ } else if ((strcmp(cmd.list[0],"delete")==0) ||
+ (strcmp(cmd.list[0],"undo")==0)) {
+ if (strcmp(cmd.list[0],"delete")==0) {
+ if (undo_stack_next==0)
+ activateDaVinciMenu("undo");
+ for(i=0;(i<select_nodes_next) && (undo_stack_next<NoNodes);i++)
+ undo_stack[undo_stack_next++] = select_nodes[i];
+ if (undo_stack_next==NoDeletes)
+ activateDaVinciMenu("delete");
+ cmdDaVinci("window(show_status(\"Deleted node (s)\"))");
+ select_nodes_next=0;
+ } else {
+ if (undo_stack_next==NoDeletes)
+ activateDaVinciMenu("delete");
+ undo_stack_next--;
+ if (undo_stack_next==0)
+ activateDaVinciMenu("undo");
+ cmdDaVinci("window(show_status(\"Undone deletion\"))");
+ select_nodes_next=1;
+ select_nodes[0]=undo_stack[undo_stack_next];
+
+ for(i=0;i<raw_profile_next;i++)
+ raw_profile[i].active=1;
+ }
+ activateDaVinciMenu("default");
+ for(i=0;i<undo_stack_next;i++) {
+ for(j=0;j<raw_profile_next;j++) {
+ for(k=0;k<raw_profile[j].stack_size;k++) {
+ if (raw_profile[j].stack[k]==undo_stack[i])
+ raw_profile[j].active=0;
+ }
+ }
+ }
+ cmdDaVinci("window(show_message(\"Deleting node...\"))");
+ freeMat(&graph);
+ freeMat(&costs);
+ createConnectivityMatrix(NoNodes,&graph,&costs,&root,1);
+ graphToDaVinci(root,&graph,&costs,0);
+ if (strcmp(cmd.list[0],"undo")==0) {
+ if ((select_nodes[0]>0) &&
+ (select_nodes[0] < NoNodes) &&
+ (Mat_dense(graph,select_nodes[0],select_nodes[0]))) {
+ cmdDaVinci("special(focus_node(\"%d\"))\n",select_nodes[0]);
+ cmdDaVinci("special(select_nodes([\"%d\"]))",select_nodes[0]);
+ //Pie chart stuff not wanted for GHC
+ //tclPieUpdate(&Mat(object_cost,costs,select_nodes[0],0),
+ // select_nodes[0],
+ // PieView);
+ }
+ }
+ }
+ }
+ break;
+ case DAVINCI_TCL:
+ // This stuff can go as it is related to the input for the Pie chart tool
+ if (cmd.size>0) {
+ if (strcmp(cmd.list[0], "comm")==0) {
+ PieView=TCL_COMM;
+ } else if (strcmp(cmd.list[0], "comp")==0) {
+ PieView=TCL_COMP;
+ } else if (strcmp(cmd.list[0], "hrel")==0) {
+ PieView=TCL_HREL;
+ } else if (strcmp(cmd.list[0], "wait")==0) {
+ PieView=TCL_WAIT;
+ } else if (strcmp(cmd.list[0], "combine")==0) {
+ PieCombine=!PieCombine;
+ } else if (strlen(cmd.list[0])==0) {
+ break;
+ }
+ if (select_nodes_next>0) break;
+ //Added a break for compiliation above since it does not compile if
+ //we just remove the Pie chart code
+ //tclPieUpdate(&Mat(object_cost,costs,select_nodes[0],0),
+ // select_nodes[0],
+ // PieView);
+ }
+ break;
+ case DAVINCI_ERROR:
+ default:
+ fprintf(stderr,"CGPROF error:\n"
+ "\tCommand = %s\n"
+ "\tError = %s\n",lastDavinciCmd,davinci_stdin);
+ exit(1);
+ break;
+ }
+ fflush(stdout);
+ fflush(logFile);
+ }
+
+ return 0;
+}
diff --git a/utils/prof/cgprof/matrix.c b/utils/prof/cgprof/matrix.c
new file mode 100644
index 0000000000..b4ca43f96b
--- /dev/null
+++ b/utils/prof/cgprof/matrix.c
@@ -0,0 +1,98 @@
+/* ------------------------------------------------------------------------
+ * $Id: matrix.c,v 1.3 2006/01/09 14:32:31 simonmar Exp $
+ *
+ * Copyright (C) 1995-2000 University of Oxford
+ *
+ * Permission to use, copy, modify, and distribute this software,
+ * and to incorporate it, in whole or in part, into other software,
+ * is hereby granted without fee, provided that
+ * (1) the above copyright notice and this permission notice appear in
+ * all copies of the source code, and the above copyright notice
+ * appear in clearly visible form on all supporting documentation
+ * and distribution media;
+ * (2) modified versions of this software be accompanied by a complete
+ * change history describing author, date, and modifications made;
+ * and
+ * (3) any redistribution of the software, in original or modified
+ * form, be without fee and subject to these same conditions.
+ * --------------------------------------------------------------------- */
+
+/* Not very clever sparse representation of a matrix. However, it will do
+ * for the call graph profiler.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include "matrix.h"
+
+Matrix newMat(int rows,int cols, int elsize, void *zero) {
+ Matrix res;
+
+ res.elsize= elsize;
+ res.zero = malloc(elsize);
+ if (res.zero==NULL) {
+ fprintf(stderr,"{newMat} unable to allocate storage\n");
+ exit(1);
+ }
+ memcpy(res.zero,zero,elsize);
+ res.rows = rows;
+ res.cols = cols;
+ res.mat=NULL;
+ return res;
+}
+
+void freeMat(Matrix *mat) {
+ Matrix_element *tmp_ptr, *ptr=mat->mat;
+ free(mat->zero);
+
+ while(ptr!=NULL) {
+ free(ptr->data);
+ tmp_ptr = ptr->next;
+ free(ptr);
+ ptr=tmp_ptr;
+ }
+}
+
+void *_Mat(Matrix *mat,int x, int y,int lineno, char *filename) {
+ Matrix_element *ptr= mat->mat;
+ if (x<0 || x>=mat->rows || y<0 || y>=mat->cols) {
+ fprintf(stderr,"Mat[%d,%d] out of bound index at line %d of \"%s\"\n",
+ x,y,lineno,filename);
+ exit(1);
+ }
+ while(ptr) {
+ if ((x==ptr->x) && (y==ptr->y)) {
+ return ptr->data;
+ }
+ ptr=ptr->next;
+ }
+ /* Not in list */
+ ptr = (Matrix_element*) malloc(sizeof(Matrix_element));
+ if (ptr==NULL) {
+ fprintf(stderr,"{_Mat} failed to allocate %zd bytes\n",
+ sizeof(Matrix_element));
+ exit(1);
+ }
+ ptr->data = (void*) malloc(mat->elsize);
+ if (ptr->data==NULL) {
+ fprintf(stderr,"{_Mat} failed to allocate element of size %d bytes\n",
+ mat->elsize);
+ exit(1);
+ }
+ ptr->x=x;
+ ptr->y=y;
+ memcpy(ptr->data,mat->zero,mat->elsize);
+ ptr->next=mat->mat;
+ mat->mat=ptr;
+ return ptr->data;
+}
+
+int Mat_dense(Matrix mat,int x,int y) {
+ Matrix_element *ptr= mat.mat;
+ while (ptr) {
+ if ((x==ptr->x) && (y==ptr->y)) return 1;
+ ptr=ptr->next;
+ }
+ return 0;
+}
diff --git a/utils/prof/cgprof/matrix.h b/utils/prof/cgprof/matrix.h
new file mode 100644
index 0000000000..bf70cf7c90
--- /dev/null
+++ b/utils/prof/cgprof/matrix.h
@@ -0,0 +1,42 @@
+/* ------------------------------------------------------------------------
+ * $Id: matrix.h,v 1.1 2000/04/05 10:06:36 simonmar Exp $
+ *
+ * Copyright (C) 1995-2000 University of Oxford
+ *
+ * Permission to use, copy, modify, and distribute this software,
+ * and to incorporate it, in whole or in part, into other software,
+ * is hereby granted without fee, provided that
+ * (1) the above copyright notice and this permission notice appear in
+ * all copies of the source code, and the above copyright notice
+ * appear in clearly visible form on all supporting documentation
+ * and distribution media;
+ * (2) modified versions of this software be accompanied by a complete
+ * change history describing author, date, and modifications made;
+ * and
+ * (3) any redistribution of the software, in original or modified
+ * form, be without fee and subject to these same conditions.
+ * --------------------------------------------------------------------- */
+
+#ifndef _MATRIX_H_
+#define _MATRIX_H_
+typedef struct _Matrix_element {
+ int x,y;
+ void *data;
+ struct _Matrix_element *next;
+} Matrix_element;
+
+typedef struct {
+ int elsize;
+ void *zero;
+ int rows,cols;
+ Matrix_element *mat;
+} Matrix;
+
+
+extern Matrix newMat(int,int,int,void*);
+extern void *_Mat(Matrix*,int,int,int,char*);
+extern int Mat_dense(Matrix,int,int);
+extern void freeMat(Matrix *);
+
+#define Mat(t,m,i,j) (*((t*) _Mat(&(m),i,j,__LINE__,__FILE__)))
+#endif
diff --git a/utils/prof/cgprof/symbol.c b/utils/prof/cgprof/symbol.c
new file mode 100644
index 0000000000..133f59b2db
--- /dev/null
+++ b/utils/prof/cgprof/symbol.c
@@ -0,0 +1,115 @@
+/* ------------------------------------------------------------------------
+ * $Id: symbol.c,v 1.3 2003/08/01 14:50:50 panne Exp $
+ *
+ * Copyright (C) 1995-2000 University of Oxford
+ *
+ * Permission to use, copy, modify, and distribute this software,
+ * and to incorporate it, in whole or in part, into other software,
+ * is hereby granted without fee, provided that
+ * (1) the above copyright notice and this permission notice appear in
+ * all copies of the source code, and the above copyright notice
+ * appear in clearly visible form on all supporting documentation
+ * and distribution media;
+ * (2) modified versions of this software be accompanied by a complete
+ * change history describing author, date, and modifications made;
+ * and
+ * (3) any redistribution of the software, in original or modified
+ * form, be without fee and subject to these same conditions.
+ * --------------------------------------------------------------------- */
+
+#include <string.h>
+#include "symbol.h"
+
+/* -----------------------------------------------------------------------------
+ * Data structures
+ * -------------------------------------------------------------------------- */
+int symbol_table_next=0;
+int symbol_table_size=0;
+name_object *symbol_table=NULL;
+
+/* -----------------------------------------------------------------------------
+ * Create/grow symbol table
+ * -------------------------------------------------------------------------- */
+
+void enlargeSymbolTable() {
+
+ if (symbol_table_size==0) {
+ symbol_table_next = 0;
+ symbol_table_size = SYMBOL_TABLE_INIT_SIZE;
+ symbol_table = calloc(symbol_table_size,sizeof(name_object));
+ } else {
+ symbol_table_size += SYMBOL_TABLE_INIT_SIZE;
+ symbol_table = realloc(symbol_table,
+ symbol_table_size*sizeof(name_object));
+ }
+ if (symbol_table==NULL) {
+ fprintf(stderr,"{enlargeSymbolTable} unable to allocate %d elements",
+ symbol_table_size);
+ exit(1);
+ }
+}
+
+/* -----------------------------------------------------------------------------
+ * Lookup/add name to symbol table
+ * -------------------------------------------------------------------------- */
+
+name_id lookupSymbolTable(int type,int lineno,char* str) {
+ int i;
+ extern FILE *logFile;
+
+ for(i=0;i<symbol_table_next;i++) {
+ if ((type==symbol_table[i].type) &&
+ (strcmp(str,symbol_table[i].filename)==0) &&
+ (type==CG_STACK || (lineno==symbol_table[i].lineno))) {
+ return i;
+ }
+ }
+ fprintf(logFile,"{lookupSymbolTable} %d at %s line %d\n",type,str,lineno);
+ if (symbol_table_next==symbol_table_size) enlargeSymbolTable();
+ symbol_table[symbol_table_next].type = type;
+ symbol_table[symbol_table_next].lineno = lineno;
+ symbol_table[symbol_table_next].filename= malloc(1+strlen(str));
+ if (symbol_table[symbol_table_next].filename==NULL) {
+ fprintf(stderr,"{lookupSymbolTable} failed to allocate space");
+ exit(1);
+ }
+ strcpy(symbol_table[symbol_table_next].filename,str);
+ return (symbol_table_next++);
+}
+
+/* -----------------------------------------------------------------------------
+ * Comparison function to be used by \texttt{qsort}
+ * -------------------------------------------------------------------------- */
+
+int cmp_symbol_entry(const int *x, const int *y) {
+ int i;
+
+ if (symbol_table[*x].type==symbol_table[*y].type) {
+ i = strcmp(symbol_table[*x].filename,symbol_table[*y].filename);
+ if (i==0) return (symbol_table[*x].lineno - symbol_table[*y].lineno);
+ else return i;
+ } else {
+ if (symbol_table[*x].type==CG_STACK) return 1;
+ else return -1;
+ }
+}
+
+
+/* -----------------------------------------------------------------------------
+ * Pretty print a symbol table entry
+ * -------------------------------------------------------------------------- */
+
+void printSymbolTable_entry(int idx) {
+ extern FILE *logFile;
+ if (symbol_table[idx].type==CG_SSTEP) {
+ fprintf(logFile,"(line %d of %s) ",symbol_table[idx].lineno,
+ symbol_table[idx].filename);
+ } else {
+ fprintf(logFile,"%s ",symbol_table[idx].filename);
+ }
+}
+
+void getNameFromSymbolTable(int idx, char* name) {
+ strcpy(name,symbol_table[idx].filename);
+}
+
diff --git a/utils/prof/cgprof/symbol.h b/utils/prof/cgprof/symbol.h
new file mode 100644
index 0000000000..697973150c
--- /dev/null
+++ b/utils/prof/cgprof/symbol.h
@@ -0,0 +1,58 @@
+/* ------------------------------------------------------------------------
+ * $Id: symbol.h,v 1.1 2000/04/05 10:06:36 simonmar Exp $
+ *
+ * Copyright (C) 1995-2000 University of Oxford
+ *
+ * Permission to use, copy, modify, and distribute this software,
+ * and to incorporate it, in whole or in part, into other software,
+ * is hereby granted without fee, provided that
+ * (1) the above copyright notice and this permission notice appear in
+ * all copies of the source code, and the above copyright notice
+ * appear in clearly visible form on all supporting documentation
+ * and distribution media;
+ * (2) modified versions of this software be accompanied by a complete
+ * change history describing author, date, and modifications made;
+ * and
+ * (3) any redistribution of the software, in original or modified
+ * form, be without fee and subject to these same conditions.
+ * --------------------------------------------------------------------- */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <limits.h>
+
+/* -----------------------------------------------------------------------------
+ * Symbol table associated with cost centres
+ * -------------------------------------------------------------------------- */
+
+#ifndef _SYMBOL_H_
+#define _SYMBOL_H_
+#define CG_STACK 42
+#define CG_SSTEP 1968
+
+
+#define MAX_PROFILE_LINE_LENGTH 10000
+#define MAX_STACK_DEPTH 60
+#define MAX_FUNNAME 80
+
+
+typedef struct {
+ int type; /* Either CG_STACK or CG_SSTEP */
+ int lineno;
+ char *filename;
+} name_object;
+
+typedef int name_id; /* i.e. index into symbol table */
+
+#define SYMBOL_TABLE_INIT_SIZE 100
+extern int symbol_table_next;
+extern int symbol_table_size;
+extern name_object *symbol_table;
+
+
+extern void printSymbolTable(int , int *);
+extern int cmp_symbol_entry(const int *, const int *);
+extern name_id lookupSymbolTable(int,int,char*);
+extern void printSymbolTable_entry(int);
+extern void getNameFromSymbolTable(int,char*);
+#endif