rc_reconfigurable.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_reconfigurable.h"
00038 #include "rc_control.h"
00039 
00040 namespace ReChannel {
00041 
00042 namespace internals {
00043 namespace reconfigurable {
00044 
00045 rc_reconfigurable* begin_construction::s_current = NULL;
00046 
00047 begin_construction::begin_construction(rc_reconfigurable& reconf)
00048     : p_previous(s_current), p_finished(false)
00049 {
00050     s_current = &reconf;
00051 }
00052 
00053 void begin_construction::finish()
00054 {
00055     if (!p_finished) {
00056         s_current = p_previous;
00057         p_finished = true;
00058     }
00059 }
00060 
00061 void begin_construction::finish(sc_object& reconf)
00062 {
00063     if (!p_finished) {
00064         if (s_current != NULL) {
00065             s_current->_rc_set_sc_object(reconf);
00066         }
00067         s_current = p_previous;
00068         p_finished = true;
00069     }
00070 }
00071 
00072 } // namespace reconfigurable
00073 } // namespace internals
00074 
00075 std::vector<rc_reconfigurable*> rc_reconfigurable::s_reconfigurables;
00076 
00077 rc_reconfigurable::rc_reconfigurable(sc_object* this_)
00078     : p_sc_object(this_), p_is_no_sc_object(false),
00079       p_state(UNLOADED), p_next_state(UNLOADED),
00080       p_transaction_count(0),
00081       p_switch_commobj_index(p_switch_commobj_map.get<0>()),
00082       p_commobj_switch_index(p_switch_commobj_map.get<1>()),
00083       p_control(NULL), p_curr_switch_conn(NULL)
00084 {
00085     p_self_set.insert(*this);
00086 
00087     p_delta_sync.set_callback(
00088         boost::bind(
00089             &rc_reconfigurable::_rc_delta_sync_state_change, this, _1));
00090 
00091     // add this instance to the global registry vector
00092     s_reconfigurables.push_back(this);
00093 }
00094 
00095 rc_reconfigurable::~rc_reconfigurable()
00096 { }
00097 
00098 std::string rc_reconfigurable::rc_get_name() const
00099 {
00100     const sc_object* const obj = this->rc_get_object();
00101     if (obj != NULL) {
00102         return obj->name();
00103     } else {
00104         return "(unknown)";
00105     }
00106 }
00107 
00108 void rc_reconfigurable::bind(rc_switch_connector_base& switch_connector)
00109 {
00110     for (portmap_vector::iterator it = p_portmap_vector.begin();
00111         it != p_portmap_vector.end();
00112         ++it)
00113     {
00114         rc_portmap_base& portmap = *(*it);
00115         if (switch_connector.is_compatible(portmap)) {
00116             switch_connector.bind_dynamic(portmap);
00117             p_curr_switch_conn = &switch_connector;
00118             return;
00119         }
00120     }
00121     RC_REPORT_ERROR(RC_ID_SWITCH_CONNECTOR_BINDING_ERROR_,
00122         "incompatible switch connector '" << switch_connector.name() << "'"
00123         " (in reconfigurable '" << this->rc_get_name() << "')");
00124 }
00125 
00126 void rc_reconfigurable::rc_register_switch(
00127     rc_switch& switch_obj, const rc_object_handle& bound_obj)
00128 {
00129     if (rc_is_registered(switch_obj)) {
00130         RC_REPORT_ERROR(RC_ID_SWITCH_BINDING_ERROR_,
00131             "switch '" << switch_obj.get_switch_name()
00132             << "' already registered at this reconfigurable object"
00133                " (in reconfigurable '" << this->rc_get_name() << "')");
00134     }
00135     sc_interface* dyn_if = bound_obj.get_interface();
00136     sc_interface* dyn_if_switch =
00137         switch_obj.get_registered_interface(*this);
00138     if (dyn_if == NULL) {
00139         RC_REPORT_ERROR(RC_ID_SWITCH_BINDING_ERROR_,
00140             "registration of switch '" << switch_obj.get_switch_name()
00141             << "' failed: no interface given"
00142             << " (in reconfigurable '" << this->rc_get_name() << "')");
00143     } else if (dyn_if_switch == NULL) {
00144         assert(dyn_if != NULL);
00145         switch_obj.register_reconfigurable(*this, *dyn_if);
00146     } else if (dyn_if_switch != dyn_if) {
00147         RC_REPORT_ERROR(RC_ID_SWITCH_BINDING_ERROR_,
00148             "registration of switch '" << switch_obj.get_switch_name()
00149             << "' failed: interface mismatch"
00150             << " (in reconfigurable '" << this->rc_get_name() << "')");
00151     }
00152     p_switch_commobj_index.insert(
00153         switch_commobj_pair(&switch_obj, bound_obj));
00154 }
00155 
00156 bool rc_reconfigurable::rc_is_registered(rc_switch& switch_obj) const
00157 {
00158     return (p_switch_commobj_index.find(&switch_obj)
00159         != p_switch_commobj_index.end());
00160 }
00161 
00162 void rc_reconfigurable::rc_register_resettable(rc_resettable& resettable)
00163 {
00164     p_resettable_set.insert(&resettable);
00165 }
00166 
00167 bool rc_reconfigurable::rc_is_registered(rc_resettable& resettable) const
00168 {
00169     return (p_resettable_set.find(&resettable) != p_resettable_set.end());
00170 }
00171 
00172 void rc_reconfigurable::rc_possible_deactivation()
00173 {
00174     // check whether deactivation of this reconfigurable is requested
00175     //    and the transaction count equals zero
00176     if ((p_transaction_count == 0 && rc_is_deactivation_requested())
00177         || rc_get_state() != ACTIVE) {
00178         const rc_process_handle hproc = rc_get_current_process_handle();
00179         // THREADs can be reset or suspended until reactivation
00180         if (hproc.proc_kind() == SC_THREAD_PROC_) {
00181             // wait for deactivation
00182             rc_wait(p_pctrl.get_deactivation_event());
00183             // (reconfigurable processes won't reach this line)
00184             if (!p_pctrl.is_active()) { // in case of non-resettable procs
00185                 // wait for reactivation
00186                 rc_wait(p_pctrl.get_activation_event());
00187             }
00188         }
00189     }
00190 }
00191 
00192 void rc_reconfigurable::rc_possible_deactivation_delta()
00193 {
00194     // check whether deactivation of this reconfigurable is requested
00195     if (rc_is_deactivation_requested() || rc_get_state() != ACTIVE) {
00196         const rc_process_handle hproc = rc_get_current_process_handle();
00197         // THREADs can be reset or suspended until reactivation
00198         if (hproc.proc_kind() == SC_THREAD_PROC_) {
00199             // wait one delta cycle (to give the deactivation a chance)
00200             rc_wait(SC_ZERO_TIME);
00201         }
00202     }
00203 }
00204 
00205 void rc_reconfigurable::rc_set_delay(action_type a, sc_time t)
00206 {
00207     p_action_delays[a] = t;
00208     if (p_control == NULL) {
00209         p_action_default_delays[a] = t;
00210     }
00211 }
00212 
00213 void rc_reconfigurable::rc_add_filter(
00214     const rc_object_handle& commobj_, rc_interface_filter& filter_)
00215 {
00216     // check if filter is added for the first time
00217     if (this->rc_has_filter(filter_)) {
00218         RC_REPORT_ERROR(RC_ID_DUPLICATE_ENTRY_,
00219             "filter already added"
00220             " (in reconfigurable '" << this->rc_get_name() << "')");
00221     }
00222 
00223     // insert filter
00224     p_filter_set.insert(&filter_);
00225     p_commobj_filters_map[commobj_].push_back(&filter_);
00226 }
00227 
00228 int rc_reconfigurable::rc_get_filter_count(
00229     const rc_object_handle& commobj_) const
00230 {
00231     commobj_filters_map::const_iterator it =
00232         p_commobj_filters_map.find(commobj_);
00233     if (it != p_commobj_filters_map.end()) {
00234         return it->second.size();
00235     } else {
00236         return 0;
00237     }
00238 }
00239 
00240 rc_reconfigurable::filter_chain
00241 rc_reconfigurable::rc_get_filter_chain(
00242     const rc_object_handle& commobj_) const
00243 {
00244     commobj_filters_map::const_iterator it =
00245         p_commobj_filters_map.find(commobj_);
00246     return (it != p_commobj_filters_map.end()
00247         ? it->second : filter_chain());
00248 }
00249 
00250 bool rc_reconfigurable::rc_has_filter(rc_interface_filter& filter_) const
00251 {
00252     return (p_filter_set.find(&filter_) != p_filter_set.end());
00253 }
00254 
00255 void rc_reconfigurable::rc_refresh_notify(
00256     const rc_object_handle& commobj_)
00257 {
00258     commobj_switch_range range =
00259         p_commobj_switch_index.equal_range(commobj_);
00260     for (commobj_switch_index::iterator it = range.first;
00261         it != range.second;
00262         ++it)
00263     {
00264         it->first->refresh_notify();
00265     }
00266 }
00267 
00268 void rc_reconfigurable::rc_refresh_notify_all()
00269 {
00270     for (switch_commobj_index::iterator it =
00271             p_switch_commobj_index.begin();
00272         it != p_switch_commobj_index.end();
00273         ++it)
00274     {
00275         it->first->refresh_notify();
00276     }
00277 }
00278 
00279 void rc_reconfigurable::start_of_simulation()
00280 {
00281     // initialise all registered resettables
00282     for (resettable_set::const_iterator it = p_resettable_set.begin();
00283         it != p_resettable_set.end();
00284         ++it)
00285     {
00286         (*it)->rc_on_init_resettable();
00287     }
00288 
00289     // initialise switch states
00290     switch(p_state) {
00291     case INACTIVE:
00292         change_switch_state(rc_switch::CLOSED);
00293         break;
00294     case ACTIVE:
00295         change_switch_state(rc_switch::OPEN);
00296         break;
00297     default:
00298         break;
00299     }
00300 
00301     // if active, activate the resettable processes
00302     if (rc_is_active()) {
00303         p_pctrl.activate();
00304     }
00305 }
00306 
00307 void rc_reconfigurable::reconfigure(state_type new_state)
00308 {
00309     const bool has_lock_share_ = has_lock_share();
00310     if (!has_lock_share_) {
00311         p_mutex.lock();
00312     }
00313     try {
00314         switch(p_state) {
00315         case UNLOADED:
00316             switch(new_state) {
00317             case INACTIVE:
00318                 _rc_load();
00319                 break;
00320             case ACTIVE:
00321                 _rc_load();
00322                 _rc_activate();
00323                 break;
00324             default:
00325                 break;
00326             }
00327             break;
00328         case INACTIVE:
00329             switch(new_state) {
00330             case UNLOADED:
00331                 _rc_unload();
00332                 break;
00333             case ACTIVE:
00334                 _rc_activate();
00335                 break;
00336             default:
00337                 break;
00338             }
00339             break;
00340         case ACTIVE:
00341             switch(new_state) {
00342             case UNLOADED:
00343                 _rc_deactivate();
00344                 _rc_unload();
00345                 break;
00346             case INACTIVE:
00347                 _rc_deactivate();
00348                 break;
00349             default:
00350                 break;
00351             }
00352             break;
00353         }
00354     } catch(...) {
00355         if (!has_lock_share_) {
00356             p_mutex.unlock();
00357         }
00358         throw;
00359     }
00360     if (!has_lock_share_) {
00361         p_mutex.unlock();
00362     }
00363 }
00364 
00365 void rc_reconfigurable::change_switch_state(
00366     rc_switch::state_type new_state)
00367 {
00368     for (switch_commobj_index::iterator it =
00369             p_switch_commobj_index.begin();
00370         it != p_switch_commobj_index.end();
00371         ++it)
00372     {
00373         rc_switch& switch_ = *(it->first);
00374 
00375         switch(new_state) {
00376         case rc_switch::OPEN:
00377         {
00378             // search for registered filters
00379             commobj_filters_map::const_iterator it2 =
00380                 p_commobj_filters_map.find(it->second);
00381 
00382             if (it2 != p_commobj_filters_map.end()) {
00383                 // open switch (and apply filters)
00384                 switch_.open(*this, it2->second);
00385             } else {
00386                 // open switch (without filters)
00387                 switch_.open(*this);
00388             }
00389             break;
00390         }
00391         case rc_switch::CLOSED:
00392             // close switch
00393             switch_.close();
00394             break;
00395         case rc_switch::UNDEF:
00396             // set switch to undefined state
00397             switch_.set_undefined();
00398             break;
00399         }
00400     }
00401 }
00402 
00403 void rc_reconfigurable::move(switch_conn_type& target)
00404 {
00405     assert(!(rc_is_loaded() || rc_is_state_changing()));
00406 
00407     rc_portmap_base* const portmap = _rc_get_compatible_portmap(target);
00408     if (portmap == NULL) {
00409         RC_REPORT_ERROR(RC_ID_SWITCH_CONNECTOR_INCOMPATIBLE_ERROR_,
00410             "switch connector '" << target.name() << "' is incompatible"
00411             << " (in reconfigurable '" << this->rc_get_name() << "')");
00412     }
00413     if (p_curr_switch_conn != &target) {
00414         p_curr_switch_conn = NULL;
00415         const int count = portmap->size();
00416         for (int i=0; i < count; i++) {
00417             // get the commobj at index i
00418             rc_object_handle commobj = portmap->get(i);
00419             // unregister commobj at its old switch
00420             commobj_switch_index::iterator it =
00421                 p_commobj_switch_index.find(commobj);
00422             if (it != p_commobj_switch_index.end()) {
00423                 rc_switch& switch_ = *it->first;
00424                 switch_.unregister_reconfigurable(*this);
00425                 p_commobj_switch_index.erase(it);
00426             }
00427             // register commobj with the new switch
00428             rc_switch& switch_ = target[i];
00429             sc_interface* const if_ = commobj.get_interface();
00430             assert(if_ != NULL);
00431             switch_.register_reconfigurable(*this, *if_);
00432             p_commobj_switch_index.insert(
00433                 commobj_switch_index::value_type(&switch_, commobj));
00434         }
00435         p_curr_switch_conn = &target;
00436     }
00437 }
00438 
00439 bool rc_reconfigurable::unlock()
00440 {
00441     const bool has_unlocked = p_mutex.unlock();
00442     if (has_unlocked && p_lock_share.valid()) {
00443         p_lock_share = sc_process_handle();
00444     }
00445     return has_unlocked;
00446 }
00447 
00448 bool rc_reconfigurable::share_lock(sc_process_handle proc)
00449 {
00450     if (p_mutex.has_lock()) {
00451         p_lock_share = proc;
00452         return true;
00453     } else {
00454         return false;
00455     }
00456 }
00457 
00458 bool rc_reconfigurable::reset_lock_share()
00459 {
00460     if (p_mutex.has_lock()) {
00461         p_lock_share = sc_process_handle();
00462         return true;
00463     } else {
00464         return false;
00465     }
00466 }
00467 
00468 bool rc_reconfigurable::lock_switches(bool report_error)
00469 {
00470     int unlocked_count = 0;
00471     // check whether all of the switches can be locked
00472     for (switch_commobj_index::iterator it =
00473             p_switch_commobj_index.begin();
00474         it != p_switch_commobj_index.end();
00475         ++it)
00476     {
00477         rc_switch& switch_ = *(it->first);
00478 
00479         if (!switch_.is_lock_owner(*this)) {
00480             if (!switch_.is_locked()) {
00481                 ++unlocked_count;
00482             } else {
00483                 // failure, lock hold by another module
00484                 if (report_error) {
00485                     RC_REPORT_ERROR(RC_ID_SWITCH_CONFLICT_,
00486                         "switch '" << switch_.get_switch_name()
00487                         << "' is already in use by another reconfigurable object"
00488                         << " (in reconfigurable '" << this->rc_get_name()
00489                         << "')");
00490                 } else {
00491                     return false;
00492                 }
00493             }
00494         }
00495     }
00496     // lock the switches (if necessary)
00497     if (unlocked_count > 0) {
00498         bool succ = false;
00499         for (switch_commobj_index::iterator it =
00500                 p_switch_commobj_index.begin();
00501             it != p_switch_commobj_index.end();
00502             ++it)
00503         {
00504             rc_switch& switch_ = *(it->first);
00505 
00506             // the previous check loop should guarantee a success
00507             succ = switch_.set_locked(*this, true);
00508             assert(succ == true);
00509         }
00510     }
00511     return true;
00512 }
00513 
00514 void rc_reconfigurable::unlock_switches()
00515 {
00516     // unlock the switches locked by this reconfigurable object
00517     for (switch_commobj_index::iterator it =
00518             p_switch_commobj_index.begin();
00519         it != p_switch_commobj_index.end();
00520         ++it)
00521     {
00522         rc_switch& switch_ = *(it->first);
00523         switch_.set_locked(*this, false);
00524     }
00525 }
00526 
00527 void rc_reconfigurable::reset_transaction_count()
00528 {
00529     p_transaction_count = 0;
00530     if (rc_is_deactivation_requested()) {
00531         p_delta_sync.request_update();
00532     }
00533 }
00534 
00535 void rc_reconfigurable::rc_add_portmap(rc_portmap_base& portmap)
00536 {
00537     sc_object* const this_obj = this->rc_get_object();
00538     if (dynamic_cast<sc_module*>(this_obj) == NULL) {
00539         RC_REPORT_ERROR(RC_ID_INVALID_USAGE_,
00540             "this reconfigurable is incapable of attaching a port map"
00541             " (in reconfigurable '" << this->rc_get_name() << "')");
00542     }
00543     const unsigned int count = portmap.size();
00544     for(unsigned int i=0; i < count; ++i) {
00545         sc_object& obj = portmap.get_object(i);
00546         if (obj.get_parent_object() != this_obj) {
00547             RC_REPORT_ERROR(RC_ID_PORTMAP_INCOMPATIBLE_ERROR_,
00548                 "port map contains an object from a different parent"
00549                 " (in reconfigurable '" << this->rc_get_name()
00550                 << "', at index: " << i <<")");
00551         }
00552     }
00553     const int found_index = this->_rc_is_compatible(portmap);
00554     if (found_index >= 0) {
00555         if (p_portmap_vector[found_index] != &portmap) {
00556             RC_REPORT_ERROR(RC_ID_DUPLICATE_ENTRY_,
00557             "port map with identical type already registered"
00558             " (in reconfigurable '" << this->rc_get_name() << "')");
00559         }
00560         return;
00561     }
00562 
00563     p_portmap_vector.push_back(&portmap);
00564 }
00565 
00566 void rc_reconfigurable::rc_clear_portmaps()
00567 {
00568     p_portmap_vector.clear();
00569 }
00570 
00571 rc_portmap_base& rc_reconfigurable::get_portmap(int index)
00572 {
00573     assert(index < 0 || index >= (int)p_portmap_vector.size());
00574     return *(p_portmap_vector[index]);
00575 }
00576 
00577 int rc_reconfigurable::_rc_is_compatible(
00578     const rc_portmap_base& portmap) const
00579 {
00580     const int count = (int)p_portmap_vector.size();
00581     for (int i=0; i < count; ++i) {
00582         if (portmap.is_compatible(*p_portmap_vector[i])) {
00583             return i;
00584         }
00585     }
00586     return -1;
00587 }
00588 
00589 rc_portmap_base* rc_reconfigurable::_rc_get_compatible_portmap(
00590         const rc_switch_connector_base& switch_conn) const
00591 {
00592     const int count = (int)p_portmap_vector.size();
00593     for (int i=0; i < count; ++i) {
00594         rc_portmap_base* const portmap = p_portmap_vector[i];
00595         if (switch_conn.is_compatible(*portmap)) {
00596             return portmap;
00597         }
00598     }
00599     return NULL;
00600 }
00601 
00602 void rc_reconfigurable::_rc_set_sc_object(sc_object& reconf)
00603 {
00604     if (p_sc_object == NULL) {
00605         p_sc_object = &reconf;
00606         p_is_no_sc_object = false;
00607     }
00608 }
00609 
00610 const sc_object* rc_reconfigurable::rc_get_object() const
00611 {
00612     sc_object* obj = p_sc_object;
00613     if (obj == NULL) {
00614         if (!p_is_no_sc_object) {
00615             obj = dynamic_cast<sc_object*>(
00616                     const_cast<rc_reconfigurable*>(this));
00617             if (obj != NULL) {
00618                 p_sc_object = obj;
00619             } else {
00620                 p_is_no_sc_object = true;
00621             }
00622         }
00623     }
00624     return obj;
00625 }
00626 
00627 sc_object* rc_reconfigurable::rc_get_object()
00628 {
00629     sc_object* obj = p_sc_object;
00630     if (obj == NULL) {
00631         if (!p_is_no_sc_object) {
00632             obj = dynamic_cast<sc_object*>(this);
00633             if (obj != NULL) {
00634                 p_sc_object = obj;
00635             } else {
00636                 p_is_no_sc_object = true;
00637             }
00638         }
00639     }
00640     return obj;
00641 }
00642 
00643 void rc_reconfigurable::_rc_delta_sync_state_change(
00644     rc_delta_sync_object& delta_sync)
00645 {
00646     assert(&delta_sync == &p_delta_sync);
00647 
00648     if (p_state == INACTIVE && p_next_state == ACTIVE) {
00649         // activate reconfigurable object
00650         p_state = ACTIVE;
00651         p_delta_sync.set_enabled(false);
00652         p_pctrl.activate();
00653         change_switch_state(rc_switch::OPEN);
00654     } else if (p_state == ACTIVE && p_next_state == INACTIVE) {
00655         // check whether reconfigurable object is ready to be deactivated
00656         if (p_transaction_count == 0) {
00657             // deactivate reconfigurable object
00658             p_state = INACTIVE;
00659             p_delta_sync.set_enabled(false);
00660             p_pctrl.deactivate();
00661             change_switch_state(rc_switch::CLOSED);
00662         }
00663     } else {
00664         RC_REPORT_ERROR(RC_ID_INTERNAL_ERROR_, "internal error");
00665     }
00666 }
00667 
00668 void rc_reconfigurable::_rc_unload()
00669 {
00670     p_next_state = UNLOADED;
00671     if (sc_is_running()) {
00672         sc_time delay = rc_get_delay(UNLOAD);
00673         if (delay != SC_ZERO_TIME) {
00674             ::sc_core::wait(delay);
00675         }
00676         p_state = UNLOADED;
00677         unlock_switches();
00678         rc_on_unload();
00679     } else {
00680         p_state = UNLOADED;
00681         unlock_switches();
00682     }
00683 }
00684 
00685 void rc_reconfigurable::_rc_load()
00686 {
00687     p_next_state = INACTIVE;
00688     lock_switches(true);
00689     if (sc_is_running()) {
00690         sc_time delay = rc_get_delay(LOAD);
00691         if (delay != SC_ZERO_TIME) {
00692             ::sc_core::wait(delay);
00693         }
00694         p_state = INACTIVE;
00695         rc_on_load();
00696     } else {
00697         p_state = INACTIVE;
00698     }
00699 }
00700 
00701 void rc_reconfigurable::_rc_activate()
00702 {
00703     p_next_state = ACTIVE;
00704     if (sc_is_running()) {
00705         // reset all registered resettables
00706         _rc_reset();
00707         // wait activation time (wait at least for one delta cycle)
00708         ::sc_core::wait(rc_get_delay(ACTIVATE));
00709 
00710         p_delta_sync.set_enabled(true);
00711         p_delta_sync.request_update();
00712         ::sc_core::wait(p_pctrl.get_activation_event());
00713         assert(p_state == ACTIVE);
00714         rc_on_activate();
00715     } else {
00716         p_state = ACTIVE;
00717     }
00718 }
00719 
00720 void rc_reconfigurable::_rc_deactivate()
00721 {
00722     p_next_state = INACTIVE;
00723     if (sc_is_running()) {
00724         p_delta_sync.set_enabled(true);
00725         p_delta_sync.request_update();
00726         ::sc_core::wait(p_pctrl.get_deactivation_event());
00727         assert(p_state == INACTIVE);
00728         sc_time delay = rc_get_delay(DEACTIVATE);
00729         if (delay != SC_ZERO_TIME) {
00730             ::sc_core::wait(delay);
00731         }
00732         rc_on_deactivate();
00733         _rc_reset(); // reset all registered resettables
00734     } else {
00735         p_state = INACTIVE;
00736     }
00737 }
00738 
00739 void rc_reconfigurable::_rc_reset()
00740 {
00741     const sc_dt::uint64 curr_delta = sc_delta_count();
00742     const sc_time start_time = sc_time_stamp();
00743     bool has_consumed_deltas = false;
00744 
00745     // reset all registered resettables
00746     for (resettable_set::const_iterator it = p_resettable_set.begin();
00747         it != p_resettable_set.end();
00748         ++it)
00749     {
00750         // reset the resettable
00751         (*it)->rc_on_reset();
00752 
00753         // check whether any delta cycles were consumed
00754         if (has_consumed_deltas == false
00755         && sc_delta_count() != curr_delta)
00756         {
00757             has_consumed_deltas = true;
00758         }
00759     }
00760     // report a warning if at least one of the resettables consumed time
00761     if (has_consumed_deltas) {
00762         const sc_time time_consumed = sc_time_stamp() - start_time;
00763         if (time_consumed > SC_ZERO_TIME) {
00764             RC_REPORT_WARNING(
00765                 RC_ID_TIME_CONSUMED_WARNING_,
00766                 "resetting the resettable objects"
00767                 << " consumed time (in reconfigurable '"
00768                 << this->rc_get_name() << "')");
00769         } else {
00770             RC_REPORT_WARNING(
00771                 RC_ID_DELTAS_CONSUMED_WARNING_,
00772                 "resetting the resettable objects"
00773                 << " consumed one or more delta cycles"
00774                 << " (in reconfigurable '"
00775                 << this->rc_get_name() << "')");
00776         }
00777     }
00778 }
00779 
00780 rc_transaction::~rc_transaction()
00781 {
00782     if (!p_has_ended && reconf != NULL) {
00783         reconf->rc_end_transaction();
00784     }
00785 }
00786 
00787 rc_reconfigurable* rc_get_reconfigurable_context()
00788 {
00789     using namespace internals::reconfigurable;
00790 
00791     if (begin_construction::s_current != NULL) {
00792         return begin_construction::s_current;
00793     }
00794 
00795     sc_object* start_search = NULL;
00796     if (!sc_is_running()) {
00797         std::auto_ptr<temporary_object> tmp_obj(
00798             new temporary_object());
00799         start_search = tmp_obj->get_parent_object();
00800     } else {
00801         start_search =
00802             sc_get_current_process_handle().get_parent_object();
00803     }
00804     return rc_get_reconfigurable_context(start_search);
00805 }
00806 
00807 rc_reconfigurable* rc_get_reconfigurable_context(sc_object* start_search)
00808 {
00809     using namespace internals::reconfigurable;
00810 
00811     static sc_object*         s_cached_search = NULL;
00812     static rc_reconfigurable* s_cached_result = NULL;
00813 
00814     if (begin_construction::s_current != NULL) {
00815         return begin_construction::s_current;
00816     }
00817 
00818     if (start_search != NULL) {
00819         if (start_search == s_cached_search) {
00820             return s_cached_result;
00821         }
00822         rc_reconfigurable* reconf =
00823             dynamic_cast<rc_reconfigurable*>(start_search);
00824         if (reconf == NULL) {
00825             if (start_search->get_parent_object() == s_cached_search) {
00826                 return s_cached_result;
00827             }
00828             while(start_search != NULL
00829                 && (reconf = dynamic_cast<rc_reconfigurable*>(
00830                     start_search = start_search->get_parent_object()))
00831                    == NULL);
00832         }
00833         s_cached_search = start_search;
00834         s_cached_result = reconf;
00835         return reconf;
00836     } else {
00837         return NULL;
00838     }
00839 }
00840 
00841 const rc_reconfigurable* rc_register_resettable(
00842     rc_resettable& resettable, sc_object* search_start)
00843 {
00844     rc_reconfigurable* const reconf =
00845         rc_get_reconfigurable_context(search_start);
00846     if (reconf != NULL) {
00847         reconf->rc_register_resettable(resettable);
00848     }
00849     return reconf;
00850 }
00851 
00852 } // namespace ReChannel
00853 
00854 //
00855 // $Id: rc_reconfigurable.cpp,v 1.22 2008/01/01 13:34:00 felke Exp $
00856 // $Source: /var/cvs/projekte/ReChannel-v2/src/ReChannel/core/rc_reconfigurable.cpp,v $
00857 //

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