ModelCheck.cpp

Go to the documentation of this file.
00001 /** @file ModelCheck.cpp
00002 * @author Gabor Madl
00003 * @date Created 08/2005
00004 * @brief Model Checker library.
00005 * @warning This library is experimental.
00006 *
00007 *
00008 * =================================================================
00009 * DREAM License v2.0
00010 * 
00011 * DREAM - Distributed Real-time Embedded Analysis Method
00012 * http://dre.sourceforge.net.
00013 * Copyright (c) 2005-2007 Gabor Madl, All Rights Reserved.
00014 * 
00015 * This file is part of DREAM.
00016 * 
00017 * DREAM is free software; you can redistribute it and/or modify it
00018 * under the terms of the GNU General Public License version 2 as
00019 * published by the Free Software Foundation. No future versions of
00020 * the GPL license may be automatically applied to DREAM. It is in
00021 * the sole discretion of the copyright holder to determine whether
00022 * DREAM may be released under a different license or terms. There
00023 * are no restrictions on the use of DREAM for any purpose.
00024 * 
00025 * DREAM is distributed in the hope that it will be useful,
00026 * but WITHOUT ANY WARRANTY; without even the implied warranty of
00027 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00028 * GNU General Public License for more details.
00029 * 
00030 * You should have received a copy of the GNU General Public License
00031 * along with this program; if not, write to the Free Software
00032 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
00033 * MA 02110-1301, USA.
00034 * 
00035 * By submitting comments, suggestions, code, code snippets,
00036 * techniques (including that of usage), and algorithms, submitters
00037 * acknowledge that they have the right to do so, that any such
00038 * submissions are given freely and unreservedly, and that they
00039 * waive any claims to copyright or ownership. In addition,
00040 * submitters acknowledge that any such submission might become
00041 * part of the copyright maintained on the overall body of code,
00042 * which comprises DREAM. By making a submission, submitter agrees
00043 * to these terms. Furthermore, submitters acknowledge that the
00044 * incorporation or modification of such submissions is entirely
00045 * at the discretion of the moderators of the DREAM project.
00046 * 
00047 * DREAM links to the Libxml2 third party library. Please see 
00048 * COPYING-libxml for the copyright information of Libxml2.
00049 * =================================================================
00050 */
00051 
00052 #include "ModelCheck.h"
00053 
00054 namespace DREAM
00055 {
00056 
00057 ModelCheck::ModelCheck (DREAM::System* system_ptr)
00058 : system_ptr_ (system_ptr), endtoend_ (0.0)
00059 {
00060 }
00061 
00062 bool ModelCheck::branching_point (DREAM::NODE_AVLTREE* node_avltree, bool verbose)
00063 {
00064         DREAM::Context contextvalue;
00065 
00066 #ifdef DREAM_RACE_CONDITION
00067         if (Option::race_condition_)
00068         {
00069                 // Iterate through priority inversion list
00070                 if (system_ptr_->inversion ())
00071                         return true;
00072                 else
00073                         system_ptr_->destroy_priority_list ();
00074         }
00075 #endif
00076         DREAM::NODE_AVLTREE::iterator node_iter;
00077 
00078         for (node_iter = node_avltree->begin (); node_iter != node_avltree->end (); node_iter++)
00079         {
00080                 contextvalue = node_iter->second->context ();
00081 
00082 #ifdef DREAM_BRANCHING
00083                 if ((contextvalue == branchingpoint) && (Option::branching_))
00084                 {
00085                         node_iter->second->branching_point ();
00086                         return true;
00087                 }
00088                 else 
00089 #endif
00090                 if (contextvalue == worstcase)
00091                 {
00092                         node_iter->second->context (bestcase);
00093                         return true;
00094                 }
00095                 else
00096                 {
00097                         node_iter->second->context (worstcase);
00098                 }
00099         }
00100 
00101         return false;
00102 }
00103 
00104 bool ModelCheck::random_testing (DREAM::System* system_ptr, bool verbose)
00105 #ifdef DREAM_ENHANCED_EXCEPTION_CHECKING
00106         throw (DREAM::Exception)
00107 #endif
00108 {
00109         endtoend_ = 0.0;
00110         double temp;
00111         time_t start_time, start_block, end_block;
00112         time (&start_time);
00113         time (&start_block);
00114 
00115         if (verbose)
00116         {
00117                 std::cout << std::endl << "Testing " << Option::number_of_repetitions_ << " random cases." << std::endl;
00118                 if (19999 < Option::number_of_repetitions_)
00119                 {
00120                         std::cout << "Reporting partial results after 10^4 simulations." << std::endl << std::endl;
00121                         std::cout << "============================================================================" << std::endl;
00122                         std::cout << " 10^4 sim time\t| Avg trace sim time\t| End-to-end performance" << std::endl;
00123                         std::cout << "----------------------------------------------------------------------------" << std::endl;
00124                 }
00125         }
00126 
00127         DREAM::Solution solution (system_ptr);
00128 
00129         uint i, j = 0;
00130         for (i = 0; i < Option::number_of_repetitions_; i++)
00131         {
00132                 if (solution.fitness (Option::verbose1_, false, &temp) != 0.0)
00133                 {
00134                         if (endtoend_ < temp) endtoend_ = temp;
00135 
00136                         if (verbose)
00137                         {
00138                                 // Repeat simulation to show execution trace that has missed the deadline
00139                                 DREAM::NODE_MAP task_map;
00140                                 DREAM::NODE_MAP channel_map;
00141                                 DREAM::NODE_MAP timer_map;
00142 
00143                                 system_ptr->visitor_map (&task_map, &channel_map, &timer_map);
00144 
00145                                 for (DREAM::NODE_MAP::const_iterator node_map_iter = task_map.begin (); node_map_iter != task_map.end (); node_map_iter++)
00146                                         node_map_iter->second->context (repeat);
00147 
00148                                 for (DREAM::NODE_MAP::const_iterator node_map_iter = channel_map.begin (); node_map_iter != channel_map.end (); node_map_iter++)
00149                                         node_map_iter->second->context (repeat);
00150 
00151                                 for (DREAM::NODE_MAP::const_iterator node_map_iter = timer_map.begin (); node_map_iter != timer_map.end (); node_map_iter++)
00152                                         node_map_iter->second->context (repeat);
00153 
00154                                 system_ptr->reset ();
00155                                 system_ptr->simulate (true, false, &temp);
00156 
00157                                 time_t end_time;
00158                                 time (&end_time);
00159                                 uint perf = end_time - start_time;
00160 //                              std::cout << "System is unschedulable." << std::endl;
00161                                 std::cout << "Analysis time: " << perf << " seconds." << std::endl;
00162                                 std::cout << "Worst case end-to-end performance encountered: " << endtoend_ << std::endl;
00163                         }
00164 
00165                         return false;
00166                 }
00167                 if (endtoend_ < temp) endtoend_ = temp;
00168 
00169                 if (++j == 10000)
00170                 {
00171                         time_t end_block;
00172                         time (&end_block);
00173                         uint block = end_block - start_block;
00174                         std::cout << " " << block << " secs\t\t| " << std::fixed << std::setprecision (1) << (double)block/10 << " ms\t\t| " << endtoend_ << std::endl;
00175                         j = 0;
00176                         time (&start_block);
00177                 }
00178         }
00179 
00180         if (verbose)
00181         {
00182                 time_t end_time;
00183                 time (&end_time);
00184                 uint perf = end_time - start_time;
00185                 std::cout << "Analysis complete. No errors found." << std::endl;
00186                 std::cout << "Analysis time: " << perf << " seconds." << std::endl;
00187                 std::cout << "Worst case end-to-end performance: " << endtoend_ << std::endl;
00188         }
00189 
00190         return true;
00191 }
00192         
00193 bool ModelCheck::trace_based_model_check (DREAM::System* system_ptr, bool verbose)
00194         throw (DREAM::Exception)
00195 {
00196         endtoend_ = 0.0;
00197         double temp;
00198         time_t start_time, start_block, end_block;
00199         time (&start_time);
00200         time (&start_block);
00201 
00202         if (verbose)
00203                 std::cout << std::endl << "Model checking DREAM model." << std::endl << std::endl;
00204 
00205         DREAM::Solution solution (system_ptr);
00206 
00207         if (!solution.deterministic ())
00208                 throw DREAM::Exception ("Model checking is supported on deterministic sub-priorities only (same sub-priorities are disallowed). Try to optimize the scheduling first...");
00209 
00210         DREAM::SCHEDULER_MAP::const_iterator scheduler_iter;
00211 
00212         for (scheduler_iter = system_ptr->scheduler_map ()->begin (); scheduler_iter != system_ptr->scheduler_map ()->end (); scheduler_iter++)
00213         {
00214                 if (scheduler_iter->second->threadpoolsize () > 1)
00215                         throw DREAM::Exception ("ModelCheck::trace_based_model_check () currently can ony be used to check non-preemptive systems with no thread pools.");
00216         }
00217 
00218         DREAM::NODE_AVLTREE mc_queue;
00219         DREAM::NODE_MAP::const_iterator node_map_iter;
00220         DREAM::NODE_AVLTREE::const_iterator node_iter;
00221         DREAM::NODE_MAP::const_iterator node_iter2;
00222         
00223         DREAM::NODE_MAP task_map;
00224         DREAM::NODE_MAP channel_map;
00225         DREAM::NODE_MAP timer_map;
00226 
00227         system_ptr->visitor_map (&task_map, &channel_map, &timer_map);
00228 
00229         for (node_map_iter = task_map.begin (); node_map_iter != task_map.end (); node_map_iter++)
00230         {
00231                 // If Task with bcet found put it in a queue
00232                 if (node_map_iter->second->bcet () != node_map_iter->second->wcet ())
00233                 {
00234                         mc_queue.insert (node_map_iter->first, node_map_iter->second);
00235                 }
00236         }
00237 
00238         for (node_map_iter = channel_map.begin (); node_map_iter != channel_map.end (); node_map_iter++)
00239         {
00240                 // If Channel with bcet found put it in a queue
00241                 if (node_map_iter->second->bcet () != node_map_iter->second->wcet ())
00242                 {
00243                         mc_queue.insert (node_map_iter->first, node_map_iter->second);
00244                 }
00245         }
00246 
00247         bool drifting = false;
00248         for (node_map_iter = timer_map.begin (); node_map_iter != timer_map.end (); node_map_iter++)
00249         {
00250                 // If Timer with bcet found put it in a queue
00251                 if (node_map_iter->second->bcet () != node_map_iter->second->wcet ())
00252                 {
00253                         mc_queue.insert (node_map_iter->first, node_map_iter->second);
00254                         drifting = true;
00255                 }
00256         }
00257 
00258         if (verbose)
00259         {
00260                 if (drifting)
00261                         std::cout << std::endl << std::endl << "WARNING: Arbitrarily drifting clocks found. This model is too permissive and probably cannot be verified using finite simulation time." << std::endl << std::endl;
00262         }
00263 
00264         // Initialize wcet times
00265         for (node_iter = mc_queue.begin (); node_iter != mc_queue.end (); node_iter++)
00266         {
00267                 node_iter->second->context (worstcase);
00268                 node_iter->second->remote_dep (false);
00269         }
00270 
00271         // Check for remote dependents
00272         const DREAM::NODE_MAP* node_map;
00273         uint remote_deps = 0;
00274 
00275         for (node_iter = mc_queue.begin (); node_iter != mc_queue.end (); node_iter++)
00276         {
00277                 node_map = node_iter->second->get_dependent_map ();
00278 
00279                 for (node_iter2 = node_map->begin (); node_iter2 != node_map->end (); node_iter2++)
00280                 {
00281                         // Check for immediate dependents
00282                         if (node_iter->second->scheduler () != node_iter2->second->scheduler ())
00283                         {
00284                                 node_iter->second->remote_dep (true);
00285                         }
00286                 }
00287         }
00288 
00289         // Count remote dependencies
00290         for (node_iter = mc_queue.begin (); node_iter != mc_queue.end (); node_iter++)
00291         {
00292                 if (node_iter->second->remote_dep ())
00293                         remote_deps++;
00294         }
00295 
00296         if (verbose)
00297         {
00298                 std::cout << "Number of nodes with remote dependencies: " << remote_deps << " out of " << mc_queue.size () << "." << std::endl;
00299                 std::cout << std::endl << "Verification in progress..." << std::endl;
00300 
00301                 std::cout << "Reporting partial results after 10^4 simulations." << std::endl << std::endl;
00302                 std::cout << "============================================================================" << std::endl;
00303                 std::cout << " 10^4 sim time\t| Avg trace sim time\t| End-to-end performance" << std::endl;
00304                 std::cout << "----------------------------------------------------------------------------" << std::endl;
00305         }
00306 
00307         uint i = 0;
00308 
00309         // Check the state space exhaustively
00310         do
00311         {
00312                 // Solution has direct pointers to the Tasks in the core...
00313                 if (solution.fitness (Option::verbose1_, true, &temp) > 0.0)
00314                 {
00315                         if (endtoend_ < temp) endtoend_ = temp;
00316                         if (verbose)
00317                         {
00318                                 std::cout << std::endl << std::endl << "System is unschedulable. Execution trace:" << std::endl;
00319                                 system_ptr->reset ();
00320                                 bool verbose = Option::verbose1_;
00321                                 Option::verbose1_ = true;
00322                                 system_ptr->simulate (Option::verbose1_, true);
00323                                 Option::verbose1_ = verbose;
00324 
00325                                 time_t end_time;
00326                                 time (&end_time);
00327                                 uint perf = end_time - start_time;
00328                                 std::cout << std::endl << "Analysis complete. System is unschedulable." << std::endl;
00329                                 std::cout << "Analysis time: " << perf << " seconds." << std::endl;
00330                                 std::cout << "Worst case end-to-end performance encountered: " << endtoend_ << std::endl;
00331                         }
00332 
00333                         return false;
00334                 }
00335 
00336                 if (endtoend_ < temp) endtoend_ = temp;
00337 
00338                 if (++i == 10000)
00339                 {
00340                         time_t end_block;
00341                         time (&end_block);
00342                         uint block = end_block - start_block;
00343                         std::cout << " " << block << " secs\t\t| " << std::fixed << std::setprecision (1) << (double)block/10 << " ms\t\t| " << endtoend_ << std::endl;
00344                         i = 0;
00345                         time (&start_block);
00346                 }
00347 
00348                 system_ptr->reset ();
00349         }
00350         while (branching_point (&mc_queue, verbose));
00351 
00352         if (verbose)
00353         {
00354                 time_t end_time;
00355                 time (&end_time);
00356                 uint perf = end_time - start_time;
00357                 std::cout << "Analysis complete. No errors found." << std::endl;
00358                 std::cout << "Analysis time: " << perf << " seconds." << std::endl;
00359                 std::cout << "Worst case end-to-end performance: " << endtoend_ << std::endl;
00360         }
00361         return true;
00362 }
00363         
00364 };
00365 

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