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 #include "rc_abstract_exportal.h"
00038
00039 namespace ReChannel {
00040
00041 rc_exportal_base::rc_exportal_base(
00042 const sc_module_name& module_name,
00043 state_type& state, unsigned int& transaction_count,
00044 wrapper_pool& s_wrapper_pool_)
00045 : sc_module(module_name), p_state(state),
00046 p_transaction_count(transaction_count),
00047 s_wrapper_pool(s_wrapper_pool_),
00048 p_first_dyn_filter(NULL), p_dyn_module(NULL),
00049 p_exclusive_wrapper(NULL)
00050 { }
00051
00052 sc_interface* rc_exportal_base::get_dynamic_interface() const
00053 {
00054 if (p_dyn_wrapper_handle.valid()) {
00055 return &p_dyn_wrapper_handle->get_wrapped_interface();
00056 } else {
00057 return NULL;
00058 }
00059 }
00060
00061 void rc_exportal_base::bind_dynamic(rc_export_handle export_)
00062 {
00063 if (!export_.valid()) {
00064 RC_REPORT_ERROR(RC_ID_NULL_POINTER_,
00065 "binding failed: invalid export handle given (in exportal '"
00066 << this->name() << "')");
00067 }
00068 if (sc_is_running()) {
00069 RC_REPORT_ERROR(RC_ID_SWITCH_BINDING_ERROR_,
00070 "binding attempt with export '" << export_->name()
00071 << "' at simulation time (in exportal '"
00072 << this->name() << "')");
00073 }
00074
00075 rc_reconfigurable* module =
00076 rc_get_reconfigurable_context(export_->get_parent_object());
00077 if (module == NULL) {
00078 RC_REPORT_ERROR(RC_ID_SWITCH_BINDING_ERROR_,
00079 "binding attempt with non-reconfigurable export '"
00080 << export_->name()
00081 << "' (in exportal '" << this->name() << "')");
00082 }
00083 sc_interface* dyn_if = export_.get_interface();
00084 if (dyn_if == NULL) {
00085 RC_REPORT_ERROR(RC_ID_SWITCH_BINDING_ERROR_,
00086 "export '" << export_->name()
00087 << "' is unbound: interface expected"
00088 "(in exportal '" << this->name() << "')");
00089 }
00090 this->register_reconfigurable(*module, *dyn_if);
00091 module->rc_register_switch(*this, export_);
00092 }
00093
00094 void rc_exportal_base::bind_dynamic(sc_interface& dynamic_if_)
00095 {
00096 if (sc_is_running()) {
00097 RC_REPORT_ERROR(RC_ID_SWITCH_BINDING_ERROR_,
00098 "binding attempt with an interface"
00099 << " at simulation time (in exportal '"
00100 << this->name() << "')");
00101 }
00102 sc_object* channel_ = dynamic_cast<sc_object*>(&dynamic_if_);
00103 if (channel_ == NULL) {
00104 RC_REPORT_ERROR(RC_ID_SWITCH_BINDING_ERROR_,
00105 "binding attempt with an interface"
00106 << " that is no sc_object (in exportal '"
00107 << this->name() << "')");
00108 }
00109 rc_reconfigurable* module = rc_get_reconfigurable_context(channel_);
00110 if (module == NULL) {
00111 RC_REPORT_ERROR(RC_ID_SWITCH_BINDING_ERROR_,
00112 "binding attempt with an interface"
00113 << " from a non-reconfigurable context (in exportal '"
00114 << this->name() << "')");
00115 }
00116 this->register_reconfigurable(*module, dynamic_if_);
00117 module->rc_register_switch(*this, *channel_);
00118 }
00119
00120 void rc_exportal_base::bind_exclusively(rc_interface_wrapper_base& wrapper)
00121 {
00122 if (sc_is_running()) {
00123 RC_REPORT_ERROR(RC_ID_SWITCH_BINDING_ERROR_,
00124 "binding attempt with an interface"
00125 << " at simulation time (in exportal '"
00126 << this->name() << "')");
00127 }
00128 if (p_exclusive_wrapper != NULL) {
00129 RC_REPORT_ERROR(RC_ID_SWITCH_BINDING_ERROR_,
00130 "only one exclusively bound interface"
00131 " can be registered (in exportal '"
00132 << this->name() << "')");
00133 }
00134 sc_interface& dynamic_if_ = wrapper.get_wrapped_interface();
00135 sc_object* channel_ = dynamic_cast<sc_object*>(&dynamic_if_);
00136 if (channel_ == NULL) {
00137 RC_REPORT_ERROR(RC_ID_SWITCH_BINDING_ERROR_,
00138 "binding attempt with an interface"
00139 << " that is no sc_object (in exportal '"
00140 << this->name() << "')");
00141 }
00142 rc_reconfigurable* module = rc_get_reconfigurable_context(channel_);
00143 if (module == NULL) {
00144 module = &rc_non_reconfigurable::get_instance();
00145 }
00146 this->register_reconfigurable(*module, dynamic_if_);
00147 module->rc_register_switch(*this, *channel_);
00148 p_exclusive_wrapper = &wrapper;
00149 }
00150
00151 void rc_exportal_base::open()
00152 {
00153 if (p_state == rc_switch::CLOSED) {
00154
00155 if (p_dyn_module != NULL && p_dyn_module->rc_is_active()) {
00156 this->open(*p_dyn_module, p_dyn_filter_chain);
00157 } else {
00158 this->set_undefined();
00159 }
00160 }
00161 }
00162
00163 void rc_exportal_base::open(
00164 rc_reconfigurable& module, const filter_chain& filters)
00165 {
00166
00167 sc_interface* dyn_if = this->get_registered_interface(module);
00168 if (dyn_if == NULL) {
00169
00170 RC_REPORT_ERROR(RC_ID_SWITCH_BINDING_ERROR_,
00171 "dynamic module '" << module.rc_get_name()
00172 << "' is not registered (in exportal '"
00173 << this->name() << "')");
00174 }
00175
00176 if (p_state == rc_switch::OPEN) {
00177 if (&module == p_dyn_module) {
00178 if (filters != p_dyn_filter_chain) {
00179
00180 RC_REPORT_ERROR(RC_ID_SWITCH_CONFLICT_,
00181 "cannot change interface filter chain while"
00182 " exportal is open (in exportal '"
00183 << this->name() << "')");
00184 } else {
00185
00186 return;
00187 }
00188 } else {
00189
00190 RC_REPORT_ERROR(RC_ID_SWITCH_CONFLICT_,
00191 "opening exportal for dynamic module '"
00192 << module.rc_get_name()
00193 << "' conflicts with currently active dynamic module"
00194 " '" << p_dyn_module->rc_get_name() << "'"
00195 << " (in exportal '" << this->name() << "')");
00196 }
00197 } else {
00198
00199 assert(p_dyn_wrapper_handle.valid() == false);
00200 }
00201
00202
00203 if (!module.rc_is_active()) {
00204 this->set_undefined();
00205 return;
00206 }
00207
00208
00209 if (this->_rc_check_interface_type(dyn_if) == false) {
00210 RC_REPORT_ERROR(RC_ID_SWITCH_BINDING_ERROR_,
00211 "an invalid interface type '" << typeid(dyn_if).name()
00212 << "' has been registered for dynamic module '"
00213 << module.rc_get_name()
00214 << " (in exportal '" << this->name() << "')");
00215 }
00216
00217
00218 if (p_reserved_wrapper_handle.valid()
00219 && &p_reserved_wrapper_handle->get_wrapped_interface() == dyn_if) {
00220
00221 p_dyn_wrapper_handle = p_reserved_wrapper_handle;
00222
00223 assert(p_reserved_wrapper_handle.valid() == false);
00224 } else {
00225
00226 if (p_exclusive_wrapper != NULL
00227 && &p_exclusive_wrapper->get_wrapped_interface() == dyn_if) {
00228
00229 p_dyn_wrapper_handle = p_exclusive_wrapper;
00230 } else {
00231
00232 wrapper_handle handle =
00233 rc_exportal_base::s_wrapper_pool.get(*dyn_if, this);
00234 p_dyn_wrapper_handle = handle;
00235
00236
00237
00238
00239 this->_rc_set_interface_wrapper_owner(
00240 p_dyn_wrapper_handle.get_object());
00241 }
00242
00243 p_reserved_wrapper_handle.release();
00244 }
00245
00246
00247 accessor_base_type& static_accessor = this->_rc_get_static_accessor();
00248
00249
00250 if (filters.empty()) {
00251
00252 static_accessor.rc_set_target(*p_dyn_wrapper_handle);
00253 } else {
00254 accessor_base_type* first_dyn_filter = NULL;
00255 rc_interface_filter* const last_dyn_filter = filters.back();
00256
00257
00258
00259 if (&filters != &p_dyn_filter_chain) {
00260
00261 for (filter_chain::const_reverse_iterator it = filters.rbegin();
00262 it != filters.rend();
00263 ++it)
00264 {
00265 rc_interface_filter* filter_ = *it;
00266 first_dyn_filter =
00267 dynamic_cast<accessor_base_type*>(filter_);
00268 if (first_dyn_filter == NULL
00269 || _rc_check_accessor_if_type(first_dyn_filter) == false)
00270 {
00271 RC_REPORT_ERROR(RC_ID_SWITCH_INVALID_FILTER_,
00272 "imcompatible filter object type '"
00273 << typeid(filter_).name()
00274 << "' supplied by dynamic module '"
00275 << module.rc_get_name()
00276 << "': accessor type expected"
00277 " (in portal '" << this->name() << "')");
00278 }
00279 }
00280
00281 p_dyn_filter_chain = filters;
00282 } else {
00283
00284
00285 first_dyn_filter = p_first_dyn_filter;
00286 }
00287
00288
00289 first_dyn_filter->rc_set_target(*p_dyn_wrapper_handle);
00290
00291 p_first_dyn_filter = first_dyn_filter;
00292
00293 this->add_event_forwarder_target(
00294 *first_dyn_filter, first_dyn_filter->rc_get_event_filter());
00295
00296 const unsigned int count = filters.size();
00297
00298 for (unsigned int i=1; i < count; ++i) {
00299 if (filters[i]->rc_set_target(*filters[i-1]) == false) {
00300 RC_REPORT_ERROR(RC_ID_SWITCH_INVALID_FILTER_,
00301 "connecting the filter chain for "
00302 " dynamic module '" << module.rc_get_name()
00303 << "' failed (in exportal '" << this->name() << "')");
00304 }
00305
00306 this->add_event_forwarder_target(
00307 *filters[i], filters[i]->rc_get_event_filter());
00308 }
00309
00310 if (static_accessor.rc_set_target(
00311 *last_dyn_filter, module.rc_get_process_control()) == false)
00312 {
00313 RC_REPORT_ERROR(RC_ID_SWITCH_INVALID_FILTER_,
00314 "connecting the accessor of "
00315 " dynamic module '" << module.rc_get_name()
00316 << "' failed (in exportal '" << this->name() << "')");
00317 }
00318 }
00319
00320 this->add_event_forwarder_target(
00321 static_accessor, static_accessor.rc_get_event_filter());
00322
00323 p_dyn_module = &module;
00324
00325 p_state = rc_switch::OPEN;
00326
00327 if (sc_is_running()) {
00328 this->rc_on_open();
00329 }
00330 }
00331
00332 void rc_exportal_base::close()
00333 {
00334
00335 if (p_transaction_count > 0) {
00336 RC_REPORT_ERROR(RC_ID_SWITCH_CONFLICT_,
00337 "closing portal while communication in progress"
00338 " (in portal '" << this->name() << "')");
00339 }
00340
00341 if (p_state != rc_switch::CLOSED) {
00342
00343
00344
00345 this->_rc_get_static_accessor().rc_clear_target();
00346 for (int i=p_dyn_filter_chain.size()-1; i >= 1; --i) {
00347 p_dyn_filter_chain[i]->rc_clear_target();
00348 }
00349
00350 this->clear_event_forwarder_targets();
00351
00352 p_reserved_wrapper_handle = p_dyn_wrapper_handle;
00353
00354 p_state = rc_switch::CLOSED;
00355
00356 if (sc_is_running()) {
00357 this->rc_on_close();
00358 }
00359 }
00360 }
00361
00362 void rc_exportal_base::set_undefined()
00363 {
00364
00365 if (p_transaction_count > 0) {
00366 RC_REPORT_ERROR(RC_ID_SWITCH_CONFLICT_,
00367 "changing portal to undefined state while communication"
00368 " in progress (in portal '" << this->name() << "')");
00369 }
00370
00371 if (p_state != rc_switch::UNDEF) {
00372 p_dyn_module = NULL;
00373 this->_rc_get_static_accessor().rc_clear_target();
00374 for (int i=p_dyn_filter_chain.size()-1; i >= 1; --i) {
00375 p_dyn_filter_chain[i]->rc_clear_target();
00376 }
00377 p_dyn_filter_chain.clear();
00378 p_first_dyn_filter = NULL;
00379
00380 this->clear_event_forwarder_targets();
00381
00382 p_reserved_wrapper_handle = p_dyn_wrapper_handle;
00383
00384 p_state = rc_switch::UNDEF;
00385
00386 if (sc_is_running()) {
00387
00388 this->rc_on_close();
00389 }
00390 }
00391 }
00392
00393 void rc_exportal_base::register_reconfigurable(
00394 rc_reconfigurable& module, sc_interface& dyn_if)
00395 {
00396
00397 if (this->_rc_check_interface_type(&dyn_if) == false) {
00398 RC_REPORT_ERROR(RC_ID_SWITCH_BINDING_ERROR_,
00399 "registering dynamic module '" << module.rc_get_name()
00400 << "' failed: compatible interface expected"
00401 " (in portal '" << this->name() << "')");
00402 }
00403 }
00404
00405 void rc_exportal_base::unregister_reconfigurable(
00406 rc_reconfigurable& module)
00407 {
00408
00409 if (p_dyn_module == &module) {
00410 if (p_state == rc_switch::OPEN) {
00411 RC_REPORT_ERROR(RC_ID_SWITCH_BINDING_ERROR_,
00412 "unregistering dynamic module '" << module.rc_get_name()
00413 << "' while portal is open"
00414 " (in portal '" << this->name() << "')");
00415 }
00416 assert(
00417 p_state == rc_switch::CLOSED
00418 || p_state == rc_switch::UNDEF);
00419
00420 p_reserved_wrapper_handle.release();
00421 p_first_dyn_filter = NULL;
00422 p_dyn_filter_chain.clear();
00423 p_dyn_module = NULL;
00424 }
00425 }
00426
00427 void rc_exportal_base::notify_event(const std::string& event_name)
00428 {
00429 if (p_dyn_wrapper_handle.valid()) {
00430 rc_event_forwarder_host* const event_forwarder_host =
00431 p_dyn_wrapper_handle->get_event_forwarder_host();
00432 if (event_forwarder_host != NULL) {
00433 event_forwarder_host->notify_event(event_name);
00434 }
00435 }
00436 }
00437
00438 rc_interface_wrapper_base*
00439 rc_exportal_base::get_interface_wrapper_base() const
00440 {
00441 if (p_dyn_wrapper_handle.valid()) {
00442 return p_dyn_wrapper_handle.get_object();
00443 } else if (p_reserved_wrapper_handle.valid()) {
00444 return p_reserved_wrapper_handle.get_object();
00445 } else {
00446 return NULL;
00447 }
00448 }
00449
00450 void rc_exportal_base::add_event_forwarder_target(
00451 sc_interface& target_if, rc_event_filter* filter)
00452 {
00453 rc_event_forwarder_host* const event_finder_host =
00454 p_dyn_wrapper_handle->get_event_forwarder_host();
00455 if (event_finder_host == NULL) {
00456 RC_REPORT_ERROR(RC_ID_INTERNAL_ERROR_,
00457 "interface wrapper doesn't support event forarding"
00458 " (in exportal '" << this->name() << "')");
00459 }
00460 event_finder_host->add_event_forwarder_target(target_if, filter);
00461 }
00462
00463 void rc_exportal_base::clear_event_forwarder_targets()
00464 {
00465 rc_event_forwarder_host* const event_finder_host =
00466 p_dyn_wrapper_handle->get_event_forwarder_host();
00467 if (event_finder_host != NULL) {
00468 event_finder_host->clear_event_forwarder_targets();
00469 }
00470 }
00471
00472 }
00473
00474
00475
00476
00477