rc_control.cpp

Go to the documentation of this file.
00001 // vim:set et sts=4 ts=4 tw=75 sw=4 ai ci cin cino=g0,t0:
00002 /*
00003  * Copyright (C) 2007, Technical Computer Science Group,
00004  *                     University of Bonn
00005  *
00006  * This file is part of the ReChannel library.
00007  *
00008  * The ReChannel library is free software; you can redistribute it and/or
00009  * modify it under the terms of the GNU General Public License as
00010  * published by the Free Software Foundation; either version 2 of the
00011  * License, or (at your option) any later version.
00012  *
00013  * This library is distributed in the hope that it will be
00014  * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00016  * General Public License for more details.
00017  *
00018  * You should have received a copy of the GNU General Public License
00019  * along with this library; see the file COPYING. If not, write to the
00020  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
00021  * Boston, MA 02110-1301, USA.
00022  *
00023  * Authors: Andreas Raabe and Armin Felke. Implementation by Armin Felke.
00024  *          {raabe, felke}@cs.uni-bonn.de
00025  */
00037 #include "rc_control.h"
00038 
00039 namespace ReChannel {
00040 
00041 bool rc_control::has_control(
00042     const rc_reconfigurable_set& reconf_set) const
00043 {
00044     rc_reconfigurable_set::const_iterator it;
00045     for(it = reconf_set.begin(); it != reconf_set.end(); ++it) {
00046         rc_reconfigurable& reconf = *(*it);
00047         if (p_reconfigurable_set.find(reconf)
00048         == p_reconfigurable_set.end()) {
00049             return false;
00050         }
00051     }
00052     return true;
00053 }
00054 
00055 void rc_control::add(const rc_reconfigurable_set& reconf_set)
00056 {
00057     rc_reconfigurable_set::const_iterator it;
00058     for(it = reconf_set.begin(); it != reconf_set.end(); ++it) {
00059         rc_reconfigurable& reconf = *(*it);
00060         rc_control* owner = reconf.get_control();
00061         if (owner != NULL && owner != this) {
00062             RC_REPORT_ERROR(RC_ID_CONTROL_CONFLICT_,
00063                 "dynamic object '" << reconf.rc_get_name()
00064                 << "' still controlled by control '"
00065                 << owner->name() << "' (in control '"
00066                 << this->name() << "'");
00067         }
00068         // let reconf be controlled by this object
00069         reconf.set_control(this);
00070         // calculate and set the delays for the reconfiguration actions
00071         for (int i=0; i < rc_reconfigurable::ACTION_COUNT; i++) {
00072             typedef rc_reconfigurable::action_type action_type;
00073             reconf.rc_set_delay(
00074                 (action_type)i, takes_time(reconf, (action_type)i));
00075         }
00076         p_reconfigurable_set.insert(reconf);
00077         sc_object* obj = reconf.rc_get_object();
00078         if (obj != NULL) {
00079             p_obj_reconf_map.insert(
00080                 obj_reconf_map::value_type(obj, &reconf));
00081         }
00082     }
00083 }
00084 
00085 void rc_control::remove(const rc_reconfigurable_set& reconf_set)
00086 {
00087     lock(reconf_set);
00088     try {
00089         unload(reconf_set);
00090         rc_reconfigurable_set::const_iterator it;
00091         for(it = reconf_set.begin(); it != reconf_set.end(); ++it) {
00092             rc_reconfigurable& reconf = *(*it);
00093             reconf.set_control(NULL);
00094             p_reconfigurable_set.erase(reconf);
00095             sc_object* obj = reconf.rc_get_object();
00096             if (obj != NULL) {
00097                 p_obj_reconf_map.erase(obj);
00098             }
00099         }
00100     } catch(...) {
00101         unlock(reconf_set);
00102         throw;
00103     }
00104     // release ALL locks hold by this process
00105     rc_reconfigurable_set::const_iterator it;
00106     for(it = reconf_set.begin(); it != reconf_set.end(); ++it) {
00107         rc_reconfigurable& reconf = *(*it);
00108         // calls unlock() until no lock is hold anymore
00109         while(reconf.unlock());
00110     }
00111     // the modules are "free" now
00112 }
00113 
00114 void rc_control::load(const rc_reconfigurable_set& reconf_set)
00115 {
00116     _rc_do_action(
00117         reconf_set, rc_reconfigurable::INACTIVE,
00118         rc_reconfigurable::UNLOADED);
00119 }
00120 
00121 void rc_control::unload(const rc_reconfigurable_set& reconf_set)
00122 {
00123     _rc_do_action(reconf_set, rc_reconfigurable::UNLOADED);
00124 }
00125 
00126 void rc_control::activate(const rc_reconfigurable_set& reconf_set)
00127 {
00128     _rc_do_action(reconf_set, rc_reconfigurable::ACTIVE);
00129 }
00130 
00131 void rc_control::deactivate(const rc_reconfigurable_set& reconf_set)
00132 {
00133     _rc_do_action(
00134         reconf_set, rc_reconfigurable::INACTIVE,
00135         rc_reconfigurable::ACTIVE);
00136 }
00137 
00138 void rc_control::move(
00139     const rc_reconfigurable_set& reconf_set,
00140     rc_switch_connector_base& target)
00141 {
00142     lock(reconf_set);
00143     try {
00144         unload(reconf_set);
00145         rc_reconfigurable_set::const_iterator it;
00146         for(it = reconf_set.begin(); it != reconf_set.end(); ++it) {
00147             rc_reconfigurable& reconf = *(*it);
00148             reconf.move(target);
00149         }
00150     } catch(...) {
00151         unlock(reconf_set);
00152         throw;
00153     }
00154     unlock(reconf_set);
00155 }
00156 
00157 void rc_control::lock(const rc_reconfigurable_set& reconf_set)
00158 {
00159     rc_reconfigurable_set::const_iterator it;
00160     for(it = reconf_set.begin(); it != reconf_set.end(); ++it) {
00161         rc_reconfigurable& reconf = *(*it);
00162         if (reconf.get_control() != this) {
00163             // unlock all previously locked reconfigurables
00164             _rc_unlock(reconf_set.begin(), it);
00165             RC_REPORT_ERROR(RC_ID_CONTROL_CONFLICT_,
00166                 "no control over dynamic object '"
00167                 << reconf.rc_get_name() << "' (in control '"
00168                 << this->name() << "'");
00169         }
00170         reconf.lock();
00171     }
00172 }
00173 
00174 bool rc_control::trylock(const rc_reconfigurable_set& reconf_set)
00175 {
00176     rc_reconfigurable_set::const_iterator it;
00177     for(it = reconf_set.begin(); it != reconf_set.end(); ++it) {
00178         rc_reconfigurable& reconf = *(*it);
00179         if (reconf.get_control() != this) {
00180             // unlock all previously locked reconfigurables
00181             _rc_unlock(reconf_set.begin(), it);
00182             RC_REPORT_ERROR(RC_ID_CONTROL_CONFLICT_,
00183                 "no control over dynamic object '"
00184                 << reconf.rc_get_name() << "' (in control '"
00185                 << this->name() << "'");
00186         }
00187         if (!reconf.trylock()) {
00188             // unlock all previously locked reconfigurables
00189             _rc_unlock(reconf_set.begin(), it);
00190             return false;
00191         }
00192     }
00193     return true;
00194 }
00195 
00196 void rc_control::unlock(const rc_reconfigurable_set& reconf_set)
00197 {
00198     _rc_unlock(reconf_set.begin(), reconf_set.end());
00199 }
00200 
00201 bool rc_control::is_locked(const rc_reconfigurable_set& reconf_set) const
00202 {
00203     rc_reconfigurable_set::const_iterator it;
00204     for(it = reconf_set.begin(); it != reconf_set.end(); ++it) {
00205         rc_reconfigurable& reconf = *(*it);
00206         if (!reconf.is_locked()) {
00207             return false;
00208         }
00209     }
00210     return true;
00211 }
00212 
00213 sc_time rc_control::takes_time(
00214     const rc_reconfigurable& reconf,
00215     rc_reconfigurable::action_type action) const
00216 {
00217     return reconf.rc_get_default_delay(action);
00218 }
00219 
00220 void rc_control::update_delays(rc_reconfigurable::action_type action)
00221 {
00222     // iterate through all controlled rc_reconfigurables
00223     rc_reconfigurable_set::const_iterator it;
00224     for(it = p_reconfigurable_set.begin();
00225         it != p_reconfigurable_set.end();
00226         ++it)
00227     {
00228         rc_reconfigurable& reconf = *(*it);
00229         // update the delay of the given reconfiguration action
00230         reconf.rc_set_delay(action, takes_time(reconf, action));
00231     }
00232 }
00233 
00234 void rc_control::get_controlled_set(
00235     rc_reconfigurable_set& copy_dest) const
00236 {
00237     copy_dest = p_reconfigurable_set; // copy the internal set
00238 }
00239 
00240 void rc_control::start_of_simulation()
00241 {
00242     static bool s_start_of_simulation_called = false;
00243 
00244     // call start_of_simulation() ONCE on ALL existing rc_reconfigurables
00245     if (!s_start_of_simulation_called) {
00246         std::vector<rc_reconfigurable*> all_reconfigurables;
00247         rc_reconfigurable::get_all_reconfigurables(all_reconfigurables);
00248         std::vector<rc_reconfigurable*>::const_iterator it;
00249         for(it = all_reconfigurables.begin();
00250            it != all_reconfigurables.end();
00251            ++it)
00252         {
00253             rc_reconfigurable& reconf = *(*it);
00254             reconf.start_of_simulation();
00255         }
00256         s_start_of_simulation_called = true;
00257     }
00258 }
00259 
00260 void rc_control::_rc_unlock(
00261     rc_reconfigurable_set::const_iterator start_,
00262     rc_reconfigurable_set::const_iterator end_) const
00263 {
00264     rc_reconfigurable_set::const_iterator it;
00265     for(it = start_; it != end_; ++it) {
00266         rc_reconfigurable& reconf = *(*it);
00267         reconf.unlock();
00268     }
00269 }
00270 
00271 void rc_control::_rc_do_action(
00272     const rc_reconfigurable_set& reconf_set,
00273     rc_reconfigurable::state_type new_state)
00274 {
00275     if (reconf_set.size() == 0) {
00276         return;
00277     }
00278     lock(reconf_set);
00279     try {
00280         _rc_reconfigure(reconf_set, new_state);
00281     } catch(...) {
00282         unlock(reconf_set);
00283         throw;
00284     }
00285     unlock(reconf_set);
00286 }
00287 
00288 void rc_control::_rc_do_action(
00289     const rc_reconfigurable_set& reconf_set,
00290     rc_reconfigurable::state_type new_state,
00291     rc_reconfigurable::state_type only_change_state)
00292 {
00293     if (reconf_set.size() == 0) {
00294         return;
00295     }
00296     lock(reconf_set);
00297     try {
00298         rc_reconfigurable_set dyn_objects_to_change;
00299         rc_reconfigurable_set::const_iterator it;
00300         for(it = reconf_set.begin(); it != reconf_set.end(); ++it) {
00301             rc_reconfigurable& reconf = *(*it);
00302             if (reconf.rc_get_state() == only_change_state) {
00303                 dyn_objects_to_change.insert(reconf);
00304             }
00305         }
00306         _rc_reconfigure(dyn_objects_to_change, new_state);
00307     } catch(...) {
00308         unlock(reconf_set);
00309         throw;
00310     }
00311     unlock(reconf_set);
00312 }
00313 
00314 void rc_control::_rc_reconfigure(
00315     const rc_reconfigurable_set& reconf_set,
00316     rc_reconfigurable::state_type new_state)
00317 {
00318     if (sc_is_running()) {
00319         if (reconf_set.size() == 0) {
00320             return;
00321         } else if (reconf_set.size() == 1) {
00322             rc_reconfigurable& reconf = *(*(reconf_set.begin()));
00323             if (reconf.rc_get_state() != new_state) {
00324                 reconf.reconfigure(new_state);
00325             }
00326         } else {
00327             typedef std::vector<sc_process_handle> proc_vector_type;
00328             proc_vector_type procs;
00329             rc_reconfigurable_set::const_iterator it;
00330             for(it = reconf_set.begin(); it != reconf_set.end(); ++it) {
00331                 rc_reconfigurable& reconf = *(*it);
00332                 if (reconf.rc_get_state() != new_state) {
00333                     sc_process_handle proc =
00334                         sc_spawn(
00335                             sc_bind(
00336                                 &rc_reconfigurable::reconfigure,
00337                                 &reconf, new_state));
00338                     reconf.share_lock(proc);
00339                     procs.push_back(proc);
00340                 }
00341             }
00342             if (procs.size() > 0) {
00343                 if (procs.size() == 1) {
00344                     ::sc_core::wait((*procs.begin()).terminated_event());
00345                 } else { // procs.size() >= 2
00346                     sc_event_and_list& event_and_list =
00347                         (*procs.begin()).terminated_event()
00348                         & (*(++procs.begin())).terminated_event();
00349                     proc_vector_type::iterator it;
00350                     for(it = procs.begin() + 3; it != procs.end(); ++it) {
00351                         event_and_list & (*it).terminated_event();
00352                     }
00353                     ::sc_core::wait(event_and_list);
00354                 }
00355             }
00356         }
00357     } else {
00358         rc_reconfigurable_set::const_iterator it;
00359         for(it = reconf_set.begin(); it != reconf_set.end(); ++it) {
00360             rc_reconfigurable& reconf = *(*it);
00361             // (note: reconfigure() may also be invoked during elaboration)
00362             reconf.reconfigure(new_state);
00363         }
00364     }
00365 }
00366 
00367 } // namespace ReChannel
00368 
00369 //
00370 // $Id: rc_control.cpp,v 1.19 2007/12/20 20:29:16 felke Exp $
00371 // $Source: /var/cvs/projekte/ReChannel-v2/src/ReChannel/core/rc_control.cpp,v $
00372 //

Generated on Tue Jan 1 23:13:31 2008 for ReChannel by  doxygen 1.5.3