rc_abstract_portal.h

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 #ifndef RC_ABSTRACT_PORTAL_H_
00038 #define RC_ABSTRACT_PORTAL_H_
00039 
00040 #include "ReChannel/communication/rc_abstract_switch.h"
00041 #include "ReChannel/communication/rc_abstract_interface_wrapper.h"
00042 #include "ReChannel/communication/rc_event_forwarder.h"
00043 #include "ReChannel/communication/accessors/rc_accessor.h"
00044 #include "ReChannel/core/rc_reconfigurable.h"
00045 #include "ReChannel/core/rc_non_reconfigurable.h"
00046 #include "ReChannel/util/rc_port_traits.h"
00047 
00048 namespace ReChannel {
00049 
00053 class rc_portal_base
00054     : public sc_module,
00055       virtual public rc_switch
00056 {
00057 private:
00058     typedef rc_switch::state_type state_type;
00059 
00060 protected:
00061     typedef rc_interface_wrapper_base::accessor_base accessor_base_type;
00062     typedef rc_switch::filter_chain                  filter_chain;
00063 
00064 protected:
00065     rc_portal_base(
00066         const sc_module_name& module_name,
00067         state_type& m_state, unsigned int& m_transaction_count);
00068 
00070     void _rc_init(rc_interface_wrapper_base& interface_wrapper);
00071 
00072 public:
00073 
00075     virtual rc_reconfigurable* get_current_reconfigurable() const
00076         { return p_dyn_module; }
00077 
00079     virtual sc_interface* get_dynamic_interface() const
00080         { return p_dyn_accessor; }
00081 
00082 protected:
00083 
00084     void register_port(rc_port_handle port_);
00085 
00087     virtual void rc_on_open() { }
00088 
00090     virtual void rc_on_close() { }
00091 
00093     virtual void rc_on_undef() { }
00094 
00096     virtual void rc_on_refresh_notify() = 0;
00097 
00099     virtual void open();
00100 
00102     virtual void open(
00103         rc_reconfigurable& module,
00104         const filter_chain& filters = filter_chain());
00105 
00107     virtual void close();
00108 
00110     virtual void set_undefined();
00111 
00113     virtual void refresh_notify()
00114         { this->rc_on_refresh_notify(); }
00115 
00117     virtual void register_reconfigurable(
00118         rc_reconfigurable& module, sc_interface& dyn_interface);
00119 
00121     virtual void unregister_reconfigurable(rc_reconfigurable& module);
00122 
00124     inline rc_process_behavior_change begin_access_callback();
00125 
00127     inline void end_access_callback();
00128 
00129     virtual ~rc_portal_base() {}
00130 
00131 private:
00132 
00133     void add_event_forwarder_target(
00134         sc_interface& target_if, rc_event_filter* filter=NULL);
00135 
00136     void clear_event_forwarder_targets();
00137 
00138 private:
00139 
00140 /* special callback method */
00141 
00142     virtual bool _rc_check_accessor_if_type(
00143         accessor_base_type* accessor) const = 0;
00144 
00145 private:
00146 
00148     state_type&   p_state;
00149 
00151     unsigned int& p_transaction_count;
00152 
00154     rc_interface_wrapper_base* p_interface_wrapper;
00155 
00157     accessor_base_type* p_dyn_accessor;
00158 
00160     accessor_base_type* p_last_dyn_filter;
00161 
00163     filter_chain p_dyn_filter_chain;
00164 
00166     rc_reconfigurable* p_dyn_module;
00167 };
00168 
00172 template<class IF>
00173 class rc_portal_b
00174     : public rc_portal_base,
00175       public rc_abstract_switch<IF>
00176 {
00177     RC_STATIC_ASSERT_VALID_INTERFACE(IF);
00178 
00179 private:
00180     typedef rc_portal_b<IF>        this_type;
00181     typedef rc_portal_base         base_type;
00182     typedef rc_abstract_switch<IF> switch_parent_type;
00183 
00184     typedef typename base_type::accessor_base_type      accessor_base_type;
00185     typedef typename rc_interface_wrapper<IF>::accessor accessor_b_type;
00186 
00187     typedef rc_switch::state_type state_type;
00188 
00189     typedef boost::function<const sc_event& (IF*)> event_getter_functor;
00190     typedef std::vector<std::pair<event_getter_functor, std::string> >
00191         ef_constr_vector;
00192 
00193 protected:
00194     using switch_parent_type::m_state;
00195     using switch_parent_type::m_transaction_count;
00196 
00197 public:
00198     typedef IF              if_type;
00199     typedef rc_accessor<IF> accessor_type;
00200 
00201 private:
00202     class interface_wrapper;
00203 
00204 protected:
00206     explicit rc_portal_b(const sc_module_name& module_name);
00207 
00209     void _rc_init(rc_port_handle static_port);
00210 
00211 public:
00212 
00214     virtual std::string get_switch_kind() const
00215         { return "portal"; }
00216 
00218     virtual std::string get_switch_name() const
00219         { return this->name(); }
00220 
00222     virtual sc_interface* get_static_interface() const;
00223 
00224 protected:
00225 
00227     virtual accessor_type* create_accessor() const
00228         { return new accessor_type(); }
00229 
00231     virtual void rc_on_refresh_notify() { }
00232 
00234     virtual void register_reconfigurable(
00235         rc_reconfigurable& module, sc_interface& dyn_interface);
00236 
00238     virtual void unregister_reconfigurable(rc_reconfigurable& module);
00239 
00241     virtual void end_of_elaboration();
00242 
00244     virtual void unused() = 0;
00245 
00246     virtual bool is_unused() const = 0;
00247 
00249     template<class IF_>
00250     inline
00251     void add_event_forwarder(
00252         const sc_event& (IF_::*event_getter)() const,
00253         const std::string& event_name=NULL);
00254 
00256     inline void notify_event(const std::string& event_name)
00257         { p_interface_wrapper.notify_event(event_name); }
00258 
00260     inline rc_interface_wrapper<IF>& get_interface_wrapper()
00261         { return p_interface_wrapper; }
00262 
00263 private:
00264 
00265 /* for internal use only */
00266 
00267     virtual bool _rc_check_accessor_if_type(
00268         accessor_base_type* accessor) const;
00269 
00270 private:
00272     interface_wrapper p_interface_wrapper;
00273 
00275     rc_port_handle p_static_port;
00276 
00278     ef_constr_vector p_ef_constr_vector;
00279 };
00280 
00284 template<class IF>
00285 class rc_portal_b<IF>::interface_wrapper
00286     : public rc_abstract_interface_wrapper<IF>
00287 {
00288     friend class rc_portal_b<IF>;
00289 
00290 private:
00291     typedef rc_portal_b<IF> portal_type;
00292     typedef rc_abstract_interface_wrapper<IF> base_type;
00293 
00294     typedef const sc_event& (IF::*event_getter_ptr)() const;
00295 
00296 public:
00297     typedef typename base_type::accessor_type accessor_type;
00298 
00299 public:
00300     explicit interface_wrapper(portal_type& owner_portal)
00301         : base_type(), p_portal(owner_portal)
00302         { }
00303 
00305     virtual std::string get_interface_wrapper_name() const
00306         { return p_portal.name(); }
00307 
00308     virtual void register_port(
00309         sc_port_base& port_, const char* if_typename)
00310         { /* ignore */ }
00311 
00313     inline void add_event_forwarder(
00314         IF& trigger_if, event_getter_functor functor,
00315         const std::string& event_name)
00316     { base_type::add_event_forwarder(trigger_if, functor, event_name); }
00317 
00318 protected:
00320     virtual accessor_type* create_accessor() const
00321         { return p_portal.create_accessor(); }
00322 
00324     virtual rc_process_behavior_change begin_access_callback()
00325         { return p_portal.begin_access_callback(); }
00326 
00328     virtual void end_access_callback()
00329         { p_portal.end_access_callback(); }
00330 
00331 private:
00333     portal_type& p_portal;
00334 };
00335 
00339 template<class PORT>
00340 class rc_abstract_portal
00341     : public rc_portal_b<typename rc_port_traits<PORT>::if_type>
00342 {
00343     RC_STATIC_ASSERT_VALID_PORT(PORT);
00344 
00345 private:
00346     typedef rc_port_traits<PORT> port_traits;
00347 
00348 public:
00349     typedef PORT                          port_type;
00350     typedef typename port_traits::if_type if_type;
00351     typedef rc_accessor<if_type>          accessor_type;
00352 
00353 private:
00354     typedef rc_abstract_portal<port_type> this_type;
00355     typedef rc_portal_b<if_type>          base_type;
00356 
00357 protected:
00359     rc_abstract_portal();
00360     explicit rc_abstract_portal(const sc_module_name& module_name);
00361 
00362 public:
00363 
00365     void bind_static(port_type& port_)
00366         { static_port.bind(port_); }
00367 
00369     void bind_static(if_type& channel_)
00370         { static_port.bind(channel_); }
00371 
00373     void bind_dynamic(port_type& port_);
00374 
00376     void dynamic_port(port_type& port_)
00377         { this->bind_dynamic(port_); }
00378 
00380     virtual void unused();
00381 
00382     virtual bool is_unused() const
00383         { return p_is_unused; }
00384 
00386     inline port_type& get_static_port()
00387         { return static_port; }
00388 
00389 protected:
00390 
00391     virtual void bind_static_object(const rc_object_handle& obj_to_bind);
00392 
00393     virtual void bind_dynamic_object(const rc_object_handle& obj_to_bind);
00394 
00395 public:
00397     port_type static_port;
00398 
00399 private:
00400 
00402     bool p_is_unused;
00403 };
00404 
00405 /* inline code */
00406 
00407 inline rc_process_behavior_change rc_portal_base::begin_access_callback()
00408 {
00409     ++p_transaction_count;
00410     if (p_dyn_module != NULL) {
00411         p_dyn_module->rc_begin_transaction();
00412     }
00413     rc_process_handle hproc = rc_get_current_process_handle();
00414     return hproc.behavior_change(false);
00415 }
00416 
00417 inline void rc_portal_base::end_access_callback()
00418 {
00419     if (p_transaction_count > 0) {
00420         --p_transaction_count;
00421     }
00422     if (p_dyn_module != NULL) {
00423         p_dyn_module->rc_end_transaction();
00424     }
00425 }
00426 
00427 /* template code */
00428 
00429 template<class IF>
00430 rc_portal_b<IF>::rc_portal_b(
00431     const sc_module_name& module_name)
00432     : base_type(module_name, m_state, m_transaction_count),
00433       p_interface_wrapper(*this)
00434 {
00435     base_type::_rc_init(p_interface_wrapper);
00436 }
00437 
00438 template<class IF>
00439 void rc_portal_b<IF>::_rc_init(rc_port_handle static_port)
00440 {
00441     // check correct usage
00442     assert(!p_static_port.valid());
00443 
00444     // initialize (if necessary)
00445     if (!p_static_port.valid()) {
00446         p_static_port = static_port;
00447     }
00448 }
00449 
00450 template<class IF>
00451 sc_interface* rc_portal_b<IF>::get_static_interface() const
00452 {
00453     // check valid initialization
00454     assert(p_static_port.valid());
00455 
00456     return p_static_port->get_interface();
00457 }
00458 
00459 template<class IF>
00460 template<class IF_>
00461 inline
00462 void rc_portal_b<IF>::add_event_forwarder(
00463     const sc_event& (IF_::*event_getter)() const,
00464     const std::string& event_name)
00465 {
00466     // check valid internal initialization
00467     assert(p_static_port.valid());
00468 
00469     if (!this->is_unused()) {
00470         // (note: get_interface() will most likely return NULL)
00471         IF* trigger_if = dynamic_cast<IF*>(p_static_port.get_interface());
00472         if (trigger_if == NULL) {
00473             p_ef_constr_vector.push_back(
00474                 typename ef_constr_vector::value_type(event_getter, event_name));
00475         } else {
00476             p_interface_wrapper.add_event_forwarder(
00477                 *trigger_if, event_getter, event_name);
00478         }
00479     }
00480 }
00481 
00482 template<class IF>
00483 void rc_portal_b<IF>::register_reconfigurable(
00484         rc_reconfigurable& module, sc_interface& dyn_if)
00485 {
00486     base_type::register_reconfigurable(module, dyn_if);
00487     switch_parent_type::register_reconfigurable(module, dyn_if);
00488 }
00489 
00490 template<class IF>
00491 void rc_portal_b<IF>::unregister_reconfigurable(rc_reconfigurable& module)
00492 {
00493     base_type::unregister_reconfigurable(module);
00494     switch_parent_type::unregister_reconfigurable(module);
00495 }
00496 
00497 template<class IF>
00498 void rc_portal_b<IF>::end_of_elaboration()
00499 {
00500     base_type::end_of_elaboration();
00501     sc_interface* static_if = this->get_static_interface();
00502     if (static_if == NULL
00503     || p_interface_wrapper.set_wrapped_interface(*static_if) == false)
00504     {
00505         RC_REPORT_ERROR(RC_ID_INTERNAL_ERROR_,
00506             "static port is incompatible with the declared"
00507             " interface (in portal '" << this->name() << "')");
00508     }
00509 
00510     if (!this->is_unused()) {
00511         IF* trigger_if = dynamic_cast<IF*>(static_if);
00512         if (trigger_if != NULL) {
00513             for (typename ef_constr_vector::iterator it =
00514                     p_ef_constr_vector.begin();
00515                 it != p_ef_constr_vector.end();
00516                 ++it)
00517             {
00518                 typename ef_constr_vector::value_type& ef_constr = (*it);
00519                 p_interface_wrapper.add_event_forwarder(
00520                     *trigger_if, ef_constr.first,
00521                     ef_constr.second.c_str());
00522             }
00523         }
00524         p_ef_constr_vector.clear();
00525     }
00526 }
00527 
00528 template<class IF>
00529 bool rc_portal_b<IF>::_rc_check_accessor_if_type(
00530     accessor_base_type* accessor) const
00531 {
00532     return (dynamic_cast<accessor_b_type*>(accessor) != NULL);
00533 }
00534 
00535 template<class PORT>
00536 rc_abstract_portal<PORT>::rc_abstract_portal()
00537     : base_type(sc_gen_unique_name("portal")),
00538       static_port("static_port"), p_is_unused(false)
00539 {
00540     base_type::_rc_init(static_port);
00541 }
00542 
00543 template<class PORT>
00544 rc_abstract_portal<PORT>::rc_abstract_portal(
00545     const sc_module_name& module_name)
00546     : base_type(module_name),
00547       static_port("static_port"), p_is_unused(false)
00548 {
00549     base_type::_rc_init(static_port);
00550 }
00551 
00552 template<class PORT>
00553 void rc_abstract_portal<PORT>::bind_dynamic(port_type& port_)
00554 {
00555     if (port_.get_interface() == NULL) {
00556         accessor_type* accessor_ = this->create_accessor();
00557         if (accessor_ == NULL) {
00558             RC_REPORT_ERROR(RC_ID_NULL_POINTER_,
00559                 "method create_accessor() did not create an accessor"
00560                 " (in portal '" << this->name() << "')");
00561         }
00562         port_.bind(*accessor_);
00563     }
00564     register_port(port_);
00565 }
00566 
00567 template<class PORT>
00568 void rc_abstract_portal<PORT>::unused()
00569 {
00570     if_type* undef_if = rc_fallback_interface_factory<if_type>::create();
00571     if (undef_if != NULL) {
00572         static_port.bind(*undef_if);
00573         p_is_unused = true;
00574     } else {
00575         RC_REPORT_ERROR(RC_ID_NOT_IMPLEMENTED_,
00576             "no matching rc_fallback_interface found"
00577             " (in portal '" << this->name() << "')");
00578     }
00579 }
00580 
00581 template<class PORT>
00582 void rc_abstract_portal<PORT>::bind_static_object(
00583     const rc_object_handle& obj_to_bind)
00584 {
00585     if (obj_to_bind.is_port()) {
00586         port_type* port_to_bind =
00587             dynamic_cast<port_type*>(*obj_to_bind);
00588         if (port_to_bind != NULL) {
00589             static_port.bind(*port_to_bind);
00590             return;
00591         }
00592     } else if (obj_to_bind.is_channel()) {
00593         if_type* if_to_bind = dynamic_cast<if_type*>(*obj_to_bind);
00594         if (if_to_bind != NULL) {
00595             static_port.bind(*if_to_bind);
00596             return;
00597         }
00598     }
00599     RC_REPORT_ERROR(RC_ID_SWITCH_BINDING_ERROR_,
00600         "'" << obj_to_bind->name() << "'"
00601         " is incompatible with the static port"
00602         " (in portal '" << this->name() << "')");
00603 }
00604 
00605 template<class PORT>
00606 void rc_abstract_portal<PORT>::bind_dynamic_object(
00607     const rc_object_handle& obj_to_bind)
00608 {
00609     if (obj_to_bind.is_port()) {
00610         port_type* port_to_bind = dynamic_cast<port_type*>(*obj_to_bind);
00611         if (port_to_bind != NULL) {
00612             this->bind_dynamic(*port_to_bind);
00613             return;
00614         }
00615     }
00616     RC_REPORT_ERROR(RC_ID_SWITCH_BINDING_ERROR_,
00617         "'" << obj_to_bind->name() << "'"
00618         " is incompatible with the dynamic port"
00619         " (in portal '" << this->name() << "')");
00620 }
00621 
00622 } // namespace ReChannel
00623 
00624 #endif // RC_ABSTRACT_PORTAL_H_
00625 //
00626 // $Id: rc_abstract_portal.h,v 1.12 2008/01/01 13:46:06 felke Exp $
00627 // $Source: /var/cvs/projekte/ReChannel-v2/src/ReChannel/communication/portals/rc_abstract_portal.h,v $
00628 //

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