drake  1.0.0
src/drawgraph-2.c
Go to the documentation of this file.
00001 /*
00002  Copyright 2015 Nicolas Melot, Christoph Kessler
00003 
00004  This file is part of Drake.
00005 
00006  Drake is free software: you can redistribute it and/or modify
00007  it under the terms of the GNU General Public License as published by
00008  the Free Software Foundation, either version 3 of the License, or
00009  (at your option) any later version.
00010 
00011  Drake is distributed in the hope that it will be useful,
00012  but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00014  GNU General Public License for more details.
00015 
00016  You should have received a copy of the GNU General Public License
00017  along with Drake. If not, see <http://www.gnu.org/licenses/>.
00018 
00019 */
00020 
00021 
00022 // drawgraph.c JK May 23, 2008
00023 
00024 #include <stdio.h>
00025 #include <stdlib.h>
00026 #include <string.h>
00027 #include <stdlib.h>
00028 
00029 #include <drake/mapping.h>
00030 #include <drake/platform.h>
00031 #include "drawgraph-2.h"
00032 
00033 FILE *input, *output, *error;
00034 
00035 // left upper corner of image
00036 double xref = 0.0;
00037 double yref = 0.0;
00038 
00039 // radius of a circle
00040 double yrad = 225.0;
00041 
00042 // distances between nodes
00043 double xdiff;
00044 double ydiff;
00045 
00046 // max no of proc and nodes +1
00047 // x[i][j] == 1 iff node i is mapped onto proc j
00048 int x[NMAX][PMAX];
00049 int num_procs = 0;
00050 int num_tasks = 0;
00051 
00052 typedef struct prel
00053 {
00054         int proc;
00055         int index;
00056 } Prel;
00057 
00058 // order in which processors are drawn
00059 Prel ranklist[PMAX];
00060 
00061 // actual no of processors and nodes 1..p 1..n
00062 int p, n, logn;
00063 
00064 typedef struct pt
00065 {
00066         double x;
00067         double y;
00068 } Pt;
00069 
00070 //
00071 Pt pos[NMAX];
00072 
00073 // routines to draw
00074 
00075 void
00076 initimage(void)
00077 {
00078         fprintf(
00079             output,
00080             "\
00081 #FIG 3.2\n\
00082 Portrait\n\
00083 Center\n\
00084 Metric\n\
00085 A4 \n\
00086 100.0\n\
00087 Single\n\
00088 -2\n\
00089 1200 2\n");
00090 }
00091 
00092 void
00093 dashline(double x1, double y1, double x2, double y2)
00094 {
00095         fprintf(output, "2 1 1 4 0 0 100 1 -1  6.40 0 0 12 0 0 2\n");
00096         fprintf(output, "       %d %d %d %d\n", (int) x1, (int) y1, (int) x2,
00097             (int) y2);
00098 }
00099 
00100 void
00101 circle(double xcenter, double ycenter, double radius)
00102 {
00103         //  fprintf(output, "circle %lf %lf %lf\n",xcenter,ycenter,radius);
00104         fprintf(output, "1 1 0 2 0 0 100 1 -1  6.40 1 0.0 %d %d %d %d %d %d %d %d\n",
00105 
00106         (int) xcenter, (int) ycenter, (int) radius, (int) radius, (int) (xcenter
00107             - radius), (int) (ycenter - radius), (int) (xcenter + radius),
00108             (int) (ycenter + radius));
00109 }
00110 
00111 void
00112 arc(double x1, double y1, double x2, double y2)
00113 {
00114         //  fprintf(output, "arc %lf %lf %lf %lf\n",x1,y1,x2,y2);
00115         fprintf(output, "2 1 0 2 0 0 100 1 -1  6.40 0 0 12 1 0 2\n");
00116         fprintf(output, "  2 1 1.0 144.00 200.00\n");
00117         fprintf(output, "       %d %d %d %d\n", (int) x1, (int) y1, (int) x2,
00118             (int) y2);
00119 
00120 }
00121 
00122 void
00123 textout(double x1, double y1, char* str, int size)
00124 {
00125         //  fprintf(output, "text %lf %lf %s\n",x1,y1,str);
00126         fprintf(output, "4 1 0 100 1 0 %d.0 0.0 4 267.0 %lf %d %d %s\\001\n", size,
00127             (double) strlen(str) * 100.0, (int) x1, (int) (y1 + yrad / 2.0), str);
00128 
00129 }
00130 
00131 #define STRL 255
00132 
00133 int
00134 inputstructure(void)
00135 {
00136         char instr[STRL], *endstr;
00137         int flag = 0;
00138         int i, j;
00139         int tmp;
00140         char str[2], *end;
00141 
00142         while (!feof(input))
00143         {
00144                 char *res = fgets(instr, STRL, input);
00145                 if(res == NULL)
00146                 {
00147                         fprintf(stderr, "[%s:%s:%d][ERROR] Cannot read character from input.\n", __FILE__, __FUNCTION__, __LINE__);
00148                         abort();
00149                 }
00150 
00151                 if (!strncmp(instr, "k =", 3))
00152                 {
00153                         flag = 1;
00154                         sscanf(instr + 4, "%d", &p);
00155                         break;
00156                 }
00157         }
00158         if (flag == 0)
00159         {
00160                 fprintf(output, "could not find line beginning with k =\n");
00161                 return 0;
00162         }
00163         n = (1 << p) - 1;
00164         logn = p;
00165 
00166         flag = 0;
00167         while (!feof(input))
00168         {
00169                 char *res = fgets(instr, STRL, input);
00170                 if(res == NULL)
00171                 {
00172                         fprintf(stderr, "[%s:%s:%d][ERROR] Cannot read character from input.\n", __FILE__, __FUNCTION__, __LINE__);
00173                         abort();
00174                 }
00175 
00176                 if (!strncmp(instr, "x [", 3))
00177                 {
00178                         flag = 1;
00179                         break;
00180                 }
00181         }
00182         if (flag == 0)
00183         {
00184                 fprintf(output, "could not find line beginning with x [\n");
00185                 return 0;
00186         }
00187 
00188         char *res = fgets(instr, STRL, input);
00189         if(res == NULL)
00190         {
00191                 fprintf(stderr, "[%s:%s:%d][ERROR] Cannot read character from input.\n", __FILE__, __FUNCTION__, __LINE__);
00192                 abort();
00193         }
00194 
00195 
00196         str[1] = '\0';
00197         i = 1;
00198         while (1)
00199         {
00200                 flag = fscanf(input, "%s", (char*) &instr);
00201                 tmp = strtol(instr, &endstr, 10);
00202 
00203                 j = 1;
00204                 int n = fscanf(input, "%c", &str[0]);
00205                 if(n < 1 || n == EOF)
00206                 {
00207                         fprintf(stderr, "[%s:%s:%d][ERROR] Could not read input file.\n", __FILE__, __FUNCTION__, __LINE__);
00208                         abort();
00209                 }
00210 
00211                 while (str[0] != '\n')
00212                 {
00213                         tmp = strtol(str, &end, 2);
00214                         if (end - str > 0)
00215                         {
00216                                 x[i][j] = tmp;
00217                                 num_procs = j;
00218                                 j++;
00219                         }
00220                         n = fscanf(input, "%c", str);
00221                         if(n < 1 || n == EOF)
00222                         {
00223                                 fprintf(stderr, "[%s:%s:%d][ERROR] Could not read input file.\n", __FILE__, __FUNCTION__, __LINE__);
00224                                 abort();
00225                         }
00226                 }
00227 
00228                 if (flag == 0 || flag == EOF || endstr != instr + strlen(instr))
00229                 {
00230                         break;
00231                 }
00232                 i++;
00233                 num_tasks = i;
00234         }
00235 
00236         return 1;
00237 }
00238 
00239 int
00240 prelcmp(const void *p1, const void *p2)
00241 {
00242         int index1, index2;
00243 
00244         index1 = ((Prel*) p1)->index;
00245         index2 = ((Prel*) p2)->index;
00246 
00247         if (index1 < index2)
00248                 return 1;
00249         else if (index1 > index2)
00250                 return -1;
00251 
00252         return 0;
00253 }
00254 
00255 void
00256 rankprocessors(void)
00257 {
00258         int i, j;
00259 
00260         // fill ranklist first with minimum numbers of nodes placed
00261         for (j = 1; j <= p; j++)
00262         {
00263                 ranklist[j].index = n + 1; // no element placed
00264                 ranklist[j].proc = j; // proc j
00265                 for (i = 1; i <= n; i++)
00266                 {
00267                         if (x[i][j] == 1)
00268                         {
00269                                 ranklist[j].index = i;
00270                                 break;
00271                         }
00272                 }
00273         }
00274         qsort((void*) (&(ranklist[1])), p, sizeof(Prel), prelcmp);
00275 }
00276 
00277 int
00278 drawproc(int proc, int line)
00279 {
00280         int i, level;
00281         int incline;
00282         int flag;
00283         char str[100];
00284 
00285         incline = 0;
00286         for (level = logn - 1; level >= 0; level--)
00287         {
00288                 flag = 0;
00289                 for (i = 1 << level; i < (1 << (level + 1)); i++)
00290                 {
00291                         if (x[i][proc] == 1)
00292                         {
00293                                 flag = 1; // node in this level placed
00294                                 pos[i].x = xref + ((double) ((i - (1 << level)) * (1 << (logn - level))
00295                                     + (1 << (logn - 1 - level))) + 0.5) * xdiff;
00296                                 pos[i].y = yref + ((double) line + 0.5) * ydiff;
00297                                 circle(pos[i].x, pos[i].y, yrad);
00298                                 sprintf(str, "%d", i);
00299                                 textout(pos[i].x, pos[i].y, str, 20);
00300                         }
00301                 }
00302                 if (flag)
00303                 {
00304                         incline++;
00305                         line++;
00306                 }
00307         }
00308 
00309         if (incline == 0)
00310                 incline++;
00311 
00312         sprintf(str, "SPE%d", proc);
00313         textout(480.0, yref + ((double) line - 0.25) * ydiff, str, 24);
00314 
00315         return incline;
00316 }
00317 
00318 void
00319 drawline(int line)
00320 {
00321         dashline(xref, yref + ((double) line) * ydiff, xref + xdiff
00322             * (double) (n + 1), yref + ((double) line) * ydiff);
00323 }
00324 
00325 void
00326 drawedges(void)
00327 {
00328         int i;
00329 
00330         for (i = n; i >= 2; i--)
00331         {
00332                 if (pos[i].y < pos[i / 2].y) // normal case, edges going from top to bottom
00333                         // leaves node at bottom, hits node at top
00334                         arc(pos[i].x, pos[i].y + yrad, pos[i / 2].x, pos[i / 2].y - yrad);
00335                 else
00336                 { // leaves and hits nodes at appropriate sides
00337                         if (pos[i].x <= pos[i / 2].x) // edge going left to right
00338                                 arc(pos[i].x + yrad, pos[i].y, pos[i / 2].x - yrad, pos[i / 2].y);
00339                         else
00340                                 // edge going right to left
00341                                 arc(pos[i].x, pos[i].y - yrad, pos[i / 2].x + yrad, pos[i / 2].y);
00342                 }
00343         }
00344 }
00345 
00346 void
00347 drawallprocessors(void)
00348 {
00349         int j;
00350         int line = 0;
00351 
00352         initimage();
00353         for (j = 1; j <= p; j++)
00354         {
00355                 // draw proc ranklist[j].proc starting from line line
00356                 line += drawproc(ranklist[j].proc, line);
00357                 // if j!=p draw horizontal dashline
00358                 if (j < p)
00359                         drawline(line);
00360         }
00361         drawedges();
00362 }
00363 
00364 void
00365 pelib_drawgraph2_draw(FILE * read_from, FILE * print_to, FILE * err_to)
00366 {
00367         input = read_from;
00368         output = print_to;
00369         error = err_to;
00370 
00371         if (input == NULL)
00372         {
00373                 input = stdin;
00374         }
00375         if (output == NULL)
00376         {
00377                 output = stdout;
00378         }
00379         if (error == NULL)
00380         {
00381                 error = stderr;
00382         }
00383 
00384         xdiff = 1.1 * yrad;
00385         ydiff = 4 * yrad;
00386 
00387         if (inputstructure())
00388         {
00389                 rankprocessors();
00390                 drawallprocessors();
00391         }
00392 }
00393 
00394 mapping_t*
00395 pelib_drawgraph2_load(FILE* read_from, mapping_t* mapping, int
00396 ( filter)(task_t*))
00397 {
00398         int i, j;
00399         processor_t *processor = NULL;
00400         task_t task;
00401 
00402         input = read_from;
00403         output = fopen("std-bitbucket.txt", "w");
00404         error = fopen("err-bitbucket.txt", "w");
00405         num_procs = 0;
00406         num_tasks = 0;
00407         inputstructure();
00408 
00409         fprintf(stderr, "[%s:%s:%d] mapping = pelib_alloc_collection(mapping_t)(%d);\n", __FILE__, __FUNCTION__, __LINE__, DRAKE_MAPPING_MAX_PROCESSOR_COUNT);
00410         mapping = pelib_alloc_collection(mapping_t)(DRAKE_MAPPING_MAX_PROCESSOR_COUNT);
00411 
00412         // Fills mapping with processors and processors with tasks
00413         for (j = 1; j <= num_procs; j++)
00414         {
00415                 fprintf(stderr, "[%s:%s:%d] processor = pelib_alloc_collection(processor_t)(%d);\n", __FILE__, __FUNCTION__, __LINE__, DRAKE_MAPPING_MAX_TASK_COUNT);
00416                 processor = pelib_alloc_collection(processor_t)(DRAKE_MAPPING_MAX_TASK_COUNT);
00417                 fprintf(stderr, "[%s:%s:%d] processor->id = %d - 1;\n", __FILE__, __FUNCTION__, __LINE__, j);
00418                 processor->id = j - 1;
00419                 fprintf(stderr, "[%s:%s:%d] processor->source = pelib_alloc_collection(array_t(cross_link_tp))(%d);\n", __FILE__, __FUNCTION__, __LINE__, num_tasks);
00420                 processor->source = pelib_alloc_collection(array_t(cross_link_tp))(num_tasks);
00421                 fprintf(stderr, "[%s:%s:%d] processor->sink = pelib_alloc_collection(array_t(cross_link_tp))(%d);\n", __FILE__, __FUNCTION__, __LINE__, num_tasks);
00422                 processor->sink = pelib_alloc_collection(array_t(cross_link_tp))(num_tasks);
00423                 fprintf(stderr, "[%s:%s:%d] nb_mapping_insert_processor(mapping, processor);\n", __FILE__, __FUNCTION__, __LINE__);
00424                 drake_mapping_insert_processor(mapping, processor);
00425 
00426                 for (i = 1; i < num_tasks; i++)
00427                 {
00428                         if (x[i][j] == 1)
00429                         {
00430                                 task.id = i;
00431                                 if (filter(&task) != 0)
00432                                 {
00433                                         fprintf(stderr, "[%s:%s:%d] task.id = %d\n", __FILE__, __FUNCTION__, __LINE__, i);
00434 
00435                                         fprintf(stderr, "[%s:%s:%d] task.pred = pelib_alloc_collection(array_t(link_tp))(%d);\n", __FILE__, __FUNCTION__, __LINE__, num_tasks);
00436                                         task.pred = pelib_alloc(map_t(string, link_tp))();
00437                                         pelib_init(map_t(string, link_tp))(task.pred);
00438                                         fprintf(stderr, "[%s:%s:%d] task.succ = pelib_alloc_collection(array_t(link_tp))(%d);\n", __FILE__, __FUNCTION__, __LINE__, num_tasks);
00439                                         task.succ = pelib_alloc(map_t(string, link_tp))();
00440                                         pelib_init(map_t(string, link_tp))(task.succ);
00441                                         fprintf(stderr, "[%s:%s:%d] task.source = pelib_alloc_collection(array_t(cross_link_tp))(%d);\n", __FILE__, __FUNCTION__, __LINE__, num_tasks);
00442                                         task.source = pelib_alloc_collection(array_t(cross_link_tp))(num_tasks);
00443                                         fprintf(stderr, "[%s:%s:%d] task.sink = pelib_alloc_collection(array_t(cross_link_tp))(%d);\n", __FILE__, __FUNCTION__, __LINE__, num_tasks);
00444                                         task.sink = pelib_alloc_collection(array_t(cross_link_tp))(num_tasks);
00445 
00446                                         fprintf(stderr, "[%s:%s:%d] task.status = TASK_INIT;\n", __FILE__, __FUNCTION__, __LINE__);
00447                                         task.status = TASK_INIT;
00448 
00449                                         fprintf(stderr, "[%s:%s:%d] drake_mapping_insert_task(mapping, %d - 1, &task);\n", __FILE__, __FUNCTION__, __LINE__, j);
00450                                         drake_mapping_insert_task(mapping, j - 1, &task);
00451                                 }
00452                                 continue;
00453                         }
00454                 }
00455         }
00456 
00457         fflush(stdin);
00458         fflush(stdout);
00459         fflush(stderr);
00460 
00461         input = stdin;
00462         output = stdout;
00463         error = stderr;
00464 
00465         return mapping;
00466 }
00467