Task.cpp

Go to the documentation of this file.
00001 /** @file Task.cpp
00002 * @author Gabor Madl
00003 * @date Created 02/2005
00004 * @brief Specifies basic elements in the DRE Semantic Domain.
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 "Task.h"
00052 
00053 namespace DREAM
00054 {
00055 
00056 /////////////////////////////////////////////////////////////////////////////
00057 //
00058 // Node
00059 //
00060 /////////////////////////////////////////////////////////////////////////////
00061 
00062 Node::Node (const std::string& id, DREAM::Thread* thread_ptr, bool executed = false)
00063         : id_ (id),
00064                 thread_ptr_ (thread_ptr),
00065                 executed_ (executed),
00066                 clock_exec_ (0),
00067                 remote_dep_ (false)
00068 {
00069         dependent_map_ = new DREAM::NodeList ();
00070         if (thread_ptr)
00071                 thread_ptr->add (this);
00072 }
00073 
00074 Node::Node (const DREAM::Node& node)
00075         : id_ (node.id_),
00076                 thread_ptr_ (node.thread_ptr_),
00077                 executed_ (node.executed_),
00078                 clock_exec_ (node.clock_exec_),
00079                 remote_dep_ (false)
00080 {
00081         dependent_map_ = new DREAM::NodeList ();
00082         if (node.thread_ptr_)
00083                 node.thread_ptr_->add (this);
00084 }
00085 
00086 Node::~Node ()
00087 {
00088         delete dependent_map_;
00089 }
00090 
00091 inline void Node::add_dependent (DREAM::Node* node_ptr)
00092 {
00093         dependent_map_->add (node_ptr);
00094 }
00095 
00096 uint Node::bcet () const
00097 #ifdef DREAM_ENHANCED_EXCEPTION_CHECKING
00098         throw (DREAM::Exception)
00099 #endif
00100 {
00101 #ifdef DREAM_ENHANCED_EXCEPTION_CHECKING
00102         std::string message;
00103         message << "Node \"" << id_ << "\" does not have best case execution time. Use the inherited classes which implement this feature.";
00104         throw DREAM::BaseClassException (message);
00105 #else
00106         return 0;
00107 #endif
00108 }
00109 
00110 void Node::bcet (uint bcet)
00111 #ifdef DREAM_ENHANCED_EXCEPTION_CHECKING
00112         throw (DREAM::Exception)
00113 #endif
00114 {
00115 #ifdef DREAM_ENHANCED_EXCEPTION_CHECKING
00116         std::string message;
00117         message << "Node \"" << id_ << "\" does not have best case execution time. Use the inherited classes which implement this feature.";
00118         throw DREAM::BaseClassException (message);
00119 #endif
00120 }
00121 
00122 #ifdef DREAM_BRANCHING
00123 void Node::branching_point ()
00124 #ifdef DREAM_ENHANCED_EXCEPTION_CHECKING
00125         throw (DREAM::Exception)
00126 #endif
00127 {
00128 #ifdef DREAM_ENHANCED_EXCEPTION_CHECKING
00129         std::string message;
00130         message << "Node \"" << id_ << "\" does not have branching points. Use the inherited classes which implement this feature.";
00131         throw DREAM::BaseClassException (message);
00132 #endif
00133 }
00134 #endif
00135 
00136 DREAM::Context Node::context () const
00137 #ifdef DREAM_ENHANCED_EXCEPTION_CHECKING
00138         throw (DREAM::Exception)
00139 #endif
00140 {
00141 #ifdef DREAM_ENHANCED_EXCEPTION_CHECKING
00142         std::string message;
00143         message << "Node \"" << id_ << "\" does not have context. Use the inherited classes which implement this feature.";
00144         throw DREAM::BaseClassException (message);
00145 #else
00146         return DREAM::randomcase;
00147 #endif
00148 }
00149 
00150 void Node::context (DREAM::Context context)
00151 #ifdef DREAM_ENHANCED_EXCEPTION_CHECKING
00152         throw (DREAM::Exception)
00153 #endif
00154 {
00155 #ifdef DREAM_ENHANCED_EXCEPTION_CHECKING
00156         std::string message;
00157         message << "Node \"" << id_ << "\" does not have context. Use the inherited classes which implement this feature.";
00158         throw DREAM::BaseClassException (message);
00159 #endif
00160 }
00161 
00162 double Node::clock_dl () const
00163 #ifdef DREAM_ENHANCED_EXCEPTION_CHECKING
00164         throw (DREAM::Exception)
00165 #endif
00166 {
00167 #ifdef DREAM_ENHANCED_EXCEPTION_CHECKING
00168         std::string message;
00169         message << "Node \"" << id_ << "\" does not have deadline clock. Use the inherited classes which implement this feature.";
00170         throw DREAM::BaseClassException (message);
00171 #else
00172         return 0;
00173 #endif
00174 }
00175 
00176 double Node::clock_dl_reset () const
00177 #ifdef DREAM_ENHANCED_EXCEPTION_CHECKING
00178         throw (DREAM::Exception)
00179 #endif
00180 {
00181 #ifdef DREAM_ENHANCED_EXCEPTION_CHECKING
00182         std::string message;
00183         message << "Node \"" << id_ << "\" does not have deadline clock. Use the inherited classes which implement this feature.";
00184         throw DREAM::BaseClassException (message);
00185 #else
00186         return 0;
00187 #endif
00188 }
00189 
00190 inline double Node::clock_exec () const
00191 {
00192         return clock_exec_;
00193 }
00194 
00195 inline void Node::clock_exec_reset ()
00196 {
00197         clock_exec_ = 0;
00198 }
00199 
00200 inline void Node::clock_step (double clock_step)
00201 {
00202         clock_exec_ += clock_step;
00203 }
00204 
00205 void Node::consume ()
00206 #ifdef DREAM_ENHANCED_EXCEPTION_CHECKING
00207         throw (DREAM::Exception)
00208 #endif
00209 {
00210 #ifdef DREAM_ENHANCED_EXCEPTION_CHECKING
00211         std::string message;
00212         message << "Node \"" << id_ << "\" does not consume events. Use the inherited classes which implement this feature.";
00213         throw DREAM::BaseClassException (message);
00214 #endif
00215 }
00216 
00217 uint Node::deadline () const
00218 #ifdef DREAM_ENHANCED_EXCEPTION_CHECKING
00219         throw (DREAM::Exception)
00220 #endif
00221 {
00222 #ifdef DREAM_ENHANCED_EXCEPTION_CHECKING
00223         std::string message;
00224         message << "Node \"" << id_ << "\" does not have deadline. Use the inherited classes which implement this feature.";
00225         throw DREAM::BaseClassException (message);
00226 #else
00227         return 0;
00228 #endif
00229 }
00230 
00231 void Node::deadline (uint deadline)
00232 #ifdef DREAM_ENHANCED_EXCEPTION_CHECKING
00233         throw (DREAM::Exception)
00234 #endif
00235 {
00236 #ifdef DREAM_ENHANCED_EXCEPTION_CHECKING
00237         std::string message;
00238         message << "Node\"" << id_ << "\" does not have deadline. Use the inherited classes which implement this feature.";
00239         throw DREAM::BaseClassException (message);
00240 #endif
00241 }
00242 
00243 void Node::deploy (DREAM::Thread* thread_ptr)
00244 {
00245         if (thread_ptr_)
00246                 thread_ptr_->erase (id_);
00247 
00248         thread_ptr_ = thread_ptr;
00249         thread_ptr->add (this);
00250 }
00251 
00252 inline bool Node::executed () const
00253 {
00254         return executed_;
00255 }
00256 
00257 inline void Node::executed (bool executed)
00258 {
00259         executed_ = executed;
00260 }
00261 
00262 inline Node* Node::get_dependent (const std::string& id) const
00263 {
00264         return dependent_map_->find (id);
00265 }
00266 
00267 inline const NODE_MAP* Node::get_dependent_map () const
00268 {
00269         return dependent_map_->get_map ();
00270 }
00271 
00272 const DREAM::Node* Node::get_source (DREAM::NODE_MAP* task_map, DREAM::NODE_MAP* channel_map, DREAM::NODE_MAP* timer_map) const
00273         throw (DREAM::Exception)
00274 {
00275         DREAM::Node* node_ptr = NULL;
00276 
00277         // Figure out if the Node is subscribed to a Channel
00278         for (DREAM::NODE_MAP::const_iterator node_iter = channel_map->begin (); node_iter != channel_map->end (); node_iter++)
00279         {
00280                 if (node_iter->second->get_dependent (id_))
00281                         return NULL;
00282         };
00283 
00284         // Figure out if the Node is subscribed to a Task
00285         for (DREAM::NODE_MAP::const_iterator node_iter = task_map->begin (); node_iter != task_map->end (); node_iter++)
00286         {
00287                 if (node_iter->second->get_dependent (id_))
00288                 {
00289                         if (!node_ptr)
00290                                 node_ptr = node_iter->second;
00291                         else
00292                                 throw DREAM::Exception ("Node::get_source () found multiple non-channel sources.");
00293                 }
00294         };
00295 
00296         // Figure out if the Task is subscribed to a Timer
00297         for (DREAM::NODE_MAP::const_iterator node_iter = timer_map->begin (); node_iter != timer_map->end (); node_iter++)
00298         {
00299                 if (node_iter->second->get_dependent (id_))
00300                 {
00301                         if (!node_ptr)
00302                                 node_ptr = node_iter->second;
00303                         else
00304                                 throw DREAM::Exception ("Node::get_source () found multiple non-channel sources.");
00305                 }
00306         };
00307 
00308         if (!node_ptr)
00309                 throw DREAM::Exception ("Node::get_source () construction failed. Most likely the input models are semantically incorrect.");
00310 
00311         return node_ptr;
00312 }
00313 
00314 inline std::string Node::id () const
00315 {
00316         return id_;
00317 }
00318 
00319 bool Node::isidle () const
00320 #ifdef DREAM_ENHANCED_EXCEPTION_CHECKING
00321         throw (DREAM::Exception)
00322 #endif
00323 {
00324 #ifdef DREAM_ENHANCED_EXCEPTION_CHECKING
00325         std::string message;
00326         message << "Node\"" << id_ << "\" cannot be checked for idleness. Use the inherited classes which implement this feature.";
00327         throw DREAM::BaseClassException (message);
00328 #else
00329         return false;
00330 #endif
00331 }
00332 
00333 inline double Node::next_event ()
00334 {
00335         return 0.0;
00336 }
00337 
00338 #ifdef DREAM_BRANCHING
00339 void Node::next_et (double next_et)
00340 #ifdef DREAM_ENHANCED_EXCEPTION_CHECKING
00341         throw (DREAM::Exception)
00342 #endif
00343 {
00344 #ifdef DREAM_ENHANCED_EXCEPTION_CHECKING
00345         std::string message;
00346         message << "Node\"" << id_ << "\" does not have clocks. Use the inherited classes which implement this feature.";
00347         throw DREAM::BaseClassException (message);
00348 #endif
00349 }
00350 #endif
00351 
00352 void Node::preempt ()
00353 #ifdef DREAM_ENHANCED_EXCEPTION_CHECKING
00354         throw (DREAM::Exception)
00355 #endif
00356 {
00357 #ifdef DREAM_ENHANCED_EXCEPTION_CHECKING
00358         std::string message;
00359         message << "Node\"" << id_ << "\" cannot be preempted. Use the inherited classes which implement this feature.";
00360         throw DREAM::BaseClassException (message);
00361 #endif
00362 }
00363 
00364 uint Node::priority () const
00365 #ifdef DREAM_ENHANCED_EXCEPTION_CHECKING
00366         throw (DREAM::Exception)
00367 #endif
00368 {
00369 #ifdef DREAM_ENHANCED_EXCEPTION_CHECKING
00370         std::string message;
00371         message << "Node\"" << id_ << "\" does not have priority. Use the inherited classes which implement this feature.";
00372         throw DREAM::BaseClassException (message);
00373 #else
00374         return 0;
00375 #endif
00376 }
00377 
00378 void Node::priority (uint priority)
00379 #ifdef DREAM_ENHANCED_EXCEPTION_CHECKING
00380         throw (DREAM::Exception)
00381 #endif
00382 {
00383 #ifdef DREAM_ENHANCED_EXCEPTION_CHECKING
00384         std::string message;
00385         message << "Node\"" << id_ << "\" does not have priority. Use the inherited classes which implement this feature.";
00386         throw DREAM::BaseClassException (message);
00387 #endif
00388 }
00389 
00390 inline void Node::publish ()
00391 {
00392         if (thread_ptr_)
00393         {
00394 #ifdef DREAM_VERBOSE2
00395                 if (Option::verbose1_ && Option::verbose2_)
00396                 {
00397                         std::string message;
00398                         thread_ptr_->trace (message << id_ << " is publishing...");
00399                 }
00400 #endif
00401                 dependent_map_->publish ();
00402                 thread_ptr_->scheduler ()->system ()->relevant_event (true);
00403         }
00404 }
00405 
00406 inline void Node::remove_dependent (const std::string& id)
00407 {
00408         dependent_map_->erase (id);
00409 }
00410 
00411 inline bool Node::remote_dep () const
00412 {
00413         return remote_dep_;
00414 }
00415 
00416 inline void Node::remote_dep (bool flag)
00417 {
00418         remote_dep_ = flag;
00419 }
00420 
00421 inline void Node::reset ()
00422 {
00423         clock_exec_reset ();
00424 //      executed (0);
00425 }
00426 
00427 inline DREAM::Scheduler* Node::scheduler () const
00428 {
00429         return thread_ptr_? thread_ptr_->scheduler () : NULL;
00430 }
00431 
00432 uint Node::subpriority () const
00433 #ifdef DREAM_ENHANCED_EXCEPTION_CHECKING
00434         throw (DREAM::Exception)
00435 #endif
00436 {
00437 #ifdef DREAM_ENHANCED_EXCEPTION_CHECKING
00438         std::string message;
00439         message << "Node\"" << id_ << "\" does not have subpriority. Use the inherited classes which implement this feature.";
00440         throw DREAM::BaseClassException (message);
00441 #else
00442         return 0;
00443 #endif
00444 }
00445 
00446 void Node::subpriority (uint subpriority)
00447 #ifdef DREAM_ENHANCED_EXCEPTION_CHECKING
00448         throw (DREAM::Exception)
00449 #endif
00450 {
00451 #ifdef DREAM_ENHANCED_EXCEPTION_CHECKING
00452         std::string message;
00453         message << "Node\"" << id_ << "\" does not have subpriority. Use the inherited classes which implement this feature.";
00454         throw DREAM::BaseClassException (message);
00455 #endif
00456 }
00457 
00458 void Node::take_transitions ()
00459 #ifdef DREAM_ENHANCED_EXCEPTION_CHECKING
00460         throw (DREAM::Exception)
00461 #endif
00462 {
00463 #ifdef DREAM_ENHANCED_EXCEPTION_CHECKING
00464         std::string message;
00465         message << "Node\"" << id_ << "\" does not take transitions. Use the inherited classes which implement this feature.";
00466         throw DREAM::BaseClassException (message);
00467 #endif
00468 }
00469 
00470 uint Node::wcet () const
00471 #ifdef DREAM_ENHANCED_EXCEPTION_CHECKING
00472         throw (DREAM::Exception)
00473 #endif
00474 {
00475 #ifdef DREAM_ENHANCED_EXCEPTION_CHECKING
00476         std::string message;
00477         message << "Node\"" << id_ << "\" does not have worst case execution time. Use the inherited classes which implement this feature.";
00478         throw DREAM::BaseClassException (message);
00479 #else
00480         return 0;
00481 #endif
00482 }
00483 
00484 void Node::wcet (uint wcet)
00485 #ifdef DREAM_ENHANCED_EXCEPTION_CHECKING
00486         throw (DREAM::Exception)
00487 #endif
00488 {
00489 #ifdef DREAM_ENHANCED_EXCEPTION_CHECKING
00490         std::string message;
00491         message << "Node\"" << id_ << "\" does not have worst case execution time. Use the inherited classes which implement this feature.";
00492         throw DREAM::BaseClassException (message);
00493 #endif
00494 }
00495 
00496 /////////////////////////////////////////////////////////////////////////////
00497 //
00498 // Timer
00499 //
00500 /////////////////////////////////////////////////////////////////////////////
00501 
00502 Timer::Timer (const std::string& id, DREAM::Thread* thread_ptr, uint period)
00503         : DREAM::Node (id, thread_ptr, true),
00504                 period_ (period),
00505                 bcperiod_ (period),
00506                 context_ (randomcase),
00507                 et_ (period)
00508 #ifdef DREAM_BRANCHING
00509                 ,next_et_ (0.0)
00510 #endif
00511 {
00512         if (period == 0)
00513                 throw DREAM::Exception ("Timer period has to be greater than 0.");
00514 }
00515 
00516 Timer::Timer (const std::string& id, DREAM::Thread* thread_ptr, uint period, uint bcperiod)
00517         : DREAM::Node (id, thread_ptr, true),
00518                 period_ (period),
00519                 bcperiod_ (bcperiod),
00520                 context_ (randomcase),
00521                 et_ (bcperiod + random (period - bcperiod))
00522 #ifdef DREAM_BRANCHING
00523                 ,next_et_ (0.0)
00524 #endif
00525 {
00526         if ((period == 0) || (bcperiod == 0))
00527                 throw DREAM::Exception ("Timer period has to be greater than 0.");
00528         if (period <= bcperiod)
00529                 throw DREAM::Exception ("Timer best case period has to be smaller than the period.");
00530 }
00531 
00532 Timer::Timer (const DREAM::Timer& timer)
00533         : DREAM::Node (timer.id_, timer.thread_ptr_, true),
00534                 period_ (timer.period_),
00535                 bcperiod_ (timer.bcperiod_),
00536                 context_ (timer.context_),
00537                 et_ (timer.et_)
00538 #ifdef DREAM_BRANCHING
00539                 ,next_et_ (timer.bcperiod_)
00540 #endif
00541 {
00542         if ((timer.period_ == 0) || (timer.bcperiod_ == 0))
00543                 throw DREAM::Exception ("Timer period has to be greater than 0.");
00544 }
00545 
00546 
00547 Timer::~Timer ()
00548 {
00549 }
00550 
00551 #ifdef DREAM_ENHANCED_EXCEPTION_CHECKING
00552 uint Timer::bcet () const
00553         throw (DREAM::Exception)
00554 #else
00555 inline uint Timer::bcet () const
00556 #endif
00557 {
00558         return bcperiod_;
00559 }
00560 
00561 #ifdef DREAM_BRANCHING
00562 #ifdef DREAM_ENHANCED_EXCEPTION_CHECKING
00563 void Timer::branching_point ()
00564         throw (DREAM::Exception)
00565 #else
00566 inline void Timer::branching_point ()
00567 #endif
00568 {
00569         if (context_ == branchingpoint)
00570                 if (et_ == next_et_)
00571                 {
00572                         context_ = bestcase;
00573                         et_ = bcperiod_;
00574                         next_et_ = 0.0;
00575                 }
00576                 else
00577                 {
00578                         et_ = next_et_;
00579                 }
00580 }
00581 #endif
00582 
00583 #ifdef DREAM_ENHANCED_EXCEPTION_CHECKING
00584 DREAM::Context Timer::context () const
00585         throw (DREAM::Exception)
00586 #else
00587 inline DREAM::Context Timer::context () const
00588 #endif
00589 {
00590         return context_;
00591 }
00592 
00593 #ifdef DREAM_ENHANCED_EXCEPTION_CHECKING
00594 void Timer::context (DREAM::Context context)
00595         throw (DREAM::Exception)
00596 #else
00597 inline void Timer::context (DREAM::Context context)
00598 #endif
00599 {
00600         context_ = context;
00601 }
00602 
00603 inline void Timer::clock_exec_reset ()
00604 {
00605         clock_exec_ = 0;
00606 
00607         // Calculate new period
00608         if (context_ == worstcase)
00609                 et_ = period_;
00610         else if (context_ == randomcase)
00611                 et_ = bcperiod_ + random (period_ - bcperiod_);
00612         else if (context_ == bestcase)
00613                 et_ = bcperiod_;
00614 }
00615 
00616 void Timer::clock_step (double clock_step)
00617 {
00618         // Increment clock value
00619         clock_exec_ += clock_step;
00620 
00621 #ifdef DREAM_BRANCHING
00622         // IF statement optimization
00623         if (bcperiod_ < clock_exec_)
00624         {
00625                 if (next_et_ < clock_exec_)
00626                 {
00627                         if ((clock_exec_ < period_) && remote_dep_ && Option::branching_)
00628                         {
00629                                 // Encountered a possible branching point
00630                                 // Check whether it is relevant
00631                                 if (thread_ptr_->scheduler ()->system ()->relevant_event ())
00632                                 {
00633                                         // Let's blow up the state space a little more...
00634                                         std::string message;
00635                                         thread_ptr_->trace (message << "Branching point " << id_ << " bcperiod: " << bcperiod_ << " period: " << period_ << " next_et: " << clock_exec_);
00636 
00637                                         if (context_ == worstcase)
00638                                                 context_ = branchingpoint;
00639 
00640                                         next_et_ = clock_exec_;
00641                                 }
00642                         }
00643                 }
00644         }
00645 #endif
00646 }
00647 
00648 inline double Timer::next_event ()
00649 {
00650         return (et_ - clock_exec_);
00651 }
00652 
00653 #ifdef DREAM_BRANCHING
00654 #ifdef DREAM_ENHANCED_EXCEPTION_CHECKING
00655 void Timer::next_et (double next_et)
00656         throw (DREAM::Exception)
00657 #else
00658 inline void Timer::next_et (double next_et)
00659 #endif
00660 {
00661         next_et_ = next_et;
00662 }
00663 #endif
00664 
00665 uint Timer::priority () const
00666 #ifdef DREAM_ENHANCED_EXCEPTION_CHECKING
00667         throw (DREAM::Exception)
00668 #endif
00669 {
00670         uint priority = maxuint;
00671 
00672         NODE_MAP* node_map = dependent_map_->get_map ();
00673 
00674         for (DREAM::NODE_MAP::const_iterator node_iter = node_map->begin (); node_iter != node_map->end (); node_iter++)
00675         {
00676                 if (priority == maxuint) priority = node_iter->second->priority ();
00677                 else
00678                 {
00679                         if (priority > node_iter->second->priority ())                  // Remember, smaller value means higher priority
00680                                 priority = node_iter->second->priority ();
00681                 }
00682         }
00683 
00684 #ifdef DREAM_ENHANCED_EXCEPTION_CHECKING
00685         if (priority == maxuint)
00686         {
00687                 std::string message;
00688                 message << "Timer \"" << id_ << "\" has no dependents";
00689                 throw DREAM::Exception (message);
00690         }
00691 #endif
00692 
00693         return priority;
00694 }
00695 
00696 inline void Timer::publish ()
00697 {
00698         if (thread_ptr_)
00699         {
00700 #ifdef DREAM_VERBOSE2
00701                 if (Option::verbose1_ && Option::verbose2_)
00702                 {
00703                         std::string message;
00704                         message << id_ << " is publishing...";
00705                         thread_ptr_->trace (message);
00706                 }
00707 #endif
00708                 dependent_map_->publish ();
00709                 thread_ptr_->scheduler ()->system ()->relevant_event (true);
00710         }
00711 }
00712 
00713 #ifdef DREAM_ENHANCED_EXCEPTION_CHECKING
00714 void Timer::take_transitions ()
00715         throw (DREAM::Exception)
00716 #else
00717 inline void Timer::take_transitions ()
00718 #endif
00719 {
00720 #ifdef DREAM_VERBOSE2
00721 //      if (Option::verbose1_ && Option::verbose2_)
00722 //      {
00723 //              std::string message;
00724 //              thread_ptr_->trace (message << id_ << " is taking transitions.");
00725 //      }
00726 #endif
00727 
00728         // Check whether the clock_exec_ has reached the period
00729         if (clock_exec_ == et_)
00730         {
00731                 publish ();
00732                 clock_exec_reset ();
00733         }
00734 
00735 #ifdef DREAM_ENHANCED_EXCEPTION_CHECKING
00736         if (clock_exec_ > et_)
00737         {
00738                 std::string message;
00739                 message << "Execution clock value in Timer \"" << id_ << "\" is greater than the period. Most likely the period was set during simulation time. Please report bug at http://sourceforge.net/projects/dre!";
00740                 throw DREAM::Exception (message);
00741         }
00742 #endif
00743 }
00744 
00745 void Timer::visitor_if (DREAM::NODE_MAP* task_map, DREAM::NODE_MAP* channel_map, DREAM::NODE_MAP* timer_map, std::ofstream& f_stream)
00746 #ifdef DREAM_ENHANCED_EXCEPTION_CHECKING
00747         throw (DREAM::Exception)
00748 #endif
00749 {
00750         f_stream << "/*\n * Timer - " << id_ << "\n *\n */\n" << std::endl;
00751 
00752         f_stream << "process timer_" << id_ << " (1);\n\n"
00753                 << "var ce clock;\nconst period_" << id_ << "=" << period_ << ";\n\n"
00754                 << "state start #start ;\n"
00755                 << "\tdeadline eager;\n"
00756                 << "\tset ce := 0;\n"
00757                 << "\tnextstate timer;\n"
00758                 << "endstate;\n\n"
00759                 << "state timer;\n"
00760                 << "\tdeadline eager;\n"
00761                 << "\twhen ce = period_" << id_ << ";\n";
00762 
00763         const DREAM::NODE_MAP* node_map = get_dependent_map ();
00764         const DREAM::NODE_MAP* node_map2;
00765 
00766         // Check dependents
00767         DREAM::NODE_MAP::const_iterator task_iter, task_iter2, find_iter;
00768 
00769         for (task_iter = node_map->begin (); task_iter != node_map->end (); task_iter++)
00770         {
00771                 find_iter = task_map->find (task_iter->first);
00772                 if (find_iter != task_map->end ())
00773                         f_stream << "\toutput event () to {task_" << find_iter->first << "}0;\n";
00774                 else
00775                 {
00776                         find_iter = channel_map->find (task_iter->first);
00777 
00778                         // Dependent is a channel - need to find dependent tasks...
00779                         if (find_iter->second)
00780                                 node_map2 = find_iter->second->get_dependent_map ();
00781 
00782 #ifdef DREAM_ENHANCED_EXCEPTION_CHECKING
00783                         else
00784                         {
00785                                 std::string message;
00786                                 message << "Channel " << task_iter->first << " has no Task dependents. Incorrect model.";
00787                                 throw DREAM::Exception (message);
00788                         }
00789 #endif
00790 
00791                         for (task_iter2 = node_map2->begin (); task_iter2 != node_map2->end (); task_iter2++)
00792                         {
00793                                 find_iter = node_map2->find (task_iter2->first);
00794                                 if (find_iter != node_map2->end ())
00795                                 {
00796                                         if (task_iter->second->wcet () != 0)
00797                                                 f_stream << "\toutput event () via {" << task_iter->first << "}0 to {task_" << find_iter->first << "}0;\n";
00798                                         else
00799                                                 f_stream << "\toutput event () /* via {" << task_iter->first << "}0 */ to {task_" << find_iter->first << "}0;\n";
00800                                 }
00801 
00802 #ifdef DREAM_ENHANCED_EXCEPTION_CHECKING
00803                                 else
00804                                 {
00805                                         std::string message;
00806                                         message << "Node " << task_iter2->first << " could not be found as a Channel dependent in the Task list when generating IF input. Incorrect model.";
00807                                         throw DREAM::Exception (message);
00808                                 }
00809 #endif
00810 
00811                         }
00812                 }
00813         }
00814 
00815         f_stream << "\tset ce := 0;\n"
00816                 << "\t\tnextstate timer;\n"
00817                 << "endstate;\n\nendprocess;\n" << std::endl;
00818 
00819 }
00820 
00821 void Timer::visitor_map (DREAM::NODE_MAP* task_map, DREAM::NODE_MAP* channel_map, DREAM::NODE_MAP* timer_map)
00822 #ifdef DREAM_ENHANCED_EXCEPTION_CHECKING
00823         throw (DREAM::Exception)
00824 #endif
00825 {
00826         timer_map->insert (DREAM::NODE_PAIR (id_, this));
00827 }
00828 
00829 void Timer::visitor_uppaal (DREAM::NODE_MAP* task_map, DREAM::NODE_MAP* channel_map, DREAM::NODE_MAP* timer_map, std::ofstream& f_stream)
00830 #ifdef DREAM_ENHANCED_EXCEPTION_CHECKING
00831         throw (DREAM::Exception)
00832 #endif
00833 {
00834         f_stream << id_ << " := Timer (" << period_ << ", " << bcperiod_ << ", " << "publish" << id_ << ");" << std::endl;
00835 }
00836 
00837 #ifdef DREAM_ENHANCED_EXCEPTION_CHECKING
00838 uint Timer::wcet () const
00839         throw (DREAM::Exception)
00840 #else
00841 inline uint Timer::wcet () const
00842 #endif
00843 {
00844         return period_;
00845 }
00846 
00847 /////////////////////////////////////////////////////////////////////////////
00848 //
00849 // Channel
00850 //
00851 /////////////////////////////////////////////////////////////////////////////
00852 
00853 Channel::Channel (const std::string& id, DREAM::Thread* thread_ptr, uint delay, uint buffersize)
00854         : DREAM::Node (id, thread_ptr, true),
00855                 state_ (idle),
00856                 delay_ (delay),
00857                 bcdelay_ (delay),
00858                 buffersize_ (buffersize),
00859                 context_ (randomcase),
00860                 et_ (delay),
00861 #ifdef DREAM_BRANCHING
00862                 next_et_ (0.0),
00863 #endif
00864                 buffer_ (0)
00865 {
00866 }
00867 
00868 Channel::Channel (const std::string& id, DREAM::Thread* thread_ptr, uint delay, uint bcdelay, uint buffersize)
00869         : DREAM::Node (id, thread_ptr, true),
00870                 state_ (idle),
00871                 delay_ (delay),
00872                 bcdelay_ (bcdelay),
00873                 buffersize_ (buffersize),
00874                 context_ (randomcase),
00875                 et_ (bcdelay + random (delay - bcdelay)),
00876 #ifdef DREAM_BRANCHING
00877                 next_et_ (0.0),
00878 #endif
00879                 buffer_ (0)
00880 {
00881         if (delay <= bcdelay)
00882                 throw DREAM::Exception ("Channel best case delay has to be smaller than the delay.");
00883 }
00884 
00885 Channel::Channel (const DREAM::Channel& channel)
00886         : DREAM::Node (channel.id_, channel.thread_ptr_, true),
00887                 state_ (channel.state_),
00888                 delay_ (channel.delay_),
00889                 bcdelay_ (channel.bcdelay_),
00890                 buffersize_ (channel.buffersize_),
00891                 context_ (channel.context_),
00892                 et_ (channel.et_),
00893 #ifdef DREAM_BRANCHING
00894                 next_et_ (channel.bcdelay_),
00895 #endif
00896                 buffer_ (channel.buffer_)
00897 {
00898 }
00899 
00900 Channel::~Channel ()
00901 {
00902 }
00903 
00904 void Channel::add_dependent (DREAM::Node* node_ptr)
00905         throw (DREAM::Exception)
00906 {
00907         if (dependent_map_->get_map ()->size () > 0) 
00908                 throw DREAM::Exception ("Channel::add_dependent (): Channels cannot have more than 1 dependents.");
00909 
00910         dependent_map_->add (node_ptr);
00911 }
00912 
00913 #ifdef DREAM_ENHANCED_EXCEPTION_CHECKING
00914 uint Channel::bcet () const
00915         throw (DREAM::Exception)
00916 #else
00917 inline uint Channel::bcet () const
00918 #endif
00919 {
00920         return bcdelay_;
00921 }
00922 
00923 #ifdef DREAM_BRANCHING
00924 #ifdef DREAM_ENHANCED_EXCEPTION_CHECKING
00925 void Channel::branching_point ()
00926         throw (DREAM::Exception)
00927 #else
00928 inline void Channel::branching_point ()
00929 #endif
00930 {
00931         if (context_ == branchingpoint)
00932                 if (et_ == next_et_)
00933                 {
00934                         context_ = bestcase;
00935                         et_ = bcdelay_;
00936                         next_et_ = 0.0;
00937                 }
00938                 else
00939                 {
00940                         et_ = next_et_;
00941                 }
00942 }
00943 #endif
00944 
00945 inline void Channel::clock_exec_reset ()
00946 {
00947         clock_exec_ = 0;
00948 
00949         // Calculate new delay
00950         if (context_ == worstcase)
00951                 et_ = delay_;
00952         else if (context_ == randomcase)
00953                 et_ = bcdelay_ + random (delay_ - bcdelay_);
00954         else if (context_ == bestcase)
00955                 et_ = bcdelay_;
00956 }
00957 
00958 inline void Channel::clock_step (double clock_step)
00959 {
00960         // Increment clock value
00961         if (buffer_ != 0) clock_exec_ += clock_step;
00962 
00963 #ifdef DREAM_BRANCHING
00964         // IF statement optimization
00965         if (bcdelay_ < clock_exec_)
00966         {
00967                 if ((clock_exec_ < delay_) && remote_dep_ && Option::branching_)
00968                 {
00969                         if (next_et_ < clock_exec_)
00970                         {
00971                                 // Encountered a branching point
00972                                 // Check whether it is relevant
00973                                 if (thread_ptr_->scheduler ()->system ()->relevant_event ())
00974                                 {
00975                                         // Let's blow up the state space a little more...
00976                                         std::string message;
00977                                         thread_ptr_->trace (message << "Branching point " << id_ << " bcdelay: " << bcdelay_ << " wcdelay: " << delay_ << " next_et: " << clock_exec_);
00978                                         if (context_ == worstcase)
00979                                                 context_ = branchingpoint;
00980 
00981                                         next_et_ = clock_exec_;
00982                                 }
00983                         }
00984                 }
00985         }
00986 #endif
00987 }
00988 
00989 #ifdef DREAM_ENHANCED_EXCEPTION_CHECKING
00990 void Channel::consume ()
00991         throw (DREAM::Exception)
00992 #else
00993 inline void Channel::consume ()
00994 #endif
00995 {
00996         if ((buffer_ < buffersize_) || (buffersize_ == 0))
00997         {
00998                 thread_ptr_->enqueue (this);
00999 
01000                 ++buffer_;
01001 
01002                 if (state_ == idle)
01003                 {
01004                         state_ = wait;
01005                         clock_exec_reset ();
01006                 }
01007 
01008                 take_transitions ();
01009         }
01010 }
01011 
01012 #ifdef DREAM_ENHANCED_EXCEPTION_CHECKING
01013 DREAM::Context Channel::context () const
01014         throw (DREAM::Exception)
01015 #else
01016 inline DREAM::Context Channel::context () const
01017 #endif
01018 {
01019         return context_;
01020 }
01021 
01022 #ifdef DREAM_ENHANCED_EXCEPTION_CHECKING
01023 void Channel::context (DREAM::Context context)
01024         throw (DREAM::Exception)
01025 #else
01026 inline void Channel::context (DREAM::Context context)
01027 #endif
01028 {
01029         context_ = context;
01030 }
01031 
01032 #ifdef DREAM_ENHANCED_EXCEPTION_CHECKING
01033 bool Channel::idle_dependents () const
01034         throw (DREAM::Exception)
01035 #else
01036 inline bool Channel::idle_dependents () const
01037 #endif
01038 {
01039         for (DREAM::NODE_MAP::const_iterator dependent_iter = dependent_map_->get_map ()->begin ();
01040                 dependent_iter != dependent_map_->get_map ()->end ();
01041                 dependent_iter++)
01042                         if (! dependent_iter->second->isidle ())
01043                                 return false;
01044 
01045         return true;
01046 }
01047 
01048 inline double Channel::next_event ()
01049 {
01050         // If there are buffered events we publish when the delay is passed
01051         // Otherwise we have no clue...
01052         return (buffer_ && state_ == wait) ? (et_ - clock_exec_) : 0.0;
01053 }
01054 
01055 #ifdef DREAM_BRANCHING
01056 #ifdef DREAM_ENHANCED_EXCEPTION_CHECKING
01057 void Channel::next_et (double next_et)
01058         throw (DREAM::Exception)
01059 #else
01060 inline void Channel::next_et (double next_et)
01061 #endif
01062 {
01063         next_et_ = next_et;
01064 }
01065 #endif
01066 
01067 #ifdef DREAM_ENHANCED_EXCEPTION_CHECKING
01068 void Channel::publish ()
01069         throw (DREAM::Exception)
01070 #else
01071 inline void Channel::publish ()
01072 #endif
01073 {
01074 #ifdef DREAM_VERBOSE2
01075                 if (Option::verbose1_ && Option::verbose2_)
01076                 {
01077                         std::string message;
01078                         message << id_ << " is publishing...";
01079                         thread_ptr_->trace (message);
01080                 }
01081 #endif
01082 
01083         dependent_map_->publish ();
01084         thread_ptr_->scheduler ()->system ()->relevant_event (true);
01085 }
01086 
01087 inline void Channel::reset ()
01088 {
01089         buffer_ = 0;
01090         state_ = idle;
01091         clock_exec_reset ();
01092 }
01093 
01094 #ifdef DREAM_ENHANCED_EXCEPTION_CHECKING
01095 void Channel::take_transitions ()
01096         throw (DREAM::Exception)
01097 #else
01098 inline void Channel::take_transitions ()
01099 #endif
01100 {
01101 #ifdef DREAM_VERBOSE2
01102 //      if (Option::verbose1_ && Option::verbose2_)
01103 //      {
01104 //              std::string message;
01105 //              thread_ptr_->trace (message << id_ << " is taking transitions.");
01106 //      }
01107 #endif
01108 
01109         switch (state_)
01110         {
01111                 case idle:
01112                         // IF statement optimization
01113                         if (0 < buffer_)
01114                                 if (idle_dependents ())
01115                                 {
01116                                         state_ = wait;
01117                                         clock_exec_reset ();
01118                                         take_transitions ();
01119                                 }
01120                         break;
01121                 case wait:
01122                         // IF statement optimization
01123                         if (clock_exec_ == et_)
01124                         {
01125                                 if (idle_dependents ())
01126                                 {
01127                                         state_ = idle;
01128                                         if (--buffer_ == 0)
01129                                                 thread_ptr_->dequeue (this);
01130                                         publish ();
01131                                 }
01132                                 else
01133                                         state_ = idle;
01134                         }
01135 #ifdef DREAM_ENHANCED_EXCEPTION_CHECKING
01136                         else if (clock_exec_ > et_)
01137                         {
01138                                 std::string message;
01139                                 message << "Execution time in Channel \"" << id_ << "\" is greater than the delay. Please report bug at http://sourceforge.net/projects/dre!";
01140                                 throw DREAM::Exception (message);
01141                         }
01142 #endif
01143         }
01144 }
01145 
01146 void Channel::visitor_map (DREAM::NODE_MAP* task_map, DREAM::NODE_MAP* channel_map, DREAM::NODE_MAP* timer_map)
01147 #ifdef DREAM_ENHANCED_EXCEPTION_CHECKING
01148         throw (DREAM::Exception)
01149 #endif
01150 {
01151         channel_map->insert (DREAM::NODE_PAIR (id_, this));
01152 }
01153 
01154 void Channel::visitor_uppaal (DREAM::NODE_MAP* task_map, DREAM::NODE_MAP* channel_map, DREAM::NODE_MAP* timer_map, std::ofstream& f_stream)
01155 #ifdef DREAM_ENHANCED_EXCEPTION_CHECKING
01156         throw (DREAM::Exception)
01157 #endif
01158 {
01159         if (delay_ == 0)
01160                 f_stream << id_ << " := Buffer (" << buffersize_ << ", ";
01161         else
01162                 f_stream << id_ << " := Channel (" << delay_ << ", " << bcdelay_ << ", " << buffersize_ << ", ";
01163 
01164         DREAM::NODE_MAP* dependent_map = dependent_map_->get_map ();
01165         
01166 #ifdef DREAM_ENHANCED_EXCEPTION_CHECKING
01167         if (dependent_map->size () > 1)
01168                 throw DREAM::Exception ("Channel::visitor_uppaal () called for a Channel with multiple dependents, This is an invalid modeling construct for the Uppaal models. Please use multiple channels with only ONE dependent each!");
01169 #endif
01170 
01171         DREAM::NODE_MAP::const_iterator dependent_iter, task_iter;
01172         dependent_iter = dependent_map->begin ();
01173 
01174         uint i = 0;
01175 
01176         // Figure out the index of the dependent from the list...
01177         for (task_iter = task_map->begin (); task_iter != task_map->end (); task_iter++)
01178         {
01179                 if (task_iter->first == dependent_iter->first) break;
01180                 ++i;
01181         }
01182 
01183         std::string dependent = task_iter->first;
01184         
01185 #ifdef DREAM_ENHANCED_EXCEPTION_CHECKING
01186         if (task_iter == task_map->end ())
01187                 throw DREAM::Exception ("Channel::visitor_uppaal () called for a Channel with a non-task dependent. Invalid modeling construct. Please report bug at http://sourceforge.net/projects/dre!");
01188 #endif
01189 
01190         f_stream << i << ", ";
01191 
01192         if (get_source (task_map, channel_map, timer_map))
01193         {
01194                 f_stream << "publish" << get_source (task_map, channel_map, timer_map)->id ()
01195                         << ", start" << dependent
01196                         << ", publish" << dependent << ");" << std::endl;
01197         }
01198         else
01199         {
01200                 f_stream << ", start" << dependent
01201                         << ", publish" << dependent << ");" << std::endl;
01202         }
01203 }
01204 
01205 #ifdef DREAM_ENHANCED_EXCEPTION_CHECKING
01206 uint Channel::wcet () const
01207         throw (DREAM::Exception)
01208 #else
01209 inline uint Channel::wcet () const
01210 #endif
01211 {
01212         return delay_;
01213 }
01214 
01215 /////////////////////////////////////////////////////////////////////////////
01216 //
01217 // Task
01218 //
01219 /////////////////////////////////////////////////////////////////////////////
01220 
01221 Task::Task (const std::string& id, DREAM::Thread* thread_ptr, uint wcet, uint deadline)
01222         : DREAM::Node (id, thread_ptr),
01223                 wcet_ (wcet),
01224                 bcet_ (wcet),
01225                 context_ (randomcase),
01226                 et_ (wcet),
01227                 deadline_ (deadline),
01228                 state_ (idle),
01229                 clock_dl_ (0.0)
01230 #ifdef DREAM_BRANCHING
01231                 ,next_et_ (0.0)
01232 #endif
01233 #ifndef DREAM_RACE_CONDITION_ZERO
01234                 ,zero_delay_race_condition_ (2)
01235 #endif
01236 {
01237 }
01238 
01239 Task::Task (const std::string& id, DREAM::Thread* thread_ptr, uint wcet, uint deadline, uint subpriority)
01240         : DREAM::Node (id, thread_ptr),
01241                 wcet_ (wcet),
01242                 bcet_ (wcet),
01243                 context_ (randomcase),
01244                 et_ (wcet),
01245                 deadline_ (deadline),
01246                 subpriority_ (subpriority),
01247                 state_ (idle),
01248                 clock_dl_ (0.0)
01249 #ifdef DREAM_BRANCHING
01250                 ,next_et_ (0.0)
01251 #endif
01252 #ifndef DREAM_RACE_CONDITION_ZERO
01253                 ,zero_delay_race_condition_ (2)
01254 #endif
01255 {
01256 }
01257 
01258 Task::Task (const std::string& id, DREAM::Thread* thread_ptr, uint wcet, uint bcet, uint deadline, uint subpriority)
01259         : DREAM::Node (id, thread_ptr),
01260                 wcet_ (wcet),
01261                 bcet_ (bcet),
01262                 context_ (randomcase),
01263                 et_ (bcet + random (wcet - bcet)),
01264                 deadline_ (deadline),
01265                 subpriority_ (subpriority),
01266                 state_ (idle),
01267                 clock_dl_ (0.0)
01268 #ifdef DREAM_BRANCHING
01269                 ,next_et_ (0.0)
01270 #endif
01271 #ifndef DREAM_RACE_CONDITION_ZERO
01272                 ,zero_delay_race_condition_ (2)
01273 #endif
01274 {
01275         if (wcet <= bcet)
01276                 throw DREAM::Exception ("Task best case execution time has to be smaller than the worst case execution time.");
01277 }
01278 
01279 // Note: this is a protected function.
01280 Task::Task (const std::string& id, DREAM::Thread* thread_ptr, uint wcet, uint bcet, uint deadline, uint subpriority,
01281                         DREAM::Context context, double et, DREAM::State state, double clock_dl)
01282         : DREAM::Node (id, thread_ptr),
01283                 wcet_ (wcet),
01284                 bcet_ (bcet),
01285                 context_ (context),
01286                 et_ (et),
01287                 deadline_ (deadline),
01288                 subpriority_ (subpriority),
01289                 state_ (state),
01290                 clock_dl_ (clock_dl)
01291 #ifdef DREAM_BRANCHING
01292                 ,next_et_ (0.0)
01293 #endif
01294 #ifndef DREAM_RACE_CONDITION_ZERO
01295                 ,zero_delay_race_condition_ (2)
01296 #endif
01297 {
01298         if (wcet <= bcet)
01299                 throw DREAM::Exception ("Task best case execution time has to be smaller than the worst case execution time.");
01300 }
01301 
01302 Task::Task (const DREAM::Task& task)
01303         : DREAM::Node (task.id_, task.thread_ptr_),
01304                 wcet_ (task.wcet_),
01305                 bcet_ (task.bcet_),
01306                 context_ (task.context_),
01307                 et_ (task.et_),
01308                 deadline_ (task.deadline_),
01309                 subpriority_ (task.subpriority_),
01310                 state_ (task.state_),
01311                 clock_dl_ (task.clock_dl_)
01312 #ifdef DREAM_BRANCHING
01313                 ,next_et_ (task.next_et_)
01314 #endif
01315 #ifndef DREAM_RACE_CONDITION_ZERO
01316                 ,zero_delay_race_condition_ (task.zero_delay_race_condition_)
01317 #endif
01318 {
01319 }
01320 
01321 Task::~Task ()
01322 {
01323 }
01324 
01325 void Task::operator= (const DREAM::Task& task)
01326 {
01327         id_ = task.id_;
01328         // Do not try to redeploy! This will crash in VC7.1 STL map implementations.
01329         // deploy (task.thread_ptr_);
01330         wcet_ = task.wcet_;
01331         bcet_ = task.bcet_;
01332         context_ = task.context_;
01333         deadline_ = task.deadline_;
01334         subpriority_ = task.subpriority_;
01335         state_ = task.state_;
01336         clock_dl_ = task.clock_dl_;
01337 #ifdef DREAM_BRANCHING
01338         next_et_ = task.next_et_;
01339 #endif
01340 }
01341 
01342 bool Task::operator== (const DREAM::Task& task)
01343 {
01344         if (id_ == task.id_)
01345 /*       (thread_ptr_ == task.thread_ptr_) &&
01346          (wcet_ == task.wcet_) &&
01347          (bcet_ == task.bcet_) &&
01348          (context_ == task.context_) &&
01349          (deadline_ == task.deadline_) &&
01350          (subpriority_ == task.subpriority_) &&
01351          (state_ == task.state_) &&
01352          (clock_dl_ == task.clock_dl_))*/
01353                 return true;
01354         else
01355                 return false;
01356 }
01357 
01358 #ifdef DREAM_ENHANCED_EXCEPTION_CHECKING
01359 uint Task::bcet () const
01360         throw (DREAM::Exception)
01361 #else
01362 inline uint Task::bcet () const
01363 #endif
01364 {
01365         return bcet_;
01366 }
01367 
01368 #ifdef DREAM_ENHANCED_EXCEPTION_CHECKING
01369 void Task::bcet (uint bcet)
01370         throw (DREAM::Exception)
01371 #else
01372 inline void Task::bcet (uint bcet)
01373 #endif
01374 {
01375         bcet_ = bcet;
01376 }
01377 
01378 #ifdef DREAM_BRANCHING
01379 #ifdef DREAM_ENHANCED_EXCEPTION_CHECKING
01380 void Task::branching_point ()
01381         throw (DREAM::Exception)
01382 #else
01383 inline void Task::branching_point ()
01384 #endif
01385 {
01386         if (context_ == branchingpoint)
01387                 if (et_ == next_et_)
01388                 {
01389                         context_ = bestcase;
01390                         et_ = bcet_;
01391                         next_et_ = 0.0;
01392                 }
01393                 else
01394                 {
01395                         et_ = next_et_;
01396                 }
01397 }
01398 #endif
01399 
01400 #ifdef DREAM_ENHANCED_EXCEPTION_CHECKING
01401 DREAM::Context Task::context () const
01402         throw (DREAM::Exception)
01403 #else
01404 inline DREAM::Context Task::context () const
01405 #endif
01406 {
01407         return context_;
01408 }
01409 
01410 #ifdef DREAM_ENHANCED_EXCEPTION_CHECKING
01411 void Task::context (DREAM::Context context)
01412         throw (DREAM::Exception)
01413 #else
01414 inline void Task::context (DREAM::Context context)
01415 #endif
01416 {
01417         context_ = context;
01418 }
01419 
01420 #ifdef DREAM_ENHANCED_EXCEPTION_CHECKING
01421 double Task::clock_dl () const
01422         throw (DREAM::Exception)
01423 #else
01424 inline double Task::clock_dl () const
01425 #endif
01426 {
01427         return clock_dl_;
01428 }
01429 
01430 inline void Task::clock_dl_reset ()
01431 {
01432         clock_dl_ = 0;
01433 }
01434 
01435 inline void Task::clock_exec_reset ()
01436 {
01437         clock_exec_ = 0;
01438 
01439         // Calculate new execution time
01440         if (context_ == worstcase)
01441                 et_ = wcet_;
01442         else if (context_ == randomcase)
01443                 et_ = bcet_ + random (wcet_ - bcet_);
01444         else if (context_ == bestcase)
01445                 et_ = bcet_;
01446 }
01447 
01448 inline void Task::clock_step (double clock_step)
01449 {
01450         if ((state_ == enabled) || (state_ == executing) || (state_ == preempted))
01451                 clock_dl_ += clock_step;
01452         if (state_ == executing)
01453                 clock_exec_ += clock_step;
01454 
01455 #ifdef DREAM_BRANCHING
01456         // IF statement optimization
01457         if (bcet_ < clock_exec_)
01458         {
01459                 if ((clock_exec_ < wcet_) && remote_dep_ && Option::branching_)
01460                 {
01461                         if (clock_exec_ < et_)
01462                         {
01463                                 // Encountered a branching point
01464                                 // Check whether it is relevant
01465                                 if (thread_ptr_->scheduler ()->system ()->relevant_event ())
01466                                 {
01467                                         // Let's blow up the state space a little more...
01468                                         std::string message;
01469                                         thread_ptr_->trace (message << "Branching point " << id_ << " bcet: " << bcet_ << " wcet: " << wcet_ << " next_et: " << clock_exec_);
01470 
01471                                         if (context_ == worstcase)
01472                                                 context_ = branchingpoint;
01473 
01474                                         next_et_ = clock_exec_;
01475                                 }
01476                         }
01477                 }
01478         }
01479 #endif
01480 }
01481 
01482 #ifdef DREAM_ENHANCED_EXCEPTION_CHECKING
01483 void Task::consume ()
01484         throw (DREAM::Exception)
01485 #else
01486 inline void Task::consume ()
01487 #endif
01488 {
01489         if (state_ == idle)
01490         {
01491                 thread_ptr_->enqueue (this);
01492                 state_ = enabled;
01493                 clock_dl_reset ();
01494         }
01495         else
01496         {
01497                 // Error
01498                 if (state_ != error)
01499                 {
01500                         // It's either waiting or preempted
01501                         if (state_ != executing)
01502                                 thread_ptr_->dequeue (this);
01503                         state_ = error;
01504                         thread_ptr_->add_error (this);
01505                 }
01506         }
01507 }
01508 
01509 #ifdef DREAM_ENHANCED_EXCEPTION_CHECKING
01510 uint Task::deadline () const
01511         throw (DREAM::Exception)
01512 #else
01513 inline uint Task::deadline () const
01514 #endif
01515 {
01516         return deadline_;
01517 }
01518 
01519 #ifdef DREAM_ENHANCED_EXCEPTION_CHECKING
01520 void Task::deadline (uint deadline)
01521         throw (DREAM::Exception)
01522 #else
01523 inline void Task::deadline (uint deadline)
01524 #endif
01525 {
01526         deadline_ = deadline;
01527 }
01528 
01529 #ifdef DREAM_ENHANCED_EXCEPTION_CHECKING
01530 void Task::execute ()
01531         throw (DREAM::Exception)
01532 #else
01533 inline void Task::execute ()
01534 #endif
01535 {
01536         if ((state_ == enabled) || (state_ == preempted))
01537         {
01538                 state_ = executing;
01539                 thread_ptr_->dequeue (this);
01540                 clock_exec_reset ();
01541 
01542                 std::string message;
01543                 if (bcet_ != wcet_)
01544                 {
01545 #ifdef DREAM_BRANCHING
01546                         if (context_ == branchingpoint)
01547                         {
01548                                 thread_ptr_->trace (message << "Branching point is taken by " << id_);
01549                         }
01550 #endif
01551                         thread_ptr_->trace (message << id_ << " p: " << priority () 
01552                                 << " sp: " << subpriority_ << " exec time: " << et_ 
01553                                 << " <-- [" << bcet_ << ", " << wcet_ << "]");
01554                 }
01555                 else
01556                 {
01557                         thread_ptr_->trace (message << id_ << " p: " << priority () 
01558                                 << " sp: " << subpriority_ << " exec time: " << et_ );
01559                 }
01560         }
01561 #ifdef DREAM_ENHANCED_EXCEPTION_CHECKING
01562         else
01563         {
01564                 std::string message;
01565                 message << "Task " << id_ << " scheduled for execution is not enabled. Please report bug at http://sourceforge.net/projects/dre!";
01566                 throw DREAM::Exception (message);
01567         }
01568 #endif
01569 }
01570 
01571 #ifdef DREAM_ENHANCED_EXCEPTION_CHECKING
01572 bool Task::isidle () const
01573         throw (DREAM::Exception)
01574 #else
01575 inline bool Task::isidle () const
01576 #endif
01577 {
01578         return (state_ == idle) ? true : false;
01579 }
01580 
01581 inline double Task::next_event ()
01582 {
01583         // If the task executes the next event is publishing
01584         // Otherwise we have no clue...
01585         return (state_ == executing) ? et_ - clock_exec_ : 0.0;
01586 }
01587 
01588 #ifdef DREAM_BRANCHING
01589 #ifdef DREAM_ENHANCED_EXCEPTION_CHECKING
01590 void Task::next_et (double next_et)
01591         throw (DREAM::Exception)
01592 #else
01593 inline void Task::next_et (double next_et)
01594 #endif
01595 {
01596         next_et_ = next_et;
01597 }
01598 #endif
01599 
01600 #ifdef DREAM_ENHANCED_EXCEPTION_CHECKING
01601 void Task::preempt ()
01602         throw (DREAM::Exception)
01603 #else
01604 inline void Task::preempt ()
01605 #endif
01606 {
01607         if (state_ == executing) state_ = preempted;
01608         thread_ptr_->enqueue (this);
01609 }
01610 
01611 #ifdef DREAM_ENHANCED_EXCEPTION_CHECKING
01612 uint Task::priority () const
01613         throw (DREAM::Exception)
01614 #else
01615 inline uint Task::priority () const
01616 #endif
01617 {
01618         return thread_ptr_->priority ();
01619 }
01620 
01621 #ifdef DREAM_ENHANCED_EXCEPTION_CHECKING
01622 void Task::priority (uint priority)
01623         throw (DREAM::Exception)
01624 #else
01625 inline void Task::priority (uint priority)
01626 #endif
01627 {
01628         deploy (scheduler ()->get_thread (priority));
01629 }
01630 
01631 #ifdef DREAM_ENHANCED_EXCEPTION_CHECKING
01632 void Task::publish ()
01633         throw (DREAM::Exception)
01634 #else
01635 inline void Task::publish ()
01636 #endif
01637 {
01638         if (state_ == executing)
01639                 state_ = idle;
01640 #ifdef DREAM_ENHANCED_EXCEPTION_CHECKING
01641         else
01642         {
01643                 std::string message;
01644                 message << "Task::publish () called on \"" << id_ << "\" which is not executing. Please report bug at http://sourceforge.net/projects/dre!";
01645                 throw DREAM::Exception (message);
01646         }
01647 #endif
01648 
01649         dependent_map_->publish ();
01650         thread_ptr_->scheduler ()->system ()->relevant_event (true);
01651 }
01652 
01653 inline void Task::reset ()
01654 {
01655         state_ = idle;
01656         executed (0);
01657         clock_dl_reset ();
01658         clock_exec_reset ();
01659 }
01660 
01661 #ifdef DREAM_ENHANCED_EXCEPTION_CHECKING
01662 uint Task::subpriority () const
01663         throw (DREAM::Exception)
01664 #else
01665 inline uint Task::subpriority () const
01666 #endif
01667 {
01668         return subpriority_;
01669 }
01670 
01671 #ifdef DREAM_ENHANCED_EXCEPTION_CHECKING
01672 void Task::subpriority (uint subpriority)
01673         throw (DREAM::Exception)
01674 #else
01675 inline void Task::subpriority (uint subpriority)
01676 #endif
01677 {
01678         subpriority_ = subpriority;
01679 }
01680 
01681 #ifdef DREAM_ENHANCED_EXCEPTION_CHECKING
01682 void Task::take_transitions ()
01683         throw (DREAM::Exception)
01684 #else
01685 inline void Task::take_transitions ()
01686 #endif
01687 {
01688 #ifdef DREAM_VERBOSE2
01689 //      if (Option::verbose1_ && Option::verbose2_)
01690 //      {
01691 //              std::string message;
01692 //              thread_ptr_->trace (message << id_ << " is taking transitions.");
01693 //      }
01694 #endif
01695 
01696         if ((clock_dl_ < deadline_) || (deadline_ == 0))                                // 0 deadline is used for no deadline
01697         {
01698                 // Check whether the clock_exec_ has reached the execution time
01699                 // IF statement optimization
01700                 if (clock_exec_ == et_)
01701                 {
01702                         if (state_ == executing)
01703                         {
01704                                 publish ();
01705                                 clock_exec_reset ();
01706                                 clock_dl_reset ();
01707                                 executed (1);
01708 
01709                                 thread_ptr_->freethread ();
01710 
01711 #ifdef DREAM_VERBOSE2
01712                                 if (Option::verbose1_ && Option::verbose2_)
01713                                 {
01714                                         std::string message;
01715                                         thread_ptr_->trace (message << id_ << " has finished the execution");
01716                                 }
01717 #endif
01718 
01719                         }
01720                 }
01721         }
01722         else
01723         {
01724                 // Check for errors
01725                 if (state_ != error)
01726                 {
01727                         if (state_ != executing)
01728                                 thread_ptr_->dequeue (this);
01729                         // Error
01730                         state_ = error;
01731                         thread_ptr_->add_error (this);
01732                 }
01733         }
01734 
01735 #ifdef DREAM_ENHANCED_EXCEPTION_CHECKING
01736         if (clock_exec_ > et_)
01737         {
01738                 std::string message;
01739                 message << "Execution clock value \"" << clock_exec_ << "\" in Task \"" << id_ << "\" is greater than the actual execution time \"" << et_ 
01740                         << "\" (bcet: \"" << bcet_ << "\" wcet: \"" << wcet_ 
01741                         << "\"). Most likely the execution time was set during simulation. Please report bug at http://sourceforge.net/projects/dre!";
01742                 throw DREAM::Exception (message);
01743         }
01744 #endif
01745 }
01746 
01747 void Task::visitor_if (DREAM::NODE_MAP* task_map, DREAM::NODE_MAP* channel_map, DREAM::NODE_MAP* timer_map, std::ofstream& f_stream)
01748 #ifdef DREAM_ENHANCED_EXCEPTION_CHECKING
01749         throw (DREAM::Exception)
01750 #endif
01751 {
01752         if ((scheduler ()->nonpreemptive ())|| (scheduler ()->highestpriority (this)))
01753         {
01754                 DREAM::NODE_MAP::const_iterator task_iter, task_iter2;
01755                 uint i = 0;
01756 
01757                 // Figure out our index from the list...
01758                 for (task_iter = task_map->begin (); task_iter->first != id (); task_iter++)
01759                 {
01760                         ++i;
01761                 }
01762 
01763                 f_stream << "/*\n * Task " << i << " - " << id_ << "\n *\n */\n" << std::endl;
01764 
01765                 f_stream << "process task_" << id_ << " (1);\n" << std::endl;
01766 
01767                 f_stream << "var ce clock public;\nvar cd clock public;\n" << std::endl;
01768 
01769                 f_stream << "state initial #start ;\n\tdeadline eager;\n\tinput event ();\n\tset cd := 0;\n"
01770                         << "\ttask ({common}0).en[" << i << "] := true;\n\t\tnextstate wait;\nendstate;\n" << std::endl;
01771 
01772                 f_stream << "state wait;\n\tdeadline eager;\n\tprovided ({common}0).exec[" << i << "];\n\tset ce := 0;\n"
01773                         << "\t\tnextstate run;\nendstate;\n" << std::endl;
01774 
01775                 f_stream << "state run;\n\tdeadline delayable;\n\twhen ce <= wcet" << i << " and ce >= bcet" << i << ";\n"
01776                         << "\t\ttask ({common}0).en[" << i << "] := false;\n\t\treset ce;\n\t\treset cd;" << std::endl;
01777 
01778                 const DREAM::NODE_MAP* node_map = get_dependent_map ();
01779                 const DREAM::NODE_MAP* node_map2;
01780 
01781                 // Check dependents
01782                 DREAM::NODE_MAP::const_iterator find_iter;
01783 
01784                 for (task_iter = node_map->begin (); task_iter != node_map->end (); task_iter++)
01785                 {
01786                         find_iter = task_map->find (task_iter->first);
01787                         if (find_iter != task_map->end ())
01788                                 f_stream << "\t\toutput event () to {task_" << find_iter->first << "}0;\n";
01789                         else
01790                         {
01791                                 find_iter = channel_map->find (task_iter->first);
01792 
01793                                 // Dependent is a channel - need to find dependent tasks...
01794                                 if (find_iter->second)
01795                                         node_map2 = find_iter->second->get_dependent_map ();
01796 
01797 #ifdef DREAM_ENHANCED_EXCEPTION_CHECKING
01798                                 else
01799                                 {
01800                                         std::string message;
01801                                         message << "Task " << task_iter->first << " has no Channel dependents. Incorrect model.";
01802                                         throw DREAM::Exception (message);
01803                                 }
01804 #endif
01805 
01806                                 for (task_iter2 = node_map2->begin (); task_iter2 != node_map2->end (); task_iter2++)
01807                                 {
01808                                         find_iter = node_map2->find (task_iter2->first);
01809 
01810                                         if (find_iter != node_map2->end ())
01811                                         {
01812                                                 if (task_iter->second->wcet () != 0)
01813                                                         f_stream << "\t\toutput event () via {" << task_iter->first << "}0 to {task_" << find_iter->first << "}0;\n";
01814                                                 else
01815                                                         f_stream << "\t\toutput event () /* via {" << task_iter->first << "}0 */ to {task_" << find_iter->first << "}0;\n";
01816                                         }
01817 
01818 #ifdef DREAM_ENHANCED_EXCEPTION_CHECKING
01819                                         else
01820                                         {
01821                                                 std::string message;
01822                                                 message << "Node " << task_iter2->first << " could not be found as a Task dependent in the Task list when generating IF input. Incorrect model.";
01823                                                 throw DREAM::Exception (message);
01824                                         }
01825 #endif
01826 
01827                                 }
01828                         }
01829                 }
01830                         
01831                 f_stream << "\t\t\tnextstate initial;\n\tdeadline eager;\n\tprovided ({common}0).exec[" << i << "] = false;\n"
01832                         // Faster << "\t\tnextstate wait;\nendstate;\n\nendprocess;\n" << std::endl;
01833                         << "\twhen ce = 0;\n\t\tnextstate wait;\nendstate;\n\nendprocess;\n" << std::endl;
01834         }
01835         else
01836         {
01837                 DREAM::NODE_MAP::const_iterator task_iter, task_iter2;
01838                 uint i = 0;
01839 
01840                 // Figure out our index from the list...
01841                 for (task_iter = task_map->begin (); task_iter->first != id (); task_iter++)
01842                 {
01843                         ++i;
01844                 }
01845 
01846                 f_stream << "/*\n * Task " << i << " - " << id_ << "\n *\n */\n" << std::endl;
01847 
01848                 f_stream << "process task_" << id_ << " (1);\n" << std::endl;
01849 
01850                 f_stream << "var ce clock public;\nvar cd clock public;\nvar et integer public;\nvar pre integer public;\n" << std::endl;
01851 
01852                 f_stream << "state initial #start ;\n\tdeadline eager;\n\tinput event ();\n\tset cd := 0;\n\ttask et := 0;\n\ttask pre := 0;\n"
01853                         << "\ttask ({common}0).en[" << i << "] := true;\n\t\tnextstate wait;\nendstate;\n" << std::endl;
01854 
01855                 f_stream << "state wait;\n\tdeadline eager;\n\tprovided ({common}0).exec[" << i << "];\n\tset ce := 0;\n"
01856                         << "\t\tnextstate run;\nendstate;\n" << std::endl;
01857 
01858                 /* f_stream << "state run;\n\tdeadline delayable;\n\twhen ce <= wcet" << i << " - et and ce >= bcet" 
01859                         << i << " - et - pre;\n" */
01860 
01861                 f_stream << "state run;\n\tdeadline delayable;\n\twhen ce >= bcet" << i << " - et - pre;\n"
01862                         << "\t\ttask ({common}0).en[" << i << "] := false;\n\t\treset ce;\n\t\treset cd;" << std::endl;
01863 
01864                 const DREAM::NODE_MAP* node_map = get_dependent_map ();
01865                 const DREAM::NODE_MAP* node_map2;
01866 
01867                 // Check dependents
01868                 DREAM::NODE_MAP::const_iterator find_iter;
01869 
01870                 for (task_iter = node_map->begin (); task_iter != node_map->end (); task_iter++)
01871                 {
01872                         find_iter = task_map->find (task_iter->first);
01873                         if (find_iter != task_map->end ())
01874                                 f_stream << "\t\toutput event () to {task_" << find_iter->first << "}0;\n";
01875                         else
01876                         {
01877                                 find_iter = channel_map->find (task_iter->first);
01878 
01879                                 // Dependent is a channel - need to find dependent tasks...
01880                                 if (find_iter->second)
01881                                         node_map2 = find_iter->second->get_dependent_map ();
01882 
01883 #ifdef DREAM_ENHANCED_EXCEPTION_CHECKING
01884                                 else
01885                                 {
01886                                         std::string message;
01887                                         message << "Task " << task_iter->first << " has no Channel dependents. Incorrect model.";
01888                                         throw DREAM::Exception (message);
01889                                 }
01890 #endif
01891 
01892                                 for (task_iter2 = node_map2->begin (); task_iter2 != node_map2->end (); task_iter2++)
01893                                 {
01894                                         find_iter = node_map2->find (task_iter2->first);
01895                                                 if (find_iter != node_map2->end ())
01896                                                 {
01897                                                         if (task_iter->second->wcet () != 0)
01898                                                                 f_stream << "\t\toutput event () via {" << task_iter->first << "}0 to {task_" << find_iter->first << "}0;\n";
01899                                                         else
01900                                                                 f_stream << "\t\toutput event () /* via {" << task_iter->first << "}0 */ to {task_" << find_iter->first << "}0;\n";
01901                                                 }
01902 
01903 #ifdef DREAM_ENHANCED_EXCEPTION_CHECKING
01904                                                 else
01905                                                 {
01906                                                         std::string message;
01907                                                         message << "Node " << task_iter2->first << " could not be found as a Task dependent in the Task list when generating IF input. Incorrect model.";
01908                                                         throw DREAM::Exception (message);
01909                                                 }
01910 #endif
01911                                 }
01912                         }
01913                 }
01914                         
01915                 /* f_stream << "\t\t\tnextstate initial;\n\tdeadline eager;\n\twhen ce < wcet" << i << " - et and ce >= pr;" << std::endl;
01916                 f_stream << "\t\tnextstate pass;\n"; */
01917 
01918                 f_stream << "\t\t\tnextstate initial;\n\tdeadline eager;\n\twhen ce >= wcet" << i << " - et;\n"
01919                         << "\t\ttask ({common}0).en[" << i << "] := false;\n\t\treset ce;\n\t\treset cd;" << std::endl;
01920 
01921                 /* f_stream << "\t\t\tnextstate initial;\n\tdeadline eager;\n\tprovided et + pr < wcet" << i << ";\n\twhen ce >= pr;\n"
01922                         << "\t\tnextstate pass;\n\tprovided et + pr >= wcet" << i << ";\n"
01923                         << "\t\ttask ({common}0).en[" << i << "] := false;\n\t\treset ce;\n\t\treset cd;" << std::endl; */
01924 
01925                 for (task_iter = node_map->begin (); task_iter != node_map->end (); task_iter++)
01926                 {
01927                         find_iter = task_map->find (task_iter->first);
01928                         if (find_iter != task_map->end ())
01929                                 f_stream << "\t\toutput event () to {task_" << find_iter->first << "}0;\n";
01930                         else
01931                         {
01932                                 find_iter = channel_map->find (task_iter->first);
01933 
01934                                 // Dependent is a channel - need to find dependent tasks...
01935                                 if (find_iter->second)
01936                                         node_map2 = find_iter->second->get_dependent_map ();
01937 
01938 #ifdef DREAM_ENHANCED_EXCEPTION_CHECKING
01939                                 else
01940                                 {
01941                                         std::string message;
01942                                         message << "Task " << task_iter->first << " has no Channel dependents. Incorrect model.";
01943                                         throw DREAM::Exception (message);
01944                                 }
01945 #endif
01946 
01947                                 for (task_iter2 = node_map2->begin (); task_iter2 != node_map2->end (); task_iter2++)
01948                                 {
01949                                         find_iter = node_map2->find (task_iter2->first);
01950                                                 if (find_iter != node_map2->end ())
01951                                                 {
01952                                                         if (task_iter->second->wcet () != 0)
01953                                                                 f_stream << "\t\toutput event () via {" << task_iter->first << "}0 to {task_" << find_iter->first << "}0;\n";
01954                                                         else
01955                                                                 f_stream << "\t\toutput event () /* via {" << task_iter->first << "}0 */ to {task_" << find_iter->first << "}0;\n";
01956                                                 }
01957 
01958 #ifdef DREAM_ENHANCED_EXCEPTION_CHECKING
01959                                                 else
01960                                                 {
01961                                                         std::string message;
01962                                                         message << "Node " << task_iter2->first << " could not be found as a Channel dependent in the Task list when generating IF input. Incorrect model.";
01963                                                         throw DREAM::Exception (message);
01964                                                 }
01965 #endif
01966                                 }
01967                         }
01968                 }
01969 
01970                 f_stream << "\t\t\tnextstate initial;\n\tprovided et + pr < wcet" << i << ";\n\twhen ce >= pr;\n\t\tnextstate pass;\n"
01971                         << "\tprovided ({common}0).exec[" << i << "] = false and et = 0;\n"
01972 
01973                         /* << "\t\tnextstate wait;\n\tprovided ({common}0).exec[" << i << "] = false and et > 0;\n"
01974                         << "\ttask pre := pre + pr;\n\t\tnextstate wait;\n"
01975                         << "\nendstate;\n\nstate pass #unstable ;\n\tset ce := 0;\n\ttask et := et + pr;\n\t\tnextstate run;\nendstate;\n" */
01976 
01977                         << "\twhen ce = 0;\n\t\tnextstate wait;\n\tprovided ({common}0).exec[" << i << "] = false and et = 0;\n"
01978                         << "\twhen ce > 0;\n\ttask pre := pre + pr;\n\t\tnextstate wait;\n"
01979                         << "\tprovided ({common}0).exec[" << i << "] = false and et > 0;\n\ttask pre := pre + pr;\n\t\tnextstate wait;\n"
01980                         << "\nendstate;\n\nstate pass #unstable ;\n\tset ce := 0;\n\ttask et := et + pr;\n\t\tnextstate run;\nendstate;\n"
01981                         << "\nendprocess;\n" << std::endl;
01982 
01983                         /* Faster << "\t\tnextstate wait;\n\tprovided ({common}0).exec[" << i << "] = false and et > 0;\n\ttask pre := pre + pr;\n\t\tnextstate wait;\n"
01984                         << "\nendstate;\n\nstate pass #unstable ;\n\tset ce := 0;\n\ttask et := et + pr;\n\t\tnextstate run;\nendstate;\n"
01985                         << "\nendprocess;\n" << std::endl; */
01986         }
01987 }
01988 
01989 void Task::visitor_map (DREAM::NODE_MAP* task_map, DREAM::NODE_MAP* channel_map, DREAM::NODE_MAP* timer_map)
01990 #ifdef DREAM_ENHANCED_EXCEPTION_CHECKING
01991         throw (DREAM::Exception)
01992 #endif
01993 {
01994         task_map->insert (DREAM::NODE_PAIR (id_, this));
01995 }
01996 
01997 void Task::visitor_task_avltree (DREAM::TASK_AVLTREE* task_avltree)
01998 #ifdef DREAM_ENHANCED_EXCEPTION_CHECKING
01999         throw (DREAM::Exception)
02000 #endif
02001 {
02002         task_avltree->insert (id_, this);
02003 }
02004 
02005 void Task::visitor_update_task_avltree (DREAM::TASK_AVLTREE* task_avltree)
02006 #ifdef DREAM_ENHANCED_EXCEPTION_CHECKING
02007         throw (DREAM::Exception)
02008 #endif
02009 {
02010         DREAM::TASK_AVLTREE::iterator task_iter;
02011 
02012         // Update task from parameter list.
02013         for (task_iter = task_avltree->begin ();
02014                 task_iter != task_avltree->end (); task_iter++)
02015         {
02016                 if (this == (*task_iter)->second)
02017                 // Pointer refers to the same object...
02018                         break;
02019                 if ((*this) == * ((*task_iter)->second))
02020                 {
02021                          (*this) = * ((*task_iter)->second);
02022                         break;
02023                 }
02024         }
02025 }
02026 
02027 void Task::visitor_uppaal (DREAM::NODE_MAP* task_map, DREAM::NODE_MAP* channel_map, DREAM::NODE_MAP* timer_map, std::ofstream& f_stream)
02028 #ifdef DREAM_ENHANCED_EXCEPTION_CHECKING
02029         throw (DREAM::Exception)
02030 #endif
02031 {
02032         if ((scheduler ()->nonpreemptive ())|| (scheduler ()->highestpriority (this)))
02033                 f_stream << id () << " := NonpTask (";
02034         else
02035                 f_stream << id () << " := Task (";
02036 
02037         DREAM::NODE_MAP::const_iterator task_iter;
02038         uint i = 0;
02039 
02040         // Figure out our index from the list...
02041         for (task_iter = task_map->begin (); task_iter->first != id_; task_iter++)
02042         {
02043                 ++i;
02044         }
02045 
02046 #ifdef DREAM_ENHANCED_EXCEPTION_CHECKING
02047         if (task_iter == task_map->end ())
02048                 throw DREAM::Exception ("Task::visitor_uppaal () called for a nonexistent Task. Please report bug at http://sourceforge.net/projects/dre!");
02049 #endif
02050 
02051         if ((scheduler ()->nonpreemptive ())|| (scheduler ()->highestpriority (this)))
02052                 f_stream << i << ", " << wcet_ << ", " << bcet_ << ", " << deadline_ << ", ";
02053         else
02054                 f_stream << i << ", " << wcet_ << ", " << bcet_ << ", " << deadline_ << ", 1, ";
02055         
02056         if (get_source (task_map, channel_map, timer_map))
02057                 // Source is something other than a Channel
02058                 f_stream << "publish" << get_source (task_map, channel_map, timer_map)->id () ;
02059         else
02060                 // Source (s) is (are) Channel (s)
02061                 f_stream << "start" << id ();
02062 
02063         if ((scheduler ()->nonpreemptive ())|| (scheduler ()->highestpriority (this)))
02064                 f_stream << ", run" << id () << ", publish" << id () << ");" << std::endl;
02065         else
02066                 f_stream << ", run" << id () << ", publish" << id () << ", preempt"
02067                 << scheduler ()->id () << ");" << std::endl;
02068 }
02069 
02070 #ifdef DREAM_ENHANCED_EXCEPTION_CHECKING
02071 uint Task::wcet () const
02072         throw (DREAM::Exception)
02073 #else
02074 inline uint Task::wcet () const
02075 #endif
02076 {
02077         return wcet_;
02078 }
02079 
02080 #ifdef DREAM_ENHANCED_EXCEPTION_CHECKING
02081 void Task::wcet (uint wcet)
02082         throw (DREAM::Exception)
02083 #else
02084 inline void Task::wcet (uint wcet)
02085 #endif
02086 {
02087         wcet_ = wcet;
02088 }
02089 
02090 #ifndef DREAM_RACE_CONDITION_ZERO
02091 bool Task::zero_delay_race_condition (DREAM::System* system_ptr)
02092 #ifdef DREAM_ENHANCED_EXCEPTION_CHECKING
02093         throw (DREAM::Exception)
02094 #endif
02095 {
02096         if (!Option::race_condition_zero_)
02097         {
02098                 if (zero_delay_race_condition_ == 0)
02099                         return false;
02100                 else if (zero_delay_race_condition_ == 1)
02101                         return true;
02102 
02103                 DREAM::NODE_MAP task_map;
02104                 DREAM::NODE_MAP channel_map;
02105                 DREAM::NODE_MAP timer_map;
02106 
02107                 system_ptr->visitor_map (&task_map, &channel_map, &timer_map);
02108 
02109                 const DREAM::Node* source_task = get_source (&task_map, &channel_map, &timer_map);
02110                                 
02111                 if ((source_task) && (scheduler ()) && (source_task->scheduler ()))
02112                 {
02113                         if (scheduler () == source_task->scheduler ())
02114                         {
02115                                 // No race conditions as task_ptr is triggered by an event from the local machine.
02116                                 // Skip the checking of the whole list...
02117                                 zero_delay_race_condition_ = 1;
02118                                 return true;
02119                         }
02120                         else
02121                         {
02122                                 zero_delay_race_condition_ = 0;
02123                                 return false;
02124                         }
02125                 }
02126                 else
02127                 {
02128                         // Let's see whether all sources are Channels with zero-time delay
02129                         DREAM::NODE_MAP::const_iterator node_iter;
02130                         bool found = false;
02131                         bool allzero = true;
02132 
02133                         for (node_iter = channel_map.begin (); node_iter != channel_map.end (); node_iter++)
02134                         {
02135                                 if (node_iter->second->get_dependent (id_))
02136                                 {
02137                                         found = true;
02138                                         if (node_iter->second->wcet () != 0)
02139                                                 allzero = false;
02140                                 }
02141                         }
02142 
02143                         if (found && allzero)
02144                         {
02145                                 zero_delay_race_condition_ = 1;
02146                                 return true;
02147                         }
02148                         else
02149                         {
02150                                 zero_delay_race_condition_ = 0;
02151                                 return false;
02152                         }
02153                 }
02154         }
02155         else
02156                 return false;
02157 }
02158 #endif
02159 
02160 /////////////////////////////////////////////////////////////////////////////
02161 //
02162 // PowerAwareTask
02163 //
02164 /////////////////////////////////////////////////////////////////////////////
02165 /*
02166 PowerAwareTask::PowerAwareTask (const std::string& id, DREAM::Thread* thread_ptr, uint wcet, uint deadline)
02167         : DREAM::Task (id, thread_ptr, wcet, deadline)
02168 {
02169 }
02170 
02171 PowerAwareTask::PowerAwareTask (const std::string& id, DREAM::Thread* thread_ptr, uint wcet, uint deadline, uint subpriority)
02172         : DREAM::Task (id, thread_ptr, wcet, deadline, subpriority)
02173 {
02174 }
02175 
02176 PowerAwareTask::PowerAwareTask (const std::string& id, DREAM::Thread* thread_ptr, uint wcet, uint bcet, uint deadline, uint subpriority)
02177         : DREAM::Task (id, thread_ptr, wcet, bcet, deadline, subpriority)
02178 {
02179         if (wcet <= bcet)
02180                 throw DREAM::Exception ("PowerAwareTask best case execution time has to be smaller than the worst case execution time.");
02181 }
02182 
02183 PowerAwareTask::PowerAwareTask (const DREAM::PowerAwareTask& powerawaretask)
02184         : DREAM::Task (powerawaretask.id_, powerawaretask.thread_ptr_, powerawaretask.wcet_, powerawaretask.bcet_
02185                 , powerawaretask.deadline_,     powerawaretask.subpriority_, powerawaretask.context_, powerawaretask.et_
02186                 , powerawaretask.state_, powerawaretask.clock_dl_)
02187 {
02188 }
02189 
02190 PowerAwareTask::~PowerAwareTask ()
02191 {
02192 }
02193 
02194 void PowerAwareTask::operator= (const DREAM::PowerAwareTask& powerawaretask)
02195 {
02196         id_ = powerawaretask.id_;
02197         // Do not try to redeploy! This will crash in VC7.1 STL map implementations.
02198         // deploy (task.thread_ptr_);
02199         wcet_ = powerawaretask.wcet_;
02200         bcet_ = powerawaretask.bcet_;
02201         context_ = powerawaretask.context_;
02202         deadline_ = powerawaretask.deadline_;
02203         subpriority_ = powerawaretask.subpriority_;
02204         state_ = powerawaretask.state_;
02205         clock_dl_ = powerawaretask.clock_dl_;
02206 }
02207 
02208 bool PowerAwareTask::operator== (const DREAM::PowerAwareTask& powerawaretask)
02209 {
02210         if (id_ == powerawaretask.id_)
02211 /*       (thread_ptr_ == powerawaretask.thread_ptr_) &&
02212          (wcet_ == powerawaretask.wcet_) &&
02213          (bcet_ == powerawaretask.bcet_) &&
02214          (context_ == powerawaretask.context_) &&
02215          (deadline_ == powerawaretask.deadline_) &&
02216          (subpriority_ == powerawaretask.subpriority_) &&
02217          (state_ == powerawaretask.state_) &&
02218          (clock_dl_ == powerawaretask.clock_dl_))*
02219                 return true;
02220         else
02221                 return false;
02222 }
02223 
02224 inline void PowerAwareTask::clock_step (double clock_step)
02225 {
02226         if ((state_ == enabled) || (state_ == executing) || (state_ == preempted) )
02227                 clock_dl_ += clock_step;
02228         if (state_ == executing)
02229                 clock_exec_ += clock_step * thread_ptr_->scheduler ()->speed ();
02230 }
02231 
02232 inline double PowerAwareTask::next_event ()
02233 {
02234         // If the task executes the next event is publishing
02235         if (state_ == executing)
02236                 return (et_ - clock_exec_ * thread_ptr_->scheduler ()->speed ());
02237         // Otherwise we have no clue...
02238         else
02239                 return 0.0;
02240 }
02241 */
02242 /////////////////////////////////////////////////////////////////////////////
02243 //
02244 // PriorityInversionList
02245 //
02246 /////////////////////////////////////////////////////////////////////////////
02247 
02248 #ifdef DREAM_RACE_CONDITION
02249 PriorityInversionList::PriorityInversionList (DREAM::System* system_ptr)
02250 : system_ptr_ (system_ptr)
02251 {
02252 }
02253 
02254 PriorityInversionList::~PriorityInversionList ()
02255 {
02256         task_avltree_list_.destroy ();
02257 }
02258 
02259 void PriorityInversionList::add (const DREAM::TASK_AVLTREE* task_avltree_ptr, DREAM::Task* task_ptr)
02260 #ifdef DREAM_ENHANCED_EXCEPTION_CHECKING
02261         throw (DREAM::Exception)
02262 #endif
02263 {
02264         DREAM::TASK_AVLTREE* new_avltree = NULL;
02265 
02266         if (!find (task_avltree_ptr, task_ptr))
02267         {
02268                 // Task not present in priority inversion list
02269 
02270                 // Create copy of task_avltree
02271                 new_avltree = new DREAM::TASK_AVLTREE ();
02272                 task_avltree_list_.push_back (new_avltree);
02273 
02274                 new_avltree->assign (task_avltree_ptr->begin (), task_avltree_ptr->end ());
02275                 task_id_list_.push_back (new_avltree->begin ()->first);
02276         }
02277 }
02278 
02279 void PriorityInversionList::destroy ()
02280 // link issue: void PriorityInversionList::destroy ()
02281 {
02282         // Free up memory
02283         task_avltree_list_.destroy ();
02284         task_id_list_.clear ();
02285 }
02286 
02287 DREAM::Task* PriorityInversionList::find (const DREAM::TASK_AVLTREE* task_avltree_ptr, DREAM::Task* task_ptr)
02288 #ifdef DREAM_ENHANCED_EXCEPTION_CHECKING
02289         throw (DREAM::Exception)
02290 #endif
02291 {
02292 #ifdef DREAM_ENHANCED_EXCEPTION_CHECKING
02293         if (!task_ptr)
02294                 throw DREAM::Exception ("Illegal use of PriorityInversionList::find (). Please report bug at http://sourceforge.net/projects/dre!");
02295 #endif
02296 
02297         TASK_AVLTREE_LIST::const_iterator main_iter;
02298         TASK_ID_LIST::const_iterator id_iter;
02299         bool found = false;
02300         id_iter = NULL;
02301 
02302         // Iterate through the LinkedList, see if we can find task_avltree_ptr in the data structure already
02303         // Main loop
02304         for (main_iter = task_avltree_list_.begin (); main_iter != task_avltree_list_.end (); main_iter++)
02305         {
02306                 // Iterate with the task id list as well
02307                 if (id_iter == NULL)
02308                         id_iter = task_id_list_.begin ();
02309                 else
02310                         ++id_iter;
02311 
02312 #ifdef DREAM_ENHANCED_EXCEPTION_CHECKING
02313                 if (id_iter == task_id_list_.end ())
02314                         throw DREAM::Exception ("PriorityInversionList::find () task_avltree_ptr_ and task_id_list_ lists are out of sync. Please report bug at http://sourceforge.net/projects/dre!");
02315 #endif
02316 
02317                 // Let's see whether the two trees have the same size
02318                 if (main_iter->item ()->size () != task_avltree_ptr->size ())
02319                         // Trees do not match, keep iterating
02320                         break;
02321 
02322                 // Let's see whether they contain the same elements
02323                 DREAM::TASK_AVLTREE::const_iterator tree_iter;
02324                 for (tree_iter = task_avltree_ptr->begin (); tree_iter != task_avltree_ptr->end (); tree_iter++)
02325                 {
02326                         if (main_iter->item ()->find (tree_iter->first) == main_iter->item ()->end ())
02327                                 // Trees do not match, keep iterating
02328                                 break;
02329 
02330                         // Found the tree, return the element to be executed
02331                         return main_iter->item ()->find (id_iter->item ())->second;
02332                 }
02333         }
02334 
02335         return NULL;
02336 }
02337 
02338 DREAM::Task* PriorityInversionList::find_current (const DREAM::TASK_AVLTREE* task_avltree_ptr, DREAM::Task* task_ptr)
02339 // link issue: inline DREAM::Task* PriorityInversionList::find_current (const DREAM::TASK_AVLTREE* task_avltree_ptr, DREAM::Task* task_ptr)
02340 #ifdef DREAM_ENHANCED_EXCEPTION_CHECKING
02341         throw (DREAM::Exception)
02342 #endif
02343 {
02344         add (task_avltree_ptr, task_ptr);
02345         return (find (task_avltree_ptr, task_ptr));
02346 }
02347 
02348 bool PriorityInversionList::increment (TASK_AVLTREE_LIST::iterator task_avltree_list_iter,
02349                 TASK_ID_LIST::iterator task_id_list_iter)
02350 {
02351         AVLTree <std::string, DREAM::Task*>* tree_ptr = task_avltree_list_iter->item ();
02352         AVLTreeNode <std::string, DREAM::Task*>* node_ptr = tree_ptr->find (task_id_list_iter->item ());
02353         TASK_AVLTREE::iterator iter;
02354         iter = node_ptr;
02355 
02356         if (iter != task_avltree_list_iter->item ()->last ())
02357         {
02358                 // Iterate through current tree
02359                 iter++;
02360                 // Set the new element's id in the id list
02361                 task_id_list_iter->item (iter->first);
02362                 return true;
02363         }
02364         else
02365         {
02366                 // End of tree found
02367 #ifdef DREAM_RACE_CONDITION_COMBINATION
02368                 if ((Option::race_condition_combination_) && (Option::race_condition_))
02369                 {
02370                         // set task id to the first element of the AVL tree
02371                         task_id_list_iter->item (task_avltree_list_iter->item ()->begin ()->first);
02372                 }
02373 #endif
02374                 // increment next id
02375                 ++task_avltree_list_iter;
02376                 ++task_id_list_iter;
02377                 if ((task_avltree_list_iter != task_avltree_list_.end ()) && (task_id_list_iter != task_id_list_.end ()))
02378                 {
02379                         return increment (task_avltree_list_iter, task_id_list_iter);
02380                 }
02381                 else
02382                         return false;
02383         }
02384 }
02385 
02386 bool PriorityInversionList::inversion ()
02387 // link issue: inline bool PriorityInversionList::inversion ()
02388 {
02389         if (task_avltree_list_.size () == 0)
02390                 return false;
02391 
02392         TASK_AVLTREE_LIST::iterator tree_iter;
02393         TASK_ID_LIST::iterator id_iter;
02394         tree_iter = task_avltree_list_.begin ();
02395         id_iter = task_id_list_.begin ();
02396 
02397         return increment (tree_iter, id_iter);
02398 }
02399 
02400 #endif
02401 
02402 }

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