rc_abstract_portal.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_abstract_portal.h"
00038 
00039 namespace ReChannel {
00040 
00041 rc_portal_base::rc_portal_base(
00042     const sc_module_name& module_name,
00043     state_type& state, unsigned int& transaction_count)
00044     : sc_module(module_name), p_state(state),
00045       p_transaction_count(transaction_count),
00046       p_interface_wrapper(NULL), p_dyn_accessor(NULL),
00047       p_last_dyn_filter(NULL), p_dyn_module(NULL)
00048 { }
00049 
00050 void rc_portal_base::_rc_init(rc_interface_wrapper_base& interface_wrapper)
00051 {
00052     // check correct usage
00053     assert(p_interface_wrapper == NULL);
00054 
00055     // initialize (if necessary)
00056     if (p_interface_wrapper == NULL) {
00057         p_interface_wrapper = &interface_wrapper;
00058     }
00059 }
00060 
00061 void rc_portal_base::register_port(rc_port_handle port_)
00062 {
00063     if (!port_.valid()) {
00064         RC_REPORT_ERROR(RC_ID_NULL_POINTER_,
00065             "binding failed: invalid port handle given (in portal '"
00066             << this->name() << "')");
00067     }
00068     if (sc_is_running()) {
00069         RC_REPORT_ERROR(RC_ID_SWITCH_BINDING_ERROR_,
00070             "binding attempt with port '" << port_->name()
00071             << "' at simulation time (in portal '"
00072             << this->name() << "')");
00073     }
00074 
00075     rc_reconfigurable* module =
00076         rc_get_reconfigurable_context(port_->get_parent_object());
00077     if (module == NULL) {
00078         RC_REPORT_ERROR(RC_ID_SWITCH_BINDING_ERROR_,
00079             "binding attempt with non-reconfigurable port '"
00080             << port_->name()
00081             << "' (in portal '" << this->name() << "')");
00082     }
00083     sc_interface* dyn_if = port_.get_interface();
00084     if (dyn_if == NULL) {
00085         RC_REPORT_ERROR(RC_ID_SWITCH_BINDING_ERROR_,
00086             "port '" << port_->name()
00087             << "' is not bound: accessor expected"
00088             " (in portal '" << this->name() << "')");
00089     }
00090     this->register_reconfigurable(*module, *dyn_if);
00091     module->rc_register_switch(*this, port_);
00092 }
00093 
00094 void rc_portal_base::open()
00095 {
00096     if (p_state == rc_switch::CLOSED) {
00097         // check whether module is active
00098         if (p_dyn_module != NULL && p_dyn_module->rc_is_active()) {
00099             // open portal
00100             this->open(*p_dyn_module, p_dyn_filter_chain);
00101         } else {
00102             this->set_undefined();
00103         }
00104     }
00105 }
00106 
00107 void rc_portal_base::open(
00108     rc_reconfigurable& module, const filter_chain& filters)
00109 {
00110     // check valid initialization
00111     assert(p_interface_wrapper != NULL);
00112 
00113     // check whether module is bound to this portal
00114     sc_interface* dyn_if = this->get_registered_interface(module);
00115     if (dyn_if == NULL) {
00116         // binding error, module is not registered at this portal
00117         RC_REPORT_ERROR(RC_ID_SWITCH_BINDING_ERROR_,
00118             "reconfigurable module '" << module.rc_get_name()
00119             << "' is not registered (in portal '"
00120             << this->name() << "')");
00121     }
00122     // is portal open?
00123     if (p_state == rc_switch::OPEN) {
00124         if (&module == p_dyn_module) {
00125             if (filters != p_dyn_filter_chain) {
00126                 // report "change of filter chain while open" error
00127                 RC_REPORT_ERROR(RC_ID_SWITCH_CONFLICT_,
00128                     "cannot change interface filter chain while"
00129                     " portal is open (in portal '"
00130                     << this->name() << "')");
00131             } else {
00132                 // portal already open for this module (no changes)
00133                 return;
00134             }
00135         } else {
00136             // report conflict with another module
00137             RC_REPORT_ERROR(RC_ID_SWITCH_CONFLICT_,
00138                 "opening portal for reconfigurable module '"
00139                 << module.rc_get_name()
00140                 << "' conflicts with currently active reconfigurable module"
00141                 " '" << p_dyn_module->rc_get_name() << "'"
00142                 << " (in portal '" << this->name() << "')");
00143         }
00144     }
00145     // check whether module is active
00146     if (!module.rc_is_active()) {
00147         this->set_undefined();
00148         return;
00149     }
00150 
00151     // check whether given interface is a compatible accessor
00152     accessor_base_type* dyn_accessor =
00153         dynamic_cast<accessor_base_type*>(dyn_if);
00154     if (dyn_accessor == NULL
00155        || _rc_check_accessor_if_type(dyn_accessor) == false)
00156     {
00157         RC_REPORT_ERROR(RC_ID_SWITCH_BINDING_ERROR_,
00158             "an invalid accessor type '"  << typeid(dyn_if).name()
00159             << "' has been registered for reconfigurable module '"
00160             << module.rc_get_name()
00161             << " (in portal '" << this->name() << "')");
00162     }
00163     // check if an interface filter shall be applied or not
00164     if (filters.empty()) {
00165         // connect accessor with portal
00166         dyn_accessor->rc_set_target(*p_interface_wrapper);
00167     } else {
00168         rc_interface_filter* const first_dyn_filter = filters.front();
00169         accessor_base_type* last_dyn_filter = NULL;
00170 
00171         // check if filter chain is different from the stored filter chain
00172         //   (may be the same if opened from within this portal)
00173         if (&filters != &p_dyn_filter_chain) {
00174             // check if filters are compatible
00175             for (filter_chain::const_iterator it = filters.begin();
00176                 it != filters.end();
00177                 ++it)
00178             {
00179                 rc_interface_filter* filter_ = *it;
00180                 last_dyn_filter =
00181                     dynamic_cast<accessor_base_type*>(filter_);
00182                 if (last_dyn_filter == NULL
00183                 || _rc_check_accessor_if_type(last_dyn_filter) == false)
00184                 {
00185                     RC_REPORT_ERROR(RC_ID_SWITCH_INVALID_FILTER_,
00186                         "imcompatible filter object type '"
00187                         << typeid(filter_).name()
00188                         << "' supplied by reconfigurable module '"
00189                         << module.rc_get_name()
00190                         << "': accessor type expected"
00191                            " (in portal '" << this->name() << "')");
00192                 }
00193             }
00194             // store a copy of the active filter chain
00195             p_dyn_filter_chain = filters;
00196 
00197         } else {
00198             // the filter chain has not changed
00199             // and thus the last filter is already known
00200             last_dyn_filter = p_last_dyn_filter;
00201         }
00202 
00203         // connect the last filter with the interface wrapper
00204         last_dyn_filter->rc_set_target(*p_interface_wrapper);
00205         // store the pointer of the applied filter
00206         p_last_dyn_filter = last_dyn_filter;
00207         // firstly, let the event forwarder target at the last filter
00208         //    (the order of the event forwarders is essential!)
00209         this->add_event_forwarder_target(
00210             *last_dyn_filter, last_dyn_filter->rc_get_event_filter());
00211         // connect the rest of the filter chain (reverse direction!)
00212         for (int i=filters.size()-2; i >= 0; --i) {
00213             if (filters[i]->rc_set_target(*filters[i+1]) == false) {
00214                 RC_REPORT_ERROR(RC_ID_SWITCH_INVALID_FILTER_,
00215                     "connecting the filter chain for "
00216                     " reconfigurable module '" << module.rc_get_name()
00217                     << "' failed (in portal '" << this->name() << "')");
00218             }
00219             // let the event forwarder target at the filter
00220             //    (the order of the event forwarders is essential!)
00221             this->add_event_forwarder_target(
00222                 *filters[i], filters[i]->rc_get_event_filter());
00223         }
00224         // connect the accessor with the first filter
00225         if (dyn_accessor->rc_set_target(
00226             *first_dyn_filter, module.rc_get_process_control()) == false)
00227         {
00228             RC_REPORT_ERROR(RC_ID_SWITCH_INVALID_FILTER_,
00229                 "connecting the accessor of "
00230                 " reconfigurable module '" << module.rc_get_name()
00231                 << "' failed (in portal '" << this->name() << "')");
00232         }
00233     }
00234     // store the pointer of the accessor
00235     p_dyn_accessor = dyn_accessor;
00236     // let the event forwarder target at the accessor
00237     this->add_event_forwarder_target(
00238         *dyn_accessor, dyn_accessor->rc_get_event_filter());
00239     // store the pointer of the module
00240     p_dyn_module = &module;
00241     // set portal to opened state
00242     p_state = rc_switch::OPEN;
00243     // call user-defined event handler (if simulation is running)
00244     if (sc_is_running()) {
00245         this->rc_on_open();
00246     }
00247 }
00248 
00249 void rc_portal_base::close()
00250 {
00251     // set portal to closed state
00252     if (p_state != rc_switch::CLOSED) {
00253         // check whether communication is currently taking place
00254         if (p_state == rc_switch::OPEN && p_transaction_count > 0) {
00255             RC_REPORT_ERROR(RC_ID_SWITCH_CONFLICT_,
00256                 "closing portal while communication in progress"
00257                 " (in portal '" << this->name() << "')");
00258         }
00259         //note: p_dyn_module and p_last_dyn_filter_chain are kept
00260         //      (in contrast to method set_undefined()), because the
00261         //      module is still in place
00262         p_dyn_accessor->rc_clear_target();
00263         p_dyn_accessor = NULL;
00264         for (int i=p_dyn_filter_chain.size()-1; i >= 1; --i) {
00265             p_dyn_filter_chain[i]->rc_clear_target();
00266         }
00267         // cease event forwarding
00268         this->clear_event_forwarder_targets();
00269         // set state to CLOSED
00270         p_state = rc_switch::CLOSED;
00271         // call user-defined event handler (if simulation is running)
00272         if (sc_is_running()) {
00273             this->rc_on_close();
00274         }
00275     }
00276 }
00277 
00278 void rc_portal_base::set_undefined()
00279 {
00280     // set portal to undefined state
00281     if (p_state != rc_switch::UNDEF) {
00282         // check whether communication is currently taking place
00283         if (p_state == rc_switch::OPEN && p_transaction_count > 0) {
00284             RC_REPORT_ERROR(RC_ID_SWITCH_CONFLICT_,
00285                 "changing portal to undefined state while communication"
00286                 " in progress (in portal '" << this->name() << "')");
00287         }
00288 
00289         p_dyn_module = NULL;
00290         p_dyn_accessor->rc_clear_target();
00291         p_dyn_accessor = NULL;
00292         for (int i=p_dyn_filter_chain.size()-1; i >= 1; --i) {
00293             p_dyn_filter_chain[i]->rc_clear_target();
00294         }
00295         p_dyn_filter_chain.clear();
00296         p_last_dyn_filter = NULL;
00297         // cease event forwarding
00298         this->clear_event_forwarder_targets();
00299         // set state to UNDEF
00300         p_state = rc_switch::UNDEF;
00301         // call user-defined event handler (if simulation is running)
00302         if (sc_is_running()) {
00303             this->rc_on_undef();
00304         }
00305     }
00306 }
00307 
00308 void rc_portal_base::register_reconfigurable(
00309         rc_reconfigurable& module, sc_interface& dyn_if)
00310 {
00311     // check whether the dynamic interface is a compatible accessor
00312     accessor_base_type* dyn_accessor =
00313         dynamic_cast<accessor_base_type*>(&dyn_if);
00314     if (dyn_accessor == NULL
00315     || _rc_check_accessor_if_type(dyn_accessor) == false) {
00316         RC_REPORT_ERROR(RC_ID_SWITCH_BINDING_ERROR_,
00317             "registering reconfigurable module '" << module.rc_get_name()
00318             << "' failed: compatible accessor object expected"
00319                " (in portal '" << this->name() << "')");
00320     }
00321     // set the accessor initially disabled
00322     dyn_accessor->rc_clear_target();
00323 }
00324 
00325 void rc_portal_base::unregister_reconfigurable(rc_reconfigurable& module)
00326 {
00327     // there is only something to do if module is currently in use
00328     if (p_dyn_module == &module) {
00329         if (p_state == rc_switch::OPEN) {
00330             RC_REPORT_ERROR(RC_ID_SWITCH_BINDING_ERROR_,
00331                 "unregistering reconfigurable module '" << module.rc_get_name()
00332                 << "' while portal is open"
00333                    " (in portal '" << this->name() << "')");
00334         }
00335         assert(
00336             p_state == rc_switch::CLOSED
00337             || p_state == rc_switch::UNDEF);
00338         // reset members that are still storing module specific data
00339         //   (note: event forwarding has already been suspended)
00340         p_last_dyn_filter = NULL;
00341         p_dyn_filter_chain.clear();
00342         p_dyn_module = NULL;
00343     }
00344 }
00345 
00346 void rc_portal_base::add_event_forwarder_target(
00347     sc_interface& target_if, rc_event_filter* filter)
00348 {
00349     // check valid initialization
00350     assert(p_interface_wrapper != NULL);
00351 
00352     rc_event_forwarder_host* event_forwarder_host =
00353         p_interface_wrapper->get_event_forwarder_host();
00354     if (event_forwarder_host == NULL) {
00355         RC_REPORT_ERROR(RC_ID_INTERNAL_ERROR_,
00356             "interface wrapper doesn't support event forarding"
00357                " (in portal '" << this->name() << "')");
00358     }
00359     event_forwarder_host->add_event_forwarder_target(target_if, filter);
00360 }
00361 
00362 void rc_portal_base::clear_event_forwarder_targets()
00363 {
00364     // check valid initialization
00365     assert(p_interface_wrapper != NULL);
00366 
00367     rc_event_forwarder_host* event_forwarder_host =
00368         p_interface_wrapper->get_event_forwarder_host();
00369     if (event_forwarder_host != NULL) {
00370         event_forwarder_host->clear_event_forwarder_targets();
00371     }
00372 }
00373 
00374 } // namespace ReChannel
00375 //
00376 // $Id: rc_abstract_portal.cpp,v 1.9 2007/12/20 20:27:30 felke Exp $
00377 // $Source: /var/cvs/projekte/ReChannel-v2/src/ReChannel/communication/portals/rc_abstract_portal.cpp,v $
00378 //

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