IFInterpreter.cpp

Go to the documentation of this file.
00001 /** @file IFInterpreter.cpp
00002 * @author Gabor Madl
00003 * @date Created 11/2005
00004 * @brief This interpreter generates input for the IF toolset from the DREAM models.
00005 *
00006 *
00007 * =================================================================
00008 * DREAM License v2.0
00009 * 
00010 * DREAM - Distributed Real-time Embedded Analysis Method
00011 * http://dre.sourceforge.net.
00012 * Copyright (c) 2005-2007 Gabor Madl, All Rights Reserved.
00013 * 
00014 * This file is part of DREAM.
00015 * 
00016 * DREAM is free software; you can redistribute it and/or modify it
00017 * under the terms of the GNU General Public License version 2 as
00018 * published by the Free Software Foundation. No future versions of
00019 * the GPL license may be automatically applied to DREAM. It is in
00020 * the sole discretion of the copyright holder to determine whether
00021 * DREAM may be released under a different license or terms. There
00022 * are no restrictions on the use of DREAM for any purpose.
00023 * 
00024 * DREAM is distributed in the hope that it will be useful,
00025 * but WITHOUT ANY WARRANTY; without even the implied warranty of
00026 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00027 * GNU General Public License for more details.
00028 * 
00029 * You should have received a copy of the GNU General Public License
00030 * along with this program; if not, write to the Free Software
00031 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
00032 * MA 02110-1301, USA.
00033 * 
00034 * By submitting comments, suggestions, code, code snippets,
00035 * techniques (including that of usage), and algorithms, submitters
00036 * acknowledge that they have the right to do so, that any such
00037 * submissions are given freely and unreservedly, and that they
00038 * waive any claims to copyright or ownership. In addition,
00039 * submitters acknowledge that any such submission might become
00040 * part of the copyright maintained on the overall body of code,
00041 * which comprises DREAM. By making a submission, submitter agrees
00042 * to these terms. Furthermore, submitters acknowledge that the
00043 * incorporation or modification of such submissions is entirely
00044 * at the discretion of the moderators of the DREAM project.
00045 * 
00046 * DREAM links to the Libxml2 third party library. Please see 
00047 * COPYING-libxml for the copyright information of Libxml2.
00048 * =================================================================
00049 */
00050 
00051 #include "IFInterpreter.h"
00052 
00053 namespace DREAM
00054 {
00055 
00056 IFInterpreter::IFInterpreter (DREAM::System* system_ptr)
00057 : system_ptr_ (system_ptr)
00058 {
00059 }
00060 
00061 IFInterpreter::~IFInterpreter ()
00062 {
00063 }
00064 
00065 std::string IFInterpreter::create_fixedpriority_exec_assignment (NODE_MAP* node_map, std::string scheduler_id, const DREAM::Node* const node)
00066 #ifdef DREAM_ENHANCED_EXCEPTION_CHECKING
00067         throw (DREAM::Exception)
00068 #endif
00069 {
00070         uint k = 0;
00071         NODE_MAP::const_iterator node_iter;
00072         std::string output = "\t\t task ({common}0).exec[";
00073 
00074         for (node_iter = node_map->begin (); node_iter != node_map->end (); node_iter++)
00075         {
00076                 if ((node_iter->first) == node->id ())
00077                 {
00078                         output << k << "] := true;\n";
00079                 }
00080                 ++k;
00081         }
00082 
00083         k = 0;
00084         for (node_iter = node_map->begin (); node_iter != node_map->end (); node_iter++)
00085         {
00086                 if (node_iter->second->scheduler ()->id () == scheduler_id)
00087                 {
00088                         if (node_iter->second->priority () > node->priority ())
00089                         {       
00090                                 output << "\t\t task ({common}0).exec[" << k << "] := false;\n";
00091                         }
00092                 }
00093                 ++k;
00094         }
00095 
00096         return output;
00097 }
00098 
00099 std::string IFInterpreter::create_fixedpriority_guard (NODE_MAP* node_map, std::string scheduler_id, const DREAM::Node* const node)
00100 #ifdef DREAM_ENHANCED_EXCEPTION_CHECKING
00101         throw (DREAM::Exception)
00102 #endif
00103 {
00104         uint k = 0;
00105         NODE_MAP::const_iterator node_iter;
00106         std::string output = " ({common}0).en[";
00107 
00108         for (node_iter = node_map->begin (); node_iter != node_map->end (); node_iter++)
00109         {
00110                 if ((node_iter->first) == node->id ())
00111                 {
00112                                 output << k << "]";
00113                 }
00114                 ++k;
00115         }
00116 
00117         k = 0;
00118         for (node_iter = node_map->begin (); node_iter != node_map->end (); node_iter++)
00119         {
00120                 if (node_iter->second->scheduler ()->id () == scheduler_id)
00121                 {
00122                         if (node_iter->second->priority () <= node->priority ())
00123                                 if ((node_iter->second->priority () < node->priority ()) ||
00124                                                  (node_iter->second->subpriority () < node->subpriority ()))
00125                                 {       
00126                                         output << " and (({common}0).en[" << k << "] = false)";
00127                                 }
00128                 }
00129                 ++k;
00130         }
00131 
00132         return output;
00133 }
00134 
00135 std::string IFInterpreter::create_fixedpriority_back_guard (NODE_MAP* node_map, std::string scheduler_id, const DREAM::Node* const node)
00136 #ifdef DREAM_ENHANCED_EXCEPTION_CHECKING
00137         throw (DREAM::Exception)
00138 #endif
00139 {
00140         NODE_MAP::const_iterator node_iter;
00141         std::string output;
00142 
00143         uint k = 0, f = 0;
00144         for (node_iter = node_map->begin (); node_iter != node_map->end (); node_iter++)
00145         {
00146                 if (node_iter->second->scheduler ()->id () == scheduler_id)
00147                 {
00148                         if (node_iter->second->priority () == node->priority ())
00149                         {
00150                                 if (node_iter->second->subpriority () < node->subpriority ())
00151                                 {       
00152                                         if (f != 0)
00153                                                 output << " or ({common}0).en[" << k << "]";
00154                                         else
00155                                         {
00156                                                 output << " ({common}0).en[" << k << "]";
00157                                                 f = 1;
00158                                         }
00159                                 }
00160                         }
00161                 }
00162                 ++k;
00163         }
00164 
00165         return output;
00166 }
00167 
00168 std::string IFInterpreter::create_fixedpriority_preemption_guard (NODE_MAP* node_map, std::string scheduler_id, const DREAM::Node* const node)
00169 #ifdef DREAM_ENHANCED_EXCEPTION_CHECKING
00170         throw (DREAM::Exception)
00171 #endif
00172 {
00173         NODE_MAP::const_iterator node_iter;
00174         std::string output;
00175 
00176         uint k = 0, f= 0;
00177         for (node_iter = node_map->begin (); node_iter != node_map->end (); node_iter++)
00178         {
00179                 if (node_iter->second->scheduler ()->id () == scheduler_id)
00180                 {
00181                         if (node_iter->second->priority () < node->priority ())
00182                         {
00183                                 if (f != 0)
00184                                         output << " or ({common}0).en[" << k << "]";
00185                                 else
00186                                 {
00187                                         output << " ({common}0).en[" << k << "]";
00188                                         f = 1;
00189                                 }
00190                         }
00191                 }
00192                 ++k;
00193         }
00194 
00195         return output;
00196 }
00197 
00198 bool IFInterpreter::highestpriority (DREAM::Node* node_ptr)
00199 {
00200         return node_ptr->scheduler ()->highestpriority (node_ptr);
00201 }
00202 
00203 bool IFInterpreter::lowestpriority (DREAM::Node* node_ptr)
00204 {
00205         return node_ptr->scheduler ()->lowestpriority (node_ptr);
00206 }
00207 
00208 void IFInterpreter::visitor_if (char* outputFile)
00209 #ifdef DREAM_ENHANCED_EXCEPTION_CHECKING
00210         throw (DREAM::Exception)
00211 #endif
00212 {
00213         std::cout << "\nGenerating Verimag IF toolset input \"" << outputFile << "\"...\n\n";
00214 
00215         std::ofstream f_stream (outputFile, std::ios::trunc);
00216 
00217         f_stream << "/**\n"
00218                 << "* =================================================================\n"
00219                 << "* DREAM License v2.0\n"
00220                 << "* \n"
00221                 << "* DREAM - Distributed Real-time Embedded Analysis Method\n"
00222                 << "* http://dre.sourceforge.net.\n"
00223                 << "* Copyright (c) 2005-2007 Gabor Madl, All Rights Reserved.\n"
00224                 << "* \n"
00225                 << "* This file is part of DREAM.\n"
00226                 << "* \n"
00227                 << "* DREAM is free software; you can redistribute it and/or modify it\n"
00228                 << "* under the terms of the GNU General Public License version 2 as\n"
00229                 << "* published by the Free Software Foundation. No future versions of\n"
00230                 << "* the GPL license may be automatically applied to DREAM. It is in\n"
00231                 << "* the sole discretion of the copyright holder to determine whether\n"
00232                 << "* DREAM may be released under a different license or terms. There\n"
00233                 << "* are no restrictions on the use of DREAM for any purpose.\n"
00234                 << "* \n"
00235                 << "* DREAM is distributed in the hope that it will be useful,\n"
00236                 << "* but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
00237                 << "* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
00238                 << "* GNU General Public License for more details.\n"
00239                 << "* \n"
00240                 << "* You should have received a copy of the GNU General Public License\n"
00241                 << "* along with this program; if not, write to the Free Software\n"
00242                 << "* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, \n"
00243                 << "* MA 02110-1301, USA.\n"
00244                 << "* \n"
00245                 << "* By submitting comments, suggestions, code, code snippets,\n"
00246                 << "* techniques (including that of usage), and algorithms, submitters\n"
00247                 << "* acknowledge that they have the right to do so, that any such\n"
00248                 << "* submissions are given freely and unreservedly, and that they\n"
00249                 << "* waive any claims to copyright or ownership. In addition,\n"
00250                 << "* submitters acknowledge that any such submission might become\n"
00251                 << "* part of the copyright maintained on the overall body of code,\n"
00252                 << "* which comprises DREAM. By making a submission, submitter agrees\n"
00253                 << "* to these terms. Furthermore, submitters acknowledge that the\n"
00254                 << "* incorporation or modification of such submissions is entirely\n"
00255                 << "* at the discretion of the moderators of the DREAM project.\n"
00256                 << "* \n"
00257                 << "* DREAM links to the Libxml2 third party library. Please see\n"
00258                 << "* COPYING-libxml for the copyright information of Libxml2.\n"
00259                 << "* =================================================================\n" 
00260                 << "*/\n" << std::endl;
00261 
00262         f_stream << "system dre;\n\nsignal event ();\n\n/*\n * Type declarations\n *\n */\n" << std::endl;
00263 
00264         DREAM::NODE_MAP task_map;
00265         DREAM::NODE_MAP channel_map;
00266         DREAM::NODE_MAP timer_map;
00267 
00268         system_ptr_->visitor_map (&task_map, &channel_map, &timer_map);
00269 
00270         f_stream << "const pr=1;\nconst NTASKS=" << task_map.size () << ";\ntype flags=array[NTASKS] of boolean;\n" << std::endl;
00271 
00272         DREAM::NODE_MAP::const_iterator node_iter;
00273         uint i = 0;
00274 
00275         for (node_iter = task_map.begin (); node_iter != task_map.end (); node_iter++)
00276         {
00277                 f_stream << "const dl" << i << "=" << node_iter->second->deadline () << ";\n";
00278                 ++i;
00279         }
00280 
00281         f_stream << std::endl;
00282         i = 0;
00283 
00284         for (node_iter = task_map.begin (); node_iter != task_map.end (); node_iter++)
00285         {
00286                 f_stream << "const wcet" << i << "=" << node_iter->second->wcet () << ";\n";
00287                 ++i;
00288         }
00289 
00290         f_stream << std::endl;
00291         i = 0;
00292 
00293         for (node_iter = task_map.begin (); node_iter != task_map.end (); node_iter++)
00294         {
00295                 f_stream << "const bcet" << i << "=" << node_iter->second->bcet () << ";\n";
00296                 ++i;
00297         }
00298 
00299         f_stream << "\n/*\n * Signalroutes\n *\n *\n"
00300                 << " * Use signalroutes only if you have to model lossy channels\n"
00301                 << " * or channels with delays. The IF message passing builds on\n"
00302                 << " * a buffered FIFO by default therefore it is suitable to\n"
00303                 << " * model the real-time event channel mechanism as implemented\n"
00304                 << " * in several middleware. Try to avoid signalroutes as they\n"
00305                 << " * tend to agressively increase the state space size.\n *\n *\n";
00306 
00307         const DREAM::NODE_MAP* node_map;
00308         DREAM::NODE_MAP::const_iterator node_iter2;
00309 
00310         for (node_iter = channel_map.begin (); node_iter != channel_map.end (); node_iter++)
00311         {
00312                 node_map = node_iter->second-> get_dependent_map ();
00313 
00314                 for (node_iter2 = node_map->begin (); node_iter2 != node_map->end (); node_iter2++)
00315                 {
00316                         if (node_iter->second->get_source (&task_map, &channel_map, &timer_map) != NULL)
00317                         {
00318                                 if (node_iter->second->wcet () != 0)
00319                                 {
00320                                         f_stream << " */\nsignalroute " << node_iter->first << " (1) #fifo #reliable #unicast #delay["
00321                                                 << node_iter->second->bcet () << "," << node_iter->second->wcet () << "];\n"
00322                                                 << "\tfrom task_" << node_iter->second->get_source (&task_map, &channel_map, &timer_map)->id ()
00323                                                 << " to task_" << node_iter2->first << "\n\twith event;\n/*" << std::endl;
00324                                 }
00325                                 else
00326                                 {
00327                                         f_stream << " * signalroute " << node_iter->first << " (1) #fifo #reliable #unicast #urgent;\n"
00328                                                 << " *\tfrom task_" << node_iter->second->get_source (&task_map, &channel_map, &timer_map)->id ()
00329                                                 << " to task_" << node_iter2->first << "\n *\twith event;\n *" << std::endl;
00330                                 }
00331                         }
00332 
00333                         ++i;
00334                 }
00335         }
00336 
00337         f_stream << "*/\n\n/*\n * Common variables\n *\n * We need a separate process to store them...\n */\n" << std::endl;
00338 
00339         f_stream << "process common (1);\n\nvar en flags public;\nvar exec flags public;\n\nendprocess;\n" << std::endl;
00340 
00341         system_ptr_->visitor_if (&task_map, &channel_map, &timer_map, f_stream);
00342 
00343         // Generate the schedulers
00344         SCHEDULER_MAP::const_iterator scheduler_iter;
00345         const SCHEDULER_MAP* scheduler_map = system_ptr_->scheduler_map ();
00346 
00347         for (scheduler_iter = scheduler_map->begin (); scheduler_iter != scheduler_map->end (); scheduler_iter++)
00348         {
00349                 if (scheduler_iter->second->CPUs () > 0)
00350                 {
00351                         // Generate idle and select states
00352                         f_stream << "/*\n * Fixed-priority scheduler\n * \n */\n\nprocess scheduler_" << scheduler_iter->first
00353                                 << " (1);\n\nstate start #start ;\n\tdeadline eager;\n\tnextstate initial;\n"
00354                                 << "endstate;\n\n/* Scheduling enabled tasks */\n\nstate initial;\n\tdeadline eager;\n";
00355 
00356                         i = 0;
00357                         for (node_iter = task_map.begin (); node_iter != task_map.end (); node_iter++)
00358                         {
00359                                 // Check whether task belongs to scheduler
00360                                 if (node_iter->second->scheduler ()->id () == scheduler_iter->first)
00361                                 {
00362                                         f_stream << "\tprovided " << create_fixedpriority_guard (&task_map, scheduler_iter->first, node_iter->second) << ";\n"
00363                                                 << create_fixedpriority_exec_assignment (&task_map, scheduler_iter->first, node_iter->second)
00364                                                 << "\t\t\tnextstate schedule_" << node_iter->first << ";\n" << std::endl;
00365                                 }
00366 
00367                                 ++i;
00368                         }
00369 
00370                         f_stream << "endstate;\n\n";
00371 
00372                         i = 0;
00373                         for (node_iter = task_map.begin (); node_iter != task_map.end (); node_iter++)
00374                         {
00375                                 // Check whether task belongs to scheduler
00376                                 if (node_iter->second->scheduler ()->id () == scheduler_iter->first)
00377                                 {
00378                                         f_stream << "state schedule_" << node_iter->first << ";" << std::endl;
00379                                         
00380                                         std::string message = 
00381                                                 create_fixedpriority_back_guard (&task_map, scheduler_iter->first, node_iter->second);
00382                                         if (!message.empty ())
00383                                         {
00384                                                 f_stream << "\tdeadline eager;\n"
00385                                                         << "\t/*\n\t * We have to hack the scheduler to compensate for\n"
00386                                                         << "\t * the race conditions caused by non-atomic broadcasts...\n\t *\n\t */" << std::endl;
00387 
00388                                                 if ((node_iter->second->scheduler ()->nonpreemptive ())||
00389                                                          (node_iter->second->scheduler ()->highestpriority (node_iter->second)))
00390                                                 {
00391                                                         // Non-preemptive task
00392                                                         f_stream << "\tprovided " << message << ";\n"
00393                                                                 << "\twhen ({task_" << node_iter->first << "}0).ce = 0;\n"
00394                                                                 << "\t\ttask ({common}0).exec[" << i << "] := false;\n\t\t\tnextstate initial;" << std::endl;
00395                                                 }
00396                                                 else
00397                                                 {
00398                                                         // Preemptive task non-preemptive stop
00399                                                         f_stream << "\tprovided (" << message << ") and ({task_" << node_iter->first << "}0).et = 0;\n"
00400                                                                 << "\twhen ({task_" << node_iter->first << "}0).ce = 0;\n" //
00401                                                                 << "\t\ttask ({common}0).exec[" << i << "] := false;\n\t\t\tnextstate initial;" << std::endl;
00402                                                 }
00403                                         }
00404 
00405                                         // Preemptions
00406                                         message = create_fixedpriority_preemption_guard (&task_map, scheduler_iter->first, node_iter->second);
00407 
00408                                         if (!message.empty ())
00409                                         {
00410                                                 f_stream << "\t/* Preemptions */\n\tprovided " << message << ";\n"
00411                                                         << "\t\ttask ({common}0).exec[" << i << "] := false;\n\t\t\tnextstate initial;" << std::endl;
00412                                         }
00413 
00414                                         f_stream << "\tprovided ({common}0).en[" << i << "] = false;\n"
00415                                                 << "\t\ttask ({common}0).exec[" << i << "] := false;\n\t\t\tnextstate initial;\n\nendstate;\n" << std::endl;
00416                                 }
00417 
00418                                 ++i;
00419                         }
00420 
00421                         f_stream << "endprocess;\n" << std::endl;
00422                 }
00423         }
00424 
00425         // Observer
00426         f_stream << "endsystem;\n\n/*\n * Observer\n *\n */\n\npure observer safety;\n\nstate idle #start ;\n\tdeadline eager;\n" << std::endl;
00427 
00428         i = 0;
00429         for (node_iter = task_map.begin (); node_iter != task_map.end (); node_iter++)
00430         {
00431                 if ((node_iter->second->scheduler ()->nonpreemptive ())||
00432                          (node_iter->second->scheduler ()->highestpriority (node_iter->second)))
00433                 {
00434                         // Non-preemptive task
00435                         f_stream << "\tprovided ({task_" << node_iter->first << "}0) instate wait;\n"
00436                                 << "\twhen ({task_" << node_iter->first << "}0).cd >= dl" << i << ";\n\t\tnextstate error;\n"
00437                                 << "\tprovided ({task_" << node_iter->first << "}0) instate run;\n"
00438                                 << "\twhen ({task_" << node_iter->first << "}0).cd >= dl" << i << ";\n\t\tnextstate error;\n" << std::endl;
00439                 }
00440                 else
00441                 {
00442                         // Preemptive task
00443                         f_stream << "\tprovided ({task_" << node_iter->first << "}0) instate wait;\n"
00444                                 << "\twhen ({task_" << node_iter->first << "}0).cd >= dl" << i << " - ({task_" << node_iter->first << "}0).pre;\n\t\tnextstate error;\n"
00445                                 << "\tprovided ({task_" << node_iter->first << "}0) instate run;\n"
00446                                 << "\twhen ({task_" << node_iter->first << "}0).cd >= dl" << i << " - ({task_" << node_iter->first << "}0).pre;\n\t\tnextstate error;\n" << std::endl;
00447                 }
00448 
00449                 ++i;
00450         }
00451 
00452         f_stream << "endstate;\n\nstate error #error ;\nendstate;\n\nendobserver;" << std::endl;
00453 
00454         f_stream.close ();
00455 }
00456 
00457 };
00458 

Generated on Fri Jul 27 18:30:03 2007 for DREAM by  doxygen 1.5.1