drake
1.0.0
|
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