pelib  2.0.0
src/XMLSchedule.cpp
Go to the documentation of this file.
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/XMLSchedule.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 #include <pelib/Taskgraph.hpp>
00041 
00042 #include <pelib/CastException.hpp>
00043 #include <pelib/ParseException.hpp>
00044 
00045 #include <pelib/AmplInput.hpp>
00046 #include <pelib/Algebra.hpp>
00047 
00048 #define debug(expr) cerr << "[" << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << "] " << #expr << " = \"" << (expr) << "\"." << endl;
00049 
00050 using namespace pelib;
00051 using namespace std;
00052 using namespace xmlpp;
00053 
00054 XMLSchedule::~XMLSchedule()
00055 {
00056         // Do nothing
00057 }
00058 
00059 void
00060 XMLSchedule::dump(ostream& os, const Schedule &data, const Taskgraph &tg, const Platform &pt) const
00061 {
00062         dump(os, &data, &tg, &pt);
00063 }
00064 
00065 void
00066 XMLSchedule::dump(ostream& os, const Schedule *sched, const Taskgraph *tg, const Platform *pt) const
00067 {
00068         Schedule::table schedule = sched->getSchedule();
00069         //float target_makespan = sched->getMakespan();
00070         set<Task> &tasks = (set<Task>&)tg->getTasks();
00071         set<string> task_ids;
00072         
00073         for(Schedule::table::const_iterator i = schedule.begin(); i != schedule.end(); i++)
00074         {
00075                 for(Schedule::sequence::const_iterator j = i->second.begin(); j != i->second.end(); j++)
00076                 {
00077                         task_ids.insert(j->second.first->getName());
00078                 }
00079         }
00080 
00081         os << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" << endl
00082                 << "<schedule name=\"" << sched->getName() << "\" appname=\"" << sched->getAppName() << "\""
00083                 //<< "makespan=\"" << target_makespan << "\" "
00084                 << ">" << endl;
00085 
00086         // Finds and set the precision required for this schedule
00087         std::streamsize old_precision = os.precision();
00088         std::streamsize max_work_precision = 0;
00089         std::streamsize max_freq_precision = 0;
00090         std::streamsize max_start_precision = 0;
00091         for(Schedule::table::const_iterator i = schedule.begin(); i != schedule.end(); i++)
00092         {
00093                 float last_start = 0;
00094                 float last_time = 0;
00095                 for(Schedule::sequence::const_iterator j = i->second.begin(); j != i->second.end(); j++)
00096                 {
00097                         Task t = *j->second.first;
00098                         if(t.getStartTime() > 0)
00099                         {
00100                                 float delta = t.getStartTime() - last_start;
00101                                 delta = delta - floor(delta);
00102                                 std::streamsize precision = (std::streamsize)(ceil(-log10(delta)) + 2);
00103                                 if(precision > max_start_precision)
00104                                 {
00105                                         max_start_precision = precision;
00106                                 }
00107                                 last_start = t.getStartTime();
00108 
00109                                 delta = abs(t.getStartTime() - (last_start + last_time));
00110                                 delta = delta - floor(delta);
00111                                 precision = (std::streamsize)(ceil(-log10(delta)) + 1);
00112                                 if(precision > max_start_precision)
00113                                 {
00114                                         max_start_precision = precision;
00115                                 }
00116                                 const Task &tgt = *tg->getTasks().find(t);
00117                                 last_time = tgt.runtime(t.getWidth(), t.getFrequency());
00118 
00119                                 double work = t.getWorkload() - floor(t.getWorkload());
00120                                 precision = (std::streamsize)(ceil(-log10(work)) + 1);
00121                                 if(precision > max_work_precision)
00122                                 {
00123                                         max_work_precision = precision;
00124                                 }
00125 
00126                                 double freq = t.getFrequency() - floor(t.getFrequency());
00127                                 precision = (std::streamsize)(ceil(-log10(freq)) + 1);
00128                                 if(precision > max_freq_precision)
00129                                 {
00130                                         max_freq_precision = precision;
00131                                 }
00132 
00133                                 /*
00134                                 os << "<!-- core : " << i->first << " -->" << endl;
00135                                 os << "<!-- task : " << t.getName() << " -->" << endl;
00136                                 os << "<!-- start_time = " << t.getStartTime() << " -->" << endl;
00137                                 os << "<!-- last_start = " << last_start << " -->" << endl;
00138                                 */
00139 
00140                                 // update last time
00141                         }
00142                 }
00143         }
00144 
00145         for(Schedule::table::const_iterator i = schedule.begin(); i != schedule.end(); i++)
00146         {
00147                 int p = i->first;
00148                 os << " <core coreid=\"" << p << "\">" << endl;
00149                 Schedule::sequence core_schedule = i->second;
00150                 int order = 0;
00151                 double start = 0;
00152 
00153                 for(Schedule::sequence::const_iterator j = i->second.begin(); j != i->second.end(); j++, order++)
00154                 {
00155                         Task t = *j->second.first;
00156                         string taskid = t.getName();
00157                         size_t task_index = std::distance(sched->getTasks().begin(), sched->getTasks().find(t));
00158                         
00159                         os << "  <task name=\"" << taskid << "\" ";
00160                         os << setprecision(max_start_precision);
00161                         os << "start=\"" << std::fixed << (t.getStartTime() > 0 ? t.getStartTime() : start) << "\" ";
00162                         os << setprecision(old_precision);
00163                         os << "frequency=\"" << (float)t.getFrequency() << "\" ";
00164                         os << "width=\"" << t.getWidth() << "\" ";
00165                         os << "workload=\"" << t.getWorkload() << "\"";
00166                         os << "/>" << endl;
00167 
00168                         set<Task>::iterator iter = tasks.begin();
00169                         std::advance(iter, task_index);
00170                         t.setMaxWidth(iter->getMaxWidth());
00171                         t.setEfficiencyString(string(iter->getEfficiencyString()));
00172                         string eff = string(iter->getEfficiencyString());
00173                         start += t.runtime(t.getWidth(), t.getFrequency());
00174                 }
00175                 os << " </core>" << endl;
00176         }
00177         os << setprecision(old_precision);
00178 
00179         os << "</schedule>" << endl;
00180 }
00181 
00182 Schedule*
00183 XMLSchedule::parse(istream &is) const
00184 {
00185         DomParser* theSchedule = new DomParser();
00186         //theSchedule->set_throw_messages(false);
00187         //igraph_set_error_handler(igraph_error_handler_t* new_handler);
00188         //Taskgraph tg = taskgraph;
00189         
00190         try
00191         {
00192                 theSchedule->parse_stream(is);
00193         } catch(xmlpp::parse_error &e)
00194         {
00195                 throw ParseException(std::string("xmlpp::parse_error"));
00196         }
00197         
00198         // Just like taskgraph conversion
00199         // this involves turning the data structure
00200         // inside out, and to convert from
00201         // the taskids to id 1..n, in a 
00202         // deterministic fashion.
00203         // The latter is slightly more complex
00204         // than taskgraph version
00205         // since the tasks may appear more than one
00206         // in the schedule.
00207 
00208         Element *root = theSchedule->get_document()->get_root_node();
00209         xmlpp::Node::NodeList processors = root->get_children();
00210 
00211         try
00212         {
00213                 std::string name = root->get_attribute_value("name");
00214                 std::string aut_name = root->get_attribute_value("appname");
00215                 set<Task> tasks;
00216 
00217                 Schedule::table schedule;
00218                 for(xmlpp::Node::NodeList::iterator iter = processors.begin(); iter != processors.end(); ++iter) //for each core
00219                 {
00220                         if((*iter)->get_name().compare("core")) //skip indentation characters et cetera
00221                         {
00222                                 continue;
00223                         }
00224 
00225                         int core_id = atoi(dynamic_cast<xmlpp::Element*>(*iter)->get_attribute_value("coreid").c_str());
00226                         Schedule::sequence core_schedule_map;
00227                         //cout << "Core " << core_id << endl;
00228 
00229                         std::list<xmlpp::Node*> itasks = (*iter)->get_children();
00230                         for(std::list<xmlpp::Node*>::iterator taskiter = itasks.begin(); taskiter != itasks.end(); ++taskiter)
00231                         {
00232                                 if((*taskiter)->get_name().compare("task") != 0) //skip indentation characters et cetera
00233                                 {
00234                                         //cout << "Skipping " << (*taskiter)->get_name() << endl;
00235                                         continue;
00236                                 }
00237 
00238                                 Element *igraph_task = dynamic_cast<Element*>(*taskiter);
00239                                 //cout << "Task " << igraph_task->get_attribute_value("name") << endl;
00240 
00241                                 //Task &task = (Task&) tg.findTask(igraph_task->get_attribute_value("taskid"));
00242                                 Task task(igraph_task->get_attribute_value("name"));
00243                                 //cout << "Counter = " << task_id << ", tg_task.getName() = " << tg_task.getName() << ", tg_task.getTaskId() = \"" << tg_task.getTaskId() << "." << endl; 
00244 
00245                                 //Task task(tg_task.getName(), tg_task.getTaskId());
00246                                 //Task& task_tg = (Task&)*tg.getTasks().find(task);
00247 
00248                                 task.setFrequency(atof(igraph_task->get_attribute_value("frequency").c_str()));
00249                                 task.setWidth(atof(igraph_task->get_attribute_value("width").c_str()));
00250                                 //task.setWorkload(atof(igraph_task->get_attribute_value("workload").c_str()));
00251                                 task.setStartTime(atof(igraph_task->get_attribute_value("start").c_str()));
00252                                 tasks.insert(task);
00253                                 const Task &t = *tasks.find(task);
00254 
00255                                 core_schedule_map.insert(std::pair<float, Schedule::work>(task.getStartTime(), pair<const Task*, double>(&t, atof(igraph_task->get_attribute_value("workload").c_str()))));
00256                         }
00257 
00258                         schedule.insert(std::pair<int, Schedule::sequence>(core_id, core_schedule_map));
00259                 }
00260                 
00261                 Schedule *sched = new Schedule(name, aut_name, schedule);
00262 
00263                 /*
00264                 for(set<const Task*>::const_iterator j = sched->getTasks(1).begin(); j != sched->getTasks(1).end(); j++)
00265                 {
00266                         const Task *jj = *j;
00267                         Task jjj = *jj;
00268                 }
00269                 */
00270 
00271                 return sched;
00272         }
00273         catch(std::invalid_argument &e)
00274         {
00275                 throw ParseException(std::string("std::invalid_argument"));
00276         }
00277 }
00278 
00279 XMLSchedule*
00280 XMLSchedule::clone() const
00281 {
00282         return new XMLSchedule();
00283 }