00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
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
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
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
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
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
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
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
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
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
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
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