00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
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
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
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 { }
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
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
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
00442 assert(!p_static_port.valid());
00443
00444
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
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
00467 assert(p_static_port.valid());
00468
00469 if (!this->is_unused()) {
00470
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 }
00623
00624 #endif // RC_ABSTRACT_PORTAL_H_
00625
00626
00627
00628