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_reconfigurable.h"
00038 #include "rc_control.h"
00039
00040 namespace ReChannel {
00041
00042 namespace internals {
00043 namespace reconfigurable {
00044
00045 rc_reconfigurable* begin_construction::s_current = NULL;
00046
00047 begin_construction::begin_construction(rc_reconfigurable& reconf)
00048 : p_previous(s_current), p_finished(false)
00049 {
00050 s_current = &reconf;
00051 }
00052
00053 void begin_construction::finish()
00054 {
00055 if (!p_finished) {
00056 s_current = p_previous;
00057 p_finished = true;
00058 }
00059 }
00060
00061 void begin_construction::finish(sc_object& reconf)
00062 {
00063 if (!p_finished) {
00064 if (s_current != NULL) {
00065 s_current->_rc_set_sc_object(reconf);
00066 }
00067 s_current = p_previous;
00068 p_finished = true;
00069 }
00070 }
00071
00072 }
00073 }
00074
00075 std::vector<rc_reconfigurable*> rc_reconfigurable::s_reconfigurables;
00076
00077 rc_reconfigurable::rc_reconfigurable(sc_object* this_)
00078 : p_sc_object(this_), p_is_no_sc_object(false),
00079 p_state(UNLOADED), p_next_state(UNLOADED),
00080 p_transaction_count(0),
00081 p_switch_commobj_index(p_switch_commobj_map.get<0>()),
00082 p_commobj_switch_index(p_switch_commobj_map.get<1>()),
00083 p_control(NULL), p_curr_switch_conn(NULL)
00084 {
00085 p_self_set.insert(*this);
00086
00087 p_delta_sync.set_callback(
00088 boost::bind(
00089 &rc_reconfigurable::_rc_delta_sync_state_change, this, _1));
00090
00091
00092 s_reconfigurables.push_back(this);
00093 }
00094
00095 rc_reconfigurable::~rc_reconfigurable()
00096 { }
00097
00098 std::string rc_reconfigurable::rc_get_name() const
00099 {
00100 const sc_object* const obj = this->rc_get_object();
00101 if (obj != NULL) {
00102 return obj->name();
00103 } else {
00104 return "(unknown)";
00105 }
00106 }
00107
00108 void rc_reconfigurable::bind(rc_switch_connector_base& switch_connector)
00109 {
00110 for (portmap_vector::iterator it = p_portmap_vector.begin();
00111 it != p_portmap_vector.end();
00112 ++it)
00113 {
00114 rc_portmap_base& portmap = *(*it);
00115 if (switch_connector.is_compatible(portmap)) {
00116 switch_connector.bind_dynamic(portmap);
00117 p_curr_switch_conn = &switch_connector;
00118 return;
00119 }
00120 }
00121 RC_REPORT_ERROR(RC_ID_SWITCH_CONNECTOR_BINDING_ERROR_,
00122 "incompatible switch connector '" << switch_connector.name() << "'"
00123 " (in reconfigurable '" << this->rc_get_name() << "')");
00124 }
00125
00126 void rc_reconfigurable::rc_register_switch(
00127 rc_switch& switch_obj, const rc_object_handle& bound_obj)
00128 {
00129 if (rc_is_registered(switch_obj)) {
00130 RC_REPORT_ERROR(RC_ID_SWITCH_BINDING_ERROR_,
00131 "switch '" << switch_obj.get_switch_name()
00132 << "' already registered at this reconfigurable object"
00133 " (in reconfigurable '" << this->rc_get_name() << "')");
00134 }
00135 sc_interface* dyn_if = bound_obj.get_interface();
00136 sc_interface* dyn_if_switch =
00137 switch_obj.get_registered_interface(*this);
00138 if (dyn_if == NULL) {
00139 RC_REPORT_ERROR(RC_ID_SWITCH_BINDING_ERROR_,
00140 "registration of switch '" << switch_obj.get_switch_name()
00141 << "' failed: no interface given"
00142 << " (in reconfigurable '" << this->rc_get_name() << "')");
00143 } else if (dyn_if_switch == NULL) {
00144 assert(dyn_if != NULL);
00145 switch_obj.register_reconfigurable(*this, *dyn_if);
00146 } else if (dyn_if_switch != dyn_if) {
00147 RC_REPORT_ERROR(RC_ID_SWITCH_BINDING_ERROR_,
00148 "registration of switch '" << switch_obj.get_switch_name()
00149 << "' failed: interface mismatch"
00150 << " (in reconfigurable '" << this->rc_get_name() << "')");
00151 }
00152 p_switch_commobj_index.insert(
00153 switch_commobj_pair(&switch_obj, bound_obj));
00154 }
00155
00156 bool rc_reconfigurable::rc_is_registered(rc_switch& switch_obj) const
00157 {
00158 return (p_switch_commobj_index.find(&switch_obj)
00159 != p_switch_commobj_index.end());
00160 }
00161
00162 void rc_reconfigurable::rc_register_resettable(rc_resettable& resettable)
00163 {
00164 p_resettable_set.insert(&resettable);
00165 }
00166
00167 bool rc_reconfigurable::rc_is_registered(rc_resettable& resettable) const
00168 {
00169 return (p_resettable_set.find(&resettable) != p_resettable_set.end());
00170 }
00171
00172 void rc_reconfigurable::rc_possible_deactivation()
00173 {
00174
00175
00176 if ((p_transaction_count == 0 && rc_is_deactivation_requested())
00177 || rc_get_state() != ACTIVE) {
00178 const rc_process_handle hproc = rc_get_current_process_handle();
00179
00180 if (hproc.proc_kind() == SC_THREAD_PROC_) {
00181
00182 rc_wait(p_pctrl.get_deactivation_event());
00183
00184 if (!p_pctrl.is_active()) {
00185
00186 rc_wait(p_pctrl.get_activation_event());
00187 }
00188 }
00189 }
00190 }
00191
00192 void rc_reconfigurable::rc_possible_deactivation_delta()
00193 {
00194
00195 if (rc_is_deactivation_requested() || rc_get_state() != ACTIVE) {
00196 const rc_process_handle hproc = rc_get_current_process_handle();
00197
00198 if (hproc.proc_kind() == SC_THREAD_PROC_) {
00199
00200 rc_wait(SC_ZERO_TIME);
00201 }
00202 }
00203 }
00204
00205 void rc_reconfigurable::rc_set_delay(action_type a, sc_time t)
00206 {
00207 p_action_delays[a] = t;
00208 if (p_control == NULL) {
00209 p_action_default_delays[a] = t;
00210 }
00211 }
00212
00213 void rc_reconfigurable::rc_add_filter(
00214 const rc_object_handle& commobj_, rc_interface_filter& filter_)
00215 {
00216
00217 if (this->rc_has_filter(filter_)) {
00218 RC_REPORT_ERROR(RC_ID_DUPLICATE_ENTRY_,
00219 "filter already added"
00220 " (in reconfigurable '" << this->rc_get_name() << "')");
00221 }
00222
00223
00224 p_filter_set.insert(&filter_);
00225 p_commobj_filters_map[commobj_].push_back(&filter_);
00226 }
00227
00228 int rc_reconfigurable::rc_get_filter_count(
00229 const rc_object_handle& commobj_) const
00230 {
00231 commobj_filters_map::const_iterator it =
00232 p_commobj_filters_map.find(commobj_);
00233 if (it != p_commobj_filters_map.end()) {
00234 return it->second.size();
00235 } else {
00236 return 0;
00237 }
00238 }
00239
00240 rc_reconfigurable::filter_chain
00241 rc_reconfigurable::rc_get_filter_chain(
00242 const rc_object_handle& commobj_) const
00243 {
00244 commobj_filters_map::const_iterator it =
00245 p_commobj_filters_map.find(commobj_);
00246 return (it != p_commobj_filters_map.end()
00247 ? it->second : filter_chain());
00248 }
00249
00250 bool rc_reconfigurable::rc_has_filter(rc_interface_filter& filter_) const
00251 {
00252 return (p_filter_set.find(&filter_) != p_filter_set.end());
00253 }
00254
00255 void rc_reconfigurable::rc_refresh_notify(
00256 const rc_object_handle& commobj_)
00257 {
00258 commobj_switch_range range =
00259 p_commobj_switch_index.equal_range(commobj_);
00260 for (commobj_switch_index::iterator it = range.first;
00261 it != range.second;
00262 ++it)
00263 {
00264 it->first->refresh_notify();
00265 }
00266 }
00267
00268 void rc_reconfigurable::rc_refresh_notify_all()
00269 {
00270 for (switch_commobj_index::iterator it =
00271 p_switch_commobj_index.begin();
00272 it != p_switch_commobj_index.end();
00273 ++it)
00274 {
00275 it->first->refresh_notify();
00276 }
00277 }
00278
00279 void rc_reconfigurable::start_of_simulation()
00280 {
00281
00282 for (resettable_set::const_iterator it = p_resettable_set.begin();
00283 it != p_resettable_set.end();
00284 ++it)
00285 {
00286 (*it)->rc_on_init_resettable();
00287 }
00288
00289
00290 switch(p_state) {
00291 case INACTIVE:
00292 change_switch_state(rc_switch::CLOSED);
00293 break;
00294 case ACTIVE:
00295 change_switch_state(rc_switch::OPEN);
00296 break;
00297 default:
00298 break;
00299 }
00300
00301
00302 if (rc_is_active()) {
00303 p_pctrl.activate();
00304 }
00305 }
00306
00307 void rc_reconfigurable::reconfigure(state_type new_state)
00308 {
00309 const bool has_lock_share_ = has_lock_share();
00310 if (!has_lock_share_) {
00311 p_mutex.lock();
00312 }
00313 try {
00314 switch(p_state) {
00315 case UNLOADED:
00316 switch(new_state) {
00317 case INACTIVE:
00318 _rc_load();
00319 break;
00320 case ACTIVE:
00321 _rc_load();
00322 _rc_activate();
00323 break;
00324 default:
00325 break;
00326 }
00327 break;
00328 case INACTIVE:
00329 switch(new_state) {
00330 case UNLOADED:
00331 _rc_unload();
00332 break;
00333 case ACTIVE:
00334 _rc_activate();
00335 break;
00336 default:
00337 break;
00338 }
00339 break;
00340 case ACTIVE:
00341 switch(new_state) {
00342 case UNLOADED:
00343 _rc_deactivate();
00344 _rc_unload();
00345 break;
00346 case INACTIVE:
00347 _rc_deactivate();
00348 break;
00349 default:
00350 break;
00351 }
00352 break;
00353 }
00354 } catch(...) {
00355 if (!has_lock_share_) {
00356 p_mutex.unlock();
00357 }
00358 throw;
00359 }
00360 if (!has_lock_share_) {
00361 p_mutex.unlock();
00362 }
00363 }
00364
00365 void rc_reconfigurable::change_switch_state(
00366 rc_switch::state_type new_state)
00367 {
00368 for (switch_commobj_index::iterator it =
00369 p_switch_commobj_index.begin();
00370 it != p_switch_commobj_index.end();
00371 ++it)
00372 {
00373 rc_switch& switch_ = *(it->first);
00374
00375 switch(new_state) {
00376 case rc_switch::OPEN:
00377 {
00378
00379 commobj_filters_map::const_iterator it2 =
00380 p_commobj_filters_map.find(it->second);
00381
00382 if (it2 != p_commobj_filters_map.end()) {
00383
00384 switch_.open(*this, it2->second);
00385 } else {
00386
00387 switch_.open(*this);
00388 }
00389 break;
00390 }
00391 case rc_switch::CLOSED:
00392
00393 switch_.close();
00394 break;
00395 case rc_switch::UNDEF:
00396
00397 switch_.set_undefined();
00398 break;
00399 }
00400 }
00401 }
00402
00403 void rc_reconfigurable::move(switch_conn_type& target)
00404 {
00405 assert(!(rc_is_loaded() || rc_is_state_changing()));
00406
00407 rc_portmap_base* const portmap = _rc_get_compatible_portmap(target);
00408 if (portmap == NULL) {
00409 RC_REPORT_ERROR(RC_ID_SWITCH_CONNECTOR_INCOMPATIBLE_ERROR_,
00410 "switch connector '" << target.name() << "' is incompatible"
00411 << " (in reconfigurable '" << this->rc_get_name() << "')");
00412 }
00413 if (p_curr_switch_conn != &target) {
00414 p_curr_switch_conn = NULL;
00415 const int count = portmap->size();
00416 for (int i=0; i < count; i++) {
00417
00418 rc_object_handle commobj = portmap->get(i);
00419
00420 commobj_switch_index::iterator it =
00421 p_commobj_switch_index.find(commobj);
00422 if (it != p_commobj_switch_index.end()) {
00423 rc_switch& switch_ = *it->first;
00424 switch_.unregister_reconfigurable(*this);
00425 p_commobj_switch_index.erase(it);
00426 }
00427
00428 rc_switch& switch_ = target[i];
00429 sc_interface* const if_ = commobj.get_interface();
00430 assert(if_ != NULL);
00431 switch_.register_reconfigurable(*this, *if_);
00432 p_commobj_switch_index.insert(
00433 commobj_switch_index::value_type(&switch_, commobj));
00434 }
00435 p_curr_switch_conn = ⌖
00436 }
00437 }
00438
00439 bool rc_reconfigurable::unlock()
00440 {
00441 const bool has_unlocked = p_mutex.unlock();
00442 if (has_unlocked && p_lock_share.valid()) {
00443 p_lock_share = sc_process_handle();
00444 }
00445 return has_unlocked;
00446 }
00447
00448 bool rc_reconfigurable::share_lock(sc_process_handle proc)
00449 {
00450 if (p_mutex.has_lock()) {
00451 p_lock_share = proc;
00452 return true;
00453 } else {
00454 return false;
00455 }
00456 }
00457
00458 bool rc_reconfigurable::reset_lock_share()
00459 {
00460 if (p_mutex.has_lock()) {
00461 p_lock_share = sc_process_handle();
00462 return true;
00463 } else {
00464 return false;
00465 }
00466 }
00467
00468 bool rc_reconfigurable::lock_switches(bool report_error)
00469 {
00470 int unlocked_count = 0;
00471
00472 for (switch_commobj_index::iterator it =
00473 p_switch_commobj_index.begin();
00474 it != p_switch_commobj_index.end();
00475 ++it)
00476 {
00477 rc_switch& switch_ = *(it->first);
00478
00479 if (!switch_.is_lock_owner(*this)) {
00480 if (!switch_.is_locked()) {
00481 ++unlocked_count;
00482 } else {
00483
00484 if (report_error) {
00485 RC_REPORT_ERROR(RC_ID_SWITCH_CONFLICT_,
00486 "switch '" << switch_.get_switch_name()
00487 << "' is already in use by another reconfigurable object"
00488 << " (in reconfigurable '" << this->rc_get_name()
00489 << "')");
00490 } else {
00491 return false;
00492 }
00493 }
00494 }
00495 }
00496
00497 if (unlocked_count > 0) {
00498 bool succ = false;
00499 for (switch_commobj_index::iterator it =
00500 p_switch_commobj_index.begin();
00501 it != p_switch_commobj_index.end();
00502 ++it)
00503 {
00504 rc_switch& switch_ = *(it->first);
00505
00506
00507 succ = switch_.set_locked(*this, true);
00508 assert(succ == true);
00509 }
00510 }
00511 return true;
00512 }
00513
00514 void rc_reconfigurable::unlock_switches()
00515 {
00516
00517 for (switch_commobj_index::iterator it =
00518 p_switch_commobj_index.begin();
00519 it != p_switch_commobj_index.end();
00520 ++it)
00521 {
00522 rc_switch& switch_ = *(it->first);
00523 switch_.set_locked(*this, false);
00524 }
00525 }
00526
00527 void rc_reconfigurable::reset_transaction_count()
00528 {
00529 p_transaction_count = 0;
00530 if (rc_is_deactivation_requested()) {
00531 p_delta_sync.request_update();
00532 }
00533 }
00534
00535 void rc_reconfigurable::rc_add_portmap(rc_portmap_base& portmap)
00536 {
00537 sc_object* const this_obj = this->rc_get_object();
00538 if (dynamic_cast<sc_module*>(this_obj) == NULL) {
00539 RC_REPORT_ERROR(RC_ID_INVALID_USAGE_,
00540 "this reconfigurable is incapable of attaching a port map"
00541 " (in reconfigurable '" << this->rc_get_name() << "')");
00542 }
00543 const unsigned int count = portmap.size();
00544 for(unsigned int i=0; i < count; ++i) {
00545 sc_object& obj = portmap.get_object(i);
00546 if (obj.get_parent_object() != this_obj) {
00547 RC_REPORT_ERROR(RC_ID_PORTMAP_INCOMPATIBLE_ERROR_,
00548 "port map contains an object from a different parent"
00549 " (in reconfigurable '" << this->rc_get_name()
00550 << "', at index: " << i <<")");
00551 }
00552 }
00553 const int found_index = this->_rc_is_compatible(portmap);
00554 if (found_index >= 0) {
00555 if (p_portmap_vector[found_index] != &portmap) {
00556 RC_REPORT_ERROR(RC_ID_DUPLICATE_ENTRY_,
00557 "port map with identical type already registered"
00558 " (in reconfigurable '" << this->rc_get_name() << "')");
00559 }
00560 return;
00561 }
00562
00563 p_portmap_vector.push_back(&portmap);
00564 }
00565
00566 void rc_reconfigurable::rc_clear_portmaps()
00567 {
00568 p_portmap_vector.clear();
00569 }
00570
00571 rc_portmap_base& rc_reconfigurable::get_portmap(int index)
00572 {
00573 assert(index < 0 || index >= (int)p_portmap_vector.size());
00574 return *(p_portmap_vector[index]);
00575 }
00576
00577 int rc_reconfigurable::_rc_is_compatible(
00578 const rc_portmap_base& portmap) const
00579 {
00580 const int count = (int)p_portmap_vector.size();
00581 for (int i=0; i < count; ++i) {
00582 if (portmap.is_compatible(*p_portmap_vector[i])) {
00583 return i;
00584 }
00585 }
00586 return -1;
00587 }
00588
00589 rc_portmap_base* rc_reconfigurable::_rc_get_compatible_portmap(
00590 const rc_switch_connector_base& switch_conn) const
00591 {
00592 const int count = (int)p_portmap_vector.size();
00593 for (int i=0; i < count; ++i) {
00594 rc_portmap_base* const portmap = p_portmap_vector[i];
00595 if (switch_conn.is_compatible(*portmap)) {
00596 return portmap;
00597 }
00598 }
00599 return NULL;
00600 }
00601
00602 void rc_reconfigurable::_rc_set_sc_object(sc_object& reconf)
00603 {
00604 if (p_sc_object == NULL) {
00605 p_sc_object = &reconf;
00606 p_is_no_sc_object = false;
00607 }
00608 }
00609
00610 const sc_object* rc_reconfigurable::rc_get_object() const
00611 {
00612 sc_object* obj = p_sc_object;
00613 if (obj == NULL) {
00614 if (!p_is_no_sc_object) {
00615 obj = dynamic_cast<sc_object*>(
00616 const_cast<rc_reconfigurable*>(this));
00617 if (obj != NULL) {
00618 p_sc_object = obj;
00619 } else {
00620 p_is_no_sc_object = true;
00621 }
00622 }
00623 }
00624 return obj;
00625 }
00626
00627 sc_object* rc_reconfigurable::rc_get_object()
00628 {
00629 sc_object* obj = p_sc_object;
00630 if (obj == NULL) {
00631 if (!p_is_no_sc_object) {
00632 obj = dynamic_cast<sc_object*>(this);
00633 if (obj != NULL) {
00634 p_sc_object = obj;
00635 } else {
00636 p_is_no_sc_object = true;
00637 }
00638 }
00639 }
00640 return obj;
00641 }
00642
00643 void rc_reconfigurable::_rc_delta_sync_state_change(
00644 rc_delta_sync_object& delta_sync)
00645 {
00646 assert(&delta_sync == &p_delta_sync);
00647
00648 if (p_state == INACTIVE && p_next_state == ACTIVE) {
00649
00650 p_state = ACTIVE;
00651 p_delta_sync.set_enabled(false);
00652 p_pctrl.activate();
00653 change_switch_state(rc_switch::OPEN);
00654 } else if (p_state == ACTIVE && p_next_state == INACTIVE) {
00655
00656 if (p_transaction_count == 0) {
00657
00658 p_state = INACTIVE;
00659 p_delta_sync.set_enabled(false);
00660 p_pctrl.deactivate();
00661 change_switch_state(rc_switch::CLOSED);
00662 }
00663 } else {
00664 RC_REPORT_ERROR(RC_ID_INTERNAL_ERROR_, "internal error");
00665 }
00666 }
00667
00668 void rc_reconfigurable::_rc_unload()
00669 {
00670 p_next_state = UNLOADED;
00671 if (sc_is_running()) {
00672 sc_time delay = rc_get_delay(UNLOAD);
00673 if (delay != SC_ZERO_TIME) {
00674 ::sc_core::wait(delay);
00675 }
00676 p_state = UNLOADED;
00677 unlock_switches();
00678 rc_on_unload();
00679 } else {
00680 p_state = UNLOADED;
00681 unlock_switches();
00682 }
00683 }
00684
00685 void rc_reconfigurable::_rc_load()
00686 {
00687 p_next_state = INACTIVE;
00688 lock_switches(true);
00689 if (sc_is_running()) {
00690 sc_time delay = rc_get_delay(LOAD);
00691 if (delay != SC_ZERO_TIME) {
00692 ::sc_core::wait(delay);
00693 }
00694 p_state = INACTIVE;
00695 rc_on_load();
00696 } else {
00697 p_state = INACTIVE;
00698 }
00699 }
00700
00701 void rc_reconfigurable::_rc_activate()
00702 {
00703 p_next_state = ACTIVE;
00704 if (sc_is_running()) {
00705
00706 _rc_reset();
00707
00708 ::sc_core::wait(rc_get_delay(ACTIVATE));
00709
00710 p_delta_sync.set_enabled(true);
00711 p_delta_sync.request_update();
00712 ::sc_core::wait(p_pctrl.get_activation_event());
00713 assert(p_state == ACTIVE);
00714 rc_on_activate();
00715 } else {
00716 p_state = ACTIVE;
00717 }
00718 }
00719
00720 void rc_reconfigurable::_rc_deactivate()
00721 {
00722 p_next_state = INACTIVE;
00723 if (sc_is_running()) {
00724 p_delta_sync.set_enabled(true);
00725 p_delta_sync.request_update();
00726 ::sc_core::wait(p_pctrl.get_deactivation_event());
00727 assert(p_state == INACTIVE);
00728 sc_time delay = rc_get_delay(DEACTIVATE);
00729 if (delay != SC_ZERO_TIME) {
00730 ::sc_core::wait(delay);
00731 }
00732 rc_on_deactivate();
00733 _rc_reset();
00734 } else {
00735 p_state = INACTIVE;
00736 }
00737 }
00738
00739 void rc_reconfigurable::_rc_reset()
00740 {
00741 const sc_dt::uint64 curr_delta = sc_delta_count();
00742 const sc_time start_time = sc_time_stamp();
00743 bool has_consumed_deltas = false;
00744
00745
00746 for (resettable_set::const_iterator it = p_resettable_set.begin();
00747 it != p_resettable_set.end();
00748 ++it)
00749 {
00750
00751 (*it)->rc_on_reset();
00752
00753
00754 if (has_consumed_deltas == false
00755 && sc_delta_count() != curr_delta)
00756 {
00757 has_consumed_deltas = true;
00758 }
00759 }
00760
00761 if (has_consumed_deltas) {
00762 const sc_time time_consumed = sc_time_stamp() - start_time;
00763 if (time_consumed > SC_ZERO_TIME) {
00764 RC_REPORT_WARNING(
00765 RC_ID_TIME_CONSUMED_WARNING_,
00766 "resetting the resettable objects"
00767 << " consumed time (in reconfigurable '"
00768 << this->rc_get_name() << "')");
00769 } else {
00770 RC_REPORT_WARNING(
00771 RC_ID_DELTAS_CONSUMED_WARNING_,
00772 "resetting the resettable objects"
00773 << " consumed one or more delta cycles"
00774 << " (in reconfigurable '"
00775 << this->rc_get_name() << "')");
00776 }
00777 }
00778 }
00779
00780 rc_transaction::~rc_transaction()
00781 {
00782 if (!p_has_ended && reconf != NULL) {
00783 reconf->rc_end_transaction();
00784 }
00785 }
00786
00787 rc_reconfigurable* rc_get_reconfigurable_context()
00788 {
00789 using namespace internals::reconfigurable;
00790
00791 if (begin_construction::s_current != NULL) {
00792 return begin_construction::s_current;
00793 }
00794
00795 sc_object* start_search = NULL;
00796 if (!sc_is_running()) {
00797 std::auto_ptr<temporary_object> tmp_obj(
00798 new temporary_object());
00799 start_search = tmp_obj->get_parent_object();
00800 } else {
00801 start_search =
00802 sc_get_current_process_handle().get_parent_object();
00803 }
00804 return rc_get_reconfigurable_context(start_search);
00805 }
00806
00807 rc_reconfigurable* rc_get_reconfigurable_context(sc_object* start_search)
00808 {
00809 using namespace internals::reconfigurable;
00810
00811 static sc_object* s_cached_search = NULL;
00812 static rc_reconfigurable* s_cached_result = NULL;
00813
00814 if (begin_construction::s_current != NULL) {
00815 return begin_construction::s_current;
00816 }
00817
00818 if (start_search != NULL) {
00819 if (start_search == s_cached_search) {
00820 return s_cached_result;
00821 }
00822 rc_reconfigurable* reconf =
00823 dynamic_cast<rc_reconfigurable*>(start_search);
00824 if (reconf == NULL) {
00825 if (start_search->get_parent_object() == s_cached_search) {
00826 return s_cached_result;
00827 }
00828 while(start_search != NULL
00829 && (reconf = dynamic_cast<rc_reconfigurable*>(
00830 start_search = start_search->get_parent_object()))
00831 == NULL);
00832 }
00833 s_cached_search = start_search;
00834 s_cached_result = reconf;
00835 return reconf;
00836 } else {
00837 return NULL;
00838 }
00839 }
00840
00841 const rc_reconfigurable* rc_register_resettable(
00842 rc_resettable& resettable, sc_object* search_start)
00843 {
00844 rc_reconfigurable* const reconf =
00845 rc_get_reconfigurable_context(search_start);
00846 if (reconf != NULL) {
00847 reconf->rc_register_resettable(resettable);
00848 }
00849 return reconf;
00850 }
00851
00852 }
00853
00854
00855
00856
00857