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_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
00053 assert(p_interface_wrapper == NULL);
00054
00055
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
00098 if (p_dyn_module != NULL && p_dyn_module->rc_is_active()) {
00099
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
00111 assert(p_interface_wrapper != NULL);
00112
00113
00114 sc_interface* dyn_if = this->get_registered_interface(module);
00115 if (dyn_if == NULL) {
00116
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
00123 if (p_state == rc_switch::OPEN) {
00124 if (&module == p_dyn_module) {
00125 if (filters != p_dyn_filter_chain) {
00126
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
00133 return;
00134 }
00135 } else {
00136
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
00146 if (!module.rc_is_active()) {
00147 this->set_undefined();
00148 return;
00149 }
00150
00151
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
00164 if (filters.empty()) {
00165
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
00172
00173 if (&filters != &p_dyn_filter_chain) {
00174
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
00195 p_dyn_filter_chain = filters;
00196
00197 } else {
00198
00199
00200 last_dyn_filter = p_last_dyn_filter;
00201 }
00202
00203
00204 last_dyn_filter->rc_set_target(*p_interface_wrapper);
00205
00206 p_last_dyn_filter = last_dyn_filter;
00207
00208
00209 this->add_event_forwarder_target(
00210 *last_dyn_filter, last_dyn_filter->rc_get_event_filter());
00211
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
00220
00221 this->add_event_forwarder_target(
00222 *filters[i], filters[i]->rc_get_event_filter());
00223 }
00224
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
00235 p_dyn_accessor = dyn_accessor;
00236
00237 this->add_event_forwarder_target(
00238 *dyn_accessor, dyn_accessor->rc_get_event_filter());
00239
00240 p_dyn_module = &module;
00241
00242 p_state = rc_switch::OPEN;
00243
00244 if (sc_is_running()) {
00245 this->rc_on_open();
00246 }
00247 }
00248
00249 void rc_portal_base::close()
00250 {
00251
00252 if (p_state != rc_switch::CLOSED) {
00253
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
00260
00261
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
00268 this->clear_event_forwarder_targets();
00269
00270 p_state = rc_switch::CLOSED;
00271
00272 if (sc_is_running()) {
00273 this->rc_on_close();
00274 }
00275 }
00276 }
00277
00278 void rc_portal_base::set_undefined()
00279 {
00280
00281 if (p_state != rc_switch::UNDEF) {
00282
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
00298 this->clear_event_forwarder_targets();
00299
00300 p_state = rc_switch::UNDEF;
00301
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
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
00322 dyn_accessor->rc_clear_target();
00323 }
00324
00325 void rc_portal_base::unregister_reconfigurable(rc_reconfigurable& module)
00326 {
00327
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
00339
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
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
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 }
00375
00376
00377
00378