pelib
2.0.0
|
00001 /* 00002 Copyright 2015 Nicolas Melot 00003 00004 This file is part of Pelib. 00005 00006 Pelib 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 Pelib 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 Pelib. If not, see <http://www.gnu.org/licenses/>. 00018 */ 00019 00020 00021 #include <libxml++/libxml++.h> 00022 #include <exception> 00023 #include <vector> 00024 #include <sstream> 00025 #include <cstdlib> 00026 #include <string> 00027 00028 extern "C"{ 00029 #include <igraph.h> 00030 } 00031 00032 #include <pelib/Schedule.hpp> 00033 #include <pelib/DrakeCSchedule.hpp> 00034 00035 #include <pelib/Scalar.hpp> 00036 #include <pelib/Vector.hpp> 00037 #include <pelib/Matrix.hpp> 00038 #include <pelib/Set.hpp> 00039 #include <pelib/Task.hpp> 00040 00041 #include <pelib/CastException.hpp> 00042 #include <pelib/ParseException.hpp> 00043 00044 #ifndef debug 00045 #if 10 00046 #define debug(expr) cout << "[" << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << "] " << #expr << " = \"" << expr << "\"." << endl; 00047 #else 00048 #define debug(var) 00049 #endif 00050 #endif 00051 00052 using namespace pelib; 00053 using namespace std; 00054 00055 DrakeCSchedule::~DrakeCSchedule() 00056 { 00057 // Do nothing 00058 } 00059 00060 void 00061 DrakeCSchedule::dump(ostream& os, const Schedule &data, const Taskgraph &tg, const Platform &pt) const 00062 { 00063 dump(os, &data, &tg, &pt); 00064 } 00065 00066 void 00067 DrakeCSchedule::dump(ostream& os, const Schedule *sched, const Taskgraph *tg, const Platform *pt) const 00068 { 00069 size_t p = pt->getCores().size(); 00070 size_t n = tg->getTasks().size(); 00071 map<int, set<const Task*> > tasks, producers, consumers; 00072 os << "#include <stdlib.h> " << endl << endl; 00073 os << "#include <drake/schedule.h> " << endl << endl; 00074 os << "#include <drake/platform.h> " << endl << endl; 00075 00076 /* 00077 size_t max_rate = 0; 00078 for(set<Link>::const_iterator i = tg->getLinks().begin(); i != tg->getLinks().end(); i++) 00079 { 00080 max_rate = max_rate < i->getRate() ? i->getRate() : max_rate; 00081 } 00082 */ 00083 00084 for(set<Task>::const_iterator i = tg->getTasks().begin(); i != tg->getTasks().end(); i++) 00085 { 00086 const Task &t = *i; 00087 os << 00088 "#define TASK_NAME " << t.getName() << endl << 00089 "#define TASK_MODULE " << t.getModule() << endl << 00090 "#include <drake/node.h>" << endl << 00091 "#define DONE_" << t.getName() << " 1" << endl << endl; 00092 } 00093 00094 os << 00095 "int drake_task_number()" << endl << 00096 "{" << endl << 00097 " return " << n << ";" << endl << 00098 "}" << endl << endl << 00099 "char* drake_task_name(size_t index)" << endl << 00100 "{" << endl << 00101 " switch(index - 1)" << endl << " {" << endl; 00102 for(set<Task>::const_iterator i = tg->getTasks().begin(); i != tg->getTasks().end(); i++) 00103 { 00104 os << " case " << std::distance(tg->getTasks().begin(), i) << ":" << endl << " return \"" << i->getName() << "\";" << endl << " break;" << endl; 00105 } 00106 os << " default:" << endl << " return \"invalid task id\";" << endl << " break;" << endl << 00107 " }" << endl << "}" << endl << endl << 00108 "void drake_schedule_init(drake_schedule_t* schedule)" << endl << 00109 "{" << endl << 00110 " schedule->core_number = " << p << ";" << endl << 00111 " schedule->task_number = " << n << ";" << endl << 00112 " schedule->stage_time = " << tg->getDeadline(*pt) << ";" << endl << endl << 00113 " schedule->tasks_in_core = malloc(sizeof(size_t) * schedule->core_number);" << endl; 00114 00115 os << endl << " schedule->task_name = malloc(sizeof(size_t*) * schedule->task_number);" << endl; 00116 00117 for(set<Task>::const_iterator i = tg->getTasks().begin(); i != tg->getTasks().end(); i++) 00118 { 00119 os << " schedule->task_name[" << std::distance(tg->getTasks().begin(), i) << "] = \"" << i->getName() << "\";" << endl; 00120 } 00121 os << endl; 00122 00123 os << endl << " schedule->task_workload = malloc(sizeof(double) * schedule->task_number);" << endl; 00124 00125 for(set<Task>::const_iterator i = tg->getTasks().begin(); i != tg->getTasks().end(); i++) 00126 { 00127 os << " schedule->task_workload[" << std::distance(tg->getTasks().begin(), i) << "] = " << i->getWorkload() << ";" << endl; 00128 } 00129 os << endl; 00130 00131 for(Schedule::table::const_iterator i = sched->getSchedule().begin(); i != sched->getSchedule().end(); i++) 00132 { 00133 os << " schedule->tasks_in_core[" << i->first - 1 << "] = " << sched->getTasks(i->first).size() << ";" << endl; 00134 } 00135 00136 os << endl << " schedule->consumers_in_core = malloc(sizeof(size_t) * schedule->core_number);" << endl; 00137 00138 for(Schedule::table::const_iterator i = sched->getSchedule().begin(); i != sched->getSchedule().end(); i++) 00139 { 00140 const Platform::islands i1 = pt->getSharedMemoryIslands(i->first); 00141 const set<int> islands = pt->getSharedMemoryIslands(i1); 00142 //os << " schedule->consumers_in_core[" << i->first - 1 << "] = " << sched->getRemoteSharedMemoryIslandConsumers(islands, *tg, *pt).size() << ";" << endl; 00143 os << " schedule->consumers_in_core[" << i->first - 1 << "] = " << sched->getRemoteConsumers(i->first, *tg, *pt).size() << ";" << endl; 00144 } 00145 00146 os << endl << " schedule->producers_in_core = malloc(sizeof(size_t) * schedule->core_number);" << endl; 00147 00148 for(Schedule::table::const_iterator i = sched->getSchedule().begin(); i != sched->getSchedule().end(); i++) 00149 { 00150 const Platform::islands i1 = pt->getSharedMemoryIslands(i->first); 00151 const set<int> islands = pt->getSharedMemoryIslands(i1); 00152 //os << " schedule->producers_in_core[" << i->first - 1 << "] = " << sched->getRemoteSharedMemoryIslandProducers(islands, *tg, *pt).size() << ";" << endl; 00153 os << " schedule->producers_in_core[" << i->first - 1 << "] = " << sched->getRemoteProducers(i->first, *tg, *pt).size() << ";" << endl; 00154 } 00155 00156 os << endl << " schedule->consumers_in_task = malloc(sizeof(size_t) * schedule->task_number);" << endl; 00157 00158 for(set<Task>::const_iterator i = tg->getTasks().begin(); i != tg->getTasks().end(); i++) 00159 { 00160 os << " schedule->consumers_in_task[" << std::distance(tg->getTasks().begin(), i) << "] = " << i->getConsumers().size() << ";" << endl; 00161 } 00162 00163 os << endl << " schedule->producers_in_task = malloc(sizeof(size_t) * schedule->task_number);" << endl; 00164 00165 for(set<Task>::const_iterator i = tg->getTasks().begin(); i != tg->getTasks().end(); i++) 00166 { 00167 os << " schedule->producers_in_task[" << std::distance(tg->getTasks().begin(), i) << "] = " << i->getProducers().size() << ";" << endl; 00168 } 00169 00170 os << endl << " schedule->remote_consumers_in_task = malloc(sizeof(size_t) * schedule->task_number);" << endl; 00171 00172 for(set<Task>::const_iterator i = tg->getTasks().begin(); i != tg->getTasks().end(); i++) 00173 { 00174 //os << " schedule->remote_consumers_in_task[" << std::distance(tg->getTasks().begin(), i) << "] = " << sched->getRemoteSharedMemoryIslandTaskConsumers(*i, *tg, *pt).size() << ";" << endl; 00175 os << " schedule->remote_consumers_in_task[" << std::distance(tg->getTasks().begin(), i) << "] = " << sched->getRemoteTaskConsumers(*i, *tg, *pt).size() << ";" << endl; 00176 } 00177 00178 os << endl << " schedule->remote_producers_in_task = malloc(sizeof(size_t) * schedule->task_number);" << endl; 00179 00180 for(set<Task>::const_iterator i = tg->getTasks().begin(); i != tg->getTasks().end(); i++) 00181 { 00182 //os << " schedule->remote_producers_in_task[" << std::distance(tg->getTasks().begin(), i) << "] = " << sched->getRemoteSharedMemoryIslandTaskProducers(*i, *tg, *pt).size() << ";" << endl; 00183 os << " schedule->remote_producers_in_task[" << std::distance(tg->getTasks().begin(), i) << "] = " << sched->getRemoteTaskProducers(*i, *tg, *pt).size() << ";" << endl; 00184 } 00185 00186 os << endl << " schedule->producers_id = malloc(sizeof(size_t*) * schedule->task_number);" << endl; 00187 os << " schedule->producers_rate = malloc(sizeof(size_t**) * schedule->task_number);" << endl; 00188 os << " schedule->producers_name = malloc(sizeof(char*) * schedule->task_number);" << endl; 00189 00190 for(set<Task>::const_iterator i = tg->getTasks().begin(); i != tg->getTasks().end(); i++) 00191 { 00192 // Producer's id 00193 os << " schedule->producers_id[" << std::distance(tg->getTasks().begin(), i) << "] = "; 00194 if (i->getProducers().size() == 0) 00195 { 00196 os << "NULL;" << endl; 00197 } 00198 else 00199 { 00200 os << "malloc(sizeof(size_t) * " << i->getProducers().size() << ");" << endl; 00201 size_t counter = 0; 00202 for(set<const Link*>::const_iterator j = i->getProducers().begin(); j != i->getProducers().end(); j++) 00203 { 00204 os << " schedule->producers_id[" << std::distance(tg->getTasks().begin(), i) << "][" << counter << "] = " << std::distance(tg->getTasks().begin(), tg->getTasks().find(*(*j)->getProducer())) + 1 << ";" << endl; 00205 counter++; 00206 } 00207 } 00208 00209 // Producer's rate 00210 os << " schedule->producers_rate[" << std::distance(tg->getTasks().begin(), i) << "] = "; 00211 if (i->getProducers().size() == 0) 00212 { 00213 os << "NULL;" << endl; 00214 } 00215 else 00216 { 00217 os << "malloc(sizeof(size_t) * " << i->getProducers().size() << ");" << endl; 00218 size_t counter = 0; 00219 for(set<const Link*>::const_iterator j = i->getProducers().begin(); j != i->getProducers().end(); j++) 00220 { 00221 const Link *link = *j; 00222 os << " schedule->producers_rate[" << std::distance(tg->getTasks().begin(), i) << "][" << counter << "] = " << (float)link->getProducerRate() << ";" << endl; 00223 counter++; 00224 } 00225 } 00226 00227 // Producer's name 00228 os << " schedule->producers_name[" << std::distance(tg->getTasks().begin(), i) << "] = "; 00229 if (i->getProducers().size() == 0) 00230 { 00231 os << "NULL;" << endl; 00232 } 00233 else 00234 { 00235 os << "malloc(sizeof(char*) * " << i->getProducers().size() << ");" << endl; 00236 size_t counter = 0; 00237 for(set<const Link*>::const_iterator j = i->getProducers().begin(); j != i->getProducers().end(); j++) 00238 { 00239 const Link *link = *j; 00240 os << " schedule->producers_name[" << std::distance(tg->getTasks().begin(), i) << "][" << counter << "] = \"" << link->getProducerName() << "\";" << endl; 00241 counter++; 00242 } 00243 } 00244 } 00245 00246 os << endl << " schedule->consumers_id = malloc(sizeof(size_t*) * schedule->task_number);" << endl; 00247 os << " schedule->consumers_rate = malloc(sizeof(size_t**) * schedule->task_number);" << endl; 00248 os << " schedule->consumers_name = malloc(sizeof(char*) * schedule->task_number);" << endl; 00249 00250 for(set<Task>::const_iterator i = tg->getTasks().begin(); i != tg->getTasks().end(); i++) 00251 { 00252 // Consumer's ID 00253 os << " schedule->consumers_id[" << std::distance(tg->getTasks().begin(), i) << "] = "; 00254 if (i->getConsumers().size() == 0) 00255 { 00256 os << "NULL;" << endl; 00257 } 00258 else 00259 { 00260 os << "malloc(sizeof(size_t) * " << i->getConsumers().size() << ");" << endl; 00261 size_t counter = 0; 00262 for(set<const Link*>::const_iterator j = i->getConsumers().begin(); j != i->getConsumers().end(); j++) 00263 { 00264 os << " schedule->consumers_id[" << std::distance(tg->getTasks().begin(), i) << "][" << counter << "] = " << std::distance(tg->getTasks().begin(), tg->getTasks().find(*(*j)->getConsumer())) + 1 << ";" << endl; 00265 counter++; 00266 } 00267 } 00268 00269 // Link rate 00270 os << " schedule->consumers_rate[" << std::distance(tg->getTasks().begin(), i) << "] = "; 00271 if (i->getConsumers().size() == 0) 00272 { 00273 os << "NULL;" << endl; 00274 } 00275 else 00276 { 00277 os << "malloc(sizeof(size_t) * " << i->getConsumers().size() << ");" << endl; 00278 size_t counter = 0; 00279 for(set<const Link*>::const_iterator j = i->getConsumers().begin(); j != i->getConsumers().end(); j++) 00280 { 00281 const Link *link = *j; 00282 os << " schedule->consumers_rate[" << std::distance(tg->getTasks().begin(), i) << "][" << counter << "] = " << link->getConsumerRate() << ";" << endl; 00283 counter++; 00284 } 00285 } 00286 00287 // Consumer's name 00288 os << " schedule->consumers_name[" << std::distance(tg->getTasks().begin(), i) << "] = "; 00289 if (i->getConsumers().size() == 0) 00290 { 00291 os << "NULL;" << endl; 00292 } 00293 else 00294 { 00295 os << "malloc(sizeof(char*) * " << i->getConsumers().size() << ");" << endl; 00296 size_t counter = 0; 00297 for(set<const Link*>::const_iterator j = i->getConsumers().begin(); j != i->getConsumers().end(); j++) 00298 { 00299 const Link *link = *j; 00300 os << " schedule->consumers_name[" << std::distance(tg->getTasks().begin(), i) << "][" << counter << "] = \"" << link->getConsumerName() << "\";" << endl; 00301 counter++; 00302 } 00303 } 00304 } 00305 00306 os << endl << " schedule->schedule = malloc(sizeof(drake_schedule_task_t*) * schedule->core_number);" << endl; 00307 00308 for(Schedule::table::const_iterator i = sched->getSchedule().begin(); i != sched->getSchedule().end(); i++) 00309 { 00310 os << " schedule->schedule[" << i->first - 1 << "] = malloc(sizeof(drake_schedule_task_t) * " << i->second.size() << ");" << endl; 00311 00312 size_t counter = 0; 00313 for(Schedule::sequence::const_iterator j = i->second.begin(); j != i->second.end(); j++) 00314 { 00315 os << " schedule->schedule[" << i->first - 1 << "][" << counter << "].id = " << std::distance(tg->getTasks().begin(), tg->getTasks().find(*j->second.first)) + 1 << ";" << endl 00316 << " schedule->schedule[" << i->first - 1 << "][" << counter << "].start_time = " << j->second.first->getStartTime() << ";" << endl; 00317 00318 set<float>::iterator iter = (*pt->getCores().begin())->getFrequencies().find(j->second.first->getFrequency()); 00319 if(iter != (*pt->getCores().begin())->getFrequencies().end()) 00320 { 00321 os << " schedule->schedule[" << i->first - 1 << "][" << counter << "].frequency = " << std::distance((*pt->getCores().begin())->getFrequencies().begin(), iter) << ";" << endl; 00322 } 00323 else 00324 { 00325 throw PelibException("Trying to schedule a task to run on frequency not supported by target platform"); 00326 } 00327 counter++; 00328 } 00329 } 00330 00331 os << "}" << endl << endl << "void drake_schedule_destroy(drake_schedule_t* schedule)" << endl << "{" << endl; 00332 00333 for(Schedule::table::const_iterator i = sched->getSchedule().begin(); i != sched->getSchedule().end(); i++) 00334 { 00335 os << " free(schedule->schedule[" << i->first - 1 << "]);" << endl; 00336 /* 00337 for(size_t j = 0; j < i->second.size(); j++) 00338 { 00339 os << " free(schedule->schedule[" << i->first - 1 << "][" << i->second.size() - j - 1 << "]);" << endl; 00340 } 00341 */ 00342 } 00343 00344 os << endl << " free(schedule->schedule);" << endl; 00345 00346 for(set<Task>::const_iterator i = tg->getTasks().begin(); i != tg->getTasks().end(); i++) 00347 { 00348 os << " free(schedule->consumers_id[" << std::distance(tg->getTasks().begin(), i) << "]);" << endl; 00349 os << " if(schedule->consumers_rate[" << std::distance(tg->getTasks().begin(), i) << "] != NULL)" << endl; 00350 os << " {" << endl; 00351 os << " free(schedule->consumers_rate[" << std::distance(tg->getTasks().begin(), i) << "]);" << endl; 00352 os << " }" << endl; 00353 os << " free(schedule->consumers_name[" << std::distance(tg->getTasks().begin(), i) << "]);" << endl; 00354 /* 00355 for(size_t j = 0; j < i->getConsumers().size(); j++) 00356 { 00357 os << " free(schedule->consumers_id[" << std::distance(tg->getTasks().begin(), i) << "][" << i->getConsumers().size() - j - 1 << "]);" << endl; 00358 } 00359 */ 00360 } 00361 00362 os << " free(schedule->consumers_id);" << endl 00363 << " free(schedule->consumers_rate);" << endl 00364 << " free(schedule->consumers_name);" << endl 00365 << endl; 00366 00367 for(set<Task>::const_iterator i = tg->getTasks().begin(); i != tg->getTasks().end(); i++) 00368 { 00369 os << " free(schedule->producers_id[" << std::distance(tg->getTasks().begin(), i) << "]);" << endl; 00370 os << " if(schedule->producers_rate[" << std::distance(tg->getTasks().begin(), i) << "] != NULL)" << endl; 00371 os << " {" << endl; 00372 os << " free(schedule->producers_rate[" << std::distance(tg->getTasks().begin(), i) << "]);" << endl; 00373 os << " }" << endl; 00374 os << " free(schedule->producers_name[" << std::distance(tg->getTasks().begin(), i) << "]);" << endl; 00375 /* 00376 for(size_t j = 0; j < i->getProducers().size(); j++) 00377 { 00378 os << " free(schedule->producers_id[" << std::distance(tg->getTasks().begin(), i) << "][" << i->getProducers().size() - j - 1 << "]);" << endl; 00379 } 00380 */ 00381 } 00382 00383 os << " free(schedule->producers_id);" << endl 00384 << " free(schedule->producers_rate);" << endl 00385 << " free(schedule->producers_name);" << endl 00386 << " free(schedule->task_workload);" << endl 00387 << " free(schedule->remote_producers_in_task);" << endl 00388 << " free(schedule->remote_consumers_in_task);" << endl 00389 << " free(schedule->producers_in_task);" << endl 00390 << " free(schedule->consumers_in_task);" << endl 00391 << " free(schedule->producers_in_core);" << endl 00392 << " free(schedule->consumers_in_core);" << endl 00393 << " free(schedule->tasks_in_core);" << endl 00394 << " free(schedule->task_name);" << endl 00395 << "}" << endl 00396 << endl 00397 << "size_t" << endl 00398 << "drake_task_width(task_tp task)" 00399 << "{" << endl 00400 << " size_t task_width[" << tg->getTasks().size() << "] = {"; 00401 00402 for(set<Task>::const_iterator i = sched->getTasks().begin(); i != sched->getTasks().end(); i++) 00403 { 00404 os << sched->getCores(*i).size() << ", "; 00405 } 00406 00407 os << "};" << endl 00408 << " return task_width[task->id - 1];" << endl 00409 << "}" << endl 00410 << endl 00411 << "size_t" << endl 00412 << "drake_core_id(task_tp task)" 00413 << "{" << endl 00414 << " size_t local_core_id[" << pt->getCores().size() << "][" << tg->getTasks().size() << "] = {" << endl; 00415 00416 // Initializes a counter for cores allocated to tasks 00417 size_t *core_counter = (size_t*)malloc(sizeof(size_t) * tg->getTasks().size()); 00418 for(size_t i = 0; i < tg->getTasks().size(); i++) 00419 { 00420 core_counter[i] = 0; 00421 } 00422 00423 // Generates initialized core 00424 for(Schedule::table::const_iterator i = sched->getSchedule().begin(); i != sched->getSchedule().end(); i++) 00425 { 00426 os << " {"; 00427 for(set<Task>::const_iterator j = tg->getTasks().begin(); j != tg->getTasks().end(); j++) 00428 { 00429 Schedule::sequence::const_iterator k; 00430 for(k = i->second.begin(); k != i->second.end(); k++) 00431 { 00432 if(k->second.first->getName().compare(j->getName()) == 0) 00433 { 00434 size_t task_id = std::distance(tg->getTasks().begin(), (set<Task>::iterator)j); 00435 os << core_counter[task_id] << ", "; 00436 core_counter[task_id]++; 00437 break; 00438 } 00439 } 00440 00441 if(k == i->second.end()) 00442 { 00443 os << pt->getCores().size() << ", "; 00444 } 00445 } 00446 os << "}," << endl; 00447 } 00448 free(core_counter); 00449 os << " };" << endl 00450 << " return local_core_id[drake_platform_core_id()][task->id - 1];" << endl 00451 << "}" << endl 00452 << endl 00453 << "void*" << endl 00454 << "drake_function(size_t id, task_status_t status)" << endl 00455 << "{" << endl 00456 << " switch(id)" << endl 00457 << " {" << endl 00458 << " default:" << endl 00459 << " // TODO: Raise an alert" << endl 00460 << " break;" << endl; 00461 00462 for(set<Task>::const_iterator i = tg->getTasks().begin(); i != tg->getTasks().end(); i++) 00463 { 00464 os << " case " << std::distance(tg->getTasks().begin(), tg->getTasks().find(*i)) + 1<< ":" << endl 00465 << " switch(status)" << endl 00466 << " {" << endl 00467 << " case TASK_INVALID:" << endl 00468 << " return 0;" << endl 00469 << " break;" << endl 00470 << " case TASK_INIT:" << endl 00471 << " return (void*)&drake_init(" << i->getModule() << ", " << i->getName() << ");" << endl 00472 << " break;" << endl 00473 << " case TASK_START:" << endl 00474 << " return (void*)&drake_start(" << i->getModule() << ", " << i->getName() << ");" << endl 00475 << " break;" << endl 00476 << " case TASK_RUN:" << endl 00477 << " return (void*)&drake_run(" << i->getModule() << ", " << i->getName() << ");" << endl 00478 << " break;" << endl 00479 << " case TASK_KILLED:" << endl 00480 << " return (void*)&drake_kill(" << i->getModule() << ", " << i->getName() << ");" << endl 00481 << " break;" << endl 00482 << " case TASK_ZOMBIE:" << endl 00483 << " return 0;" << endl 00484 << " break;" << endl 00485 << " case TASK_DESTROY:" << endl 00486 << " return (void*)&drake_destroy(" << i->getModule() << ", " << i->getName() << ");" << endl 00487 << " break;" << endl 00488 << " default:" << endl 00489 << " return 0;" << endl 00490 << " break;" << endl 00491 << " }" << endl 00492 << " break;" << endl; 00493 } 00494 00495 os << endl 00496 << " }" << endl 00497 << endl 00498 << " return 0;" << endl 00499 << "}" << endl; 00500 } 00501 00502 DrakeCSchedule* 00503 DrakeCSchedule::clone() const 00504 { 00505 return new DrakeCSchedule(); 00506 }