sc_event.cpp

Go to the documentation of this file.
00001 /*****************************************************************************
00002 
00003   The following code is derived, directly or indirectly, from the SystemC
00004   source code Copyright (c) 1996-2006 by all Contributors.
00005   All Rights reserved.
00006 
00007   The contents of this file are subject to the restrictions and limitations
00008   set forth in the SystemC Open Source License Version 2.4 (the "License");
00009   You may not use this file except in compliance with such restrictions and
00010   limitations. You may obtain instructions on how to receive a copy of the
00011   License at http://www.systemc.org/. Software distributed by Contributors
00012   under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF
00013   ANY KIND, either express or implied. See the License for the specific
00014   language governing rights and limitations under the License.
00015 
00016  *****************************************************************************/
00017 
00018 /*****************************************************************************
00019 
00020   sc_event.cpp --
00021 
00022   Original Author: Martin Janssen, Synopsys, Inc., 2001-05-21
00023 
00024  *****************************************************************************/
00025 
00026 /*****************************************************************************
00027 
00028   MODIFICATION LOG - modifiers, enter your name, affiliation, date and
00029   changes you are making here.
00030 
00031       Name, Affiliation, Date:
00032   Description of Modification:
00033 
00034  *****************************************************************************/
00035 
00036 
00037 // $Log: sc_event.cpp,v $
00038 // Revision 1.2  2007/01/12 21:04:53  acg
00039 //  Andy Goodrich: fix for Microsoft compiler.
00040 //
00041 // Revision 1.7  2006/04/11 23:13:20  acg
00042 //   Andy Goodrich: Changes for reduced reset support that only includes
00043 //   sc_cthread, but has preliminary hooks for expanding to method and thread
00044 //   processes also.
00045 //
00046 // Revision 1.6  2006/01/25 00:31:19  acg
00047 //  Andy Goodrich: Changed over to use a standard message id of
00048 //  SC_ID_IEEE_1666_DEPRECATION for all deprecation messages.
00049 //
00050 // Revision 1.5  2006/01/24 20:59:11  acg
00051 //  Andy Goodrich: fix up of CVS comments, new version roll.
00052 //
00053 // Revision 1.4  2006/01/24 20:48:14  acg
00054 // Andy Goodrich: added deprecation warnings for notify_delayed(). Added two
00055 // new implementation-dependent methods, notify_next_delta() & notify_internal()
00056 // to replace calls to notify_delayed() from within the simulator. These two
00057 // new methods are simpler than notify_delayed() and should speed up simulations
00058 //
00059 // Revision 1.3  2006/01/13 18:44:29  acg
00060 // Added $Log to record CVS changes into the source.
00061 //
00062 #include "sysc/kernel/sc_event.h"
00063 #include "sysc/kernel/sc_kernel_ids.h"
00064 #include "sysc/kernel/sc_process.h"
00065 #include "sysc/kernel/sc_simcontext_int.h"
00066 #include "sysc/utils/sc_utils_ids.h"
00067 
00068 namespace sc_core {
00069 
00070 // ----------------------------------------------------------------------------
00071 //  CLASS : sc_event
00072 //
00073 //  The event class.
00074 // ----------------------------------------------------------------------------
00075 
00076 void
00077 sc_event::cancel()
00078 {
00079     // cancel a delta or timed notification
00080     switch( m_notify_type ) {
00081     case DELTA: {
00082         // remove this event from the delta events set
00083         m_simc->remove_delta_event( this );
00084         m_notify_type = NONE;
00085         break;
00086     }
00087     case TIMED: {
00088         // remove this event from the timed events set
00089         assert( m_timed != 0 );
00090         m_timed->m_event = 0;
00091         m_timed = 0;
00092         m_notify_type = NONE;
00093         break;
00094     }
00095     default:
00096         ;
00097     }
00098 }
00099 
00100 
00101 void
00102 sc_event::notify()
00103 {
00104     // immediate notification
00105     if( m_simc->update_phase() ) {
00106         SC_REPORT_ERROR( SC_ID_IMMEDIATE_NOTIFICATION_, "" );
00107     }
00108     cancel();
00109     trigger();
00110 }
00111 
00112 void
00113 sc_event::notify( const sc_time& t )
00114 {
00115     if( m_notify_type == DELTA ) {
00116         return;
00117     }
00118     if( t == SC_ZERO_TIME ) {
00119         if( m_notify_type == TIMED ) {
00120             // remove this event from the timed events set
00121             assert( m_timed != 0 );
00122             m_timed->m_event = 0;
00123             m_timed = 0;
00124         }
00125         // add this event to the delta events set
00126         m_delta_event_index = m_simc->add_delta_event( this );
00127         m_notify_type = DELTA;
00128         return;
00129     }
00130     if( m_notify_type == TIMED ) {
00131         assert( m_timed != 0 );
00132         if( m_timed->m_notify_time <= m_simc->time_stamp() + t ) {
00133             return;
00134         }
00135         // remove this event from the timed events set
00136         m_timed->m_event = 0;
00137         m_timed = 0;
00138     }
00139     // add this event to the timed events set
00140     sc_event_timed* et = new sc_event_timed( this, m_simc->time_stamp() + t );
00141     m_simc->add_timed_event( et );
00142     m_timed = et;
00143     m_notify_type = TIMED;
00144 }
00145 
00146 static void sc_warn_notify_delayed()
00147 {
00148     static bool warn_notify_delayed=true;
00149     if ( warn_notify_delayed )
00150     {
00151         warn_notify_delayed = false;
00152         SC_REPORT_INFO(SC_ID_IEEE_1666_DEPRECATION_,
00153       "notify_delayed(...) is deprecated, use notify(sc_time) instead" );
00154     }
00155 }
00156 
00157 void
00158 sc_event::notify_delayed()
00159 {
00160     sc_warn_notify_delayed();
00161     if( m_notify_type != NONE ) {
00162         SC_REPORT_ERROR( SC_ID_NOTIFY_DELAYED_, 0 );
00163     }
00164     // add this event to the delta events set
00165     m_delta_event_index = m_simc->add_delta_event( this );
00166     m_notify_type = DELTA;
00167 }
00168 
00169 void
00170 sc_event::notify_delayed( const sc_time& t )
00171 {
00172     sc_warn_notify_delayed();
00173     if( m_notify_type != NONE ) {
00174         SC_REPORT_ERROR( SC_ID_NOTIFY_DELAYED_, 0 );
00175     }
00176     if( t == SC_ZERO_TIME ) {
00177         // add this event to the delta events set
00178         m_delta_event_index = m_simc->add_delta_event( this );
00179         m_notify_type = DELTA;
00180     } else {
00181         // add this event to the timed events set
00182         sc_event_timed* et = new sc_event_timed( this,
00183                                                  m_simc->time_stamp() + t );
00184         m_simc->add_timed_event( et );
00185         m_timed = et;
00186         m_notify_type = TIMED;
00187     }
00188 }
00189 
00190 void
00191 sc_event::reset()
00192 {
00193     m_notify_type = NONE;
00194     m_delta_event_index = -1;
00195     m_timed = 0;
00196     // clear the dynamic sensitive methods
00197     m_methods_dynamic.resize(0);
00198     // clear the dynamic sensitive threads
00199     m_threads_dynamic.resize(0);
00200 }
00201 
00202 
00203 void
00204 sc_event::trigger()
00205 {
00206     int size;
00207 
00208     // trigger the static sensitive methods
00209 
00210     if( ( size = m_methods_static.size() ) != 0 ) {
00211         sc_method_handle* l_methods_static = &m_methods_static[0];
00212         int i = size - 1;
00213         do {
00214             sc_method_handle method_h = l_methods_static[i];
00215             if( method_h->trigger_static() ) {
00216                 m_simc->push_runnable_method( method_h );
00217             }
00218         } while( -- i >= 0 );
00219     }
00220 
00221     // trigger the dynamic sensitive methods
00222 
00223     if( ( size = m_methods_dynamic.size() ) != 0 ) {
00224         sc_method_handle* l_methods_dynamic = &m_methods_dynamic[0];
00225         int i = size - 1;
00226         do {
00227             sc_method_handle method_h = l_methods_dynamic[i];
00228             if( method_h->trigger_dynamic( this ) ) {
00229                 m_simc->push_runnable_method( method_h );
00230             }
00231         } while( -- i >= 0 );
00232         m_methods_dynamic.resize(0);
00233     }
00234 
00235     // trigger the static sensitive threads
00236 
00237     if( ( size = m_threads_static.size() ) != 0 ) {
00238         sc_thread_handle* l_threads_static = &m_threads_static[0];
00239         int i = size - 1;
00240         do {
00241             sc_thread_handle thread_h = l_threads_static[i];
00242             if( thread_h->trigger_static() ) {
00243                 m_simc->push_runnable_thread( thread_h );
00244             }
00245         } while( -- i >= 0 );
00246     }
00247 
00248     // trigger the dynamic sensitive threads
00249 
00250     if( ( size = m_threads_dynamic.size() ) != 0 ) {
00251         sc_thread_handle* l_threads_dynamic = &m_threads_dynamic[0];
00252         int i = size - 1;
00253         do {
00254             sc_thread_handle thread_h = l_threads_dynamic[i];
00255             if( thread_h->trigger_dynamic( this ) ) {
00256                 m_simc->push_runnable_thread( thread_h );
00257             }
00258         } while( -- i >= 0 );
00259         m_threads_dynamic.resize(0);
00260     }
00261 
00262     m_notify_type = NONE;
00263     m_delta_event_index = -1;
00264     m_timed = 0;
00265 }
00266 
00267 
00268 bool
00269 sc_event::remove_static( sc_method_handle method_h_ ) const
00270 {
00271     int size;
00272     if ( ( size = m_methods_static.size() ) != 0 ) {
00273       sc_method_handle* l_methods_static = &m_methods_static[0];
00274       for( int i = size - 1; i >= 0; -- i ) {
00275           if( l_methods_static[i] == method_h_ ) {
00276               l_methods_static[i] = l_methods_static[size - 1];
00277               m_methods_static.resize(size-1);
00278               return true;
00279           }
00280       }
00281     }
00282     return false;
00283 }
00284 
00285 bool
00286 sc_event::remove_static( sc_thread_handle thread_h_ ) const
00287 {
00288     int size;
00289     if ( ( size = m_threads_static.size() ) != 0 ) {
00290       sc_thread_handle* l_threads_static = &m_threads_static[0];
00291       for( int i = size - 1; i >= 0; -- i ) {
00292           if( l_threads_static[i] == thread_h_ ) {
00293               l_threads_static[i] = l_threads_static[size - 1];
00294               m_threads_static.resize(size-1);
00295               return true;
00296           }
00297       }
00298     }
00299     return false;
00300 }
00301 
00302 bool
00303 sc_event::remove_dynamic( sc_method_handle method_h_ ) const
00304 {
00305     int size;
00306     if ( ( size = m_methods_dynamic.size() ) != 0 ) {
00307       sc_method_handle* l_methods_dynamic = &m_methods_dynamic[0];
00308       for( int i = size - 1; i >= 0; -- i ) {
00309           if( l_methods_dynamic[i] == method_h_ ) {
00310               l_methods_dynamic[i] = l_methods_dynamic[size - 1];
00311               m_methods_dynamic.resize(size-1);
00312               return true;
00313           }
00314       }
00315     }
00316     return false;
00317 }
00318 
00319 bool
00320 sc_event::remove_dynamic( sc_thread_handle thread_h_ ) const
00321 {
00322     int size;
00323     if ( ( size= m_threads_dynamic.size() ) != 0 ) {
00324       sc_thread_handle* l_threads_dynamic = &m_threads_dynamic[0];
00325       for( int i = size - 1; i >= 0; -- i ) {
00326           if( l_threads_dynamic[i] == thread_h_ ) {
00327               l_threads_dynamic[i] = l_threads_dynamic[size - 1];
00328               m_threads_dynamic.resize(size-1);
00329               return true;
00330           }
00331       }
00332     }
00333     return false;
00334 }
00335 
00336 
00337 // ----------------------------------------------------------------------------
00338 //  CLASS : sc_event_timed
00339 //
00340 //  Class for storing the time to notify a timed event.
00341 // ----------------------------------------------------------------------------
00342 
00343 // dedicated memory management; not MT-Safe
00344 
00345 union sc_event_timed_u
00346 {
00347     sc_event_timed_u* next;
00348     char              dummy[sizeof( sc_event_timed )];
00349 };
00350 
00351 static
00352 sc_event_timed_u* free_list = 0;
00353 
00354 void*
00355 sc_event_timed::allocate()
00356 {
00357     const int ALLOC_SIZE = 64;
00358 
00359     if( free_list == 0 ) {
00360         free_list = (sc_event_timed_u*) malloc( ALLOC_SIZE *
00361                                                 sizeof( sc_event_timed ) );
00362         int i = 0;
00363         for( ; i < ALLOC_SIZE - 1; ++ i ) {
00364             free_list[i].next = &free_list[i + 1];
00365         }
00366         free_list[i].next = 0;
00367     }
00368 
00369     sc_event_timed_u* q = free_list;
00370     free_list = free_list->next;
00371     return q;
00372 }
00373 
00374 void
00375 sc_event_timed::deallocate( void* p )
00376 {
00377     if( p != 0 ) {
00378         sc_event_timed_u* q = RCAST<sc_event_timed_u*>( p );
00379         q->next = free_list;
00380         free_list = q;
00381     }
00382 }
00383 
00384 
00385 // ----------------------------------------------------------------------------
00386 //  CLASS : sc_event_list
00387 //
00388 //  Base class for lists of events.
00389 // ----------------------------------------------------------------------------
00390 
00391 void
00392 sc_event_list::push_back( const sc_event& e )
00393 {
00394     // make sure e is not already in the list
00395     if ( m_events.size() != 0 ) {
00396       const sc_event** l_events = &m_events[0];
00397       for( int i = m_events.size() - 1; i >= 0; -- i ) {
00398           if( &e == l_events[i] ) {
00399               // event already in the list; ignore
00400               return;
00401           }
00402       }
00403     }
00404     m_events.push_back( &e );
00405 }
00406 
00407 
00408 void
00409 sc_event_list::add_dynamic( sc_method_handle method_h )
00410 {
00411     if ( m_events.size() != 0 ) {
00412       const sc_event** l_events = &m_events[0];
00413       for( int i = m_events.size() - 1; i >= 0; -- i ) {
00414           l_events[i]->add_dynamic( method_h );
00415       }
00416   }
00417 }
00418 
00419 void
00420 sc_event_list::add_dynamic( sc_thread_handle thread_h )
00421 {
00422     if ( m_events.size() != 0 ) {
00423       const sc_event** l_events = &m_events[0];
00424       for( int i = m_events.size() - 1; i >= 0; -- i ) {
00425           l_events[i]->add_dynamic( thread_h );
00426       }
00427   }
00428 }
00429 
00430 void
00431 sc_event_list::remove_dynamic( sc_method_handle method_h,
00432                                const sc_event* e_not )
00433 {
00434     if ( m_events.size() != 0 ) {
00435       const sc_event** l_events = &m_events[0];
00436       for( int i = m_events.size() - 1; i >= 0; -- i ) {
00437           const sc_event* e = l_events[i];
00438           if( e != e_not ) {
00439               e->remove_dynamic( method_h );
00440           }
00441       }
00442   }
00443 }
00444 
00445 void
00446 sc_event_list::remove_dynamic( sc_thread_handle thread_h,
00447                                const sc_event* e_not )
00448 {
00449     if ( m_events.size() != 0 ) {
00450       const sc_event** l_events = &m_events[0];
00451       for( int i = m_events.size() - 1; i >= 0; -- i ) {
00452           const sc_event* e = l_events[i];
00453           if( e != e_not ) {
00454               e->remove_dynamic( thread_h );
00455           }
00456       }
00457   }
00458 }
00459 
00460 // ----------------------------------------------------------------------------
00461 //  Deprecated functional notation for notifying events.
00462 // ----------------------------------------------------------------------------
00463 
00464 static void sc_warn_notify()
00465 {
00466     static bool warn_notify=true;
00467     if ( warn_notify )
00468     {
00469   SC_REPORT_INFO(SC_ID_IEEE_1666_DEPRECATION_,
00470       "the notify() function is deprecated use sc_event::notify()" );
00471   warn_notify = false;
00472     }
00473 }
00474 
00475 void
00476 notify( sc_event& e )
00477 {
00478     sc_warn_notify();
00479     e.notify();
00480 }
00481 
00482 void
00483 notify( const sc_time& t, sc_event& e )
00484 {
00485     sc_warn_notify();
00486     e.notify( t );
00487 }
00488 
00489 void
00490 notify( double v, sc_time_unit tu, sc_event& e )
00491 {
00492     sc_warn_notify();
00493     e.notify( v, tu );
00494 }
00495 
00496 } // namespace sc_core
00497 
00498 // Taf!

Generated on Wed Jan 21 15:32:09 2009 for SystemC by  doxygen 1.5.5