drake  1.0.0
src/eval.c
Go to the documentation of this file.
00001 /*
00002  Copyright 2015 Nicolas Melot
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 #include <stdlib.h>
00023 #include <stdio.h>
00024 #include <string.h>
00025 #include <stddef.h>
00026 
00027 #include <drake.h>
00028 #include <drake/eval.h>
00029 
00030 #if 1 
00031 #define debug(var) printf("[%s:%s:%d:CORE %zu] %s = \"%s\"\n", __FILE__, __FUNCTION__, __LINE__, drake_platform_core_id(), #var, var); fflush(NULL)
00032 #define debug_addr(var) printf("[%s:%s:%d:CORE %zu] %s = \"%p\"\n", __FILE__, __FUNCTION__, __LINE__, drake_platform_core_id(), #var, var); fflush(NULL)
00033 #define debug_int(var) printf("[%s:%s:%d:CORE %zu] %s = \"%d\"\n", __FILE__, __FUNCTION__, __LINE__, drake_platform_core_id(), #var, var); fflush(NULL)
00034 #define debug_size_t(var) printf("[%s:%s:%d:CORE %zu] %s = \"%zu\"\n", __FILE__, __FUNCTION__, __LINE__, drake_platform_core_id(), #var, var); fflush(NULL)
00035 #else
00036 #define debug(var)
00037 #define debug_addr(var)
00038 #define debug_int(var)
00039 #define debug_size_t(var)
00040 #endif
00041 
00042 typedef struct
00043 {
00044         args_t platform, application;
00045         char **time_output_file, **power_output_file;
00046         size_t *core_ids;
00047 } arguments_t;
00048 
00049 static arguments_t
00050 parse_arguments(int argc, char** argv)
00051 {
00052         arguments_t args;
00053         size_t i;
00054 
00055         // default values
00056         args.time_output_file = malloc(sizeof(char*) * drake_platform_core_max());
00057         args.power_output_file = malloc(sizeof(char*) * drake_platform_core_max());
00058         for(i = 0; i < drake_platform_core_max(); i++)
00059         {
00060                 args.time_output_file[i] = "/dev/null";
00061                 args.power_output_file[i] = "/dev/null";
00062         }
00063 
00064         args.application.argc = 0;
00065         args.application.argv = malloc(sizeof(char*) * 1);
00066         args.application.argv[0] = NULL;
00067 
00068         args.platform.argc = 0;
00069         args.platform.argv = malloc(sizeof(char*) * 1);
00070         args.platform.argv[0] = NULL;
00071 
00072         for(argv++; argv[0] != NULL; argv++)
00073         {
00074                 if(strcmp(argv[0], "--platform-args") == 0)
00075                 {
00076                         // Proceed to next argument
00077                         argv++;
00078 
00079                         while(argv[0] != NULL && strcmp(argv[0], "--") != 0)
00080                         {
00081                                 // Backup the current argument stack and allocate one more argument slot
00082                                 char** tmp = args.platform.argv;
00083                                 args.platform.argv = malloc(sizeof(char*) * (args.platform.argc + 2));
00084 
00085                                 // Copy argument pointers as they are so far and free backup
00086                                 memcpy(args.platform.argv, tmp, sizeof(char*) * args.platform.argc);
00087                                 free(tmp);
00088 
00089                                 // Add the new argument and switch to next
00090                                 args.platform.argv[args.platform.argc] = *argv;
00091                                 argv++;
00092 
00093                                 // Increment platform argument counter and add the last NULL argument
00094                                 args.platform.argc++;
00095                                 args.platform.argv[args.platform.argc] = NULL;
00096                         }
00097 
00098                         continue;
00099                 }
00100                 
00101                 if(strcmp(argv[0], "--application-args") == 0)
00102                 {
00103                         // Proceed to next argument
00104                         argv++;
00105 
00106                         while(argv[0] != NULL && strcmp(argv[0], "--") != 0)
00107                         {
00108                                 // Backup the current argument stack and allocate one more argument slot
00109                                 char** tmp = args.application.argv;
00110                                 args.application.argv = malloc(sizeof(char*) * (args.application.argc + 2));
00111 
00112                                 // Copy argument pointers as they are so far and free backup
00113                                 memcpy(args.application.argv, tmp, sizeof(char*) * args.application.argc);
00114                                 free(tmp);
00115 
00116                                 // Add the new argument and switch to next
00117                                 args.application.argv[args.application.argc] = *argv;
00118                                 argv++;
00119 
00120                                 // Increment application argument counter and add the last NULL argument
00121                                 args.application.argc++;
00122                                 args.application.argv[args.application.argc] = NULL;
00123                         }
00124 
00125                         continue;
00126                 }
00127 
00128                 if(strcmp(argv[0], "--core-output") == 0)
00129                 {
00130                         // Proceed to next argument
00131                         argv++;
00132                         size_t core;
00133                         core = atoi(argv[0]);
00134                         argv++;
00135 
00136                         for(; argv[0] != NULL; argv++)
00137                         {
00138                                 if(strcmp(argv[0], "--time") == 0)
00139                                 {
00140                                         argv++;
00141                                         args.time_output_file[core] = argv[0];
00142                                         continue;
00143                                 }
00144         
00145                                 if(strcmp(argv[0], "--power") == 0)
00146                                 {
00147                                         argv++;
00148                                         args.power_output_file[core] = argv[0];
00149                                         continue;
00150                                 }
00151 
00152                                 break;
00153                         }
00154 
00155                         argv--;
00156                         continue;
00157                 }
00158         }
00159 
00160         return args;
00161 }
00162 
00163 int
00164 main(size_t argc, char **argv)
00165 {
00166         size_t i;
00167         arguments_t args = parse_arguments(argc, argv);
00168 
00169         drake_platform_t stream = drake_platform_init(&args.platform);
00170         drake_platform_stream_create(stream, PIPELINE);
00171 
00172         // Allocate monitoring buffers
00173         init = malloc(sizeof(drake_time_t) * drake_task_number(PIPELINE)());
00174         start = malloc(sizeof(drake_time_t) * drake_task_number(PIPELINE)());
00175         run = malloc(sizeof(drake_time_t) * drake_task_number(PIPELINE)());
00176         killed = malloc(sizeof(drake_time_t) * drake_task_number(PIPELINE)());
00177         execute = malloc(sizeof(int) * drake_task_number(PIPELINE)());
00178         core = malloc(sizeof(size_t) * drake_task_number(PIPELINE)());
00179         for(i = 0; i < drake_task_number(PIPELINE)(); i++)
00180         {
00181                 init[i] = drake_platform_time_alloc();
00182                 start[i] = drake_platform_time_alloc();
00183                 run[i] = drake_platform_time_alloc();
00184                 killed[i] = drake_platform_time_alloc();
00185                 execute[i] = 0;
00186         }
00187 
00188         // Initialize stream (The scc requires this phase to not be run in parallel because of extensive IOs when loading input)
00189         drake_platform_stream_init(stream, &args.application);
00190 
00191         // Measure global time
00192         drake_time_t global_begin = drake_platform_time_alloc();
00193         drake_time_t global_end = drake_platform_time_alloc();
00194 
00195         // Measure power consumption
00196         drake_power_t power = drake_platform_power_init(stream, SAMPLES, (1 << DRAKE_POWER_CHIP) | (1 << DRAKE_POWER_MEMORY_CONTROLLER));
00197 
00198         // Begin power measurement
00199         drake_platform_power_begin(power);
00200 
00201         // Begin time measurement
00202         drake_platform_time_get(global_begin);
00203 
00204         // Run the pipeline
00205         drake_platform_stream_run(stream);
00206 
00207         // Stop time measurement
00208         drake_platform_time_get(global_end);
00209 
00210         // Stop energy measurement
00211         size_t collected;
00212         collected = drake_platform_power_end(power);
00213 
00214         // Compute and output statistics
00215         // Time
00216         drake_time_t global = drake_platform_time_alloc();
00217         drake_platform_time_subtract(global, global_end, global_begin);
00218         
00219         if(collected > SAMPLES)
00220         {
00221                 fprintf(stderr, "[ERROR] Insufficient sample memory (%zu) to store all power data (%zu).\n", (size_t)SAMPLES, collected);
00222         }
00223 
00224         // Output time data
00225         FILE* out;
00226         if(args.time_output_file[drake_platform_core_id()] != NULL)
00227         {
00228                 out = fopen(args.time_output_file[drake_platform_core_id()], "w");
00229         }
00230         else
00231         {
00232                 out = stdout;
00233         }
00234         fprintf(out, "task__core__task_name__init__start__run__kill__global [*,*]\n:\t0\t1\t2\t3\t4\t5\t6\t7\t:=\n");
00235         for(i = 0; i < drake_task_number(PIPELINE)(); i++)
00236         {
00237                 if(execute[i] != 0)
00238                 {
00239                         fprintf(out, "%zu %zu %zu %s ", i + 1, i + 1, core[i] + 1, drake_task_name(PIPELINE)(i + 1));
00240                         drake_platform_time_printf(out, init[i]);
00241                         fprintf(out, " ");
00242                         drake_platform_time_printf(out, start[i]);
00243                         fprintf(out, " ");
00244                         drake_platform_time_printf(out, run[i]);
00245                         fprintf(out, " ");
00246                         drake_platform_time_printf(out, killed[i]);
00247                         fprintf(out, " ");
00248                         drake_platform_time_printf(out, global);
00249                         fprintf(out, "\n");
00250                 }
00251         }
00252         fprintf(out, ";\n");
00253         if(args.time_output_file[drake_platform_core_id()] != NULL)
00254         {
00255                 fclose(out);
00256         }
00257         free(init);
00258         free(start);
00259         free(run);
00260         free(killed);
00261         free(execute);
00262         free(core);
00263 
00264         // Output power data
00265         if(args.power_output_file[drake_platform_core_id()] != NULL)
00266         {
00267                 out = fopen(args.power_output_file[drake_platform_core_id()], "w");
00268         }
00269         else
00270         {
00271                 out = stdout;
00272         }
00273 
00274         // Chip and memory controller combined
00275         if((collected < SAMPLES ? collected : SAMPLES) > 0)
00276         {
00277                 fprintf(out, "time__power [*,*]\n:\t0\t1\t:=\n");
00278                 for(i = 0; i < (collected < SAMPLES ? collected : SAMPLES); i++)
00279                 {
00280                         fprintf(out, "%zu\t", i);
00281                         drake_platform_power_printf_line_cumulate(out, power, i, (1 << DRAKE_POWER_CHIP) | (1 << DRAKE_POWER_MEMORY_CONTROLLER), "\t");
00282                         fprintf(out, "\n");
00283                 }
00284                 fprintf(out, ";\n");
00285 
00286                 // Chip only
00287                 fprintf(out, "time__chippower [*,*]\n:\t0\t1\t:=\n");
00288                 for(i = 0; i < (collected < SAMPLES ? collected : SAMPLES); i++)
00289                 {
00290                         fprintf(out, "%zu\t", i);
00291                         drake_platform_power_printf_line_cumulate(out, power, i, (1 << DRAKE_POWER_CHIP), "\t");
00292                         fprintf(out, "\n");
00293                 }
00294                 fprintf(out, ";\n");
00295 
00296                 // Memory controller only
00297                 fprintf(out, "time__mmcpower [*,*]\n:\t0\t1\t:=\n");
00298                 for(i = 0; i < (collected < SAMPLES ? collected : SAMPLES); i++)
00299                 {
00300                         fprintf(out, "%zu\t", i);
00301                         drake_platform_power_printf_line_cumulate(out, power, i, (1 << DRAKE_POWER_MEMORY_CONTROLLER), "\t");
00302                         fprintf(out, "\n");
00303                 }
00304                 fprintf(out, ";\n");
00305         }
00306         if(args.power_output_file[drake_platform_core_id()] != NULL)
00307         {
00308                 fclose(out);
00309         }
00310 
00311         // cleanup
00312         drake_platform_power_destroy(power);
00313         drake_platform_time_destroy(global);
00314         drake_platform_time_destroy(global_begin);
00315         drake_platform_time_destroy(global_end);
00316 
00317         drake_platform_stream_destroy(stream);
00318         drake_platform_destroy(stream);
00319 
00320         return EXIT_SUCCESS;
00321 }
00322