summaryrefslogtreecommitdiff
path: root/ext/systemc/src/sysc/kernel/sc_runnable_int.h
diff options
context:
space:
mode:
Diffstat (limited to 'ext/systemc/src/sysc/kernel/sc_runnable_int.h')
-rw-r--r--ext/systemc/src/sysc/kernel/sc_runnable_int.h574
1 files changed, 574 insertions, 0 deletions
diff --git a/ext/systemc/src/sysc/kernel/sc_runnable_int.h b/ext/systemc/src/sysc/kernel/sc_runnable_int.h
new file mode 100644
index 000000000..510e93758
--- /dev/null
+++ b/ext/systemc/src/sysc/kernel/sc_runnable_int.h
@@ -0,0 +1,574 @@
+/*****************************************************************************
+
+ 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_runnable_int.h -- For inline definitions of some utility functions.
+ DO NOT EXPORT THIS INCLUDE FILE. Include this file
+ after "sc_process_int.h" so that we can get the base
+ class right.
+
+ Original Author: Bishnupriya Bhattacharya , Cadence Design, 28th July, 2003
+
+ CHANGE LOG AT THE END OF THE FILE
+ ******************************************************************************/
+
+#ifndef SC_RUNNABLE_INT_H
+#define SC_RUNNABLE_INT_H
+
+
+#include "sysc/kernel/sc_runnable.h"
+#include "sysc/kernel/sc_method_process.h"
+#include "sysc/kernel/sc_thread_process.h"
+
+// DEBUGGING MACROS:
+//
+// DEBUG_MSG(NAME,P,MSG)
+// MSG = message to print
+// NAME = name that must match the process for the message to print, or
+// null if the message should be printed unconditionally.
+// P = pointer to process message is for, or NULL in which case the
+// message will not print.
+#if 0
+# define DEBUG_NAME ""
+# define DEBUG_MSG(NAME,P,MSG) \
+ { \
+ if ( P && ( (strlen(NAME)==0) || !strcmp(NAME,P->name())) ) \
+ std::cout << "**** " << sc_time_stamp() << " (" \
+ << sc_get_current_process_name() << "): " << MSG \
+ << " - " << P->name() << std::endl; \
+ }
+#else
+# define DEBUG_MSG(NAME,P,MSG)
+#endif
+
+namespace sc_core {
+
+// The values below are used to indicate when a queue is empty. A non-zero
+// non-legal pointer value is used for this so that a zero value in the
+// m_execute_p field of an sc_process_b instance can be used to indicate
+// that is has not been queued for run. (If we did not use a non-zero
+// queue empty indicator then a sc_process_b instance that was queued
+// twice in a row might end up on the queue twice if it were the first
+// one that was queued!)
+
+#define SC_NO_METHODS ((sc_method_handle)0xdb)
+#define SC_NO_THREADS ((sc_thread_handle)0xdb)
+
+
+//------------------------------------------------------------------------------
+//"sc_runnable::dump"
+//
+// This method dumps the contents of this object instance.
+//------------------------------------------------------------------------------
+inline void sc_runnable::dump() const
+{
+ // Dump the thread queues:
+
+ std::cout << "thread pop queue: " << std::endl;
+ for ( sc_thread_handle p = m_threads_pop; p != SC_NO_THREADS;
+ p = p->next_runnable() )
+ {
+ std::cout << " " << p << std::endl;
+ }
+
+ std::cout << "thread push queue: " << std::endl;
+ for ( sc_thread_handle p = m_threads_push_head->next_runnable();
+ p != SC_NO_THREADS; p = p->next_runnable() )
+ {
+ std::cout << " " << p << std::endl;
+ }
+}
+
+//------------------------------------------------------------------------------
+//"sc_runnable::execute_method_next"
+//
+// This method pushes the the supplied method to execute as the next process.
+// This is done by pushing it onto the front of the m_methods_pop.
+// method_h -> method process to add to the queue.
+//------------------------------------------------------------------------------
+inline void sc_runnable::execute_method_next( sc_method_handle method_h )
+{
+ DEBUG_MSG(DEBUG_NAME,method_h,"pushing this method to execute next");
+ method_h->set_next_runnable( m_methods_pop );
+ m_methods_pop = method_h;
+}
+
+//------------------------------------------------------------------------------
+//"sc_runnable::execute_thread_next"
+//
+// This method pushes the the supplied thread to execute as the next process.
+// This is done by pushing it onto the front of the m_threads_pop.
+// thread_h -> thread process to add to the queue.
+//------------------------------------------------------------------------------
+inline void sc_runnable::execute_thread_next( sc_thread_handle thread_h )
+{
+ DEBUG_MSG(DEBUG_NAME,thread_h,"pushing this thread to execute next");
+ thread_h->set_next_runnable( m_threads_pop );
+ m_threads_pop = thread_h;
+}
+
+//------------------------------------------------------------------------------
+//"sc_runnable::init"
+//
+// This method initializes this object instance. Note we allocate the queue
+// heads if necessary. This is done here rather than in the constructor for
+// this class to eliminate CTOR processing errors with gcc.
+//------------------------------------------------------------------------------
+inline void sc_runnable::init()
+{
+ m_methods_pop = SC_NO_METHODS;
+ if ( !m_methods_push_head )
+ {
+ m_methods_push_head = new sc_method_process("methods_push_head", true,
+ (SC_ENTRY_FUNC)0, 0, 0);
+ m_methods_push_head->dont_initialize(true);
+ m_methods_push_head->detach();
+ }
+ m_methods_push_tail = m_methods_push_head;
+ m_methods_push_head->set_next_runnable(SC_NO_METHODS);
+
+ m_threads_pop = SC_NO_THREADS;
+ if ( !m_threads_push_head )
+ {
+ m_threads_push_head = new sc_thread_process("threads_push_head", true,
+ (SC_ENTRY_FUNC)0, 0, 0);
+ m_threads_push_head->dont_initialize(true);
+ m_threads_push_head->detach();
+ }
+ m_threads_push_head->set_next_runnable(SC_NO_THREADS);
+ m_threads_push_tail = m_threads_push_head;
+}
+
+
+//------------------------------------------------------------------------------
+//"sc_runnable::is_empty"
+//
+// This method returns true if the push queue is empty, or false if not.
+//------------------------------------------------------------------------------
+inline bool sc_runnable::is_empty() const
+{
+ return m_methods_push_head->next_runnable() == SC_NO_METHODS &&
+ m_methods_pop == SC_NO_METHODS &&
+ m_threads_push_head->next_runnable() == SC_NO_THREADS &&
+ m_threads_pop == SC_NO_THREADS;
+}
+
+
+//------------------------------------------------------------------------------
+//"sc_runnable::is_initialized"
+//
+// This method returns true if the push queue is already initialized.
+//------------------------------------------------------------------------------
+inline bool sc_runnable::is_initialized() const
+{
+ return m_methods_push_head && m_threads_push_head;
+}
+
+
+//------------------------------------------------------------------------------
+//"sc_runnable::push_back_method"
+//
+// This method pushes the supplied method process onto the back of the queue of
+// runnable method processes.
+// method_h -> method process to add to the queue.
+//------------------------------------------------------------------------------
+inline void sc_runnable::push_back_method( sc_method_handle method_h )
+{
+ // assert( method_h->next_runnable() == 0 ); // Can't queue twice.
+ DEBUG_MSG(DEBUG_NAME,method_h,"pushing back method");
+ method_h->set_next_runnable(SC_NO_METHODS);
+ m_methods_push_tail->set_next_runnable(method_h);
+ m_methods_push_tail = method_h;
+}
+
+
+//------------------------------------------------------------------------------
+//"sc_runnable::push_back_thread"
+//
+// This method pushes the supplied thread process onto the back of the queue of
+// runnable thread processes.
+// thread_h -> thread process to add to the queue.
+//------------------------------------------------------------------------------
+inline void sc_runnable::push_back_thread( sc_thread_handle thread_h )
+{
+ // assert( thread_h->next_runnable() == 0 ); // Can't queue twice.
+ DEBUG_MSG(DEBUG_NAME,thread_h,"pushing back thread");
+ thread_h->set_next_runnable(SC_NO_THREADS);
+ m_threads_push_tail->set_next_runnable(thread_h);
+ m_threads_push_tail = thread_h;
+}
+
+
+//------------------------------------------------------------------------------
+//"sc_runnable::push_front_method"
+//
+// This method pushes the supplied method process onto the front of the queue of
+// runnable method processes. If the queue is empty the process is the tail
+// also.
+// method_h -> method process to add to the queue.
+//------------------------------------------------------------------------------
+inline void sc_runnable::push_front_method( sc_method_handle method_h )
+{
+ // assert( method_h->next_runnable() == 0 ); // Can't queue twice.
+ DEBUG_MSG(DEBUG_NAME,method_h,"pushing front method");
+ method_h->set_next_runnable(m_methods_push_head->next_runnable());
+ if ( m_methods_push_tail == m_methods_push_head ) // Empty queue.
+ {
+ m_methods_push_tail->set_next_runnable(method_h);
+ m_methods_push_tail = method_h;
+ }
+ else // Non-empty queue.
+ {
+ m_methods_push_head->set_next_runnable(method_h);
+ }
+}
+
+
+//------------------------------------------------------------------------------
+//"sc_runnable::push_front_thread"
+//
+// This method pushes the supplied thread process onto the front of the queue of
+// runnable thread processes. If the queue is empty the process is the tail
+// also.
+// thread_h -> thread process to add to the queue.
+//------------------------------------------------------------------------------
+inline void sc_runnable::push_front_thread( sc_thread_handle thread_h )
+{
+ // assert( thread_h->next_runnable() == 0 ); // Can't queue twice.
+ DEBUG_MSG(DEBUG_NAME,thread_h,"pushing front thread");
+ thread_h->set_next_runnable(m_threads_push_head->next_runnable());
+ if ( m_threads_push_tail == m_threads_push_head ) // Empty queue.
+ {
+ m_threads_push_tail->set_next_runnable(thread_h);
+ m_threads_push_tail = thread_h;
+ }
+ else // Non-empty queue.
+ {
+ m_threads_push_head->set_next_runnable(thread_h);
+ }
+}
+
+//------------------------------------------------------------------------------
+//"sc_runnable::pop_method"
+//
+// This method pops the next method process to be executed, or returns a null
+// if no method processes are available for execution.
+//------------------------------------------------------------------------------
+inline sc_method_handle sc_runnable::pop_method()
+{
+ sc_method_handle result_p;
+
+ result_p = m_methods_pop;
+ if ( result_p != SC_NO_METHODS )
+ {
+ m_methods_pop = result_p->next_runnable();
+ result_p->set_next_runnable(0);
+ }
+ else
+ {
+ result_p = 0;
+ }
+ DEBUG_MSG(DEBUG_NAME,result_p,"popping method");
+ return result_p;
+
+}
+
+//------------------------------------------------------------------------------
+//"sc_runnable::pop_thread"
+//
+// This method pops the next thread process to be executed, or returns a null
+// if no thread processes are available for execution.
+//------------------------------------------------------------------------------
+inline sc_thread_handle sc_runnable::pop_thread()
+{
+ sc_thread_handle result_p;
+
+ result_p = m_threads_pop;
+ if ( result_p != SC_NO_THREADS )
+ {
+ m_threads_pop = result_p->next_runnable();
+ result_p->set_next_runnable(0);
+ }
+ else
+ {
+ result_p = 0;
+ }
+ DEBUG_MSG(DEBUG_NAME,result_p,"popping thread for execution");
+ return result_p;
+}
+
+
+//------------------------------------------------------------------------------
+//"sc_runnable::remove_method"
+//
+// This method removes the supplied method process from the push queue if it is
+// present. Note we clear the method's next pointer so that it may be queued
+// again.
+// remove_p -> method process to remove from the run queue.
+//------------------------------------------------------------------------------
+inline void sc_runnable::remove_method( sc_method_handle remove_p )
+{
+ sc_method_handle now_p; // Method now checking.
+ sc_method_handle prior_p; // Method prior to now_p.
+
+ // Don't try to remove things if we have not been initialized.
+
+ if ( !is_initialized() ) return;
+
+ // Search the push queue:
+
+ prior_p = m_methods_push_head;
+ for ( now_p = m_methods_push_head; now_p!= SC_NO_METHODS;
+ now_p = now_p->next_runnable() )
+ {
+ if ( remove_p == now_p )
+ {
+ prior_p->set_next_runnable( now_p->next_runnable() );
+ if (now_p == m_methods_push_tail) {
+ m_methods_push_tail = prior_p;
+ }
+ now_p->set_next_runnable(0);
+ DEBUG_MSG(DEBUG_NAME,now_p,"removing method from push queue");
+ return;
+ }
+ prior_p = now_p;
+ }
+
+ // Search the pop queue:
+
+ prior_p = NULL;
+ for ( now_p = m_methods_pop; now_p != SC_NO_METHODS;
+ now_p = now_p->next_runnable() )
+ {
+ if ( remove_p == now_p )
+ {
+ if ( prior_p )
+ prior_p->set_next_runnable( now_p->next_runnable() );
+ else
+ m_methods_pop = now_p->next_runnable();
+ now_p->set_next_runnable(0);
+ DEBUG_MSG(DEBUG_NAME,now_p,"removing method from pop queue");
+ return;
+ }
+ prior_p = now_p;
+ }
+}
+
+
+//------------------------------------------------------------------------------
+//"sc_runnable::remove_thread"
+//
+// This method removes the supplied thread process from the push or pop
+// queue if it is present. Note we clear the thread's next pointer so that it
+// may be queued again.
+// remove_p -> thread process to remove from the run queue.
+//------------------------------------------------------------------------------
+inline void sc_runnable::remove_thread( sc_thread_handle remove_p )
+{
+ sc_thread_handle now_p; // Thread now checking.
+ sc_thread_handle prior_p; // Thread prior to now_p.
+
+ // Don't try to remove things if we have not been initialized.
+
+ if ( !is_initialized() ) return;
+
+ // Search the push queue:
+
+ prior_p = m_threads_push_head;
+ for ( now_p = m_threads_push_head; now_p != SC_NO_THREADS;
+ now_p = now_p->next_runnable() )
+ {
+ if ( remove_p == now_p )
+ {
+ prior_p->set_next_runnable( now_p->next_runnable() );
+ if (now_p == m_threads_push_tail) {
+ m_threads_push_tail = prior_p;
+ }
+ now_p->set_next_runnable(0);
+ DEBUG_MSG(DEBUG_NAME,now_p,"removing thread from push queue");
+ return;
+ }
+ prior_p = now_p;
+ }
+
+ // Search the pop queue:
+
+ prior_p = NULL;
+ for ( now_p = m_threads_pop; now_p != SC_NO_THREADS;
+ now_p = now_p->next_runnable() )
+ {
+ if ( remove_p == now_p )
+ {
+ if ( prior_p )
+ prior_p->set_next_runnable( now_p->next_runnable() );
+ else
+ m_threads_pop = now_p->next_runnable();
+ now_p->set_next_runnable(0);
+ DEBUG_MSG(DEBUG_NAME,now_p,"removing thread from pop queue");
+ return;
+ }
+ prior_p = now_p;
+ }
+}
+
+//------------------------------------------------------------------------------
+//"sc_runnable::sc_runnable"
+//
+// This is the object instance constructor for this class.
+//------------------------------------------------------------------------------
+inline sc_runnable::sc_runnable() :
+ m_methods_push_head(0), m_methods_push_tail(0), m_methods_pop(SC_NO_METHODS),
+ m_threads_push_head(0), m_threads_push_tail(0), m_threads_pop(SC_NO_THREADS)
+{}
+
+//------------------------------------------------------------------------------
+//"sc_runnable::~sc_runnable"
+//
+// This is the object instance destructor for this class.
+//------------------------------------------------------------------------------
+inline sc_runnable::~sc_runnable()
+{
+ delete m_methods_push_head;
+ delete m_threads_push_head;
+}
+
+
+//------------------------------------------------------------------------------
+//"sc_runnable::toggle_methods"
+//
+// This method moves the methods push queue to the pop queue and zeros the push
+// queue. This will only be done if the pop queue is presently empty.
+//------------------------------------------------------------------------------
+inline void sc_runnable::toggle_methods()
+{
+ if ( m_methods_pop == SC_NO_METHODS )
+ {
+ m_methods_pop = m_methods_push_head->next_runnable();
+ m_methods_push_head->set_next_runnable(SC_NO_METHODS);
+ m_methods_push_tail = m_methods_push_head;
+ }
+}
+
+
+//------------------------------------------------------------------------------
+//"sc_runnable::toggle_threads"
+//
+// This method moves the threads push queue to the pop queue and zeros the push
+// queue. This will only be done if the pop queue is presently empty.
+//------------------------------------------------------------------------------
+inline void sc_runnable::toggle_threads()
+{
+ if ( m_threads_pop == SC_NO_THREADS )
+ {
+ m_threads_pop = m_threads_push_head->next_runnable();
+ m_threads_push_head->set_next_runnable(SC_NO_THREADS);
+ m_threads_push_tail = m_threads_push_head;
+ }
+}
+
+#undef SC_NO_METHODS
+#undef SC_NO_THREADS
+#undef DEBUG_MSG
+
+} // namespace sc_core
+
+
+/*******************************************************************************
+
+ MODIFICATION LOG - modifiers, enter your name, affiliation, date and
+ changes you are making here.
+ Andy Goodrich, Forte Design Systems, 2 September 2003
+ Changed queue heads to instances to eliminate the checks for null heads.
+
+ ******************************************************************************/
+
+// $Log: sc_runnable_int.h,v $
+// Revision 1.19 2011/08/24 22:05:51 acg
+// Torsten Maehne: initialization changes to remove warnings.
+//
+// Revision 1.18 2011/08/07 19:08:04 acg
+// Andy Goodrich: moved logs to end of file so line number synching works
+// better between versions.
+//
+// Revision 1.17 2011/04/13 02:45:11 acg
+// Andy Goodrich: eliminated warning message that occurred if the DEBUG_MSG
+// macro was used.
+//
+// Revision 1.16 2011/04/10 22:18:23 acg
+// Andy Goodrich: debugging message clean up.
+//
+// Revision 1.15 2011/04/08 18:26:07 acg
+// Andy Goodrich: added execute_method_next() to handle method dispatch
+// for asynchronous notifications that occur outside the evaluation phase.
+//
+// Revision 1.14 2011/04/01 21:31:10 acg
+// Andy Goodrich: turn off diagnostic messages by default.
+//
+// Revision 1.13 2011/04/01 21:30:02 acg
+// Andy Goodrich: inserted conditional displays for queue manipulations.
+//
+// Revision 1.12 2011/03/30 00:01:34 acg
+// Philip A. Hartmann: change break to return in remove_method() to short
+// circuit the search the way remove_thread() works.
+//
+// Revision 1.11 2011/03/28 13:02:52 acg
+// Andy Goodrich: Changes for disable() interactions.
+//
+// Revision 1.10 2011/03/06 15:58:17 acg
+// Andy Goodrich: formatting changes.
+//
+// Revision 1.9 2011/02/18 20:27:14 acg
+// Andy Goodrich: Updated Copyrights.
+//
+// Revision 1.8 2011/02/13 21:47:38 acg
+// Andy Goodrich: update copyright notice.
+//
+// Revision 1.7 2011/02/02 06:37:03 acg
+// Andy Goodrich: removed toggle() method since it is no longer used.
+//
+// Revision 1.6 2011/02/01 21:09:13 acg
+// Andy Goodrich: addition of toggle_methods() and toggle_threads() calls.
+//
+// Revision 1.5 2011/01/25 20:50:37 acg
+// Andy Goodrich: changes for IEEE 1666 2011.
+//
+// Revision 1.4 2010/07/22 20:02:33 acg
+// Andy Goodrich: bug fixes.
+//
+// Revision 1.3 2009/02/28 00:26:58 acg
+// Andy Goodrich: changed boost name space to sc_boost to allow use with
+// full boost library applications.
+//
+// Revision 1.2 2008/05/22 17:06:26 acg
+// Andy Goodrich: updated copyright notice to include 2008.
+//
+// Revision 1.1.1.1 2006/12/15 20:20:05 acg
+// SystemC 2.3
+//
+// Revision 1.4 2006/04/20 17:08:17 acg
+// Andy Goodrich: 3.0 style process changes.
+//
+// Revision 1.3 2006/01/13 18:44:30 acg
+// Added $Log to record CVS changes into the source.
+//
+
+#endif // SC_RUNNABLE_INT_H
+
+// Taf!