rc_process.cpp

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 #include "rc_process.h"
00038 
00039 namespace ReChannel {
00040 
00041 rc_process_control::rc_process_control(
00042     bool is_initially_active, bool deactivate_silently)
00043 :  p_activation_delta(0), p_cancel_flag(!is_initially_active),
00044    p_cancel_delta(0), p_deactivate_silently(deactivate_silently),
00045    p_parent(NULL)
00046 { }
00047 
00048 rc_process_control::rc_process_control(
00049     const rc_process_control& parent, bool is_initially_active,
00050     bool deactivate_silently)
00051 :  p_activation_delta(0), p_cancel_flag(!is_initially_active),
00052    p_cancel_delta(0), p_deactivate_silently(deactivate_silently),
00053    p_parent(&parent)
00054 {
00055     parent.p_child_set.insert(this);
00056 }
00057 
00058 rc_process_control::~rc_process_control()
00059 {
00060     if (p_parent != NULL) {
00061         p_parent->p_child_set.erase(this);
00062     }
00063     for (pctrl_set::iterator it=p_child_set.begin();
00064         it != p_child_set.end();
00065         ++it)
00066     {
00067         (*it)->p_parent = NULL;
00068     }
00069 }
00070 
00071 void rc_process_control::activate()
00072 {
00073     if (sc_is_running()) {
00074         rc_notify(p_activation_event);
00075         p_activation_delta = sc_delta_count();
00076     }
00077     p_cancel_flag = false;
00078 
00079     // activate dependent process controls
00080     for (pctrl_set::iterator it=p_child_set.begin();
00081         it != p_child_set.end();
00082         ++it)
00083     {
00084         (*it)->activate();
00085     }
00086 }
00087 
00088 void rc_process_control::deactivate()
00089 {
00090     if (sc_is_running()) {
00091         if (!p_deactivate_silently) {
00092             rc_notify(p_cancel_event);
00093         }
00094         p_cancel_delta = sc_delta_count();
00095     }
00096     p_cancel_flag = true;
00097 
00098     // deactivate dependent process controls
00099     for (pctrl_set::iterator it=p_child_set.begin();
00100         it != p_child_set.end();
00101         ++it)
00102     {
00103         rc_process_control* const pctrl = *it;
00104         pctrl->deactivate();
00105         if (pctrl->p_deactivate_silently) {
00106             //pctrl->p_cancel_event.notify(SC_ZERO_TIME);
00107             rc_notify(pctrl->p_cancel_event);
00108         }
00109     }
00110 }
00111 
00112 const sc_event rc_process_handle::s_never_notified;
00113 
00114 rc_process_registry* rc_process_registry::s_instance = NULL;
00115 
00116 rc_process_registry::rc_process_registry()
00117 {}
00118 
00119 rc_process_handle rc_process_registry::get_process_handle(
00120     const sc_process_handle& hproc, bool implicit_creation)
00121 {
00122     process_map::iterator it =
00123         p_process_map.find(hproc.get_process_object());
00124     if (it != p_process_map.end()) {
00125         return rc_process_handle(&it->second);
00126     } else if (implicit_creation) {
00127         return this->register_process(hproc);
00128     } else {
00129         return rc_process_handle();
00130     }
00131 }
00132 
00133 rc_process_handle rc_process_registry::register_process(
00134     const sc_process_handle& hproc)
00135 {
00136     if ((p_process_map.size() % gc_interval) == 0) {
00137         this->gc();
00138     }
00139     rc_process_info& pinfo = p_process_map[hproc.get_process_object()];
00140     pinfo.ref_count = 0;
00141     pinfo.handle = hproc;
00142     pinfo.dont_initialize = false;
00143     pinfo.is_cancelable = false;
00144     pinfo.is_terminated = false;
00145     pinfo.is_temporary = false;
00146     pinfo.cancel_event = NULL;
00147     pinfo.cancel_flag = NULL;
00148     pinfo.cancel_delta = NULL;
00149     pinfo.terminated_event = NULL;
00150     return rc_process_handle(pinfo);
00151 }
00152 
00153 rc_process_handle rc_process_registry::register_process(
00154     const sc_process_handle& hproc,
00155     bool dont_initialize, bool is_cancelable,
00156     const rc_process_control& pctrl, bool is_temporary)
00157 {
00158     if ((p_process_map.size() % gc_interval) == 0) {
00159         this->gc();
00160     }
00161     rc_process_info& pinfo = p_process_map[hproc.get_process_object()];
00162     pinfo.ref_count = 0;
00163     pinfo.handle = hproc;
00164     pinfo.dont_initialize = dont_initialize;
00165     pinfo.is_cancelable = is_cancelable;
00166     pinfo.is_terminated = false;
00167     pinfo.is_temporary = is_temporary;
00168     pinfo.cancel_event = &pctrl.p_cancel_event;
00169     pinfo.cancel_flag = &pctrl.p_cancel_flag;
00170     pinfo.cancel_delta = &pctrl.p_cancel_delta;
00171     pinfo.terminated_event = new sc_event(); // will be deleted by gc()
00172     return rc_process_handle(pinfo);
00173 }
00174 
00175 rc_process_handle rc_process_registry::register_process(
00176     const sc_process_handle& hproc,
00177     bool dont_initialize, bool is_cancelable,
00178     const sc_event* cancel_event, const bool* cancel_flag,
00179     const sc_dt::uint64* cancel_delta, bool is_temporary)
00180 {
00181     if ((p_process_map.size() % gc_interval) == 0) {
00182         this->gc();
00183     }
00184     rc_process_info& pinfo = p_process_map[hproc.get_process_object()];
00185     pinfo.ref_count = 0;
00186     pinfo.handle = hproc;
00187     pinfo.dont_initialize = dont_initialize;
00188     pinfo.is_cancelable = is_cancelable;
00189     pinfo.is_terminated = false;
00190     pinfo.is_temporary = is_temporary;
00191     pinfo.cancel_event = cancel_event;
00192     pinfo.cancel_flag = cancel_flag;
00193     pinfo.cancel_delta = cancel_delta;
00194     pinfo.terminated_event = new sc_event(); // will be deleted by gc()
00195     return rc_process_handle(pinfo);
00196 }
00197 
00198 void rc_process_registry::gc()
00199 {
00200     for(process_map::iterator it = p_process_map.begin();
00201         it != p_process_map.end();
00202         ++it)
00203     {
00204         rc_process_info& pinfo = it->second;
00205         // delete process if it is unreferenced and physically terminated
00206         if (pinfo.ref_count == 0 && pinfo.handle.terminated()) {
00207             if (pinfo.terminated_event != NULL) {
00208                 delete pinfo.terminated_event;
00209             }
00210             p_process_map.erase(it);
00211         }
00212     }
00213 }
00214 
00215 void rc_process_registry::_rc_create_singleton()
00216 {
00217     if (rc_process_registry::s_instance == NULL) {
00218         rc_process_registry::s_instance = new rc_process_registry();
00219     }
00220 }
00221 
00222 void rc_process_registry::_rc_wait_event_and_list_proc(
00223     sc_event_and_list& el,
00224     sc_event* continue_event)
00225 {
00226     std::auto_ptr<sc_event> delete_on_exit(continue_event);
00227     ::sc_core::wait(el);
00228     continue_event->notify();
00229 
00230     ::sc_core::wait(SC_ZERO_TIME); // (only for safety reasons)
00231     // delete continue_event
00232 }
00233 
00234 void rc_process_registry::_rc_wait_event_and_list_proc(
00235     const sc_time& t, sc_event_and_list& el,
00236     sc_event* continue_event)
00237 {
00238     std::auto_ptr<sc_event> delete_on_exit(continue_event);
00239     ::sc_core::wait(t, el);
00240     continue_event->notify();
00241 
00242     ::sc_core::wait(SC_ZERO_TIME); // (only for safety reasons)
00243     // delete continue_event
00244 }
00245 
00246 bool rc_process_handle::terminate()
00247 {
00248     if (p_proc_info != NULL
00249     && p_proc_info->terminated_event != NULL) {
00250         if (p_proc_info->is_terminated) {
00251             return true;
00252         }
00253         p_proc_info->is_terminated = true;
00254         p_proc_info->terminated_event->notify();
00255         throw new rc_process_cancel_exception();
00256     }
00257     return false;
00258 }
00259 
00260 void rc_process_handle::wait_terminated(const sc_event& reactivation_event)
00261 {
00262     if (p_proc_info != NULL
00263     && p_proc_info->terminated_event != NULL) {
00264         if (!p_proc_info->is_terminated) {
00265             p_proc_info->is_terminated = true;
00266             p_proc_info->terminated_event->notify();
00267         }
00268         ::sc_core::wait(reactivation_event);
00269         p_proc_info->is_terminated = false;
00270     } else {
00271         ::sc_core::wait(reactivation_event);
00272     }
00273 }
00274 
00275 rc_spawn_options::rc_spawn_options()
00276     : p_is_dont_initialize(false)
00277 { }
00278 
00279 void rc_spawn_options::set_reset_signal(
00280     const sc_in<bool>& reset_port_, bool active_level_)
00281 {
00282     p_reset_port_vector.push_back(
00283         reset_port_vector::value_type(&reset_port_, active_level_));
00284 }
00285 
00286 void rc_spawn_options::set_reset_signal(
00287     const sc_signal<bool>& reset_signal_, bool active_level_)
00288 {
00289     p_reset_signal_vector.push_back(
00290         reset_signal_vector::value_type(&reset_signal_, active_level_));
00291 }
00292 
00293 void rc_spawn_options::set_reset_signal(
00294     rc_reset_channel_if& reset_channel_, bool active_level_)
00295 {
00296     p_reset_channel_vector.push_back(
00297         reset_channel_vector::value_type(&reset_channel_, active_level_));
00298 }
00299 
00300 void rc_spawn_options::set_reset(rc_process_reset& process_reset_)
00301 {
00302     p_process_reset_vector.push_back(&process_reset_);
00303 }
00304 
00305 void rc_next_trigger()
00306 {
00307     sc_core::next_trigger();
00308 }
00309 
00310 void rc_next_trigger(const sc_event& e)
00311 {
00312     rc_process_handle hproc = rc_get_current_process_handle();
00313     if (hproc.is_cancelable()) {
00314         sc_core::next_trigger(e | hproc.get_cancel_trigger_event());
00315     } else {
00316         sc_core::next_trigger(e);
00317     }
00318 }
00319 
00320 void rc_next_trigger(sc_event_or_list& el)
00321 {
00322     rc_process_handle hproc = rc_get_current_process_handle();
00323     if (hproc.is_cancelable()) {
00324         sc_core::next_trigger(el | hproc.get_cancel_trigger_event());
00325     } else {
00326         sc_core::next_trigger(el);
00327     }
00328 }
00329 
00330 void rc_next_trigger(sc_event_and_list& el)
00331 {
00332     rc_process_handle hproc = rc_get_current_process_handle();
00333     if (hproc.is_cancelable()) {
00334         // omit time and effort if the process was already canceled
00335         if (!hproc.is_canceled()) {
00336             std::auto_ptr<sc_event> continue_event(new sc_event());
00337             sc_spawn(
00338                 sc_bind(
00339                     &rc_process_registry::_rc_wait_event_and_list_proc,
00340                     sc_ref(el), continue_event.get()));
00341             sc_core::next_trigger(
00342                 *(continue_event.release()) | hproc.get_cancel_trigger_event());
00343             // (continue_event will be deleted by the spawned process)
00344         } else {
00345             sc_core::next_trigger(el);
00346         }
00347     } else {
00348         sc_core::next_trigger(el);
00349     }
00350 }
00351 
00352 void rc_next_trigger(const sc_time& t)
00353 {
00354     rc_process_handle hproc = rc_get_current_process_handle();
00355     if (hproc.is_cancelable()) {
00356         sc_core::next_trigger(t, hproc.get_cancel_trigger_event());
00357     } else {
00358         sc_core::next_trigger(t);
00359     }
00360 }
00361 
00362 void rc_next_trigger(double v, sc_time_unit tu)
00363 {
00364     rc_next_trigger(sc_time(v, tu));
00365 }
00366 
00367 void rc_next_trigger(const sc_time& t, const sc_event& e)
00368 {
00369     rc_process_handle hproc = rc_get_current_process_handle();
00370     if (hproc.is_cancelable()) {
00371         sc_core::next_trigger(t, e | hproc.get_cancel_trigger_event());
00372     } else {
00373         sc_core::next_trigger(t, e);
00374     }
00375 }
00376 
00377 void rc_next_trigger(double v, sc_time_unit tu, const sc_event& e)
00378 {
00379     rc_next_trigger(sc_time(v, tu), e);
00380 }
00381 
00382 void rc_next_trigger(const sc_time& t, sc_event_or_list& el)
00383 {
00384     rc_process_handle hproc = rc_get_current_process_handle();
00385     if (hproc.is_cancelable()) {
00386         sc_core::next_trigger(t, el | hproc.get_cancel_trigger_event());
00387     } else {
00388         sc_core::next_trigger(t, el);
00389     }
00390 }
00391 
00392 void rc_next_trigger(double v, sc_time_unit tu, sc_event_or_list& el)
00393 {
00394     rc_next_trigger(sc_time(v, tu), el);
00395 }
00396 
00397 void rc_next_trigger(const sc_time& t, sc_event_and_list& el)
00398 {
00399     rc_process_handle hproc = rc_get_current_process_handle();
00400     if (hproc.is_cancelable()) {
00401         // omit time and effort if the process was already canceled
00402         if (!hproc.is_canceled()) {
00403             std::auto_ptr<sc_event> continue_event(new sc_event());
00404             sc_spawn(
00405                 sc_bind(
00406                     &rc_process_registry::_rc_wait_event_and_list_proc,
00407                     sc_cref(t), sc_ref(el), continue_event.get()));
00408             sc_core::next_trigger(
00409                 t, (*(continue_event.release())
00410                 | hproc.get_cancel_trigger_event()));
00411             // (continue_event will be deleted by the spawned process)
00412         } else {
00413             sc_core::next_trigger(t, el);
00414         }
00415     } else {
00416         sc_core::next_trigger(t, el);
00417     }
00418 }
00419 
00420 void rc_next_trigger(double v, sc_time_unit tu, sc_event_and_list& el)
00421 {
00422     rc_next_trigger(sc_time(v, tu), el);
00423 }
00424 
00425 void rc_wait()
00426 {
00427     rc_process_handle hproc = rc_get_current_process_handle();
00428     if (hproc.is_cancelable()) {
00429         if (hproc.is_canceled()) {
00430             throw new rc_process_cancel_exception();
00431         } else {
00432             ::sc_core::wait();
00433             if (hproc.is_canceled() || hproc.is_cancel_event()) {
00434                 throw new rc_process_cancel_exception();
00435             }
00436         }
00437     } else {
00438         ::sc_core::wait();
00439     }
00440 }
00441 
00442 void rc_wait(int n)
00443 {
00444     rc_process_handle hproc = rc_get_current_process_handle();
00445     if (hproc.is_cancelable() && n > 0) {
00446         if (hproc.is_canceled()) {
00447             throw new rc_process_cancel_exception();
00448         } else {
00449             for (int i=0; i < n; i++) {
00450                 ::sc_core::wait();
00451                 if (hproc.is_canceled() || hproc.is_cancel_event()) {
00452                     throw new rc_process_cancel_exception();
00453                 }
00454             }
00455         }
00456     } else {
00457         ::sc_core::wait(n);
00458     }
00459 }
00460 
00461 void rc_wait(const sc_event& e)
00462 {
00463     rc_process_handle hproc = rc_get_current_process_handle();
00464     if (hproc.is_cancelable()) {
00465         if (hproc.is_canceled()) {
00466             throw new rc_process_cancel_exception();
00467         } else {
00468             ::sc_core::wait(e | hproc.get_cancel_trigger_event());
00469             if (hproc.is_canceled() || hproc.is_cancel_event()) {
00470                 throw new rc_process_cancel_exception();
00471             }
00472         }
00473     } else {
00474         ::sc_core::wait(e);
00475     }
00476 }
00477 
00478 void rc_wait(sc_event_or_list& el)
00479 {
00480     rc_process_handle hproc = rc_get_current_process_handle();
00481     if (hproc.is_cancelable()) {
00482         if (hproc.is_canceled()) {
00483             throw new rc_process_cancel_exception();
00484         } else {
00485             ::sc_core::wait(el | hproc.get_cancel_trigger_event());
00486             if (hproc.is_canceled() || hproc.is_cancel_event()) {
00487                 throw new rc_process_cancel_exception();
00488             }
00489         }
00490     } else {
00491         ::sc_core::wait(el);
00492     }
00493 }
00494 
00495 void rc_wait(sc_event_and_list& el)
00496 {
00497     rc_process_handle hproc = rc_get_current_process_handle();
00498     if (hproc.is_cancelable()) {
00499         if (hproc.is_canceled()) {
00500             throw new rc_process_cancel_exception();
00501         } else {
00502             std::auto_ptr<sc_event> continue_event(new sc_event());
00503             sc_spawn_options opt;
00504             opt.set_stack_size(RC_PROCESS_TEMP_PROC_STACK_SIZE);
00505             sc_spawn(
00506                 sc_bind(
00507                     &rc_process_registry::_rc_wait_event_and_list_proc,
00508                     sc_ref(el), continue_event.get()),
00509                 NULL, &opt);
00510             ::sc_core::wait(
00511                 *(continue_event.release()) | hproc.get_cancel_trigger_event());
00512             // (continue_event will be deleted by the spawned process)
00513 
00514             if (hproc.is_canceled() || hproc.is_cancel_event()) {
00515                 throw new rc_process_cancel_exception();
00516             }
00517         }
00518     } else {
00519         ::sc_core::wait(el);
00520     }
00521 }
00522 
00523 void rc_wait(const sc_time& t)
00524 {
00525     rc_process_handle hproc = rc_get_current_process_handle();
00526     if (hproc.is_cancelable()) {
00527         if (hproc.is_canceled()) {
00528             throw new rc_process_cancel_exception();
00529         } else {
00530             ::sc_core::wait(t, hproc.get_cancel_trigger_event());
00531             if (hproc.is_canceled() || hproc.is_cancel_event()) {
00532                 throw new rc_process_cancel_exception();
00533             }
00534         }
00535     } else {
00536         ::sc_core::wait(t);
00537     }
00538 }
00539 
00540 void rc_wait(double v, sc_time_unit tu)
00541 {
00542     rc_wait(sc_time(v, tu));
00543 }
00544 
00545 void rc_wait(const sc_time& t, const sc_event& e)
00546 {
00547     rc_process_handle hproc = rc_get_current_process_handle();
00548     if (hproc.is_cancelable()) {
00549         if (hproc.is_canceled()) {
00550             throw new rc_process_cancel_exception();
00551         } else {
00552             ::sc_core::wait(t, e | hproc.get_cancel_trigger_event());
00553             if (hproc.is_canceled() || hproc.is_cancel_event()) {
00554                 throw new rc_process_cancel_exception();
00555             }
00556         }
00557     } else {
00558         ::sc_core::wait(t, e);
00559     }
00560 }
00561 
00562 void rc_wait(double v, sc_time_unit tu, const sc_event& e)
00563 {
00564     rc_wait(sc_time(v, tu), e);
00565 }
00566 
00567 void rc_wait(const sc_time& t, sc_event_or_list& el)
00568 {
00569     rc_process_handle hproc = rc_get_current_process_handle();
00570     if (hproc.is_cancelable()) {
00571         if (hproc.is_canceled()) {
00572             throw new rc_process_cancel_exception();
00573         } else {
00574             ::sc_core::wait(t, el | hproc.get_cancel_trigger_event());
00575             if (hproc.is_canceled() || hproc.is_cancel_event()) {
00576                 throw new rc_process_cancel_exception();
00577             }
00578         }
00579     } else {
00580         ::sc_core::wait(t, el);
00581     }
00582 }
00583 
00584 void rc_wait(double v, sc_time_unit tu, sc_event_or_list& el)
00585 {
00586     rc_wait(sc_time(v, tu), el);
00587 }
00588 
00589 void rc_wait(const sc_time& t, sc_event_and_list& el)
00590 {
00591     rc_process_handle hproc = rc_get_current_process_handle();
00592     if (hproc.is_cancelable()) {
00593         if (hproc.is_canceled()) {
00594             throw new rc_process_cancel_exception();
00595         } else {
00596             std::auto_ptr<sc_event> continue_event(new sc_event());
00597             sc_spawn_options opt;
00598             opt.set_stack_size(RC_PROCESS_TEMP_PROC_STACK_SIZE);
00599             sc_spawn(
00600                 sc_bind(
00601                     &rc_process_registry::_rc_wait_event_and_list_proc,
00602                     sc_cref(t), sc_ref(el), continue_event.get()),
00603                 NULL, &opt);
00604             ::sc_core::wait(
00605                 t, (*(continue_event.release())
00606                 | hproc.get_cancel_trigger_event()));
00607             // (continue_event will be deleted by the spawned process)
00608 
00609             if (hproc.is_canceled() || hproc.is_cancel_event()) {
00610                 throw new rc_process_cancel_exception();
00611             }
00612         }
00613     } else {
00614         ::sc_core::wait(t, el);
00615     }
00616 }
00617 
00618 void rc_wait(double v, sc_time_unit tu, sc_event_and_list& el)
00619 {
00620     rc_wait(sc_time(v, tu), el);
00621 }
00622 
00623 bool rc_is_update_phase()
00624 {
00625     static bool          s_is_update_phase = false;
00626     static sc_dt::uint64 s_last_delta = 0;
00627     static sc_event      s_test_event;
00628 
00629     if (s_is_update_phase == false
00630     || s_last_delta != sc_delta_count()) {
00631         try {
00632             s_test_event.notify();
00633             return false;
00634         } catch(sc_report r) {
00635             s_is_update_phase = true;
00636             s_last_delta = sc_delta_count();
00637         }
00638     }
00639     return true;
00640 }
00641 
00642 void rc_notify(sc_event& e)
00643 {
00644     static bool          s_is_update_phase = false;
00645     static sc_dt::uint64 s_last_delta = 0;
00646 
00647     if (s_is_update_phase == true) {
00648         if (s_last_delta == sc_delta_count()) {
00649             e.notify(SC_ZERO_TIME);
00650             return;
00651         } else {
00652             s_is_update_phase = false;
00653         }
00654     }
00655     try {
00656         e.notify();
00657     } catch(sc_report r) {
00658         s_is_update_phase = true;
00659         s_last_delta = sc_delta_count();
00660         e.notify(SC_ZERO_TIME);
00661     }
00662 }
00663 
00664 } // namespace ReChannel
00665 
00666 //
00667 // $Id: rc_process.cpp,v 1.9 2007/12/20 20:35:40 felke Exp $
00668 // $Source: /var/cvs/projekte/ReChannel-v2/src/ReChannel/core/rc_process.cpp,v $
00669 //

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