| /***************************************************************************** | |
| Licensed to Accellera Systems Initiative Inc. (Accellera) under one or | |
| more contributor license agreements. See the NOTICE file distributed | |
| with this work for additional information regarding copyright ownership. | |
| Accellera licenses this file to you under the Apache License, Version 2.0 | |
| (the "License"); you may not use this file except in compliance with the | |
| License. You may obtain a copy of the License at | |
| http://www.apache.org/licenses/LICENSE-2.0 | |
| Unless required by applicable law or agreed to in writing, software | |
| distributed under the License is distributed on an "AS IS" BASIS, | |
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or | |
| implied. See the License for the specific language governing | |
| permissions and limitations under the License. | |
| *****************************************************************************/ | |
| /***************************************************************************** | |
| sc_event.cpp -- | |
| Original Author: Martin Janssen, Synopsys, Inc., 2001-05-21 | |
| CHANGE LOG APPEARS AT THE END OF THE FILE | |
| *****************************************************************************/ | |
| #include <stdlib.h> | |
| #include <string.h> | |
| #include "sysc/kernel/sc_event.h" | |
| #include "sysc/kernel/sc_kernel_ids.h" | |
| #include "sysc/kernel/sc_phase_callback_registry.h" | |
| #include "sysc/kernel/sc_process.h" | |
| #include "sysc/kernel/sc_process_handle.h" | |
| #include "sysc/kernel/sc_simcontext_int.h" | |
| #include "sysc/kernel/sc_object_manager.h" | |
| #include "sysc/utils/sc_utils_ids.h" | |
| namespace sc_core { | |
| // ---------------------------------------------------------------------------- | |
| // CLASS : sc_event | |
| // | |
| // The event class. | |
| // ---------------------------------------------------------------------------- | |
| const char* | |
| sc_event::basename() const | |
| { | |
| const char* p = strrchr( m_name.c_str(), SC_HIERARCHY_CHAR ); | |
| return p ? (p + 1) : m_name.c_str(); | |
| } | |
| void | |
| sc_event::cancel() | |
| { | |
| // cancel a delta or timed notification | |
| switch( m_notify_type ) { | |
| case DELTA: { | |
| // remove this event from the delta events set | |
| m_simc->remove_delta_event( this ); | |
| m_notify_type = NONE; | |
| break; | |
| } | |
| case TIMED: { | |
| // remove this event from the timed events set | |
| sc_assert( m_timed != 0 ); | |
| m_timed->m_event = 0; | |
| m_timed = 0; | |
| m_notify_type = NONE; | |
| break; | |
| } | |
| default: | |
| ; | |
| } | |
| } | |
| void | |
| sc_event::notify() | |
| { | |
| // immediate notification | |
| if( | |
| // coming from sc_prim_channel::update | |
| m_simc->update_phase() | |
| #if SC_HAS_PHASE_CALLBACKS_ | |
| // coming from phase callbacks | |
| || m_simc->notify_phase() | |
| #endif | |
| ) | |
| { | |
| SC_REPORT_ERROR( SC_ID_IMMEDIATE_NOTIFICATION_, "" ); | |
| return; | |
| } | |
| cancel(); | |
| trigger(); | |
| } | |
| void | |
| sc_event::notify( const sc_time& t ) | |
| { | |
| if( m_notify_type == DELTA ) { | |
| return; | |
| } | |
| if( t == SC_ZERO_TIME ) { | |
| # if SC_HAS_PHASE_CALLBACKS_ | |
| if( SC_UNLIKELY_( m_simc->get_status() | |
| & (SC_END_OF_UPDATE|SC_BEFORE_TIMESTEP) ) ) | |
| { | |
| std::stringstream msg; | |
| msg << m_simc->get_status() | |
| << ":\n\t delta notification of `" | |
| << name() << "' ignored"; | |
| SC_REPORT_WARNING( SC_ID_PHASE_CALLBACK_FORBIDDEN_ | |
| , msg.str().c_str() ); | |
| return; | |
| } | |
| # endif | |
| if( m_notify_type == TIMED ) { | |
| // remove this event from the timed events set | |
| sc_assert( m_timed != 0 ); | |
| m_timed->m_event = 0; | |
| m_timed = 0; | |
| } | |
| // add this event to the delta events set | |
| m_delta_event_index = m_simc->add_delta_event( this ); | |
| m_notify_type = DELTA; | |
| return; | |
| } | |
| # if SC_HAS_PHASE_CALLBACKS_ | |
| if( SC_UNLIKELY_( m_simc->get_status() | |
| & (SC_END_OF_UPDATE|SC_BEFORE_TIMESTEP) ) ) | |
| { | |
| std::stringstream msg; | |
| msg << m_simc->get_status() | |
| << ":\n\t timed notification of `" | |
| << name() << "' ignored"; | |
| SC_REPORT_WARNING( SC_ID_PHASE_CALLBACK_FORBIDDEN_ | |
| , msg.str().c_str() ); | |
| return; | |
| } | |
| # endif | |
| if( m_notify_type == TIMED ) { | |
| sc_assert( m_timed != 0 ); | |
| if( m_timed->m_notify_time <= m_simc->time_stamp() + t ) { | |
| return; | |
| } | |
| // remove this event from the timed events set | |
| m_timed->m_event = 0; | |
| m_timed = 0; | |
| } | |
| // add this event to the timed events set | |
| sc_event_timed* et = new sc_event_timed( this, m_simc->time_stamp() + t ); | |
| m_simc->add_timed_event( et ); | |
| m_timed = et; | |
| m_notify_type = TIMED; | |
| } | |
| static void sc_warn_notify_delayed() | |
| { | |
| static bool warn_notify_delayed=true; | |
| if ( warn_notify_delayed ) | |
| { | |
| warn_notify_delayed = false; | |
| SC_REPORT_INFO(SC_ID_IEEE_1666_DEPRECATION_, | |
| "notify_delayed(...) is deprecated, use notify(sc_time) instead" ); | |
| } | |
| } | |
| void | |
| sc_event::notify_delayed() | |
| { | |
| sc_warn_notify_delayed(); | |
| if( m_notify_type != NONE ) { | |
| SC_REPORT_ERROR( SC_ID_NOTIFY_DELAYED_, 0 ); | |
| } | |
| // add this event to the delta events set | |
| m_delta_event_index = m_simc->add_delta_event( this ); | |
| m_notify_type = DELTA; | |
| } | |
| void | |
| sc_event::notify_delayed( const sc_time& t ) | |
| { | |
| sc_warn_notify_delayed(); | |
| if( m_notify_type != NONE ) { | |
| SC_REPORT_ERROR( SC_ID_NOTIFY_DELAYED_, 0 ); | |
| } | |
| if( t == SC_ZERO_TIME ) { | |
| // add this event to the delta events set | |
| m_delta_event_index = m_simc->add_delta_event( this ); | |
| m_notify_type = DELTA; | |
| } else { | |
| // add this event to the timed events set | |
| sc_event_timed* et = new sc_event_timed( this, | |
| m_simc->time_stamp() + t ); | |
| m_simc->add_timed_event( et ); | |
| m_timed = et; | |
| m_notify_type = TIMED; | |
| } | |
| } | |
| // +---------------------------------------------------------------------------- | |
| // |"sc_event::register_event" | |
| // | | |
| // | This method sets the name of this object instance and optionally adds | |
| // | it to the object manager's hierarchy. The object instance will be | |
| // | inserted into the object manager's hierarchy if one of the following is | |
| // | true: | |
| // | (a) the leaf name is non-null and does not start with | |
| // | SC_KERNEL_EVENT_PREFIX. | |
| // | (b) the event is being created before the start of simulation. | |
| // | | |
| // | Arguments: | |
| // | leaf_name = leaf name of the object or NULL. | |
| // +---------------------------------------------------------------------------- | |
| void sc_event::register_event( const char* leaf_name ) | |
| { | |
| sc_object_manager* object_manager = m_simc->get_object_manager(); | |
| m_parent_p = m_simc->active_object(); | |
| // No name provided, if we are not executing then create a name: | |
| if( !leaf_name || !leaf_name[0] ) | |
| { | |
| if ( sc_is_running( m_simc ) ) return; | |
| leaf_name = sc_gen_unique_name("event"); | |
| } | |
| // Create a hierarchichal name and place it into the object manager if | |
| // its not a kernel event: | |
| object_manager->create_name( leaf_name ).swap( m_name ); | |
| if ( strncmp( leaf_name, SC_KERNEL_EVENT_PREFIX, | |
| strlen(SC_KERNEL_EVENT_PREFIX) ) ) | |
| { | |
| object_manager->insert_event(m_name, this); | |
| if ( m_parent_p ) | |
| m_parent_p->add_child_event( this ); | |
| else | |
| m_simc->add_child_event( this ); | |
| } | |
| } | |
| void | |
| sc_event::reset() | |
| { | |
| m_notify_type = NONE; | |
| m_delta_event_index = -1; | |
| m_timed = 0; | |
| // clear the dynamic sensitive methods | |
| m_methods_dynamic.resize(0); | |
| // clear the dynamic sensitive threads | |
| m_threads_dynamic.resize(0); | |
| } | |
| // +---------------------------------------------------------------------------- | |
| // |"sc_event::sc_event(name)" | |
| // | | |
| // | This is the object instance constructor for named sc_event instances. | |
| // | If the name is non-null or the this is during elaboration add the | |
| // | event to the object hierarchy. | |
| // | | |
| // | Arguments: | |
| // | name = name of the event. | |
| // +---------------------------------------------------------------------------- | |
| sc_event::sc_event( const char* name ) : | |
| m_name(), | |
| m_parent_p(NULL), | |
| m_simc( sc_get_curr_simcontext() ), | |
| m_notify_type( NONE ), | |
| m_delta_event_index( -1 ), | |
| m_timed( 0 ), | |
| m_methods_static(), | |
| m_methods_dynamic(), | |
| m_threads_static(), | |
| m_threads_dynamic() | |
| { | |
| // Skip simulator's internally defined events. | |
| register_event( name ); | |
| } | |
| // +---------------------------------------------------------------------------- | |
| // |"sc_event::sc_event(name)" | |
| // | | |
| // | This is the object instance constructor for non-named sc_event instances. | |
| // | If this is during elaboration add create a name and add it to the object | |
| // | hierarchy. | |
| // +---------------------------------------------------------------------------- | |
| sc_event::sc_event() : | |
| m_name(), | |
| m_parent_p(NULL), | |
| m_simc( sc_get_curr_simcontext() ), | |
| m_notify_type( NONE ), | |
| m_delta_event_index( -1 ), | |
| m_timed( 0 ), | |
| m_methods_static(), | |
| m_methods_dynamic(), | |
| m_threads_static(), | |
| m_threads_dynamic() | |
| { | |
| register_event( NULL ); | |
| } | |
| // +---------------------------------------------------------------------------- | |
| // |"sc_event::~sc_event" | |
| // | | |
| // | This is the object instance destructor for this class. It cancels any | |
| // | outstanding waits and removes the event from the object manager's | |
| // | instance table if it has a name. | |
| // +---------------------------------------------------------------------------- | |
| sc_event::~sc_event() | |
| { | |
| cancel(); | |
| if ( m_name.length() != 0 ) | |
| { | |
| sc_object_manager* object_manager_p = m_simc->get_object_manager(); | |
| object_manager_p->remove_event( m_name ); | |
| } | |
| } | |
| // +---------------------------------------------------------------------------- | |
| // |"sc_event::trigger" | |
| // | | |
| // | This method "triggers" this object instance. This consists of scheduling | |
| // | for execution all the processes that are schedulable and waiting on this | |
| // | event. | |
| // +---------------------------------------------------------------------------- | |
| void | |
| sc_event::trigger() | |
| { | |
| int last_i; // index of last element in vector now accessing. | |
| int size; // size of vector now accessing. | |
| // trigger the static sensitive methods | |
| if( ( size = m_methods_static.size() ) != 0 ) | |
| { | |
| sc_method_handle* l_methods_static = &m_methods_static[0]; | |
| int i = size - 1; | |
| do { | |
| sc_method_handle method_h = l_methods_static[i]; | |
| method_h->trigger_static(); | |
| } while( -- i >= 0 ); | |
| } | |
| // trigger the dynamic sensitive methods | |
| if( ( size = m_methods_dynamic.size() ) != 0 ) | |
| { | |
| last_i = size - 1; | |
| sc_method_handle* l_methods_dynamic = &m_methods_dynamic[0]; | |
| for ( int i = 0; i <= last_i; i++ ) | |
| { | |
| sc_method_handle method_h = l_methods_dynamic[i]; | |
| if ( method_h->trigger_dynamic( this ) ) | |
| { | |
| l_methods_dynamic[i] = l_methods_dynamic[last_i]; | |
| last_i--; | |
| i--; | |
| } | |
| } | |
| m_methods_dynamic.resize(last_i+1); | |
| } | |
| // trigger the static sensitive threads | |
| if( ( size = m_threads_static.size() ) != 0 ) | |
| { | |
| sc_thread_handle* l_threads_static = &m_threads_static[0]; | |
| int i = size - 1; | |
| do { | |
| sc_thread_handle thread_h = l_threads_static[i]; | |
| thread_h->trigger_static(); | |
| } while( -- i >= 0 ); | |
| } | |
| // trigger the dynamic sensitive threads | |
| if( ( size = m_threads_dynamic.size() ) != 0 ) | |
| { | |
| last_i = size - 1; | |
| sc_thread_handle* l_threads_dynamic = &m_threads_dynamic[0]; | |
| for ( int i = 0; i <= last_i; i++ ) | |
| { | |
| sc_thread_handle thread_h = l_threads_dynamic[i]; | |
| if ( thread_h->trigger_dynamic( this ) ) | |
| { | |
| l_threads_dynamic[i] = l_threads_dynamic[last_i]; | |
| i--; | |
| last_i--; | |
| } | |
| } | |
| m_threads_dynamic.resize(last_i+1); | |
| } | |
| m_notify_type = NONE; | |
| m_delta_event_index = -1; | |
| m_timed = 0; | |
| } | |
| bool | |
| sc_event::remove_static( sc_method_handle method_h_ ) const | |
| { | |
| int size; | |
| if ( ( size = m_methods_static.size() ) != 0 ) { | |
| sc_method_handle* l_methods_static = &m_methods_static[0]; | |
| for( int i = size - 1; i >= 0; -- i ) { | |
| if( l_methods_static[i] == method_h_ ) { | |
| l_methods_static[i] = l_methods_static[size - 1]; | |
| m_methods_static.resize(size-1); | |
| return true; | |
| } | |
| } | |
| } | |
| return false; | |
| } | |
| bool | |
| sc_event::remove_static( sc_thread_handle thread_h_ ) const | |
| { | |
| int size; | |
| if ( ( size = m_threads_static.size() ) != 0 ) { | |
| sc_thread_handle* l_threads_static = &m_threads_static[0]; | |
| for( int i = size - 1; i >= 0; -- i ) { | |
| if( l_threads_static[i] == thread_h_ ) { | |
| l_threads_static[i] = l_threads_static[size - 1]; | |
| m_threads_static.resize(size-1); | |
| return true; | |
| } | |
| } | |
| } | |
| return false; | |
| } | |
| bool | |
| sc_event::remove_dynamic( sc_method_handle method_h_ ) const | |
| { | |
| int size; | |
| if ( ( size = m_methods_dynamic.size() ) != 0 ) { | |
| sc_method_handle* l_methods_dynamic = &m_methods_dynamic[0]; | |
| for( int i = size - 1; i >= 0; -- i ) { | |
| if( l_methods_dynamic[i] == method_h_ ) { | |
| l_methods_dynamic[i] = l_methods_dynamic[size - 1]; | |
| m_methods_dynamic.resize(size-1); | |
| return true; | |
| } | |
| } | |
| } | |
| return false; | |
| } | |
| bool | |
| sc_event::remove_dynamic( sc_thread_handle thread_h_ ) const | |
| { | |
| int size; | |
| if ( ( size= m_threads_dynamic.size() ) != 0 ) { | |
| sc_thread_handle* l_threads_dynamic = &m_threads_dynamic[0]; | |
| for( int i = size - 1; i >= 0; -- i ) { | |
| if( l_threads_dynamic[i] == thread_h_ ) { | |
| l_threads_dynamic[i] = l_threads_dynamic[size - 1]; | |
| m_threads_dynamic.resize(size-1); | |
| return true; | |
| } | |
| } | |
| } | |
| return false; | |
| } | |
| // ---------------------------------------------------------------------------- | |
| // CLASS : sc_event_timed | |
| // | |
| // Class for storing the time to notify a timed event. | |
| // ---------------------------------------------------------------------------- | |
| // dedicated memory management; not MT-Safe | |
| union sc_event_timed_u | |
| { | |
| sc_event_timed_u* next; | |
| char dummy[sizeof( sc_event_timed )]; | |
| }; | |
| static | |
| sc_event_timed_u* free_list = 0; | |
| void* | |
| sc_event_timed::allocate() | |
| { | |
| const int ALLOC_SIZE = 64; | |
| if( free_list == 0 ) { | |
| free_list = (sc_event_timed_u*) malloc( ALLOC_SIZE * | |
| sizeof( sc_event_timed ) ); | |
| int i = 0; | |
| for( ; i < ALLOC_SIZE - 1; ++ i ) { | |
| free_list[i].next = &free_list[i + 1]; | |
| } | |
| free_list[i].next = 0; | |
| } | |
| sc_event_timed_u* q = free_list; | |
| free_list = free_list->next; | |
| return q; | |
| } | |
| void | |
| sc_event_timed::deallocate( void* p ) | |
| { | |
| if( p != 0 ) { | |
| sc_event_timed_u* q = RCAST<sc_event_timed_u*>( p ); | |
| q->next = free_list; | |
| free_list = q; | |
| } | |
| } | |
| // ---------------------------------------------------------------------------- | |
| // CLASS : sc_event_list | |
| // | |
| // Base class for lists of events. | |
| // ---------------------------------------------------------------------------- | |
| void | |
| sc_event_list::push_back( const sc_event& e ) | |
| { | |
| // make sure e is not already in the list | |
| if ( m_events.size() != 0 ) { | |
| const sc_event** l_events = &m_events[0]; | |
| for( int i = m_events.size() - 1; i >= 0; -- i ) { | |
| if( &e == l_events[i] ) { | |
| // event already in the list; ignore | |
| return; | |
| } | |
| } | |
| } | |
| m_events.push_back( &e ); | |
| } | |
| void | |
| sc_event_list::push_back( const sc_event_list& el ) | |
| { | |
| m_events.reserve( size() + el.size() ); | |
| for ( int i = el.m_events.size() - 1; i >= 0; --i ) | |
| { | |
| push_back( *el.m_events[i] ); | |
| } | |
| el.auto_delete(); | |
| } | |
| void | |
| sc_event_list::add_dynamic( sc_method_handle method_h ) const | |
| { | |
| m_busy++; | |
| if ( m_events.size() != 0 ) { | |
| const sc_event* const * l_events = &m_events[0]; | |
| for( int i = m_events.size() - 1; i >= 0; -- i ) { | |
| l_events[i]->add_dynamic( method_h ); | |
| } | |
| } | |
| } | |
| void | |
| sc_event_list::add_dynamic( sc_thread_handle thread_h ) const | |
| { | |
| m_busy++; | |
| if ( m_events.size() != 0 ) { | |
| const sc_event* const* l_events = &m_events[0]; | |
| for( int i = m_events.size() - 1; i >= 0; -- i ) { | |
| l_events[i]->add_dynamic( thread_h ); | |
| } | |
| } | |
| } | |
| void | |
| sc_event_list::remove_dynamic( sc_method_handle method_h, | |
| const sc_event* e_not ) const | |
| { | |
| if ( m_events.size() != 0 ) { | |
| const sc_event* const* l_events = &m_events[0]; | |
| for( int i = m_events.size() - 1; i >= 0; -- i ) { | |
| const sc_event* e = l_events[i]; | |
| if( e != e_not ) { | |
| e->remove_dynamic( method_h ); | |
| } | |
| } | |
| } | |
| } | |
| void | |
| sc_event_list::remove_dynamic( sc_thread_handle thread_h, | |
| const sc_event* e_not ) const | |
| { | |
| if ( m_events.size() != 0 ) { | |
| const sc_event* const* l_events = &m_events[0]; | |
| for( int i = m_events.size() - 1; i >= 0; -- i ) { | |
| const sc_event* e = l_events[i]; | |
| if( e != e_not ) { | |
| e->remove_dynamic( thread_h ); | |
| } | |
| } | |
| } | |
| } | |
| void | |
| sc_event_list::report_premature_destruction() const | |
| { | |
| // TDB: reliably detect premature destruction | |
| // | |
| // If an event list is used as a member of a module, | |
| // its lifetime may (correctly) end, although there | |
| // are processes currently waiting for it. | |
| // | |
| // Detecting (and ignoring) this corner-case is quite | |
| // difficult for similar reasons to the sc_is_running() | |
| // return value during the destruction of the module | |
| // hierarchy. | |
| // | |
| // Ignoring the lifetime checks for now, if no process | |
| // is currently running (which is only part of the story): | |
| if( sc_get_current_process_handle().valid() ) { | |
| // FIXME: improve error-handling | |
| sc_assert( false && "sc_event_list prematurely destroyed" ); | |
| } | |
| } | |
| void | |
| sc_event_list::report_invalid_modification() const | |
| { | |
| // FIXME: improve error-handling | |
| sc_assert( false && "sc_event_list modfied while being waited on" ); | |
| } | |
| // ---------------------------------------------------------------------------- | |
| // Deprecated functional notation for notifying events. | |
| // ---------------------------------------------------------------------------- | |
| static void sc_warn_notify() | |
| { | |
| static bool warn_notify=true; | |
| if ( warn_notify ) | |
| { | |
| SC_REPORT_INFO(SC_ID_IEEE_1666_DEPRECATION_, | |
| "the notify() function is deprecated use sc_event::notify()" ); | |
| warn_notify = false; | |
| } | |
| } | |
| void | |
| notify( sc_event& e ) | |
| { | |
| sc_warn_notify(); | |
| e.notify(); | |
| } | |
| void | |
| notify( const sc_time& t, sc_event& e ) | |
| { | |
| sc_warn_notify(); | |
| e.notify( t ); | |
| } | |
| void | |
| notify( double v, sc_time_unit tu, sc_event& e ) | |
| { | |
| sc_warn_notify(); | |
| e.notify( v, tu ); | |
| } | |
| } // namespace sc_core | |
| // $Log: sc_event.cpp,v $ | |
| // Revision 1.17 2011/08/26 20:46:09 acg | |
| // Andy Goodrich: moved the modification log to the end of the file to | |
| // eliminate source line number skew when check-ins are done. | |
| // | |
| // Revision 1.16 2011/08/24 22:05:50 acg | |
| // Torsten Maehne: initialization changes to remove warnings. | |
| // | |
| // Revision 1.15 2011/03/12 21:07:51 acg | |
| // Andy Goodrich: changes to kernel generated event support. | |
| // | |
| // Revision 1.14 2011/03/06 15:55:52 acg | |
| // Andy Goodrich: changes for named events. | |
| // | |
| // Revision 1.13 2011/03/05 01:39:21 acg | |
| // Andy Goodrich: changes for named events. | |
| // | |
| // Revision 1.12 2011/02/19 08:33:25 acg | |
| // Andy Goodrich: remove }'s that should have been removed before. | |
| // | |
| // Revision 1.11 2011/02/19 08:30:53 acg | |
| // Andy Goodrich: Moved process queueing into trigger_static from | |
| // sc_event::notify. | |
| // | |
| // Revision 1.10 2011/02/18 20:27:14 acg | |
| // Andy Goodrich: Updated Copyrights. | |
| // | |
| // Revision 1.9 2011/02/17 19:49:51 acg | |
| // Andy Goodrich: | |
| // (1) Changed signature of trigger_dynamic() to return a bool again. | |
| // (2) Moved process run queue processing into trigger_dynamic(). | |
| // | |
| // Revision 1.8 2011/02/16 22:37:30 acg | |
| // Andy Goodrich: clean up to remove need for ps_disable_pending. | |
| // | |
| // Revision 1.7 2011/02/13 21:47:37 acg | |
| // Andy Goodrich: update copyright notice. | |
| // | |
| // Revision 1.6 2011/02/01 21:02:28 acg | |
| // Andy Goodrich: new return code for trigger_dynamic() calls. | |
| // | |
| // Revision 1.5 2011/01/18 20:10:44 acg | |
| // Andy Goodrich: changes for IEEE1666_2011 semantics. | |
| // | |
| // Revision 1.4 2011/01/06 18:04:05 acg | |
| // Andy Goodrich: added code to leave disabled processes on the dynamic | |
| // method and thread queues. | |
| // | |
| // Revision 1.3 2008/05/22 17:06:25 acg | |
| // Andy Goodrich: updated copyright notice to include 2008. | |
| // | |
| // Revision 1.2 2007/01/17 22:44:30 acg | |
| // Andy Goodrich: fix for Microsoft compiler. | |
| // | |
| // Revision 1.7 2006/04/11 23:13:20 acg | |
| // Andy Goodrich: Changes for reduced reset support that only includes | |
| // sc_cthread, but has preliminary hooks for expanding to method and thread | |
| // processes also. | |
| // | |
| // Revision 1.6 2006/01/25 00:31:19 acg | |
| // Andy Goodrich: Changed over to use a standard message id of | |
| // SC_ID_IEEE_1666_DEPRECATION for all deprecation messages. | |
| // | |
| // Revision 1.5 2006/01/24 20:59:11 acg | |
| // Andy Goodrich: fix up of CVS comments, new version roll. | |
| // | |
| // Revision 1.4 2006/01/24 20:48:14 acg | |
| // Andy Goodrich: added deprecation warnings for notify_delayed(). Added two | |
| // new implementation-dependent methods, notify_next_delta() & notify_internal() | |
| // to replace calls to notify_delayed() from within the simulator. These two | |
| // new methods are simpler than notify_delayed() and should speed up simulations | |
| // | |
| // Revision 1.3 2006/01/13 18:44:29 acg | |
| // Added $Log to record CVS changes into the source. | |
| // Taf! |