diff options
Diffstat (limited to 'ext/systemc/src/sysc/kernel')
69 files changed, 24529 insertions, 0 deletions
diff --git a/ext/systemc/src/sysc/kernel/sc_attribute.cpp b/ext/systemc/src/sysc/kernel/sc_attribute.cpp new file mode 100644 index 000000000..de89c6adf --- /dev/null +++ b/ext/systemc/src/sysc/kernel/sc_attribute.cpp @@ -0,0 +1,191 @@ +/***************************************************************************** + + 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_attribute.cpp -- Attribute classes. + + Original Author: Martin Janssen, Synopsys, Inc., 2001-05-21 + + CHANGE LOG APPEARS AT THE END OF THE FILE + *****************************************************************************/ + +#include "sysc/kernel/sc_attribute.h" + +namespace sc_core { + +// ---------------------------------------------------------------------------- +// CLASS : sc_attr_base +// +// Attribute base class. +// ---------------------------------------------------------------------------- + +// constructors + +sc_attr_base::sc_attr_base( const std::string& name_ ) +: m_name( name_ ) +{} + +sc_attr_base::sc_attr_base( const sc_attr_base& a ) +: m_name( a.m_name ) +{} + + +// destructor (does nothing) + +sc_attr_base::~sc_attr_base() +{} + + +// get the name +const std::string& +sc_attr_base::name() const +{ + return m_name; +} + + +// ---------------------------------------------------------------------------- +// CLASS : sc_attr_cltn +// +// Attribute collection class. Stores pointers to attributes. +// Note: iterate over the collection by using iterators. +// ---------------------------------------------------------------------------- + +// constructors + +sc_attr_cltn::sc_attr_cltn() : m_cltn() +{} + +sc_attr_cltn::sc_attr_cltn( const sc_attr_cltn& a ) +: m_cltn( a.m_cltn ) +{} + + +// destructor +sc_attr_cltn::~sc_attr_cltn() +{ + remove_all(); +} + + +// add attribute to the collection. +// returns 'true' if the name of the attribute is unique, +// returns 'false' otherwise (attribute is not added). + +bool +sc_attr_cltn::push_back( sc_attr_base* attribute_ ) +{ + if( attribute_ == 0 ) { + return false; + } + for( int i = m_cltn.size() - 1; i >= 0; -- i ) { + if( attribute_->name() == m_cltn[i]->name() ) { + return false; + } + } + m_cltn.push_back( attribute_ ); + return true; +} + + +// get attribute by name. +// returns pointer to attribute, or 0 if name does not exist. + +sc_attr_base* +sc_attr_cltn::operator [] ( const std::string& name_ ) +{ + for( int i = m_cltn.size() - 1; i >= 0; -- i ) { + if( name_ == m_cltn[i]->name() ) { + return m_cltn[i]; + } + } + return 0; +} + +const sc_attr_base* +sc_attr_cltn::operator [] ( const std::string& name_ ) const +{ + for( int i = m_cltn.size() - 1; i >= 0; -- i ) { + if( name_ == m_cltn[i]->name() ) { + return m_cltn[i]; + } + } + return 0; +} + + +// remove attribute by name. +// returns pointer to attribute, or 0 if name does not exist. + +sc_attr_base* +sc_attr_cltn::remove( const std::string& name_ ) +{ + for( int i = m_cltn.size() - 1; i >= 0; -- i ) { + if( name_ == m_cltn[i]->name() ) { + sc_attr_base* attribute = m_cltn[i]; + std::swap( m_cltn[i], m_cltn.back() ); + m_cltn.pop_back(); + return attribute; + } + } + return 0; +} + + +// remove all attributes + +void +sc_attr_cltn::remove_all() +{ + m_cltn.clear(); +} + +} // namespace sc_core + +// $Log: sc_attribute.cpp,v $ +// Revision 1.7 2011/08/26 20:46:08 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.6 2011/08/24 22:05:50 acg +// Torsten Maehne: initialization changes to remove warnings. +// +// Revision 1.5 2011/02/18 20:27:14 acg +// Andy Goodrich: Updated Copyrights. +// +// Revision 1.4 2011/02/13 21:47:37 acg +// Andy Goodrich: update copyright notice. +// +// Revision 1.3 2010/07/22 20:02:33 acg +// Andy Goodrich: bug fixes. +// +// Revision 1.2 2008/05/22 17:06:24 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/01/16 22:27:08 acg +// Test of $Log comment. +// +// Revision 1.3 2006/01/13 18:44:29 acg +// Added $Log to record CVS changes into the source. + +// Taf! diff --git a/ext/systemc/src/sysc/kernel/sc_attribute.h b/ext/systemc/src/sysc/kernel/sc_attribute.h new file mode 100644 index 000000000..0efa70de5 --- /dev/null +++ b/ext/systemc/src/sysc/kernel/sc_attribute.h @@ -0,0 +1,209 @@ +/***************************************************************************** + + 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_attribute.h -- Attribute classes. + + Original Author: Martin Janssen, Synopsys, Inc., 2001-05-21 + + CHANGE LOG AT THE END OF THE FILE + *****************************************************************************/ + + +#ifndef SC_ATTRIBUTE_H +#define SC_ATTRIBUTE_H + +#include <string> +#include <vector> + +namespace sc_core { + +// ---------------------------------------------------------------------------- +// CLASS : sc_attr_base +// +// Attribute base class. +// ---------------------------------------------------------------------------- + +class sc_attr_base +{ +public: + + // constructors + sc_attr_base( const std::string& name_ ); + sc_attr_base( const sc_attr_base& ); + + // destructor (does nothing) + virtual ~sc_attr_base(); + + // get the name + const std::string& name() const; + +private: + + std::string m_name; + +private: + + // disabled + sc_attr_base(); + sc_attr_base& operator = ( const sc_attr_base& ); +}; + + +// ---------------------------------------------------------------------------- +// CLASS : sc_attr_cltn +// +// Attribute collection class. Stores pointers to attributes. +// Note: iterate over the collection by using iterators. +// ---------------------------------------------------------------------------- + +class sc_attr_cltn +{ +public: + + // typedefs + typedef sc_attr_base* elem_type; + typedef std::vector<elem_type>::iterator iterator; + typedef std::vector<elem_type>::const_iterator const_iterator; + + // constructors + sc_attr_cltn(); + sc_attr_cltn( const sc_attr_cltn& ); + + // destructor + ~sc_attr_cltn(); + + // add attribute to the collection. + // returns 'true' if the name of the attribute is unique, + // returns 'false' otherwise (attribute is not added). + bool push_back( sc_attr_base* ); + + // get attribute by name. + // returns pointer to attribute, or 0 if name does not exist. + sc_attr_base* operator [] ( const std::string& name_ ); + const sc_attr_base* operator [] ( const std::string& name_ ) const; + + // remove attribute by name. + // returns pointer to attribute, or 0 if name does not exist. + sc_attr_base* remove( const std::string& name_ ); + + // remove all attributes + void remove_all(); + + // get the size of the collection + int size() const + { return m_cltn.size(); } + + // get the begin iterator + iterator begin() + { return m_cltn.begin(); } + const_iterator begin() const + { return m_cltn.begin(); } + + // get the end iterator + iterator end() + { return m_cltn.end(); } + const_iterator end() const + { return m_cltn.end(); } + +private: + std::vector<sc_attr_base*> m_cltn; + +private: + + // disabled + sc_attr_cltn& operator = ( const sc_attr_cltn& ); +}; + + +// ---------------------------------------------------------------------------- +// CLASS : sc_attribute<T> +// +// Attribute class. +// Note: T must have a default constructor and copy constructor. +// ---------------------------------------------------------------------------- + +template <class T> +class sc_attribute +: public sc_attr_base +{ +public: + + // constructors + + sc_attribute( const std::string& name_ ) + : sc_attr_base( name_ ), value() + {} + + sc_attribute( const std::string& name_, const T& value_ ) + : sc_attr_base( name_ ), value( value_ ) + {} + + sc_attribute( const sc_attribute<T>& a ) + : sc_attr_base( a.name() ), value( a.value ) + {} + + + // destructor (does nothing) + + virtual ~sc_attribute() + {} + +public: + + // public data member; for easy access + T value; + +private: + + // disabled + sc_attribute(); + sc_attribute<T>& operator = ( const sc_attribute<T>& ); +}; + +} // namespace sc_core + +// $Log: sc_attribute.h,v $ +// Revision 1.6 2011/08/26 20:46:08 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.5 2011/02/18 20:27:14 acg +// Andy Goodrich: Updated Copyrights. +// +// Revision 1.4 2011/02/13 21:47:37 acg +// Andy Goodrich: update copyright notice. +// +// Revision 1.3 2010/07/22 20:02:33 acg +// Andy Goodrich: bug fixes. +// +// Revision 1.2 2008/05/22 17:06:24 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.3 2006/01/13 18:44:29 acg +// Added $Log to record CVS changes into the source. +// + +#endif + +// Taf! diff --git a/ext/systemc/src/sysc/kernel/sc_boost.h b/ext/systemc/src/sysc/kernel/sc_boost.h new file mode 100644 index 000000000..4383c21c9 --- /dev/null +++ b/ext/systemc/src/sysc/kernel/sc_boost.h @@ -0,0 +1,94 @@ +/***************************************************************************** + + 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_boost.h -- Thread Semantics Provided By The Boost Library + + Original Author: Stuart Swan, Cadence Design Systems, Inc + + CHANGE LOG AT THE END OF THE FILE + *****************************************************************************/ + + +#ifndef SC_BOOST_H +#define SC_BOOST_H + +// namespace sc_dp { This is off because of bugs with gcc 2.9x + +// SET THE NAME OF OBJECTS THAT THE SC_BOOST LIBRARY WILL PRODUCE AND INCLUDE IT + +#if defined(_MSC_VER) && !defined(__ICL) && !defined(__COMO__) +# pragma warning(disable: 4786) // identifier truncated in debug info +# pragma warning(disable: 4710) // function not inlined +# pragma warning(disable: 4711) // funct. selected for auto-inline expansion +# pragma warning(disable: 4514) // unreferenced inline removed +#endif + +#include <functional> + +#if defined(SC_BOOST_MSVC) && (SC_BOOST_MSVC < 1300) +# pragma warning(push, 3) +#endif + +#if defined(SC_BOOST_MSVC) && (SC_BOOST_MSVC < 1300) +# pragma warning(pop) +#endif + +// } // namespace sc_dp This is off because of bugs with gcc 2.9x + +// macros to help avoid direct user code dependencies on boost lib +// +// note the use of the sc_boost namespace for the SystemC version of +// boost. to replace the version shipped with SystemC with another boost +// you will need to change the namespace prefix back to boost. + +#define sc_bind std::bind +#define sc_ref(r) std::ref(r) +#define sc_cref(r) std::cref(r) + +// $Log: sc_boost.h,v $ +// Revision 1.7 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.6 2011/02/18 20:27:14 acg +// Andy Goodrich: Updated Copyrights. +// +// Revision 1.5 2011/02/13 21:47:37 acg +// Andy Goodrich: update copyright notice. +// +// Revision 1.4 2009/07/28 01:10:53 acg +// Andy Goodrich: updates for 2.3 release candidate. +// +// 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:24 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.3 2006/01/13 18:44:29 acg +// Added $Log to record CVS changes into the source. +// + +#endif // SC_BOOST_H diff --git a/ext/systemc/src/sysc/kernel/sc_cmnhdr.h b/ext/systemc/src/sysc/kernel/sc_cmnhdr.h new file mode 100644 index 000000000..fcbb2f568 --- /dev/null +++ b/ext/systemc/src/sysc/kernel/sc_cmnhdr.h @@ -0,0 +1,138 @@ +/***************************************************************************** + + 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_cmnhdr.h - Common header file containing handy pragmas, macros and + definitions common to all SystemC source files. + + Original Author: Amit Rao, Synopsys, Inc. + + CHANGE LOG AT THE END OF THE FILE + *****************************************************************************/ + + +#ifndef SC_CMNHDR_H +#define SC_CMNHDR_H + +#if defined(_WIN32) || defined(_MSC_VER) || defined(__BORLANDC__) || \ + defined(__MINGW32__) + +// all windows 32-bit compilers should define WIN32 +#if !defined(WIN32) && !defined(WIN64) && !defined(_WIN64) +#define WIN32 +#endif + +// Windows Version Build Option +#ifndef _WIN32_WINNT +#define _WIN32_WINNT 0x0400 +#endif + +// remember to later include windows.h, if needed +#define SC_HAS_WINDOWS_H_ + +#endif // WIN32 + +// ---------------------------------------------------------------------------- + +#ifdef _MSC_VER + +// Disable VC++ warnings that are harmless + +// this : used in base member initializer list +#pragma warning(disable: 4355) + +// new and delete warning when exception handling is turned on +#pragma warning(disable: 4291) + +// in many places implicit conversion to bool +// from other integral types is performed +#pragma warning(disable: 4800) + +// unary minus operator applied to unsigned +#pragma warning(disable: 4146) + +// multiple copy constructors +#pragma warning(disable: 4521) + +// identifier was truncated to '255' characters in the browser information +#pragma warning(disable: 4786) + +#endif + +// ---------------------------------------------------------------------------- +// helper macros to aid branch prediction on GCC (compatible) compilers + +#ifndef __GNUC__ +# define SC_LIKELY_( x ) !!(x) +# define SC_UNLIKELY_( x ) !!(x) +#else +# define SC_LIKELY_( x ) __builtin_expect( !!(x), 1 ) +# define SC_UNLIKELY_( x ) __builtin_expect( !!(x), 0 ) +#endif + +// ---------------------------------------------------------------------------- + +#include <cassert> +#include <cstdio> +#include <cstdlib> + +#endif // SC_CMNHDR_H + +// ---------------------------------------------------------------------------- +// only include Windows.h, if explicitly requested +// (deliberately outside of include guards to enable later effect) +#if defined(SC_HAS_WINDOWS_H_) && defined(SC_INCLUDE_WINDOWS_H) +# undef SC_HAS_WINDOWS_H_ +# include <Windows.h> +#endif + +// $Log: sc_cmnhdr.h,v $ +// Revision 1.8 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.7 2011/05/09 04:07:48 acg +// Philipp A. Hartmann: +// (1) Restore hierarchy in all phase callbacks. +// (2) Ensure calls to before_end_of_elaboration. +// +// Revision 1.6 2011/05/05 17:45:27 acg +// Philip A. Hartmann: changes in WIN64 support. +// Andy Goodrich: additional DEBUG_MSG instances to trace process handling. +// +// Revision 1.5 2011/02/18 20:27:14 acg +// Andy Goodrich: Updated Copyrights. +// +// Revision 1.4 2011/02/13 21:47:37 acg +// Andy Goodrich: update copyright notice. +// +// Revision 1.3 2009/05/22 16:06:29 acg +// Andy Goodrich: process control updates. +// +// Revision 1.2 2008/05/22 17:06:24 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.3 2006/01/13 18:44:29 acg +// Added $Log to record CVS changes into the source. + +// Taf! diff --git a/ext/systemc/src/sysc/kernel/sc_constants.h b/ext/systemc/src/sysc/kernel/sc_constants.h new file mode 100644 index 000000000..1ff20adbd --- /dev/null +++ b/ext/systemc/src/sysc/kernel/sc_constants.h @@ -0,0 +1,82 @@ +/***************************************************************************** + + 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_constants.h -- Default constants whose values may need to be + changed depending on the application. + + Original Author: Ali Dasdan, Synopsys, Inc. + + CHANGE LOG AT THE END OF THE FILE + *****************************************************************************/ + +#ifndef SC_CONSTANTS_H +#define SC_CONSTANTS_H + +namespace sc_core { + +// Maximum number of bits for arbitrary precision arithmetic. If +// defined, the arithmetic becomes faster. If not defined, the +// arithmetic becomes slower and the precision becomes infinite. It +// is a good idea to define this constant as a multiple of +// BITS_PER_DIGIT, which is defined in numeric_bit/sc_nbdefs.h. +//#define SC_MAX_NBITS 510 // 17 * BITS_PER_DIGIT + + +// deprecated in 1666-2005 and later, but kept for backwards compatibility +// - can be set by defining SC_OVERRIDE_DEFAULT_STACK_SIZE +// - defaults defined in sc_thread_process.cpp +extern const int SC_DEFAULT_STACK_SIZE; + + +#ifdef DEBUG_SYSTEMC +const int SC_MAX_NUM_DELTA_CYCLES = 10000; +#endif + +} // namespace sc_core + +// $Log: sc_constants.h,v $ +// Revision 1.7 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.6 2011/02/18 20:33:26 acg +// Philipp A. Hartmann: added default stack size for CYGWIN32. +// +// Revision 1.5 2011/02/18 20:27:14 acg +// Andy Goodrich: Updated Copyrights. +// +// Revision 1.4 2011/02/13 21:47:37 acg +// Andy Goodrich: update copyright notice. +// +// Revision 1.3 2010/03/15 18:29:25 acg +// Andy Goodrich: Changed the default stack size to 128K from 64K. +// +// Revision 1.2 2008/05/22 17:06:24 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.3 2006/01/13 18:44:29 acg +// Added $Log to record CVS changes into the source. +// + +#endif diff --git a/ext/systemc/src/sysc/kernel/sc_cor.h b/ext/systemc/src/sysc/kernel/sc_cor.h new file mode 100644 index 000000000..49892ca7a --- /dev/null +++ b/ext/systemc/src/sysc/kernel/sc_cor.h @@ -0,0 +1,157 @@ +/***************************************************************************** + + 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_cor.h -- Coroutine abstract base classes. + + Original Author: Martin Janssen, Synopsys, Inc., 2001-12-18 + + CHANGE LOG AT THE END OF THE FILE + *****************************************************************************/ + + +#ifndef SC_COR_H +#define SC_COR_H + + +#include <cassert> +#include <cstdlib> + +namespace sc_core { + +class sc_simcontext; + + +// ---------------------------------------------------------------------------- +// TYPEDEF : sc_cor_fn +// +// Function type for creating coroutines. +// ---------------------------------------------------------------------------- + +typedef void (sc_cor_fn)( void* ); + + +// ---------------------------------------------------------------------------- +// CLASS : sc_cor +// +// Coroutine abstract base class. +// ---------------------------------------------------------------------------- + +class sc_cor +{ +protected: + + // constructor + sc_cor() {} + +public: + + // destructor + virtual ~sc_cor() {} + + // switch stack protection on/off + virtual void stack_protect( bool /* enable */ ) {} + +private: + + // disabled + sc_cor( const sc_cor& ); + sc_cor& operator = ( const sc_cor& ); +}; + + +// ---------------------------------------------------------------------------- +// CLASS : sc_cor_pkg +// +// Coroutine package abstract base class. +// ---------------------------------------------------------------------------- + +class sc_cor_pkg +{ +public: + + // constructor + sc_cor_pkg( sc_simcontext* simc ) + : m_simc( simc ) { assert( simc != 0 ); } + + // destructor + virtual ~sc_cor_pkg() {} + + // create a new coroutine + virtual sc_cor* create( + std::size_t stack_size, sc_cor_fn* fn, void* arg ) = 0; + + // yield to the next coroutine + virtual void yield( sc_cor* next_cor ) = 0; + + // abort the current coroutine (and resume the next coroutine) + virtual void abort( sc_cor* next_cor ) = 0; + + // get the main coroutine + virtual sc_cor* get_main() = 0; + + // get the simulation context + sc_simcontext* simcontext() + { return m_simc; } + +private: + + sc_simcontext* m_simc; + +private: + + // disabled + sc_cor_pkg(); + sc_cor_pkg( const sc_cor_pkg& ); + sc_cor_pkg& operator = ( const sc_cor_pkg& ); +}; + +} // namespace sc_core + +// $Log: sc_cor.h,v $ +// Revision 1.7 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.6 2011/08/15 16:43:24 acg +// Torsten Maehne: changes to remove unused argument warnings. +// +// Revision 1.5 2011/02/18 20:27:14 acg +// Andy Goodrich: Updated Copyrights. +// +// Revision 1.4 2011/02/13 21:47:37 acg +// Andy Goodrich: update copyright notice. +// +// Revision 1.3 2011/01/19 23:21:49 acg +// Andy Goodrich: changes for IEEE 1666 2011 +// +// Revision 1.2 2008/05/22 17:06:24 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.3 2006/01/13 18:44:29 acg +// Added $Log to record CVS changes into the source. +// + +#endif + +// Taf! diff --git a/ext/systemc/src/sysc/kernel/sc_cor_fiber.cpp b/ext/systemc/src/sysc/kernel/sc_cor_fiber.cpp new file mode 100644 index 000000000..77cec8227 --- /dev/null +++ b/ext/systemc/src/sysc/kernel/sc_cor_fiber.cpp @@ -0,0 +1,224 @@ +/***************************************************************************** + + 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_cor_fiber.cpp -- Coroutine implementation with fibers. + + Original Author: Martin Janssen, Synopsys, Inc., 2001-12-18 + + CHANGE LOG APPEARS AT THE END OF THE FILE + *****************************************************************************/ + +#if defined(_WIN32) || defined(WIN32) || defined(WIN64) + +#ifndef SC_INCLUDE_WINDOWS_H +# define SC_INCLUDE_WINDOWS_H // include Windows.h, if needed +#endif + +#include "sysc/kernel/sc_cor_fiber.h" +#include "sysc/kernel/sc_simcontext.h" +#if defined(__GNUC__) && __USING_SJLJ_EXCEPTIONS__ +# if (__GNUC__ > 3) || ((__GNUC__ == 3) && (__GNUC_MINOR__ > 2)) +# include <unwind.h> +# else + extern "C" void _Unwind_SjLj_Register (struct SjLj_Function_Context *); + extern "C" void _Unwind_SjLj_Unregister (struct SjLj_Function_Context *); +# endif +#endif + +namespace sc_core { + +// ---------------------------------------------------------------------------- +// File static variables. +// ---------------------------------------------------------------------------- + +// main coroutine + +static sc_cor_fiber main_cor; +#if defined(__GNUC__) && __USING_SJLJ_EXCEPTIONS__ +// current coroutine +static sc_cor_fiber* curr_cor; +#endif + + +// ---------------------------------------------------------------------------- +// CLASS : sc_cor_fiber +// +// Coroutine class implemented with Windows fibers. +// ---------------------------------------------------------------------------- + +// destructor + +sc_cor_fiber::~sc_cor_fiber() +{ + if( m_fiber != 0 ) { + PVOID cur_fiber = GetCurrentFiber(); + if (m_fiber != cur_fiber) + DeleteFiber( m_fiber ); + } +} + + +// ---------------------------------------------------------------------------- +// CLASS : sc_cor_pkg_fiber +// +// Coroutine package class implemented with QuickThreads. +// ---------------------------------------------------------------------------- + +int sc_cor_pkg_fiber::instance_count = 0; + + +// constructor + +sc_cor_pkg_fiber::sc_cor_pkg_fiber( sc_simcontext* simc ) +: sc_cor_pkg( simc ) +{ + if( ++ instance_count == 1 ) { + // initialize the main coroutine + assert( main_cor.m_fiber == 0 ); + main_cor.m_fiber = ConvertThreadToFiber( 0 ); + + if( !main_cor.m_fiber && GetLastError() == ERROR_ALREADY_FIBER ) { + // conversion of current thread to fiber has failed, because + // someone else already converted the main thread to a fiber + // -> store current fiber + main_cor.m_fiber = GetCurrentFiber(); + } + assert( main_cor.m_fiber != 0 ); + +# if defined(__GNUC__) && __USING_SJLJ_EXCEPTIONS__ + // initialize the current coroutine + assert( curr_cor == 0 ); + curr_cor = &main_cor; +# endif + } +} + + +// destructor + +sc_cor_pkg_fiber::~sc_cor_pkg_fiber() +{ + if( -- instance_count == 0 ) { + // cleanup the main coroutine + main_cor.m_fiber = 0; +# if defined(__GNUC__) && __USING_SJLJ_EXCEPTIONS__ + // cleanup the current coroutine + curr_cor = 0; +# endif + } +} + + +// create a new coroutine + +sc_cor* +sc_cor_pkg_fiber::create( std::size_t stack_size, sc_cor_fn* fn, void* arg ) +{ + sc_cor_fiber* cor = new sc_cor_fiber; + cor->m_pkg = this; + cor->m_stack_size = stack_size; + cor->m_fiber = CreateFiberEx( cor->m_stack_size / 2, cor->m_stack_size, 0, + (LPFIBER_START_ROUTINE) fn, arg ); + return cor; +} + + +// yield to the next coroutine + +void +sc_cor_pkg_fiber::yield( sc_cor* next_cor ) +{ + sc_cor_fiber* new_cor = SCAST<sc_cor_fiber*>( next_cor ); +# if defined(__GNUC__) && __USING_SJLJ_EXCEPTIONS__ + // Switch SJLJ exception handling function contexts + _Unwind_SjLj_Register(&curr_cor->m_eh); + _Unwind_SjLj_Unregister(&new_cor->m_eh); + curr_cor = new_cor; +# endif + SwitchToFiber( new_cor->m_fiber ); +} + + +// abort the current coroutine (and resume the next coroutine) + +void +sc_cor_pkg_fiber::abort( sc_cor* next_cor ) +{ + sc_cor_fiber* new_cor = SCAST<sc_cor_fiber*>( next_cor ); +# if defined(__GNUC__) && __USING_SJLJ_EXCEPTIONS__ + // Switch SJLJ exception handling function contexts + _Unwind_SjLj_Register(&curr_cor->m_eh); + _Unwind_SjLj_Unregister(&new_cor->m_eh); + curr_cor = new_cor; +# endif + SwitchToFiber( new_cor->m_fiber ); +} + + +// get the main coroutine + +sc_cor* +sc_cor_pkg_fiber::get_main() +{ + return &main_cor; +} + +} // namespace sc_core + + +// $Log: sc_cor_fiber.cpp,v $ +// Revision 1.9 2011/09/08 16:12:45 acg +// Philipp A. Hartmann: make sure we don't try to make a thread a fiber if +// its already a fiber. +// +// Revision 1.8 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.7 2011/06/25 17:08:39 acg +// Andy Goodrich: Jerome Cornet's changes to use libtool to build the +// library. +// +// Revision 1.6 2011/02/18 20:27:14 acg +// Andy Goodrich: Updated Copyrights. +// +// Revision 1.5 2011/02/13 21:47:37 acg +// Andy Goodrich: update copyright notice. +// +// Revision 1.4 2011/01/19 23:21:50 acg +// Andy Goodrich: changes for IEEE 1666 2011 +// +// Revision 1.3 2009/05/22 16:06:29 acg +// Andy Goodrich: process control updates. +// +// Revision 1.2 2008/05/22 17:06:25 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.3 2006/01/13 18:44:29 acg +// Added $Log to record CVS changes into the source. +// + +#endif + +// Taf! diff --git a/ext/systemc/src/sysc/kernel/sc_cor_fiber.h b/ext/systemc/src/sysc/kernel/sc_cor_fiber.h new file mode 100644 index 000000000..96163f497 --- /dev/null +++ b/ext/systemc/src/sysc/kernel/sc_cor_fiber.h @@ -0,0 +1,169 @@ +/***************************************************************************** + + 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_cor_fiber.h -- Coroutine implementation with fibers. + + Original Author: Martin Janssen, Synopsys, Inc., 2001-12-18 + + CHANGE LOG AT THE END OF THE FILE + *****************************************************************************/ + + +#ifndef SC_COR_FIBER_H +#define SC_COR_FIBER_H + +#if defined(_WIN32) || defined(WIN32) || defined(WIN64) + +#include "sysc/kernel/sc_cor.h" +#include "sysc/kernel/sc_cmnhdr.h" + +#if defined(__GNUC__) && __USING_SJLJ_EXCEPTIONS__ + // _Unwind_SjLj_Register() & _Unwind_SjLj_Unregister() only need first field. + struct SjLj_Function_Context { + struct SjLj_Function_Context *prev; + }; +#endif + +namespace sc_core { + +class sc_cor_pkg_fiber; +typedef sc_cor_pkg_fiber sc_cor_pkg_t; + +#if( defined(_MSC_VER) && _MSC_VER >= 1300 ) +typedef std::size_t size_t; +#endif + +// ---------------------------------------------------------------------------- +// CLASS : sc_cor_fiber +// +// Coroutine class implemented with QuickThreads. +// ---------------------------------------------------------------------------- + +class sc_cor_fiber +: public sc_cor +{ + +public: + + // constructor + sc_cor_fiber() + : m_stack_size( 0 ), m_fiber( 0 ), m_pkg( 0 ) + { +# if defined(__GNUC__) && __USING_SJLJ_EXCEPTIONS__ + m_eh.prev = 0; +# endif + } + + // destructor + virtual ~sc_cor_fiber(); + +public: + + std::size_t m_stack_size; // stack size + void* m_fiber; // fiber + + sc_cor_pkg_fiber* m_pkg; // the creating coroutine package +#if defined(__GNUC__) && __USING_SJLJ_EXCEPTIONS__ + struct SjLj_Function_Context m_eh; // the exception handling context +#endif + + +private: + + // disabled + sc_cor_fiber( const sc_cor_fiber& ); + sc_cor_fiber& operator = ( const sc_cor_fiber& ); +}; + + +// ---------------------------------------------------------------------------- +// CLASS : sc_cor_pkg_fiber +// +// Coroutine package class implemented with QuickThreads. +// ---------------------------------------------------------------------------- + +class sc_cor_pkg_fiber +: public sc_cor_pkg +{ + public: + + // constructor + sc_cor_pkg_fiber( sc_simcontext* simc ); + + // destructor + virtual ~sc_cor_pkg_fiber(); + + // create a new coroutine + virtual sc_cor* create( std::size_t stack_size, sc_cor_fn* fn, void* arg ); + + // yield to the next coroutine + virtual void yield( sc_cor* next_cor ); + + // abort the current coroutine (and resume the next coroutine) + virtual void abort( sc_cor* next_cor ); + + // get the main coroutine + virtual sc_cor* get_main(); + +private: + + static int instance_count; + +private: + + // disabled + sc_cor_pkg_fiber(); + sc_cor_pkg_fiber( const sc_cor_pkg_fiber& ); + sc_cor_pkg_fiber& operator = ( const sc_cor_pkg_fiber& ); +}; + +} // namespace sc_core + +#endif // WIN32 + +// $Log: sc_cor_fiber.h,v $ +// Revision 1.6 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.5 2011/06/25 17:08:39 acg +// Andy Goodrich: Jerome Cornet's changes to use libtool to build the +// library. +// +// Revision 1.4 2011/02/18 20:27:14 acg +// Andy Goodrich: Updated Copyrights. +// +// Revision 1.3 2011/02/13 21:47:37 acg +// Andy Goodrich: update copyright notice. +// +// Revision 1.2 2008/05/22 17:06:25 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.3 2006/01/13 18:44:29 acg +// Added $Log to record CVS changes into the source. +// + +#endif + +// Taf! diff --git a/ext/systemc/src/sysc/kernel/sc_cor_pthread.cpp b/ext/systemc/src/sysc/kernel/sc_cor_pthread.cpp new file mode 100644 index 000000000..d95eca93b --- /dev/null +++ b/ext/systemc/src/sysc/kernel/sc_cor_pthread.cpp @@ -0,0 +1,313 @@ +/***************************************************************************** + + 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_cor_pthread.cpp -- Coroutine implementation with pthreads. + + Original Author: Andy Goodrich, Forte Design Systems, 2002-11-10 + + CHANGE LOG APPEARS AT THE END OF THE FILE + *****************************************************************************/ + +#if !defined(_WIN32) && !defined(WIN32) && defined(SC_USE_PTHREADS) + +// ORDER OF THE INCLUDES AND namespace sc_core IS IMPORTANT!!! + +#include "sysc/kernel/sc_cor_pthread.h" +#include "sysc/kernel/sc_simcontext.h" + +using namespace std; + +namespace sc_core { + +// MAKE SURE WE HAVE A NULL THAT WILL WORK: + +#if defined(__hpux) +# define PTHREAD_NULL cma_c_null +#else // !defined(__hpux) +# define PTHREAD_NULL NULL +#endif // !defined(__hpux) + +#define DEBUGF \ + if (0) std::cout << "sc_cor_pthread.cpp(" << __LINE__ << ") " + +// ---------------------------------------------------------------------------- +// File static variables. +// +// (1) The thread creation mutex and the creation condition are used to +// suspend the thread creating another one until the created thread +// reaches its invoke_module_method. This allows us to get control of +// thread scheduling away from the pthread package. +// ---------------------------------------------------------------------------- + +static sc_cor_pthread* active_cor_p=0; // Active co-routine. +static pthread_cond_t create_condition; // See note 1 above. +static pthread_mutex_t create_mutex; // See note 1 above. +static sc_cor_pthread main_cor; // Main coroutine. + + +// ---------------------------------------------------------------------------- +// CLASS : sc_cor_pthread +// +// Coroutine class implemented with Posix Threads. +// ---------------------------------------------------------------------------- + +// constructor + +sc_cor_pthread::sc_cor_pthread() + : m_cor_fn_arg( 0 ), m_pkg_p( 0 ) +{ + DEBUGF << this << ": sc_cor_pthread::sc_cor_pthread()" << std::endl; + pthread_cond_init( &m_pt_condition, PTHREAD_NULL ); + pthread_mutex_init( &m_mutex, PTHREAD_NULL ); +} + + +// destructor + +sc_cor_pthread::~sc_cor_pthread() +{ + DEBUGF << this << ": sc_cor_pthread::~sc_cor_pthread()" << std::endl; + pthread_cond_destroy( &m_pt_condition); + pthread_mutex_destroy( &m_mutex ); +} + + +// This static method is a Posix Threads helper callback and invokes a thread +// for the first time. It performs some synchronization and then invokes the +// actual sc_cor helper function. +// context_p -> thread to invoke module method of. +// Result is 0 and ignored. + +void* sc_cor_pthread::invoke_module_method(void* context_p) +{ + sc_cor_pthread* p = (sc_cor_pthread*)context_p; + DEBUGF << p << ": sc_cor_pthread::invoke_module_method()" << std::endl; + + + // SUSPEND THE THREAD SO WE CAN GAIN CONTROL FROM THE PTHREAD PACKAGE: + // + // Since pthread_create schedules each thread behind our back for its + // initial execution we immediately suspend a newly created thread + // here so we can control when its execution will occur. We also wake + // up the main thread which is waiting for this thread to execute to this + // wait point. + + pthread_mutex_lock( &create_mutex ); + DEBUGF << p << ": child signalling main thread " << endl; + pthread_cond_signal( &create_condition ); + pthread_mutex_lock( &p->m_mutex ); + pthread_mutex_unlock( &create_mutex ); + pthread_cond_wait( &p->m_pt_condition, &p->m_mutex ); + pthread_mutex_unlock( &p->m_mutex ); + + + // CALL THE SYSTEMC CODE THAT WILL ACTUALLY START THE THREAD OFF: + + active_cor_p = p; + DEBUGF << p << ": about to invoke real method " + << active_cor_p << std::endl; + (p->m_cor_fn)(p->m_cor_fn_arg); + + return 0; +} + + +// ---------------------------------------------------------------------------- +// CLASS : sc_cor_pkg_pthread +// +// Coroutine package class implemented with Posix Threads. +// ---------------------------------------------------------------------------- + +int sc_cor_pkg_pthread::instance_count = 0; + + +// constructor + +sc_cor_pkg_pthread::sc_cor_pkg_pthread( sc_simcontext* simc ) +: sc_cor_pkg( simc ) +{ + // initialize the current coroutine + if( ++ instance_count == 1 ) + { + pthread_cond_init( &create_condition, PTHREAD_NULL ); + pthread_mutex_init( &create_mutex, PTHREAD_NULL ); + assert( active_cor_p == 0 ); + main_cor.m_pkg_p = this; + DEBUGF << &main_cor << ": is main co-routine" << std::endl; + active_cor_p = &main_cor; + } +} + + +// destructor + +sc_cor_pkg_pthread::~sc_cor_pkg_pthread() +{ + if( -- instance_count == 0 ) { + // cleanup the main coroutine + } +} + + +// create a new coroutine + +sc_cor* +sc_cor_pkg_pthread::create( std::size_t stack_size, sc_cor_fn* fn, void* arg ) +{ + sc_cor_pthread* cor_p = new sc_cor_pthread; + DEBUGF << &main_cor << ": sc_cor_pkg_pthread::create(" + << cor_p << ")" << std::endl; + + + // INITIALIZE OBJECT'S FIELDS FROM ARGUMENT LIST: + + cor_p->m_pkg_p = this; + cor_p->m_cor_fn = fn; + cor_p->m_cor_fn_arg = arg; + + + // SET UP THREAD CREATION ATTRIBUTES: + // + // Use default values except for stack size. If stack size is non-zero + // set it. + + pthread_attr_t attr; + pthread_attr_init( &attr ); + if ( stack_size != 0 ) + { + pthread_attr_setstacksize( &attr, stack_size ); + } + + + // ALLOCATE THE POSIX THREAD TO USE AND FORCE SEQUENTIAL EXECUTION: + // + // Because pthread_create causes the created thread to be executed, + // we need to let it run until we can block in the invoke_module_method. + // So we: + // (1) Lock the creation mutex before creating the new thread. + // (2) Sleep on the creation condition, which will be signalled by + // the newly created thread just before it goes to sleep in + // invoke_module_method. + // This scheme results in the newly created thread being dormant before + // the main thread continues execution. + + pthread_mutex_lock( &create_mutex ); + DEBUGF << &main_cor << ": about to create actual thread " + << cor_p << std::endl; + if ( pthread_create( &cor_p->m_thread, &attr, + &sc_cor_pthread::invoke_module_method, (void*)cor_p ) ) + { + std::fprintf(stderr, "ERROR - could not create thread\n"); + } + + DEBUGF << &main_cor << ": main thread waiting for signal from " + << cor_p << std::endl; + pthread_cond_wait( &create_condition, &create_mutex ); + DEBUGF << &main_cor << ": main thread signaled by " + << cor_p << endl; + pthread_attr_destroy( &attr ); + pthread_mutex_unlock( &create_mutex ); + DEBUGF << &main_cor << ": exiting sc_cor_pkg_pthread::create(" + << cor_p << ")" << std::endl; + + return cor_p; +} + + +// yield to the next coroutine +// +// We don't do anything after the p_thread_cond_wait since it won't +// happen until the thread wakes up again! + +void +sc_cor_pkg_pthread::yield( sc_cor* next_cor_p ) +{ + sc_cor_pthread* from_p = active_cor_p; + sc_cor_pthread* to_p = (sc_cor_pthread*)next_cor_p; + + DEBUGF << from_p << ": switch to " << to_p << std::endl; + if ( to_p != from_p ) + { + pthread_mutex_lock( &to_p->m_mutex ); + pthread_cond_signal( &to_p->m_pt_condition ); + pthread_mutex_lock( &from_p->m_mutex ); + pthread_mutex_unlock( &to_p->m_mutex ); + pthread_cond_wait( &from_p->m_pt_condition, &from_p->m_mutex ); + pthread_mutex_unlock( &from_p->m_mutex ); + } + + active_cor_p = from_p; // When we come out of wait make ourselves active. + DEBUGF << from_p << " restarting after yield to " << to_p << std::endl; +} + + +// abort the current coroutine (and resume the next coroutine) + +void +sc_cor_pkg_pthread::abort( sc_cor* next_cor_p ) +{ + sc_cor_pthread* n_p = (sc_cor_pthread*)next_cor_p; + + DEBUGF << active_cor_p << ": aborting, switching to " << n_p << std::endl; + pthread_mutex_lock( &n_p->m_mutex ); + pthread_cond_signal( &n_p->m_pt_condition ); + pthread_mutex_unlock( &n_p->m_mutex ); +} + + +// get the main coroutine + +sc_cor* +sc_cor_pkg_pthread::get_main() +{ + return &main_cor; +} + +} // namespace sc_core + +#endif // !defined(_WIN32) && !defined(WIN32) && defined(SC_USE_PTHREADS) + + +// $Log: sc_cor_pthread.cpp,v $ +// Revision 1.6 2011/08/30 21:51:04 acg +// Jerome Cornet: auto processing of pthread configurations. +// +// Revision 1.5 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.4 2011/02/18 20:27:14 acg +// Andy Goodrich: Updated Copyrights. +// +// Revision 1.3 2011/02/13 21:47:37 acg +// Andy Goodrich: update copyright notice. +// +// Revision 1.2 2008/05/22 17:06:25 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.3 2006/01/13 18:44:29 acg +// Added $Log to record CVS changes into the source. +// + +// Taf! diff --git a/ext/systemc/src/sysc/kernel/sc_cor_pthread.h b/ext/systemc/src/sysc/kernel/sc_cor_pthread.h new file mode 100644 index 000000000..f4d835de3 --- /dev/null +++ b/ext/systemc/src/sysc/kernel/sc_cor_pthread.h @@ -0,0 +1,157 @@ +/***************************************************************************** + + 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_cor_pthread.h -- Coroutine implementation with pthreads. + + Original Author: Andy Goodrich, Forte Design Systems, 2002-11-10 + + CHANGE LOG AT THE END OF THE FILE + *****************************************************************************/ + + +#ifndef SC_COR_PTHREAD_H +#define SC_COR_PTHREAD_H + + +#if defined(SC_USE_PTHREADS) + +#include "sysc/kernel/sc_cor.h" +#include "sysc/kernel/sc_cmnhdr.h" +#include <pthread.h> + +namespace sc_core { + +class sc_cor_pkg_pthread; +typedef sc_cor_pkg_pthread sc_cor_pkg_t; + +// ---------------------------------------------------------------------------- +// CLASS : sc_cor_pthread +// +// Coroutine class implemented with Posix Threads. +// +// Notes: +// (1) The thread creation mutex and the creation condition are used to +// suspend the thread creating another one until the created thread +// reaches its invoke_module_method. This allows us to get control of +// thread scheduling away from the pthread package. +// ---------------------------------------------------------------------------- + +class sc_cor_pthread : public sc_cor +{ + public: + + // constructor + sc_cor_pthread(); + + // destructor + virtual ~sc_cor_pthread(); + + // module method invocator (starts thread execution) + static void* invoke_module_method( void* context_p ); + + public: + static sc_cor_pthread* m_active_cor_p; // Active coroutine. + + public: + sc_cor_fn* m_cor_fn; // Core function. + void* m_cor_fn_arg; // Core function argument. + pthread_mutex_t m_mutex; // Mutex to suspend thread on. + sc_cor_pkg_pthread* m_pkg_p; // the creating coroutine package + pthread_cond_t m_pt_condition; // Condition waiting for. + pthread_t m_thread; // Our pthread storage. + +private: + + // disabled + sc_cor_pthread( const sc_cor_pthread& ); + sc_cor_pthread& operator = ( const sc_cor_pthread& ); +}; + + +// ---------------------------------------------------------------------------- +// CLASS : sc_cor_pkg_pthread +// +// Coroutine package class implemented with Posix Threads. +// ---------------------------------------------------------------------------- + +class sc_cor_pkg_pthread +: public sc_cor_pkg +{ +public: + + // constructor + sc_cor_pkg_pthread( sc_simcontext* simc ); + + // destructor + virtual ~sc_cor_pkg_pthread(); + + // create a new coroutine + virtual sc_cor* create( std::size_t stack_size, sc_cor_fn* fn, void* arg ); + + // yield to the next coroutine + virtual void yield( sc_cor* next_cor ); + + // abort the current coroutine (and resume the next coroutine) + virtual void abort( sc_cor* next_cor ); + + // get the main coroutine + virtual sc_cor* get_main(); + +private: + + static int instance_count; + +private: + + // disabled + sc_cor_pkg_pthread(); + sc_cor_pkg_pthread( const sc_cor_pkg_pthread& ); + sc_cor_pkg_pthread& operator = ( const sc_cor_pkg_pthread& ); +}; + +} // namespace sc_core + +#endif + +// $Log: sc_cor_pthread.h,v $ +// Revision 1.5 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.4 2011/02/18 20:27:14 acg +// Andy Goodrich: Updated Copyrights. +// +// Revision 1.3 2011/02/13 21:47:37 acg +// Andy Goodrich: update copyright notice. +// +// Revision 1.2 2008/05/22 17:06:25 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.3 2006/01/13 18:44:29 acg +// Added $Log to record CVS changes into the source. +// + +#endif // defined(SC_USE_PTHREADS) + +// Taf! diff --git a/ext/systemc/src/sysc/kernel/sc_cor_qt.cpp b/ext/systemc/src/sysc/kernel/sc_cor_qt.cpp new file mode 100644 index 000000000..d42298a62 --- /dev/null +++ b/ext/systemc/src/sysc/kernel/sc_cor_qt.cpp @@ -0,0 +1,271 @@ +/***************************************************************************** + + 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_cor_qt.cpp -- Coroutine implementation with QuickThreads. + + Original Author: Martin Janssen, Synopsys, Inc., 2001-12-18 + + CHANGE LOG APPEARS AT THE END OF THE FILE + *****************************************************************************/ + +#if !defined(_WIN32) && !defined(WIN32) && !defined(SC_USE_PTHREADS) + +#include <unistd.h> +#include <sys/mman.h> +#include <sys/types.h> + +#include "sysc/kernel/sc_cor_qt.h" +#include "sysc/kernel/sc_simcontext.h" + +namespace sc_core { + +// ---------------------------------------------------------------------------- +// File static variables. +// ---------------------------------------------------------------------------- + +// main coroutine + +static sc_cor_qt main_cor; + +// current coroutine + +static sc_cor_qt* curr_cor = 0; + + +// ---------------------------------------------------------------------------- +// CLASS : sc_cor_qt +// +// Coroutine class implemented with QuickThreads. +// ---------------------------------------------------------------------------- + +// switch stack protection on/off + +void +sc_cor_qt::stack_protect( bool enable ) +{ + // Code needs to be tested on HP-UX and disabled if it doesn't work there + // Code still needs to be ported to WIN32 + + static std::size_t pagesize; + + if( pagesize == 0 ) { +# if defined(__ppc__) + pagesize = getpagesize(); +# else + pagesize = sysconf( _SC_PAGESIZE ); +# endif + } + + assert( pagesize != 0 ); + assert( m_stack_size > ( 2 * pagesize ) ); + +#ifdef QUICKTHREADS_GROW_DOWN + // Stacks grow from high address down to low address + caddr_t redzone = caddr_t( ( ( std::size_t( m_stack ) + pagesize - 1 ) / + pagesize ) * pagesize ); +#else + // Stacks grow from low address up to high address + caddr_t redzone = caddr_t( ( ( std::size_t( m_stack ) + + m_stack_size - pagesize ) / + pagesize ) * pagesize ); +#endif + + int ret; + + // Enable the red zone at the end of the stack so that references within + // it will cause an interrupt. + + if( enable ) { + ret = mprotect( redzone, pagesize - 1, PROT_NONE ); + } + + // Revert the red zone to normal memory usage. Try to make it read - write - + // execute. If that does not work then settle for read - write + + else { + ret = mprotect( redzone, pagesize - 1, PROT_READ|PROT_WRITE|PROT_EXEC); + if ( ret != 0 ) + ret = mprotect( redzone, pagesize - 1, PROT_READ | PROT_WRITE ); + } + + assert( ret == 0 ); +} + + +// ---------------------------------------------------------------------------- +// CLASS : sc_cor_pkg_qt +// +// Coroutine package class implemented with QuickThreads. +// ---------------------------------------------------------------------------- + +int sc_cor_pkg_qt::instance_count = 0; + + +// support function + +inline +void* +stack_align( void* sp, int alignment, std::size_t* stack_size ) +{ + int round_up_mask = alignment - 1; + *stack_size = (*stack_size + round_up_mask) & ~round_up_mask; + return ( (void*)(((qt_word_t) sp + round_up_mask) & ~round_up_mask) ); +} + + +// constructor + +sc_cor_pkg_qt::sc_cor_pkg_qt( sc_simcontext* simc ) +: sc_cor_pkg( simc ) +{ + if( ++ instance_count == 1 ) { + // initialize the current coroutine + assert( curr_cor == 0 ); + curr_cor = &main_cor; + } +} + + +// destructor + +sc_cor_pkg_qt::~sc_cor_pkg_qt() +{ + if( -- instance_count == 0 ) { + // cleanup the current coroutine + curr_cor = 0; + } +} + + +// create a new coroutine + +extern "C" +void +sc_cor_qt_wrapper( void* arg, void* cor, qt_userf_t* fn ) +{ + curr_cor = RCAST<sc_cor_qt*>( cor ); + // invoke the user function + (*(sc_cor_fn*) fn)( arg ); + // not reached +} + +sc_cor* +sc_cor_pkg_qt::create( std::size_t stack_size, sc_cor_fn* fn, void* arg ) +{ + sc_cor_qt* cor = new sc_cor_qt(); + cor->m_pkg = this; + cor->m_stack_size = stack_size; + cor->m_stack = new char[cor->m_stack_size]; + void* sto = stack_align( cor->m_stack, QUICKTHREADS_STKALIGN, + &cor->m_stack_size ); + cor->m_sp = QUICKTHREADS_SP(sto, cor->m_stack_size - QUICKTHREADS_STKALIGN); + cor->m_sp = QUICKTHREADS_ARGS( cor->m_sp, arg, cor, (qt_userf_t*) fn, + sc_cor_qt_wrapper ); + return cor; +} + + +// yield to the next coroutine + +extern "C" +void* +sc_cor_qt_yieldhelp( qt_t* sp, void* old_cor, void* ) +{ + RCAST<sc_cor_qt*>( old_cor )->m_sp = sp; + return 0; +} + +void +sc_cor_pkg_qt::yield( sc_cor* next_cor ) +{ + sc_cor_qt* new_cor = SCAST<sc_cor_qt*>( next_cor ); + sc_cor_qt* old_cor = curr_cor; + curr_cor = new_cor; + QUICKTHREADS_BLOCK( sc_cor_qt_yieldhelp, old_cor, 0, new_cor->m_sp ); +} + + +// abort the current coroutine (and resume the next coroutine) + +extern "C" +void* +sc_cor_qt_aborthelp( qt_t*, void*, void* ) +{ + return 0; +} + +void +sc_cor_pkg_qt::abort( sc_cor* next_cor ) +{ + sc_cor_qt* new_cor = SCAST<sc_cor_qt*>( next_cor ); + sc_cor_qt* old_cor = curr_cor; + curr_cor = new_cor; + QUICKTHREADS_ABORT( sc_cor_qt_aborthelp, old_cor, 0, new_cor->m_sp ); +} + + +// get the main coroutine + +sc_cor* +sc_cor_pkg_qt::get_main() +{ + return &main_cor; +} + +} // namespace sc_core + +#endif + +// $Log: sc_cor_qt.cpp,v $ +// Revision 1.9 2011/08/29 18:04:32 acg +// Philipp A. Hartmann: miscellaneous clean ups. +// +// Revision 1.8 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.7 2011/02/18 20:27:14 acg +// Andy Goodrich: Updated Copyrights. +// +// Revision 1.6 2011/02/13 21:47:37 acg +// Andy Goodrich: update copyright notice. +// +// Revision 1.5 2010/08/03 16:52:14 acg +// Andy Goodrich: line formatting. +// +// Revision 1.4 2008/11/11 14:03:07 acg +// Andy Goodrich: added execute access to the release of red zone storage +// per Ulli's suggestion. +// +// Revision 1.3 2008/05/22 17:06:25 acg +// Andy Goodrich: updated copyright notice to include 2008. +// +// Revision 1.2 2008/03/24 18:32:36 acg +// Andy Goodrich: added include of sys/types.h to pick up the declaration +// of caddr_t. +// +// Revision 1.1.1.1 2006/12/15 20:20:05 acg +// SystemC 2.3 +// +// Revision 1.3 2006/01/13 18:44:29 acg +// Added $Log to record CVS changes into the source. + +// Taf! diff --git a/ext/systemc/src/sysc/kernel/sc_cor_qt.h b/ext/systemc/src/sysc/kernel/sc_cor_qt.h new file mode 100644 index 000000000..644d39c3f --- /dev/null +++ b/ext/systemc/src/sysc/kernel/sc_cor_qt.h @@ -0,0 +1,154 @@ +/***************************************************************************** + + 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_cor_qt.h -- Coroutine implementation with QuickThreads. + + Original Author: Martin Janssen, Synopsys, Inc., 2001-12-18 + + CHANGE LOG AT THE END OF THE FILE + *****************************************************************************/ + + +#ifndef SC_COR_QT_H +#define SC_COR_QT_H + + +#if !defined(_WIN32) && !defined(WIN32) && !defined(WIN64) && !defined(SC_USE_PTHREADS) + +#include "sysc/kernel/sc_cor.h" +#include "sysc/qt/qt.h" + +namespace sc_core { + +class sc_cor_pkg_qt; +typedef sc_cor_pkg_qt sc_cor_pkg_t; + +// ---------------------------------------------------------------------------- +// CLASS : sc_cor_qt +// +// Coroutine class implemented with QuickThreads. +// ---------------------------------------------------------------------------- + +class sc_cor_qt +: public sc_cor +{ +public: + + // constructor + sc_cor_qt() + : m_stack_size( 0 ), m_stack( 0 ), m_sp( 0 ), m_pkg( 0 ) + {} + + // destructor + virtual ~sc_cor_qt() + { delete[] (char*) m_stack; } + + // switch stack protection on/off + virtual void stack_protect( bool enable ); + +public: + + std::size_t m_stack_size; // stack size + void* m_stack; // stack + qt_t* m_sp; // stack pointer + + sc_cor_pkg_qt* m_pkg; // the creating coroutine package + +private: + + // disabled + sc_cor_qt( const sc_cor_qt& ); + sc_cor_qt& operator = ( const sc_cor_qt& ); +}; + + +// ---------------------------------------------------------------------------- +// CLASS : sc_cor_pkg_qt +// +// Coroutine package class implemented with QuickThreads. +// ---------------------------------------------------------------------------- + +class sc_cor_pkg_qt +: public sc_cor_pkg +{ +public: + + // constructor + sc_cor_pkg_qt( sc_simcontext* simc ); + + // destructor + virtual ~sc_cor_pkg_qt(); + + // create a new coroutine + virtual sc_cor* create( std::size_t stack_size, sc_cor_fn* fn, void* arg ); + + // yield to the next coroutine + virtual void yield( sc_cor* next_cor ); + + // abort the current coroutine (and resume the next coroutine) + virtual void abort( sc_cor* next_cor ); + + // get the main coroutine + virtual sc_cor* get_main(); + +private: + + static int instance_count; + +private: + + // disabled + sc_cor_pkg_qt(); + sc_cor_pkg_qt( const sc_cor_pkg_qt& ); + sc_cor_pkg_qt& operator = ( const sc_cor_pkg_qt& ); +}; + +} // namespace sc_core + +#endif + +// $Log: sc_cor_qt.h,v $ +// Revision 1.6 2011/08/29 18:04:32 acg +// Philipp A. Hartmann: miscellaneous clean ups. +// +// Revision 1.5 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.4 2011/02/18 20:27:14 acg +// Andy Goodrich: Updated Copyrights. +// +// Revision 1.3 2011/02/13 21:47:37 acg +// Andy Goodrich: update copyright notice. +// +// Revision 1.2 2008/05/22 17:06:25 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.3 2006/01/13 18:44:29 acg +// Added $Log to record CVS changes into the source. +// + +#endif + +// Taf! diff --git a/ext/systemc/src/sysc/kernel/sc_cthread_process.cpp b/ext/systemc/src/sysc/kernel/sc_cthread_process.cpp new file mode 100644 index 000000000..fef5cc8d8 --- /dev/null +++ b/ext/systemc/src/sysc/kernel/sc_cthread_process.cpp @@ -0,0 +1,123 @@ +/***************************************************************************** + + 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_cthread_process.cpp -- Clocked thread implementation. + + Original Author: Andy Goodrich, Forte Design Systems, 4 August 2005 + + + CHANGE LOG APPEARS AT THE END OF THE FILE + *****************************************************************************/ + +#include "sysc/kernel/sc_cthread_process.h" +#include "sysc/kernel/sc_simcontext_int.h" + +namespace sc_core { + +//------------------------------------------------------------------------------ +//"sc_cthread_process::dont_initialize" +// +// This virtual method sets the initialization switch for this object instance. +//------------------------------------------------------------------------------ +void sc_cthread_process::dont_initialize( bool /* dont */ ) +{ + SC_REPORT_WARNING( SC_ID_DONT_INITIALIZE_, 0 ); +} + +//------------------------------------------------------------------------------ +//"sc_cthread_process::sc_cthread_process" +// +// This is the object instance constructor for this class. +//------------------------------------------------------------------------------ +sc_cthread_process::sc_cthread_process( const char* name_p, + bool free_host, SC_ENTRY_FUNC method_p, + sc_process_host* host_p, const sc_spawn_options* opt_p +): + sc_thread_process(name_p, free_host, method_p, host_p, opt_p) +{ + m_dont_init = true; + m_process_kind = SC_CTHREAD_PROC_; +} + +//------------------------------------------------------------------------------ +//"sc_cthread_process::~sc_cthread_process" +// +// This is the object instance constructor for this class. +//------------------------------------------------------------------------------ +sc_cthread_process::~sc_cthread_process() +{ +} + +} // namespace sc_core + +// $Log: sc_cthread_process.cpp,v $ +// Revision 1.11 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.10 2011/08/15 16:43:24 acg +// Torsten Maehne: changes to remove unused argument warnings. +// +// Revision 1.9 2011/02/18 20:27:14 acg +// Andy Goodrich: Updated Copyrights. +// +// Revision 1.8 2011/02/13 21:47:37 acg +// Andy Goodrich: update copyright notice. +// +// Revision 1.7 2011/02/11 13:25:24 acg +// Andy Goodrich: Philipp A. Hartmann's changes: +// (1) Removal of SC_CTHREAD method overloads. +// (2) New exception processing code. +// +// Revision 1.6 2011/02/01 21:00:35 acg +// Andy Goodrich: removed throw_reset as it is now handled by parent +// sc_thread_process::throw_reset(). +// +// Revision 1.5 2011/01/18 20:10:44 acg +// Andy Goodrich: changes for IEEE1666_2011 semantics. +// +// Revision 1.4 2009/07/28 01:10:53 acg +// Andy Goodrich: updates for 2.3 release candidate. +// +// Revision 1.3 2009/05/22 16:06:29 acg +// Andy Goodrich: process control updates. +// +// Revision 1.2 2008/05/22 17:06:25 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.6 2006/04/20 17:08:16 acg +// Andy Goodrich: 3.0 style process changes. +// +// Revision 1.5 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.4 2006/01/24 20:49:04 acg +// Andy Goodrich: changes to remove the use of deprecated features within the +// simulator, and to issue warning messages when deprecated features are used. +// +// Revision 1.3 2006/01/13 18:44:29 acg +// Added $Log to record CVS changes into the source. +// diff --git a/ext/systemc/src/sysc/kernel/sc_cthread_process.h b/ext/systemc/src/sysc/kernel/sc_cthread_process.h new file mode 100644 index 000000000..6d35ece0d --- /dev/null +++ b/ext/systemc/src/sysc/kernel/sc_cthread_process.h @@ -0,0 +1,144 @@ +/***************************************************************************** + + 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_cthread_process.h -- Clocked thread declarations + + Original Author: Andy Goodrich, Forte Design Systems, 4 August 2005 + + + CHANGE LOG AT THE END OF THE FILE + *****************************************************************************/ + + +#if !defined(sc_cthread_process_h_INCLUDED) +#define sc_cthread_process_h_INCLUDED + +#include "sysc/kernel/sc_thread_process.h" + +namespace sc_core { + +// friend function declarations: + +void halt( sc_simcontext* ); +void wait( int, sc_simcontext* ); + + +//============================================================================== +// sc_cthread_process - +// +//============================================================================== +class sc_cthread_process : public sc_thread_process { + + friend class sc_module; + friend class sc_process_handle; + friend class sc_process_table; + friend class sc_thread_process; + friend class sc_simcontext; + + friend void sc_cthread_cor_fn( void* ); + + friend void halt( sc_simcontext* ); + friend void wait( int, sc_simcontext* ); + + public: + sc_cthread_process( const char* name_p, bool free_host, + SC_ENTRY_FUNC method_p, sc_process_host* host_p, + const sc_spawn_options* opt_p ); + + virtual void dont_initialize( bool dont ); + virtual const char* kind() const + { return "sc_cthread_process"; } + +private: + + sc_cthread_process( const char* nm, + SC_ENTRY_FUNC fn, + sc_process_host* host ); + + // may not be deleted manually (called from sc_process_b) + virtual ~sc_cthread_process(); + + bool eval_watchlist(); + bool eval_watchlist_curr_level(); + + void wait_halt(); + +}; + +//------------------------------------------------------------------------------ +//"sc_cthread_process::wait_halt" +// +//------------------------------------------------------------------------------ +inline void sc_cthread_process::wait_halt() +{ + m_wait_cycle_n = 0; + suspend_me(); + throw sc_halt(); +} + +} // namespace sc_core + +// $Log: sc_cthread_process.h,v $ +// Revision 1.8 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.7 2011/02/18 20:27:14 acg +// Andy Goodrich: Updated Copyrights. +// +// Revision 1.6 2011/02/13 21:47:37 acg +// Andy Goodrich: update copyright notice. +// +// Revision 1.5 2011/02/11 13:25:24 acg +// Andy Goodrich: Philipp A. Hartmann's changes: +// (1) Removal of SC_CTHREAD method overloads. +// (2) New exception processing code. +// +// Revision 1.4 2011/02/01 21:01:41 acg +// Andy Goodrich: removed throw_reset() as it is now handled by the parent +// method sc_thread_process::throw_reset(). +// +// Revision 1.3 2011/01/18 20:10:44 acg +// Andy Goodrich: changes for IEEE1666_2011 semantics. +// +// Revision 1.2 2008/05/22 17:06:25 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.6 2006/05/08 17:57:13 acg +// Andy Goodrich: Added David Long's forward declarations for friend functions +// to keep the Microsoft C++ compiler happy. +// +// Revision 1.5 2006/04/20 17:08:16 acg +// Andy Goodrich: 3.0 style process changes. +// +// Revision 1.4 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.3 2006/01/13 18:44:29 acg +// Added $Log to record CVS changes into the source. +// + +#endif // !defined(sc_cthread_process_h_INCLUDED) diff --git a/ext/systemc/src/sysc/kernel/sc_dynamic_processes.h b/ext/systemc/src/sysc/kernel/sc_dynamic_processes.h new file mode 100644 index 000000000..628c3300a --- /dev/null +++ b/ext/systemc/src/sysc/kernel/sc_dynamic_processes.h @@ -0,0 +1,67 @@ +/***************************************************************************** + + 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_dynamic_process.h -- Dynamic Process Package Definitions + + Original Author: Andy Goodrich, Forte Design Systems, 5 May 2003 + + CHANGE LOG AT THE END OF THE FILE + *****************************************************************************/ + + +#ifndef SC_DYNAMIC_PROCESSES_H +#define SC_DYNAMIC_PROCESSES_H + +#include "sysc/kernel/sc_except.h" +#include "sysc/kernel/sc_spawn.h" +#include "sysc/kernel/sc_join.h" +#include "sysc/kernel/sc_boost.h" + +// $Log: sc_dynamic_processes.h,v $ +// Revision 1.5 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.4 2011/02/18 20:27:14 acg +// Andy Goodrich: Updated Copyrights. +// +// Revision 1.3 2011/02/13 21:47:37 acg +// Andy Goodrich: update copyright notice. +// +// Revision 1.2 2008/05/22 17:06:25 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.5 2006/04/20 17:08:16 acg +// Andy Goodrich: 3.0 style process changes. +// +// Revision 1.4 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.3 2006/01/13 18:44:29 acg +// Added $Log to record CVS changes into the source. +// + +#endif // SC_DYNAMIC_PROCESSES_H diff --git a/ext/systemc/src/sysc/kernel/sc_event.cpp b/ext/systemc/src/sysc/kernel/sc_event.cpp new file mode 100644 index 000000000..488210ee9 --- /dev/null +++ b/ext/systemc/src/sysc/kernel/sc_event.cpp @@ -0,0 +1,759 @@ +/***************************************************************************** + + 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! diff --git a/ext/systemc/src/sysc/kernel/sc_event.h b/ext/systemc/src/sysc/kernel/sc_event.h new file mode 100644 index 000000000..9633752ce --- /dev/null +++ b/ext/systemc/src/sysc/kernel/sc_event.h @@ -0,0 +1,884 @@ +/***************************************************************************** + + 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.h -- + + Original Author: Martin Janssen, Synopsys, Inc., 2001-05-21 + + CHANGE LOG AT THE END OF THE FILE + *****************************************************************************/ + + +#ifndef SC_EVENT_H +#define SC_EVENT_H + +#include "sysc/kernel/sc_cmnhdr.h" +#include "sysc/kernel/sc_kernel_ids.h" +#include "sysc/kernel/sc_simcontext.h" +#include "sysc/communication/sc_writer_policy.h" + +namespace sc_core { + +// forward declarations +class sc_event; +class sc_event_timed; +class sc_event_list; +class sc_event_or_list; +class sc_event_and_list; +class sc_object; + +// friend function declarations + int sc_notify_time_compare( const void*, const void* ); + +// ---------------------------------------------------------------------------- +// CLASS : sc_event_expr +// +// The event expression class. +// ---------------------------------------------------------------------------- + +template< typename T > +class sc_event_expr +{ + friend class sc_event; + friend class sc_event_and_list; + friend class sc_event_or_list; + + typedef T type; + + inline sc_event_expr() + : m_expr( new T(true) ) + {} + +public: + + inline sc_event_expr( sc_event_expr const & e) // move semantics + : m_expr(e.m_expr) + { + e.m_expr = 0; + } + + T const & release() const + { + sc_assert( m_expr ); + T* expr = m_expr; + m_expr=0; + return *expr; + } + + void push_back( sc_event const & e) const + { + sc_assert( m_expr ); + m_expr->push_back(e); + } + + void push_back( type const & el) const + { + sc_assert( m_expr ); + m_expr->push_back(el); + } + operator T const &() const + { + return release(); + } + + ~sc_event_expr() + { + delete m_expr; + } + +private: + mutable type * m_expr; + + // disabled + void operator=( sc_event_expr const & ); +}; + +// ---------------------------------------------------------------------------- +// CLASS : sc_event_list +// +// Base class for lists of events. +// ---------------------------------------------------------------------------- + +class sc_event_list +{ + friend class sc_process_b; + friend class sc_method_process; + friend class sc_thread_process; + friend void sc_thread_cor_fn( void* arg ); + +public: + sc_event_list( const sc_event_list& ); + sc_event_list& operator = ( const sc_event_list& ); + + int size() const; + +protected: + + void push_back( const sc_event& ); + void push_back( const sc_event_list& ); + + explicit + sc_event_list( bool and_list_, bool auto_delete_ = false ); + + sc_event_list( const sc_event&, + bool and_list_, + bool auto_delete_ = false ); + + ~sc_event_list(); + + void swap( sc_event_list& ); + void move_from( const sc_event_list& ); + + bool and_list() const; + + void add_dynamic( sc_method_handle ) const; + void add_dynamic( sc_thread_handle ) const; + void remove_dynamic( sc_method_handle, const sc_event* ) const; + void remove_dynamic( sc_thread_handle, const sc_event* ) const; + + bool busy() const; + bool temporary() const; + void auto_delete() const; + + void report_premature_destruction() const; + void report_invalid_modification() const; + +private: + + std::vector<const sc_event*> m_events; + bool m_and_list; + bool m_auto_delete; + mutable unsigned m_busy; +}; + + +// ---------------------------------------------------------------------------- +// CLASS : sc_event_and_list +// +// AND list of events. +// ---------------------------------------------------------------------------- + +class sc_event_and_list +: public sc_event_list +{ + friend class sc_event; + friend class sc_event_expr<sc_event_and_list>; + friend class sc_process_b; + friend class sc_method_process; + friend class sc_thread_process; + +protected: + + explicit + sc_event_and_list( bool auto_delete_ ); + +public: + + sc_event_and_list(); + sc_event_and_list( const sc_event& ); + + void swap( sc_event_and_list& ); + sc_event_and_list& operator &= ( const sc_event& ); + sc_event_and_list& operator &= ( const sc_event_and_list & ); + + sc_event_expr<sc_event_and_list> operator & ( const sc_event& ); + sc_event_expr<sc_event_and_list> operator & ( const sc_event_and_list& ); +}; + +typedef sc_event_expr<sc_event_and_list> sc_event_and_expr; + +// ---------------------------------------------------------------------------- +// CLASS : sc_event_or_list +// +// OR list of events. +// ---------------------------------------------------------------------------- + +class sc_event_or_list +: public sc_event_list +{ + friend class sc_event; + friend class sc_event_expr<sc_event_or_list>; + friend class sc_process_b; + friend class sc_method_process; + friend class sc_thread_process; + +protected: + + explicit + sc_event_or_list( bool auto_delete_ ); + +public: + sc_event_or_list(); + sc_event_or_list( const sc_event& ); + void swap( sc_event_or_list& ); + sc_event_or_list& operator |= ( const sc_event& ); + sc_event_or_list& operator |= ( const sc_event_or_list & ); + sc_event_expr<sc_event_or_list> operator | ( const sc_event& ) const; + sc_event_expr<sc_event_or_list> operator | ( const sc_event_or_list& ) const; +}; + +typedef sc_event_expr<sc_event_or_list> sc_event_or_expr; + +// ---------------------------------------------------------------------------- +// CLASS : sc_event +// +// The event class. +// ---------------------------------------------------------------------------- + +class sc_event +{ + friend class sc_clock; + friend class sc_event_list; + friend class sc_event_timed; + friend class sc_simcontext; + friend class sc_object; + friend class sc_process_b; + friend class sc_method_process; + friend class sc_thread_process; + template<typename IF, sc_writer_policy POL> friend class sc_signal; + friend void sc_thread_cor_fn( void* arg ); + +public: + + sc_event(); + sc_event( const char* name ); + ~sc_event(); + + void cancel(); + + const char* name() const { return m_name.c_str(); } + const char* basename() const; + sc_object* get_parent_object() const { return m_parent_p; } + bool in_hierarchy() const { return m_name.length() != 0; } + + void notify(); + void notify( const sc_time& ); + void notify( double, sc_time_unit ); + + void notify_delayed(); + void notify_delayed( const sc_time& ); + void notify_delayed( double, sc_time_unit ); + + sc_event_or_expr operator | ( const sc_event& ) const; + sc_event_or_expr operator | ( const sc_event_or_list& ) const; + sc_event_and_expr operator & ( const sc_event& ) const; + sc_event_and_expr operator & ( const sc_event_and_list& ) const; + + +private: + + void add_static( sc_method_handle ) const; + void add_static( sc_thread_handle ) const; + void add_dynamic( sc_method_handle ) const; + void add_dynamic( sc_thread_handle ) const; + + void notify_internal( const sc_time& ); + void notify_next_delta(); + + bool remove_static( sc_method_handle ) const; + bool remove_static( sc_thread_handle ) const; + bool remove_dynamic( sc_method_handle ) const; + bool remove_dynamic( sc_thread_handle ) const; + + void register_event( const char* name ); + void reset(); + + void trigger(); + +private: + + enum notify_t { NONE, DELTA, TIMED }; + + std::string m_name; // name of object. + sc_object* m_parent_p; // parent sc_object for this event. + sc_simcontext* m_simc; + notify_t m_notify_type; + int m_delta_event_index; + sc_event_timed* m_timed; + + mutable std::vector<sc_method_handle> m_methods_static; + mutable std::vector<sc_method_handle> m_methods_dynamic; + mutable std::vector<sc_thread_handle> m_threads_static; + mutable std::vector<sc_thread_handle> m_threads_dynamic; + +private: + + // disabled + sc_event( const sc_event& ); + sc_event& operator = ( const sc_event& ); +}; + +#define SC_KERNEL_EVENT_PREFIX "$$$$kernel_event$$$$_" + +extern sc_event sc_non_event; // Event that never happens. + +// ---------------------------------------------------------------------------- +// CLASS : sc_event_timed +// +// Class for storing the time to notify a timed event. +// ---------------------------------------------------------------------------- + +class sc_event_timed +{ + friend class sc_event; + friend class sc_simcontext; + + friend int sc_notify_time_compare( const void*, const void* ); + +private: + + sc_event_timed( sc_event* e, const sc_time& t ) + : m_event( e ), m_notify_time( t ) + {} + + ~sc_event_timed() + { if( m_event != 0 ) { m_event->m_timed = 0; } } + + sc_event* event() const + { return m_event; } + + const sc_time& notify_time() const + { return m_notify_time; } + + static void* operator new( std::size_t ) + { return allocate(); } + + static void operator delete( void* p, std::size_t ) + { deallocate( p ); } + +private: + + // dedicated memory management + static void* allocate(); + static void deallocate( void* ); + +private: + + sc_event* m_event; + sc_time m_notify_time; + +private: + + // disabled + sc_event_timed(); + sc_event_timed( const sc_event_timed& ); + sc_event_timed& operator = ( const sc_event_timed& ); +}; + + +// IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII + +inline +void +sc_event::notify( double v, sc_time_unit tu ) +{ + notify( sc_time( v, tu, m_simc ) ); +} + + +inline +void +sc_event::notify_internal( const sc_time& t ) +{ + 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 { + 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; + } +} + +inline +void +sc_event::notify_next_delta() +{ + 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; +} + +inline +void +sc_event::notify_delayed( double v, sc_time_unit tu ) +{ + notify_delayed( sc_time( v, tu, m_simc ) ); +} + + +inline +void +sc_event::add_static( sc_method_handle method_h ) const +{ + m_methods_static.push_back( method_h ); +} + +inline +void +sc_event::add_static( sc_thread_handle thread_h ) const +{ + m_threads_static.push_back( thread_h ); +} + +inline +void +sc_event::add_dynamic( sc_method_handle method_h ) const +{ + m_methods_dynamic.push_back( method_h ); +} + +inline +void +sc_event::add_dynamic( sc_thread_handle thread_h ) const +{ + m_threads_dynamic.push_back( thread_h ); +} + + +// ---------------------------------------------------------------------------- +// Deprecated functional notation for notifying events. +// ---------------------------------------------------------------------------- + +extern void notify( sc_event& e ); +extern void notify( const sc_time& t, sc_event& e ); +extern void notify( double v, sc_time_unit tu, sc_event& e ); + + +// IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII + +inline +sc_event_list::sc_event_list( bool and_list_, bool auto_delete_ ) + : m_events() + , m_and_list( and_list_ ) + , m_auto_delete( auto_delete_ ) + , m_busy( 0 ) +{ +} + +inline +sc_event_list::sc_event_list( const sc_event& e, + bool and_list_, + bool auto_delete_ ) + : m_events() + , m_and_list( and_list_ ) + , m_auto_delete( auto_delete_ ) + , m_busy(0) +{ + m_events.push_back( &e ); +} + +inline +sc_event_list::sc_event_list( sc_event_list const & that ) + : m_events() + , m_and_list( that.m_and_list ) + , m_auto_delete( false ) + , m_busy( 0 ) +{ + move_from( that ); + that.auto_delete(); // free automatic lists +} + +inline +sc_event_list& +sc_event_list::operator=( sc_event_list const & that ) +{ + if( m_busy ) + report_invalid_modification(); + + move_from( that ); + that.auto_delete(); // free automatic lists + + return *this; +} + +inline +sc_event_list::~sc_event_list() +{ + if( m_busy ) + report_premature_destruction(); +} + +inline +void +sc_event_list::swap( sc_event_list& that ) +{ + if( busy() || that.busy() ) + report_invalid_modification(); + m_events.swap( that.m_events ); +} + +inline +void +sc_event_list::move_from( sc_event_list const& that ) +{ + if( that.temporary() ) { + swap( const_cast<sc_event_list&>(that) ); // move from source + } else { + m_events = that.m_events; // copy from source + } +} + +inline +int +sc_event_list::size() const +{ + return m_events.size(); +} + +inline +bool +sc_event_list::and_list() const +{ + return m_and_list; +} + + +inline +bool +sc_event_list::busy() const +{ + return m_busy != 0; +} + + +inline +bool +sc_event_list::temporary() const +{ + return m_auto_delete && ! m_busy; +} + +inline +void +sc_event_list::auto_delete() const +{ + if( m_busy ) { + --m_busy; + } + if( ! m_busy && m_auto_delete ) { + delete this; + } +} + + + +// IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII + +inline +sc_event_or_list::sc_event_or_list() + : sc_event_list( false ) +{} + +inline +sc_event_or_list::sc_event_or_list( const sc_event& e ) +: sc_event_list( false ) +{ + push_back( e ); +} + +inline +sc_event_or_list::sc_event_or_list( bool auto_delete_ ) +: sc_event_list( false, auto_delete_ ) +{} + +inline +sc_event_or_list& +sc_event_or_list::operator |= ( const sc_event& e ) +{ + if( busy() ) + report_invalid_modification(); + + push_back( e ); + return *this; +} + +inline +sc_event_or_list& +sc_event_or_list::operator |= ( const sc_event_or_list& el ) +{ + if( busy() ) + report_invalid_modification(); + + push_back( el ); + return *this; +} + +inline +sc_event_or_expr +sc_event_or_list::operator | ( const sc_event& e2 ) const +{ + sc_event_or_expr expr; + expr.push_back( *this ); + expr.push_back( e2 ); + return expr; +} + +inline +sc_event_or_expr +sc_event_or_list::operator | ( const sc_event_or_list& e2 ) const +{ + sc_event_or_expr expr; + expr.push_back( *this ); + expr.push_back( e2 ); + return expr; +} + + +// sc_event + +inline +sc_event_or_expr +sc_event::operator | ( const sc_event& e2 ) const +{ + sc_event_or_expr expr; + expr.push_back( *this ); + expr.push_back( e2 ); + return expr; +} + +inline +sc_event_or_expr +sc_event::operator | ( const sc_event_or_list& e2 ) const +{ + sc_event_or_expr expr; + expr.push_back( *this ); + expr.push_back( e2 ); + return expr; +} + +// sc_event_expr + +inline +sc_event_or_expr +operator | ( sc_event_or_expr expr, sc_event const & e ) +{ + expr.push_back( e ); + return expr; +} + +inline +sc_event_or_expr +operator | ( sc_event_or_expr expr, sc_event_or_list const & el ) +{ + expr.push_back( el ); + return expr; +} + +inline +void +sc_event_or_list::swap( sc_event_or_list & that ) +{ + sc_event_list::swap( that ); +} + + + +// IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII + +inline +sc_event_and_list::sc_event_and_list() + : sc_event_list( true ) +{} + +inline +sc_event_and_list::sc_event_and_list( const sc_event& e ) +: sc_event_list( true ) +{ + push_back( e ); +} + +inline +sc_event_and_list::sc_event_and_list( bool auto_delete_ ) +: sc_event_list( true, auto_delete_ ) +{} + +inline +void +sc_event_and_list::swap( sc_event_and_list & that ) +{ + sc_event_list::swap( that ); +} + + +inline +sc_event_and_list& +sc_event_and_list::operator &= ( const sc_event& e ) +{ + if( busy() ) + report_invalid_modification(); + + push_back( e ); + return *this; +} + +inline +sc_event_and_list& +sc_event_and_list::operator &= ( const sc_event_and_list& el ) +{ + if( busy() ) + report_invalid_modification(); + + push_back( el ); + return *this; +} + +inline +sc_event_and_expr +sc_event_and_list::operator & ( const sc_event& e ) +{ + sc_event_and_expr expr; + expr.push_back( *this ); + expr.push_back( e ); + return expr; +} + +inline +sc_event_and_expr +sc_event_and_list::operator & ( const sc_event_and_list& el ) +{ + sc_event_and_expr expr; + expr.push_back( *this ); + expr.push_back( el ); + return expr; +} + +// sc_event + +inline +sc_event_and_expr +sc_event::operator & ( const sc_event& e2 ) const +{ + sc_event_and_expr expr; + expr.push_back( *this ); + expr.push_back( e2 ); + return expr; +} + +inline +sc_event_and_expr +sc_event::operator & ( const sc_event_and_list& e2 ) const +{ + sc_event_and_expr expr; + expr.push_back( *this ); + expr.push_back( e2 ); + return expr; +} + +// sc_event_expr + +inline +sc_event_and_expr +operator & ( sc_event_and_expr expr, sc_event const & e ) +{ + expr.push_back( e ); + return expr; +} + +inline +sc_event_and_expr +operator & ( sc_event_and_expr expr, sc_event_and_list const & el ) +{ + expr.push_back( el ); + return expr; +} + +} // namespace sc_core + +// $Log: sc_event.h,v $ +// Revision 1.14 2011/08/29 18:04:32 acg +// Philipp A. Hartmann: miscellaneous clean ups. +// +// Revision 1.13 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.12 2011/08/24 22:05:50 acg +// Torsten Maehne: initialization changes to remove warnings. +// +// Revision 1.11 2011/03/12 21:07:51 acg +// Andy Goodrich: changes to kernel generated event support. +// +// Revision 1.10 2011/03/06 15:55:11 acg +// Andy Goodrich: Changes for named events. +// +// Revision 1.9 2011/03/05 01:39:21 acg +// Andy Goodrich: changes for named events. +// +// Revision 1.8 2011/02/18 20:27:14 acg +// Andy Goodrich: Updated Copyrights. +// +// Revision 1.7 2011/02/13 21:47:37 acg +// Andy Goodrich: update copyright notice. +// +// Revision 1.6 2011/02/01 21:03:23 acg +// Andy Goodrich: new return codes for trigger_dynamic calls. +// +// Revision 1.5 2011/01/18 20:10:44 acg +// Andy Goodrich: changes for IEEE1666_2011 semantics. +// +// Revision 1.4 2010/12/07 20:09:11 acg +// Andy Goodrich: writer policy fix. +// +// Revision 1.3 2009/05/22 16:06:29 acg +// Andy Goodrich: process control updates. +// +// Revision 1.2 2008/05/22 17:06:25 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.8 2006/05/26 20:33:16 acg +// Andy Goodrich: changes required by additional platform compilers (i.e., +// Microsoft VC++, Sun Forte, HP aCC). +// +// Revision 1.7 2006/05/08 17:57:51 acg +// Andy Goodrich: added David Long's forward declarations for friend +// functions, methods, and operators to keep the Microsoft compiler happy. +// +// Revision 1.6 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.5 2006/01/24 20:56:00 acg +// Andy Goodrich: fixed up CVS comment. +// +// 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. +// + +#endif + +// Taf! diff --git a/ext/systemc/src/sysc/kernel/sc_except.cpp b/ext/systemc/src/sysc/kernel/sc_except.cpp new file mode 100644 index 000000000..2699f8daf --- /dev/null +++ b/ext/systemc/src/sysc/kernel/sc_except.cpp @@ -0,0 +1,142 @@ +/***************************************************************************** + + 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_except.cpp -- kill/reset exception handling + + Original Author: Philipp A. Hartmann, OFFIS + + CHANGE LOG APPEARS AT THE END OF THE FILE + *****************************************************************************/ + +#include "sysc/kernel/sc_cmnhdr.h" +// +#include "sysc/kernel/sc_except.h" +#include "sysc/kernel/sc_process.h" +// +#include "sysc/utils/sc_report.h" + +namespace sc_core { + +sc_unwind_exception::sc_unwind_exception( sc_process_b* proc_p, bool is_reset ) + : m_proc_p(proc_p), m_is_reset( is_reset ) +{ + sc_assert( m_proc_p ); + m_proc_p->start_unwinding(); +} + +bool +sc_unwind_exception::active() const +{ + return m_proc_p && m_proc_p->is_unwinding(); +} + +void +sc_unwind_exception::clear() const +{ + sc_assert( m_proc_p ); + m_proc_p->clear_unwinding(); +} + +const char* +sc_unwind_exception::what() const throw() +{ + return ( m_is_reset ) ? "RESET" : "KILL"; +} + +sc_unwind_exception::~sc_unwind_exception() throw() +{ + if( active() ) { + // can't throw an exception, since we're already throwing + // -> abort instead + SC_REPORT_FATAL( SC_ID_RETHROW_UNWINDING_, m_proc_p->name() ); + } +} + +// handle and translate uncaught exceptions here +// +// These exceptions can either escape from sc_main() directly, +// indirectly from an SC_METHOD(), or are thrown from within +// an SC_(C)THREAD() +// +// returns a pointer to a dynamically allocated sc_report object, +// containing the caught message + +sc_report* +sc_handle_exception() +{ + try { + + // re-throw exception here + try { throw; } + + catch( sc_report & ) // to be on the safe side + { + throw; // continue + } + catch( sc_unwind_exception const & ) + { + sc_assert( false && "Unhandled kill/reset, should never happen" ); + } + catch( std::exception const & x ) + { + SC_REPORT_ERROR( SC_ID_SIMULATION_UNCAUGHT_EXCEPTION_, x.what() ); + } + catch( char const * x ) + { + SC_REPORT_ERROR( SC_ID_SIMULATION_UNCAUGHT_EXCEPTION_, x ); + } + catch( ... ) + { + SC_REPORT_ERROR( SC_ID_SIMULATION_UNCAUGHT_EXCEPTION_, + "UNKNOWN EXCEPTION" ); + } + } + // everything is an sc_report now + catch( sc_report & rpt ) + { + sc_report* rpt_p = new sc_report; + rpt_p->swap( rpt ); + return rpt_p; + } + return 0; +} + +} // namespace sc_core + +// $Log: sc_except.cpp,v $ +// Revision 1.4 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.3 2011/05/09 04:07:48 acg +// Philipp A. Hartmann: +// (1) Restore hierarchy in all phase callbacks. +// (2) Ensure calls to before_end_of_elaboration. +// +// Revision 1.2 2011/02/13 21:47:37 acg +// Andy Goodrich: update copyright notice. +// +// Revision 1.1 2011/02/10 22:47:38 acg +// Andy Goodrich: first check in of Philipp A. Hartmann's new exception +// processing code. +// + +// Taf! diff --git a/ext/systemc/src/sysc/kernel/sc_except.h b/ext/systemc/src/sysc/kernel/sc_except.h new file mode 100644 index 000000000..e3bacbd9c --- /dev/null +++ b/ext/systemc/src/sysc/kernel/sc_except.h @@ -0,0 +1,178 @@ +/***************************************************************************** + + 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_except.h - Exception classes to be handled by SystemC. + + Original Author: Stan Y. Liao, Synopsys, Inc. + + CHANGE LOG AT THE END OF THE FILE + *****************************************************************************/ + + +#ifndef SC_EXCEPT_H +#define SC_EXCEPT_H + +#include <exception> + +namespace sc_core { + +class sc_simcontext; +class sc_process_b; +class sc_method_process; +class sc_thread_process; +void sc_thread_cor_fn( void* arg ); + +/* + * These classes are intentionally empty. Their raison d'etre is for + * the implementation of various SystemC throws. + */ + +class sc_user +{ + /*EMPTY*/ +public: + sc_user() {} + sc_user( const sc_user& ) {} +}; + +class sc_halt +{ +public: + sc_halt() {} + sc_halt( const sc_halt& ) {} +}; + +class sc_kill +{ +public: + sc_kill() {} + sc_kill( const sc_kill& ) {} +}; + +class sc_unwind_exception : public std::exception +{ + friend class sc_simcontext; + friend class sc_process_b; + friend class sc_method_process; + friend class sc_thread_process; + friend void sc_thread_cor_fn( void* arg ); + + public: + virtual bool is_reset() const { return m_is_reset; } + virtual const char* what() const throw(); + + public: + + // enable catch by value + sc_unwind_exception( const sc_unwind_exception& ); + virtual ~sc_unwind_exception() throw(); + + protected: + explicit + sc_unwind_exception( sc_process_b* target_p, bool is_reset = false ); + + bool active() const; + void clear() const; + + private: + // disabled + sc_unwind_exception& operator=( const sc_unwind_exception& ); + + mutable sc_process_b* m_proc_p; // used to check, if caught by the kernel + const bool m_is_reset; // true if this is an unwind of a reset + +}; + +inline +sc_unwind_exception::sc_unwind_exception( const sc_unwind_exception& that ) + : std::exception( that ) + , m_proc_p( that.m_proc_p ) + , m_is_reset( that.m_is_reset ) +{ + that.m_proc_p = 0; // move to new instance +} + +//------------------------------------------------------------------------------ +// global exception handling +//------------------------------------------------------------------------------ + +class sc_report; +sc_report* sc_handle_exception(); + +} // namespace sc_core + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affiliation, date and + changes you are making here. + + Name, Affiliation, Date: Gene Bushuyev. Synopsys, Inc. + Description of Modification: - Had to add empty public default and copy + constructors to satisfy VC6.0. + + Name, Affiliation, Date: + Description of Modification: + + *****************************************************************************/ + +// $Log: sc_except.h,v $ +// Revision 1.11 2011/08/26 21:40:26 acg +// Philipp A. Hartmann: fix up sc_unwind_exception copy-ctor. +// +// Revision 1.10 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.9 2011/08/24 22:05:50 acg +// Torsten Maehne: initialization changes to remove warnings. +// +// Revision 1.8 2011/05/09 04:07:48 acg +// Philipp A. Hartmann: +// (1) Restore hierarchy in all phase callbacks. +// (2) Ensure calls to before_end_of_elaboration. +// +// Revision 1.7 2011/02/18 20:27:14 acg +// Andy Goodrich: Updated Copyrights. +// +// Revision 1.6 2011/02/13 21:47:37 acg +// Andy Goodrich: update copyright notice. +// +// Revision 1.5 2011/02/11 13:25:24 acg +// Andy Goodrich: Philipp A. Hartmann's changes: +// (1) Removal of SC_CTHREAD method overloads. +// (2) New exception processing code. +// +// Revision 1.4 2011/01/18 20:10:44 acg +// Andy Goodrich: changes for IEEE1666_2011 semantics. +// +// Revision 1.3 2009/05/22 16:06:29 acg +// Andy Goodrich: process control updates. +// +// Revision 1.2 2008/05/22 17:06:25 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.3 2006/01/13 18:44:29 acg +// Added $Log to record CVS changes into the source. + +#endif diff --git a/ext/systemc/src/sysc/kernel/sc_externs.h b/ext/systemc/src/sysc/kernel/sc_externs.h new file mode 100644 index 000000000..1d1818089 --- /dev/null +++ b/ext/systemc/src/sysc/kernel/sc_externs.h @@ -0,0 +1,65 @@ +/***************************************************************************** + + 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_externs.h -- Declaration of `sc_main' and other global variables. + + Original Author: Stan Y. Liao, Synopsys, Inc. + + CHANGE LOG AT THE END OF THE FILE + *****************************************************************************/ + + +#ifndef SC_EXTERNS_H +#define SC_EXTERNS_H + + + +extern "C" int sc_main( int argc, char* argv[] ); + +namespace sc_core { + extern "C" int sc_elab_and_sim( int argc, char* argv[] ); + extern "C" int sc_argc(); + extern "C" const char* const* sc_argv(); + +} // namespace sc_core + +// $Log: sc_externs.h,v $ +// Revision 1.5 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.4 2011/02/18 20:27:14 acg +// Andy Goodrich: Updated Copyrights. +// +// Revision 1.3 2011/02/13 21:47:37 acg +// Andy Goodrich: update copyright notice. +// +// Revision 1.2 2008/05/22 17:06:25 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.3 2006/01/13 18:44:29 acg +// Added $Log to record CVS changes into the source. +// + +#endif diff --git a/ext/systemc/src/sysc/kernel/sc_join.cpp b/ext/systemc/src/sysc/kernel/sc_join.cpp new file mode 100644 index 000000000..25f6f6cea --- /dev/null +++ b/ext/systemc/src/sysc/kernel/sc_join.cpp @@ -0,0 +1,143 @@ +/***************************************************************************** + + 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_join.cpp -- Join Process Synchronization Implementation + + Original Author: Andy Goodrich, Forte Design Systems, 5 May 2003 + + CHANGE LOG APPEARS AT THE END OF THE FILE + *****************************************************************************/ + + +#include <cassert> +#include <cstdlib> +#include <cstddef> + +#include "sysc/kernel/sc_process_handle.h" +#include "sysc/kernel/sc_simcontext.h" +#include "sysc/kernel/sc_simcontext_int.h" +#include "sysc/kernel/sc_kernel_ids.h" +#include "sysc/kernel/sc_thread_process.h" +#include "sysc/kernel/sc_join.h" + +namespace sc_core { + +//------------------------------------------------------------------------------ +//"sc_join::sc_join" +// +// This is the object instance constructor for this class. +//------------------------------------------------------------------------------ +sc_join::sc_join() + : m_join_event( (std::string(SC_KERNEL_EVENT_PREFIX)+"_join_event").c_str() ) + , m_threads_n(0) +{} + +//------------------------------------------------------------------------------ +//"sc_join::add_process - sc_process_b*" +// +// This method adds a process to this join object instance. This consists of +// incrementing the count of processes in the join process and adding this +// object instance to the supplied thread's monitoring queue. +// process_p -> thread to be monitored. +//------------------------------------------------------------------------------ +void sc_join::add_process( sc_process_b* process_p ) +{ + sc_thread_handle handle = DCAST<sc_thread_handle>(process_p); + assert( handle != 0 ); + m_threads_n++; + handle->add_monitor( this ); +} + + +//------------------------------------------------------------------------------ +//"sc_join::add_process - sc_process_handle" +// +// This method adds a process to this join object instance. This consists of +// incrementing the count of processes in the join process and adding this +// object instance to the supplied thread's monitoring queue. +// process_h = handle for process to be monitored. +//------------------------------------------------------------------------------ +void sc_join::add_process( sc_process_handle process_h ) +{ + sc_thread_handle thread_p; // Thread within process_h. + + thread_p = process_h.operator sc_thread_handle(); + if ( thread_p ) + { + m_threads_n++; + thread_p->add_monitor( this ); + } + else + { + SC_REPORT_ERROR( SC_ID_JOIN_ON_METHOD_HANDLE_, 0 ); + } +} + + +//------------------------------------------------------------------------------ +//"sc_join::signal" +// +// This virtual method is called when a process being monitored by this object +// instance sends a signal. If the signal type is spm_exit and the count of +// threads that we are waiting to terminate on goes to zero we fire our join +// event. +// thread_p -> thread that is signalling. +// type = type of signal being sent. +//------------------------------------------------------------------------------ +void sc_join::signal(sc_thread_handle thread_p, int type) +{ + switch ( type ) + { + case sc_process_monitor::spm_exit: + thread_p->remove_monitor(this); + if ( --m_threads_n == 0 ) m_join_event.notify(); + break; + } +} + +} // namespace sc_core + +// $Log: sc_join.cpp,v $ +// Revision 1.7 2011/08/26 21:45:00 acg +// Andy Goodrich: fix internal event naming. +// +// Revision 1.6 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.5 2011/02/18 20:27:14 acg +// Andy Goodrich: Updated Copyrights. +// +// Revision 1.4 2011/02/13 21:47:37 acg +// Andy Goodrich: update copyright notice. +// +// Revision 1.3 2009/07/28 01:10:53 acg +// Andy Goodrich: updates for 2.3 release candidate. +// +// Revision 1.2 2008/05/22 17:06:25 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.3 2006/01/13 18:44:29 acg +// Added $Log to record CVS changes into the source. +// diff --git a/ext/systemc/src/sysc/kernel/sc_join.h b/ext/systemc/src/sysc/kernel/sc_join.h new file mode 100644 index 000000000..e240f51a2 --- /dev/null +++ b/ext/systemc/src/sysc/kernel/sc_join.h @@ -0,0 +1,136 @@ +/***************************************************************************** + + 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_join.h -- Join Process Synchronization Definition + + Original Author: Andy Goodrich, Forte Design Systems, 5 May 2003 + + CHANGE LOG AT THE END OF THE FILE + *****************************************************************************/ + +// $Log: sc_join.h,v $ +// Revision 1.8 2011/08/26 21:45:00 acg +// Andy Goodrich: fix internal event naming. +// +// Revision 1.7 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. +// + +#ifndef SC_JOIN_H +#define SC_JOIN_H + +#include "sysc/kernel/sc_process.h" +#include "sysc/kernel/sc_wait.h" + +namespace sc_core { + +//============================================================================== +// CLASS sc_join +// +// This class provides a way of waiting for a set of threads to complete their +// execution. The threads whose completion is to be monitored are registered, +// and upon their completion an event notification will occur. +//============================================================================== +class sc_join : public sc_process_monitor { + friend class sc_process_b; + friend class sc_process_handle; + public: + sc_join(); + void add_process( sc_process_handle process_h ); + inline int process_count(); + virtual void signal(sc_thread_handle thread_p, int type); + inline void wait(); + inline void wait_clocked(); + + protected: + void add_process( sc_process_b* process_p ); + + protected: + sc_event m_join_event; // Event to notify when all threads have reported. + int m_threads_n; // # of threads still need to wait for. +}; + +int sc_join::process_count() { return m_threads_n; } + +// suspend a thread that does not have a sensitivity list: + +inline void sc_join::wait() { ::sc_core::wait(m_join_event); } + +// suspend a thread that has a sensitivity list: + +inline void sc_join::wait_clocked() +{ + do { ::sc_core::wait(); } while (m_threads_n != 0); +} + +#define SC_CJOIN \ + }; \ + sc_core::sc_join join; \ + for ( unsigned int i = 0; \ + i < sizeof(forkees)/sizeof(sc_core::sc_process_handle); \ + i++ ) \ + join.add_process(forkees[i]); \ + join.wait_clocked(); \ +} + +#define SC_FORK \ +{ \ + sc_core::sc_process_handle forkees[] = { + +#define SC_JOIN \ + }; \ + sc_core::sc_join join; \ + for ( unsigned int i = 0; \ + i < sizeof(forkees)/sizeof(sc_core::sc_process_handle); \ + i++ ) \ + join.add_process(forkees[i]); \ + join.wait(); \ +} + +} // namespace sc_core + +// Revision 1.6 2011/08/24 22:05:50 acg +// Torsten Maehne: initialization changes to remove warnings. +// +// Revision 1.5 2011/02/18 20:27:14 acg +// Andy Goodrich: Updated Copyrights. +// +// Revision 1.4 2011/02/13 21:47:37 acg +// Andy Goodrich: update copyright notice. +// +// Revision 1.3 2009/07/28 01:10:53 acg +// Andy Goodrich: updates for 2.3 release candidate. +// +// Revision 1.2 2008/05/22 17:06:25 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.5 2006/04/28 21:38:27 acg +// Andy Goodrich: fixed loop constraint that was using sizeof(sc_thread_handle) +// rather than sizeof(sc_process_handle). +// +// Revision 1.4 2006/01/13 18:44:29 acg +// Added $Log to record CVS changes into the source. + +#endif // SC_JOIN_H diff --git a/ext/systemc/src/sysc/kernel/sc_kernel_ids.h b/ext/systemc/src/sysc/kernel/sc_kernel_ids.h new file mode 100644 index 000000000..32846df12 --- /dev/null +++ b/ext/systemc/src/sysc/kernel/sc_kernel_ids.h @@ -0,0 +1,321 @@ +/***************************************************************************** + + 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_kernel_ids.h -- Report ids for the kernel code. + + Original Author: Martin Janssen, Synopsys, Inc., 2002-01-17 + + CHANGE LOG AT THE END OF THE FILE + *****************************************************************************/ + +#ifndef SC_KERNEL_IDS_H +#define SC_KERNEL_IDS_H + + +#include "sysc/utils/sc_report.h" + + +// ---------------------------------------------------------------------------- +// Report ids (kernel) +// +// Report ids in the range of 500-599. +// ---------------------------------------------------------------------------- + +#ifndef SC_DEFINE_MESSAGE +#define SC_DEFINE_MESSAGE(id,unused1,unused2) \ + namespace sc_core { extern const char id[]; } +namespace sc_core { + extern const char SC_ID_REGISTER_ID_FAILED_[]; // in sc_report_handler.cpp +} +#endif + +SC_DEFINE_MESSAGE(SC_ID_NO_BOOL_RETURNED_ , 500, + "operator does not return boolean") +SC_DEFINE_MESSAGE(SC_ID_NO_INT_RETURNED_ , 501, + "operator does not return int") +SC_DEFINE_MESSAGE(SC_ID_NO_SC_LOGIC_RETURNED_ , 502, + "operator does not return sc_logic") +SC_DEFINE_MESSAGE(SC_ID_OPERAND_NOT_SC_LOGIC_ , 503, + "operand is not sc_logic") +SC_DEFINE_MESSAGE(SC_ID_OPERAND_NOT_BOOL_ , 504, + "operand is not bool") +SC_DEFINE_MESSAGE(SC_ID_INSTANCE_EXISTS_ , 505, + "object already exists") +SC_DEFINE_MESSAGE(SC_ID_ILLEGAL_CHARACTERS_ , 506, + "illegal characters" ) +SC_DEFINE_MESSAGE(SC_ID_VC6_PROCESS_HELPER_ , 507, + "internal error: sc_vc6_process_helper" ) +SC_DEFINE_MESSAGE(SC_ID_VC6_MAX_PROCESSES_EXCEEDED_ , 508, + "maximum number of processes per module exceeded (VC6)" ) +SC_DEFINE_MESSAGE(SC_ID_END_MODULE_NOT_CALLED_ , 509, + "module construction not properly completed: did " + "you forget to add a sc_module_name parameter to " + "your module constructor?" ) +SC_DEFINE_MESSAGE(SC_ID_HIER_NAME_INCORRECT_ , 510, + "hierarchical name as shown may be incorrect due to previous errors" ) +SC_DEFINE_MESSAGE(SC_ID_SET_STACK_SIZE_ , 511, + "set_stack_size() is only allowed for SC_THREADs and SC_CTHREADs" ) +SC_DEFINE_MESSAGE(SC_ID_SC_MODULE_NAME_USE_ , 512, + "incorrect use of sc_module_name" ) +SC_DEFINE_MESSAGE(SC_ID_SC_MODULE_NAME_REQUIRED_ , 513, + "an sc_module_name parameter for your constructor is required" ) +SC_DEFINE_MESSAGE(SC_ID_SET_TIME_RESOLUTION_ , 514, + "set time resolution failed" ) +SC_DEFINE_MESSAGE(SC_ID_SET_DEFAULT_TIME_UNIT_ , 515, + "set default time unit failed" ) +SC_DEFINE_MESSAGE(SC_ID_DEFAULT_TIME_UNIT_CHANGED_ , 516, + "default time unit changed to time resolution" ) +SC_DEFINE_MESSAGE(SC_ID_INCONSISTENT_API_CONFIG_ , 517, + "inconsistent library configuration detected" ) +// available message number 518 +SC_DEFINE_MESSAGE(SC_ID_WAIT_NOT_ALLOWED_ , 519, + "wait() is only allowed in SC_THREADs and SC_CTHREADs" ) +SC_DEFINE_MESSAGE(SC_ID_NEXT_TRIGGER_NOT_ALLOWED_ , 520, + "next_trigger() is only allowed in SC_METHODs" ) +SC_DEFINE_MESSAGE(SC_ID_IMMEDIATE_NOTIFICATION_ , 521, + "immediate notification is not allowed during the update phase" ) +SC_DEFINE_MESSAGE(SC_ID_HALT_NOT_ALLOWED_ , 522, + "halt() is only allowed in SC_CTHREADs" ) +SC_DEFINE_MESSAGE(SC_ID_WATCHING_NOT_ALLOWED_ , 523, + "watching() has been deprecated, use reset_signal_is()" ) +SC_DEFINE_MESSAGE(SC_ID_DONT_INITIALIZE_ , 524, + "dont_initialize() has no effect for SC_CTHREADs" ) +SC_DEFINE_MESSAGE(SC_ID_WAIT_N_INVALID_ , 525, + "wait(n) is only valid for n > 0" ) +SC_DEFINE_MESSAGE(SC_ID_MAKE_SENSITIVE_ , 526, + "make sensitive failed" ) +SC_DEFINE_MESSAGE(SC_ID_MAKE_SENSITIVE_POS_ , 527, + "make sensitive pos failed" ) +SC_DEFINE_MESSAGE(SC_ID_MAKE_SENSITIVE_NEG_ , 528, + "make sensitive neg failed" ) +SC_DEFINE_MESSAGE(SC_ID_INSERT_MODULE_ , 529, + "insert module failed" ) +SC_DEFINE_MESSAGE(SC_ID_REMOVE_MODULE_ , 530, + "remove module failed" ) +SC_DEFINE_MESSAGE(SC_ID_NOTIFY_DELAYED_ , 531, + "notify_delayed() cannot be called on events " + "that have pending notifications" ) +SC_DEFINE_MESSAGE(SC_ID_GEN_UNIQUE_NAME_ , 532, + "cannot generate unique name from null string" ) +SC_DEFINE_MESSAGE(SC_ID_MODULE_NAME_STACK_EMPTY_ , 533, + "module name stack is empty: did you forget to " + "add a sc_module_name parameter to your module " + "constructor?" ) +// available message number 534 +// available message number 535 +SC_DEFINE_MESSAGE( SC_ID_IMMEDIATE_SELF_NOTIFICATION_, 536, + "immediate self-notification ignored as of IEEE 1666-2011" ) +SC_DEFINE_MESSAGE( SC_ID_WAIT_DURING_UNWINDING_ , 537, + "wait() not allowed during unwinding" ) +SC_DEFINE_MESSAGE(SC_ID_CYCLE_MISSES_EVENTS_ , 538, + "the simulation contains timed-events but they are " + "ignored by sc_cycle() ==> the simulation will be " + "incorrect" ) +SC_DEFINE_MESSAGE( SC_ID_RETHROW_UNWINDING_ , 539, + "sc_unwind_exception not re-thrown during kill/reset" ) +SC_DEFINE_MESSAGE( SC_ID_PROCESS_ALREADY_UNWINDING_ , 540, + "kill/reset ignored during unwinding" ) +SC_DEFINE_MESSAGE(SC_ID_MODULE_METHOD_AFTER_START_ , 541, + "call to SC_METHOD in sc_module while simulation running" ) +SC_DEFINE_MESSAGE(SC_ID_MODULE_THREAD_AFTER_START_ , 542, + "call to SC_THREAD in sc_module while simulation running" ) +SC_DEFINE_MESSAGE(SC_ID_MODULE_CTHREAD_AFTER_START_ , 543, + "call to SC_CTHREAD in sc_module while simulation running" ) +SC_DEFINE_MESSAGE(SC_ID_SIMULATION_TIME_OVERFLOW_ , 544, + "simulation time value overflow, simulation aborted" ) +SC_DEFINE_MESSAGE(SC_ID_SIMULATION_STOP_CALLED_TWICE_ , 545, + "sc_stop has already been called" ) +SC_DEFINE_MESSAGE(SC_ID_SIMULATION_START_AFTER_STOP_ , 546, + "sc_start called after sc_stop has been called" ) +SC_DEFINE_MESSAGE(SC_ID_STOP_MODE_AFTER_START_ , 547, + "attempt to set sc_stop mode after start will be ignored" ) +SC_DEFINE_MESSAGE( SC_ID_SIMULATION_START_AFTER_ERROR_, 548, + "attempt to restart simulation after error" ) +SC_DEFINE_MESSAGE( SC_ID_SIMULATION_UNCAUGHT_EXCEPTION_, 549, + "uncaught exception" ) +SC_DEFINE_MESSAGE(SC_ID_PHASE_CALLBACKS_UNSUPPORTED_ , 550, + "simulation phase callbacks not enabled") +SC_DEFINE_MESSAGE(SC_ID_PHASE_CALLBACK_NOT_IMPLEMENTED_, 551, + "empty simulation phase callback called" ) +SC_DEFINE_MESSAGE(SC_ID_PHASE_CALLBACK_REGISTER_, 552, + "register simulation phase callback" ) +SC_DEFINE_MESSAGE(SC_ID_PHASE_CALLBACK_FORBIDDEN_, 553, + "forbidden action in simulation phase callback" ) +// available message number 554 +// available message number 555 +SC_DEFINE_MESSAGE(SC_ID_THROW_IT_IGNORED_ , 556, + "throw_it on method/non-running process is being ignored " ) +SC_DEFINE_MESSAGE(SC_ID_NOT_EXPECTING_DYNAMIC_EVENT_NOTIFY_ , 557, + "dynamic event notification encountered when sensitivity is static" ) +SC_DEFINE_MESSAGE(SC_ID_DISABLE_WILL_ORPHAN_PROCESS_ , 558, + "disable() or dont_initialize() called on process with no static sensitivity, it will be orphaned" ) +SC_DEFINE_MESSAGE(SC_ID_PROCESS_CONTROL_CORNER_CASE_ , 559, + "Undefined process control interaction" ) +SC_DEFINE_MESSAGE(SC_ID_METHOD_TERMINATION_EVENT_ , 560, + "Attempt to get terminated event for a method process" ) +SC_DEFINE_MESSAGE(SC_ID_JOIN_ON_METHOD_HANDLE_ , 561, + "Attempt to register method process with sc_join object" ) +SC_DEFINE_MESSAGE(SC_ID_NO_PROCESS_SEMANTICS_ , 563, + "Attempt to invoke process with no semantics() method" ) +SC_DEFINE_MESSAGE(SC_ID_EVENT_ON_NULL_PROCESS_ , 564, + "Attempt to get an event for non-existent process" ) +// available message number 565 +SC_DEFINE_MESSAGE(SC_ID_UNKNOWN_PROCESS_TYPE_, 566, + "Unknown process type" ) +// available message number 567 +SC_DEFINE_MESSAGE(SC_ID_NEGATIVE_SIMULATION_TIME_, 568, + "negative simulation interval specified in sc_start call" ) +SC_DEFINE_MESSAGE(SC_ID_BAD_SC_MODULE_CONSTRUCTOR_ , 569, + "sc_module(const char*), sc_module(const std::string&) " + "have been deprecated, use sc_module(const sc_module_name&)" ) +SC_DEFINE_MESSAGE(SC_ID_EMPTY_PROCESS_HANDLE_ , 570, + "attempt to use an empty process handle ignored" ) +SC_DEFINE_MESSAGE(SC_ID_NO_SC_START_ACTIVITY_ , 571, + "no activity or clock movement for sc_start() invocation" ) +SC_DEFINE_MESSAGE(SC_ID_KILL_PROCESS_WHILE_UNITIALIZED_ , 572, + "a process may not be killed before it is initialized" ) +SC_DEFINE_MESSAGE(SC_ID_RESET_PROCESS_WHILE_NOT_RUNNING_ , 573, + "a process may not be asynchronously reset while the simulation is not running" ) +SC_DEFINE_MESSAGE(SC_ID_THROW_IT_WHILE_NOT_RUNNING_ , 574, + "throw_it not allowed unless simulation is running " ) + + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affiliation, date and + changes you are making here. + + Name, Affiliation, Date: + Description of Modification: + + *****************************************************************************/ + +// $Log: sc_kernel_ids.h,v $ +// Revision 1.25 2011/08/26 22:06:34 acg +// Torsten Maehne: formating fix. +// +// Revision 1.24 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.23 2011/07/24 11:15:47 acg +// Philipp A. Hartmann: Improvements to error/warning messages related to +// process control. +// +// Revision 1.22 2011/05/09 04:07:48 acg +// Philipp A. Hartmann: +// (1) Restore hierarchy in all phase callbacks. +// (2) Ensure calls to before_end_of_elaboration. +// +// Revision 1.21 2011/04/19 19:15:41 acg +// Andy Goodrich: fix so warning message is always issued for a throw_it() +// on a method process. +// +// Revision 1.20 2011/04/19 15:04:27 acg +// Philipp A. Hartmann: clean up SC_ID messages. +// +// Revision 1.19 2011/04/19 02:39:09 acg +// Philipp A. Hartmann: added checks for additional throws during stack unwinds. +// +// Revision 1.18 2011/04/05 06:23:45 acg +// Andy Goodrich: comments for throws while the simulator is not running. +// +// Revision 1.17 2011/04/01 22:30:39 acg +// Andy Goodrich: change hard assertion to warning for trigger_dynamic() +// getting called when there is only STATIC sensitivity. This can result +// because of sc_process_handle::throw_it(). +// +// Revision 1.16 2011/03/28 13:02:51 acg +// Andy Goodrich: Changes for disable() interactions. +// +// Revision 1.15 2011/03/07 17:34:21 acg +// Andy Goodrich: changed process control corner case message. Added more +// place holders for unused message numbers. +// +// Revision 1.14 2011/03/06 19:57:11 acg +// Andy Goodrich: refinements for the illegal suspend - synchronous reset +// interaction. +// +// Revision 1.13 2011/03/06 15:56:29 acg +// Andy Goodrich: added process control corner case error message, remove +// unused messages. +// +// Revision 1.12 2011/03/05 19:44:20 acg +// Andy Goodrich: changes for object and event naming and structures. +// +// Revision 1.11 2011/02/18 20:27:14 acg +// Andy Goodrich: Updated Copyrights. +// +// Revision 1.10 2011/02/13 21:47:37 acg +// Andy Goodrich: update copyright notice. +// +// Revision 1.9 2011/02/13 21:29:16 acg +// Andy Goodrich: added error messages for throws that occur before +// simulator intialization. +// +// Revision 1.8 2011/02/11 13:25:24 acg +// Andy Goodrich: Philipp A. Hartmann's changes: +// (1) Removal of SC_CTHREAD method overloads. +// (2) New exception processing code. +// +// Revision 1.7 2011/02/07 19:17:20 acg +// Andy Goodrich: changes for IEEE 1666 compatibility. +// +// Revision 1.6 2011/01/19 23:21:50 acg +// Andy Goodrich: changes for IEEE 1666 2011 +// +// Revision 1.5 2010/07/30 05:21:22 acg +// Andy Goodrich: release 2.3 fixes. +// +// Revision 1.4 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.3 2008/11/17 15:57:15 acg +// Andy Goodrich: added deprecation message for sc_module(const char*) +// +// Revision 1.2 2008/05/22 17:06:25 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.7 2006/08/29 23:37:13 acg +// Andy Goodrich: Added check for negative time. +// +// Revision 1.6 2006/04/20 17:08:16 acg +// Andy Goodrich: 3.0 style process changes. +// +// Revision 1.5 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.4 2006/01/24 20:49:04 acg +// Andy Goodrich: changes to remove the use of deprecated features within the +// simulator, and to issue warning messages when deprecated features are used. +// +// Revision 1.3 2006/01/13 18:44:29 acg +// Added $Log to record CVS changes into the source. +// + +#endif + +// Taf! diff --git a/ext/systemc/src/sysc/kernel/sc_macros.h b/ext/systemc/src/sysc/kernel/sc_macros.h new file mode 100644 index 000000000..baa6d6e3b --- /dev/null +++ b/ext/systemc/src/sysc/kernel/sc_macros.h @@ -0,0 +1,136 @@ +/***************************************************************************** + + 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_macros.h -- Miscellaneous definitions that are needed by the headers. + + Original Author: Stan Y. Liao, Synopsys, Inc. + + CHANGE LOG AT THE END OF THE FILE + *****************************************************************************/ + + +#ifndef SC_MACROS_H +#define SC_MACROS_H + + +namespace sc_dt { + +template <class T> +inline +const T +sc_min( const T& a, const T& b ) +{ + return ( ( a <= b ) ? a : b ); +} + +template <class T> +inline +const T +sc_max( const T& a, const T& b ) +{ + return ( ( a >= b ) ? a : b ); +} + +template <class T> +inline +const T +sc_abs( const T& a ) +{ + // return ( a >= 0 ? a : -a ); + // the code below is functionaly the same as the code above; the + // difference is that the code below works for all arithmetic + // SystemC datatypes. + T z( a ); + z = 0; + if( a >= z ) { + return a; + } else { + T c( a ); + c = -a; + return c; + } +} + +} // namespace sc_dt + +namespace sc_core { + +// token stringification + +#define SC_STRINGIFY_HELPER_( Arg ) \ + SC_STRINGIFY_HELPER_DEFERRED_( Arg ) +#define SC_STRINGIFY_HELPER_DEFERRED_( Arg ) \ + SC_STRINGIFY_HELPER_MORE_DEFERRED_( Arg ) +#define SC_STRINGIFY_HELPER_MORE_DEFERRED_( Arg ) \ + #Arg + + +// token concatenation + +#define SC_CONCAT_HELPER_( a, b ) \ + SC_CONCAT_HELPER_DEFERRED_( a, b ) +#define SC_CONCAT_HELPER_DEFERRED_( a, b ) \ + SC_CONCAT_HELPER_MORE_DEFERRED_( a,b ) +#define SC_CONCAT_HELPER_MORE_DEFERRED_( a, b ) \ + a ## b +#define SC_CONCAT_UNDERSCORE_( a, b ) \ + SC_CONCAT_HELPER_( a, SC_CONCAT_HELPER_( _, b ) ) + +/* + * These help debugging -- + * -- user can find out where each process is stopped at. + */ + +#define WAIT() \ + ::sc_core::sc_set_location( __FILE__, __LINE__ ); \ + ::sc_core::wait() + +#define WAITN(n) \ + ::sc_core::sc_set_location( __FILE__, __LINE__ ); \ + ::sc_core::wait(n) + +#define WAIT_UNTIL(expr) \ + ::sc_core::sc_set_location( __FILE__, __LINE__ ); \ + do { ::sc_core::wait(); } while( !(expr) ) + +} // namespace sc_core + +// $Log: sc_macros.h,v $ +// Revision 1.5 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.4 2011/02/18 20:27:14 acg +// Andy Goodrich: Updated Copyrights. +// +// Revision 1.3 2011/02/13 21:47:37 acg +// Andy Goodrich: update copyright notice. +// +// Revision 1.2 2008/05/22 17:06:25 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.3 2006/01/13 18:44:29 acg +// Added $Log to record CVS changes into the source. + +#endif diff --git a/ext/systemc/src/sysc/kernel/sc_main.cpp b/ext/systemc/src/sysc/kernel/sc_main.cpp new file mode 100644 index 000000000..a5f780d70 --- /dev/null +++ b/ext/systemc/src/sysc/kernel/sc_main.cpp @@ -0,0 +1,58 @@ +/***************************************************************************** + + 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_main.cpp - Wrapper around user's toplevel routine `sc_main'. + + Original Author: Stan Y. Liao, Synopsys, Inc. + + CHANGE LOG APPEARS AT THE END OF THE FILE + *****************************************************************************/ + + +#include "sysc/kernel/sc_cmnhdr.h" +#include "sysc/kernel/sc_externs.h" + +int +main( int argc, char* argv[] ) +{ + return sc_core::sc_elab_and_sim( argc, argv ); +} + +// $Log: sc_main.cpp,v $ +// Revision 1.5 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.4 2011/02/18 20:27:14 acg +// Andy Goodrich: Updated Copyrights. +// +// Revision 1.3 2011/02/13 21:47:37 acg +// Andy Goodrich: update copyright notice. +// +// Revision 1.2 2008/05/22 17:06:25 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.3 2006/01/13 18:44:29 acg +// Added $Log to record CVS changes into the source. +// diff --git a/ext/systemc/src/sysc/kernel/sc_main_main.cpp b/ext/systemc/src/sysc/kernel/sc_main_main.cpp new file mode 100644 index 000000000..1cdf1eb49 --- /dev/null +++ b/ext/systemc/src/sysc/kernel/sc_main_main.cpp @@ -0,0 +1,167 @@ +/***************************************************************************** + + 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_main_main.cpp - Wrapper around user's toplevel routine `sc_main'. + + Original Author: Andy Goodrich, Forte Design Systems + + CHANGE LOG APPEARS AT THE END OF THE FILE + *****************************************************************************/ + + +#include "sysc/kernel/sc_cmnhdr.h" +#include "sysc/kernel/sc_externs.h" +#include "sysc/kernel/sc_except.h" +#include "sysc/utils/sc_iostream.h" +#include "sysc/utils/sc_report.h" +#include "sysc/utils/sc_report_handler.h" +#include "sysc/utils/sc_utils_ids.h" +#include <vector> + +namespace sc_core { + +extern void pln(); + +static int argc_copy; // Copy of argc value passed to sc_elab_and_sim. +static char** argv_copy; // Copy of argv value passed to sc_elab_and_sim. + +static +inline +void +message_function( const char* s ) +{ + ::std::cout << "\n" << s << ::std::endl; +} + +bool sc_in_action = false; + +int sc_argc() +{ + return argc_copy; +} + +const char* const* sc_argv() +{ + return argv_copy; +} + + +int +sc_elab_and_sim( int argc, char* argv[] ) +{ + int status = 1; + argc_copy = argc; + argv_copy = argv; + std::vector<char*> argv_call; + for ( int i = 0; i < argc; i++ ) + argv_call.push_back(argv[i]); + + try + { + pln(); + + // Perform initialization here + sc_in_action = true; + + status = sc_main( argc, &argv_call[0] ); + + // Perform cleanup here + sc_in_action = false; + } + catch( const sc_report& x ) + { + message_function( x.what() ); + } + catch( ... ) + { + // translate other escaping exceptions + sc_report* err_p = sc_handle_exception(); + if( err_p ) message_function( err_p->what() ); + delete err_p; + } + + // IF DEPRECATION WARNINGS WERE ISSUED TELL THE USER HOW TO TURN THEM OFF + + if ( sc_report_handler::get_count( SC_ID_IEEE_1666_DEPRECATION_ ) > 0 ) + { + std::stringstream ss; + +# define MSGNL "\n " +# define CODENL "\n " + + ss << + "You can turn off warnings about" MSGNL + "IEEE 1666 deprecated features by placing this method call" MSGNL + "as the first statement in your sc_main() function:\n" CODENL + "sc_core::sc_report_handler::set_actions( " + "\"" << SC_ID_IEEE_1666_DEPRECATION_ << "\"," CODENL + " " /* indent param */ + "sc_core::SC_DO_NOTHING );" + << std::endl; + + SC_REPORT_INFO( SC_ID_IEEE_1666_DEPRECATION_, ss.str().c_str() ); + } + + return status; +} + +} // namespace sc_core + +// $Log: sc_main_main.cpp,v $ +// Revision 1.9 2011/08/26 20:46:10 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.8 2011/05/09 04:07:48 acg +// Philipp A. Hartmann: +// (1) Restore hierarchy in all phase callbacks. +// (2) Ensure calls to before_end_of_elaboration. +// +// Revision 1.7 2011/02/18 20:27:14 acg +// Andy Goodrich: Updated Copyrights. +// +// Revision 1.6 2011/02/13 21:47:37 acg +// Andy Goodrich: update copyright notice. +// +// Revision 1.5 2010/03/15 18:29:25 acg +// Andy Goodrich: Changed the default stack size to 128K from 64K. +// +// Revision 1.4 2009/10/14 19:06:48 acg +// Andy Goodrich: changed the way the "copy" of argv is handled. It is +// now passed to sc_main, and the original is referenced via argv_copy. +// +// Revision 1.3 2008/05/22 17:06:25 acg +// Andy Goodrich: updated copyright notice to include 2008. +// +// Revision 1.2 2008/04/11 20:41:28 acg +// Andy Goodrich: changed the return value in sc_elab_and_sim() to be 1 +// when an exception occurs in sc_main() rather than 0. +// +// Revision 1.1.1.1 2006/12/15 20:20:05 acg +// SystemC 2.3 +// +// Revision 1.4 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.3 2006/01/13 18:44:29 acg +// Added $Log to record CVS changes into the source. +// diff --git a/ext/systemc/src/sysc/kernel/sc_method_process.cpp b/ext/systemc/src/sysc/kernel/sc_method_process.cpp new file mode 100644 index 000000000..994e495ad --- /dev/null +++ b/ext/systemc/src/sysc/kernel/sc_method_process.cpp @@ -0,0 +1,1023 @@ +/***************************************************************************** + + 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_method_process.cpp -- Method process implementation + + Original Author: Andy Goodrich, Forte Design Systems, 4 August 2005 + + CHANGE LOG AT THE END OF THE FILE + *****************************************************************************/ + +#include "sysc/kernel/sc_method_process.h" +#include "sysc/kernel/sc_simcontext_int.h" +#include "sysc/kernel/sc_module.h" +#include "sysc/kernel/sc_spawn_options.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 { + +// +---------------------------------------------------------------------------- +// |"sc_method_process::check_for_throws" +// | +// | This method checks to see if this method process should throw an exception +// | or not. It is called from sc_simcontext::preempt_with() to see if the +// | thread that was executed during the preemption did a kill or other +// | manipulation on this object instance that requires it to throw an +// | exception. +// +---------------------------------------------------------------------------- +void sc_method_process::check_for_throws() +{ + if ( !m_unwinding ) + { + switch( m_throw_status ) + { + case THROW_ASYNC_RESET: + simcontext()->preempt_with(this); + break; + case THROW_KILL: + throw sc_unwind_exception( this, false ); + default: + break; + } + } +} + +//------------------------------------------------------------------------------ +//"sc_method_process::clear_trigger" +// +// This method clears any pending trigger for this object instance. +//------------------------------------------------------------------------------ +void sc_method_process::clear_trigger() +{ + switch( m_trigger_type ) { + case STATIC: + return; + case EVENT: + m_event_p->remove_dynamic( this ); + m_event_p = 0; + break; + case OR_LIST: + m_event_list_p->remove_dynamic( this, 0 ); + m_event_list_p->auto_delete(); + m_event_list_p = 0; + break; + case AND_LIST: + m_event_list_p->remove_dynamic( this, 0 ); + m_event_list_p->auto_delete(); + m_event_list_p = 0; + m_event_count = 0; + break; + case TIMEOUT: + m_timeout_event_p->cancel(); + m_timeout_event_p->reset(); + break; + case EVENT_TIMEOUT: + m_timeout_event_p->cancel(); + m_timeout_event_p->reset(); + m_event_p->remove_dynamic( this ); + m_event_p = 0; + break; + case OR_LIST_TIMEOUT: + m_timeout_event_p->cancel(); + m_timeout_event_p->reset(); + m_event_list_p->remove_dynamic( this, 0 ); + m_event_list_p->auto_delete(); + m_event_list_p = 0; + break; + case AND_LIST_TIMEOUT: + m_timeout_event_p->cancel(); + m_timeout_event_p->reset(); + m_event_list_p->remove_dynamic( this, 0 ); + m_event_list_p->auto_delete(); + m_event_list_p = 0; + m_event_count = 0; + break; + } + m_trigger_type = STATIC; +} + +//------------------------------------------------------------------------------ +//"sc_method_process::disable_process" +// +// This virtual method disables this process and its children if requested to. +// descendants = indicator of whether this process' children should also +// be suspended +//------------------------------------------------------------------------------ +void sc_method_process::disable_process( + sc_descendant_inclusion_info descendants ) +{ + + // IF NEEDED PROPOGATE THE SUSPEND REQUEST THROUGH OUR DESCENDANTS: + + if ( descendants == SC_INCLUDE_DESCENDANTS ) + { + const std::vector<sc_object*>& children = get_child_objects(); + int child_n = children.size(); + + for ( int child_i = 0; child_i < child_n; child_i++ ) + { + sc_process_b* child_p = DCAST<sc_process_b*>(children[child_i]); + if ( child_p ) child_p->disable_process(descendants); + } + } + + // DON'T ALLOW CORNER CASE BY DEFAULT: + + if ( !sc_allow_process_control_corners ) + { + switch( m_trigger_type ) + { + case AND_LIST_TIMEOUT: + case EVENT_TIMEOUT: + case OR_LIST_TIMEOUT: + case TIMEOUT: + report_error( SC_ID_PROCESS_CONTROL_CORNER_CASE_, + "attempt to disable a method with timeout wait" ); + break; + default: + break; + } + } + + // DISABLE OUR OBJECT INSTANCE: + + m_state = m_state | ps_bit_disabled; + + // IF THIS CALL IS BEFORE THE SIMULATION DON'T RUN THE METHOD: + + if ( !sc_is_running() ) + { + sc_get_curr_simcontext()->remove_runnable_method(this); + } +} + + +//------------------------------------------------------------------------------ +//"sc_method_process::enable_process" +// +// This method enables the execution of this process, and if requested, its +// descendants. If the process was suspended and has a resumption pending it +// will be dispatched in the next delta cycle. Otherwise the state will be +// adjusted to indicate it is no longer suspended, but no immediate execution +// will occur. +//------------------------------------------------------------------------------ +void sc_method_process::enable_process( + sc_descendant_inclusion_info descendants ) +{ + + // IF NEEDED PROPOGATE THE RESUME REQUEST THROUGH OUR DESCENDANTS: + + if ( descendants == SC_INCLUDE_DESCENDANTS ) + { + const std::vector<sc_object*>& children = get_child_objects(); + int child_n = children.size(); + + for ( int child_i = 0; child_i < child_n; child_i++ ) + { + sc_process_b* child_p = DCAST<sc_process_b*>(children[child_i]); + if ( child_p ) child_p->enable_process(descendants); + } + } + + // ENABLE THIS OBJECT INSTANCE: + // + // If it was disabled and ready to run then put it on the run queue. + + m_state = m_state & ~ps_bit_disabled; + if ( m_state == ps_bit_ready_to_run ) + { + m_state = ps_normal; + if ( next_runnable() == 0 ) + simcontext()->push_runnable_method(this); + } +} + + +//------------------------------------------------------------------------------ +//"sc_method_process::kill_process" +// +// This method removes throws a kill for this object instance. It calls the +// sc_process_b::kill_process() method to perform low level clean up. +//------------------------------------------------------------------------------ +void sc_method_process::kill_process(sc_descendant_inclusion_info descendants) +{ + + // IF THE SIMULATION HAS NOT BEEN INITIALIZED YET THAT IS AN ERROR: + + if ( sc_get_status() == SC_ELABORATION ) + { + report_error( SC_ID_KILL_PROCESS_WHILE_UNITIALIZED_ ); + } + + // IF NEEDED, PROPOGATE THE KILL REQUEST THROUGH OUR DESCENDANTS: + + if ( descendants == SC_INCLUDE_DESCENDANTS ) + { + const std::vector<sc_object*> children = get_child_objects(); + int child_n = children.size(); + + for ( int child_i = 0; child_i < child_n; child_i++ ) + { + sc_process_b* child_p = DCAST<sc_process_b*>(children[child_i]); + if ( child_p ) child_p->kill_process(descendants); + } + } + + // IF THE PROCESS IS CURRENTLY UNWINDING OR IS ALREADY A ZOMBIE + // IGNORE THE KILL: + + if ( m_unwinding ) + { + SC_REPORT_WARNING( SC_ID_PROCESS_ALREADY_UNWINDING_, name() ); + return; + } + + if ( m_state & ps_bit_zombie ) + return; + + + // REMOVE OUR PROCESS FROM EVENTS, ETC., AND IF ITS THE ACTIVE PROCESS + // THROW ITS KILL. + // + // Note we set the throw status to kill regardless if we throw or not. + // That lets check_for_throws stumble across it if we were in the call + // chain when the kill call occurred. + + if ( next_runnable() != 0 ) + simcontext()->remove_runnable_method( this ); + disconnect_process(); + + m_throw_status = THROW_KILL; + if ( sc_get_current_process_b() == this ) + { + throw sc_unwind_exception( this, false ); + } +} + +//------------------------------------------------------------------------------ +//"sc_method_process::sc_method_process" +// +// This is the object instance constructor for this class. +//------------------------------------------------------------------------------ +sc_method_process::sc_method_process( const char* name_p, + bool free_host, SC_ENTRY_FUNC method_p, + sc_process_host* host_p, const sc_spawn_options* opt_p +): + sc_process_b( + name_p ? name_p : sc_gen_unique_name("method_p"), + false, free_host, method_p, host_p, opt_p), + m_cor(0), m_stack_size(0), m_monitor_q() +{ + + // CHECK IF THIS IS AN sc_module-BASED PROCESS AND SIMUALTION HAS STARTED: + + if ( DCAST<sc_module*>(host_p) != 0 && sc_is_running() ) + { + report_error( SC_ID_MODULE_METHOD_AFTER_START_, "" ); + } + + // INITIALIZE VALUES: + // + // If there are spawn options use them. + + m_process_kind = SC_METHOD_PROC_; + if (opt_p) { + m_dont_init = opt_p->m_dont_initialize; + + // traverse event sensitivity list + for (unsigned int i = 0; i < opt_p->m_sensitive_events.size(); i++) { + sc_sensitive::make_static_sensitivity( + this, *opt_p->m_sensitive_events[i]); + } + + // traverse port base sensitivity list + for ( unsigned int i = 0; i < opt_p->m_sensitive_port_bases.size(); i++) + { + sc_sensitive::make_static_sensitivity( + this, *opt_p->m_sensitive_port_bases[i]); + } + + // traverse interface sensitivity list + for ( unsigned int i = 0; i < opt_p->m_sensitive_interfaces.size(); i++) + { + sc_sensitive::make_static_sensitivity( + this, *opt_p->m_sensitive_interfaces[i]); + } + + // traverse event finder sensitivity list + for ( unsigned int i = 0; i < opt_p->m_sensitive_event_finders.size(); + i++) + { + sc_sensitive::make_static_sensitivity( + this, *opt_p->m_sensitive_event_finders[i]); + } + + // process any reset signal specification: + + opt_p->specify_resets(); + } + + else + { + m_dont_init = false; + } +} + +//------------------------------------------------------------------------------ +//"sc_method_process::sc_method_process" +// +// This is the object instance destructor for this class. +//------------------------------------------------------------------------------ +sc_method_process::~sc_method_process() +{ +} + + +//------------------------------------------------------------------------------ +//"sc_method_process::suspend_process" +// +// This virtual method suspends this process and its children if requested to. +// descendants = indicator of whether this process' children should also +// be suspended +//------------------------------------------------------------------------------ +void sc_method_process::suspend_process( + sc_descendant_inclusion_info descendants ) +{ + + // IF NEEDED PROPOGATE THE SUSPEND REQUEST THROUGH OUR DESCENDANTS: + + if ( descendants == SC_INCLUDE_DESCENDANTS ) + { + const std::vector<sc_object*>& children = get_child_objects(); + int child_n = children.size(); + + for ( int child_i = 0; child_i < child_n; child_i++ ) + { + sc_process_b* child_p = DCAST<sc_process_b*>(children[child_i]); + if ( child_p ) child_p->suspend_process(descendants); + } + } + + // CORNER CASE CHECKS, THE FOLLOWING ARE ERRORS: + // (a) if this method has a reset_signal_is specification + // (b) if this method is in synchronous reset + + if ( !sc_allow_process_control_corners && m_has_reset_signal ) + { + report_error(SC_ID_PROCESS_CONTROL_CORNER_CASE_, + "attempt to suspend a method that has a reset signal"); + } + else if ( !sc_allow_process_control_corners && m_sticky_reset ) + { + report_error(SC_ID_PROCESS_CONTROL_CORNER_CASE_, + "attempt to suspend a method in synchronous reset"); + } + + // SUSPEND OUR OBJECT INSTANCE: + // + // (1) If we are on the runnable queue then set suspended and ready_to_run, + // and remove ourselves from the run queue. + // (2) If this is a self-suspension then a resume should cause immediate + // scheduling of the process. + + m_state = m_state | ps_bit_suspended; + if ( next_runnable() != 0 ) + { + m_state = m_state | ps_bit_ready_to_run; + simcontext()->remove_runnable_method( this ); + } + if ( sc_get_current_process_b() == DCAST<sc_process_b*>(this) ) + { + m_state = m_state | ps_bit_ready_to_run; + } +} + +//------------------------------------------------------------------------------ +//"sc_method_process::resume_process" +// +// This method resumes the execution of this process, and if requested, its +// descendants. If the process was suspended and has a resumption pending it +// will be dispatched in the next delta cycle. Otherwise the state will be +// adjusted to indicate it is no longer suspended, but no immediate execution +// will occur. +//------------------------------------------------------------------------------ +void sc_method_process::resume_process( + sc_descendant_inclusion_info descendants ) +{ + + // IF NEEDED PROPOGATE THE RESUME REQUEST THROUGH OUR DESCENDANTS: + + if ( descendants == SC_INCLUDE_DESCENDANTS ) + { + const std::vector<sc_object*>& children = get_child_objects(); + int child_n = children.size(); + + for ( int child_i = 0; child_i < child_n; child_i++ ) + { + sc_process_b* child_p = DCAST<sc_process_b*>(children[child_i]); + if ( child_p ) child_p->resume_process(descendants); + } + } + + + // BY DEFAULT THE CORNER CASE IS AN ERROR: + + if ( !sc_allow_process_control_corners && (m_state & ps_bit_disabled) && + (m_state & ps_bit_suspended) ) + { + m_state = m_state & ~ps_bit_suspended; + report_error( SC_ID_PROCESS_CONTROL_CORNER_CASE_, + "call to resume() on a disabled suspended method"); + } + + // CLEAR THE SUSPENDED BIT: + + m_state = m_state & ~ps_bit_suspended; + + // RESUME OBJECT INSTANCE: + // + // If this is not a self-resume and the method is ready to run then + // put it on the runnable queue. + + if ( m_state & ps_bit_ready_to_run ) + { + m_state = m_state & ~ps_bit_ready_to_run; + if ( next_runnable() == 0 && + ( sc_get_current_process_b() != DCAST<sc_process_b*>(this) ) ) + { + simcontext()->push_runnable_method(this); + remove_dynamic_events(); + } + } +} + +//------------------------------------------------------------------------------ +//"sc_method_process::throw_reset" +// +// This virtual method is invoked to "throw" a reset. +// +// If the reset is synchronous this is a no-op, except for triggering the +// reset event if it is present. +// +// If the reset is asynchronous we: +// (a) cancel any dynamic waits +// (b) if it is the active process actually throw a reset exception. +// (c) if it was not the active process and does not have a static +// sensitivity emit an error if corner cases are to be considered +// errors. +// +// Notes: +// (1) If the process had a reset event it will have been triggered in +// sc_process_b::semantics() +// +// Arguments: +// async = true if this is an asynchronous reset. +//------------------------------------------------------------------------------ +void sc_method_process::throw_reset( bool async ) +{ + // IF THE PROCESS IS CURRENTLY UNWINDING OR IS ALREADY A ZOMBIE + // IGNORE THE RESET: + + if ( m_unwinding ) + { + SC_REPORT_WARNING( SC_ID_PROCESS_ALREADY_UNWINDING_, name() ); + return; + } + + if ( m_state & ps_bit_zombie ) + return; + + // Set the throw status and if its an asynchronous reset throw an + // exception: + + m_throw_status = async ? THROW_ASYNC_RESET : THROW_SYNC_RESET; + if ( async ) + { + remove_dynamic_events(); + if ( sc_get_current_process_b() == this ) + { + DEBUG_MSG(DEBUG_NAME,this,"throw_reset: throwing exception"); + m_throw_status = THROW_ASYNC_RESET; + throw sc_unwind_exception( this, true ); + } + else + { + DEBUG_MSG(DEBUG_NAME,this, + "throw_reset: queueing this method for execution"); + simcontext()->preempt_with(this); + } + } +} + + +//------------------------------------------------------------------------------ +//"sc_method_process::throw_user" +// +// This virtual method is invoked when a user exception is to be thrown. +// If requested it will also throw the exception to the children of this +// object instance. Since this is a method no throw will occur for this +// object instance. The children will be awakened from youngest child to +// eldest. +// helper_p -> object to use to throw the exception. +// descendants = indicator of whether this process' children should also +// be suspended +//------------------------------------------------------------------------------ +void sc_method_process::throw_user( const sc_throw_it_helper& helper, + sc_descendant_inclusion_info descendants ) +{ + + // IF THE SIMULATION IS NOT ACTUALLY RUNNING THIS IS AN ERROR: + + if ( sc_get_status() != SC_RUNNING ) + { + report_error( SC_ID_THROW_IT_WHILE_NOT_RUNNING_ ); + } + + // IF NEEDED PROPOGATE THE THROW REQUEST THROUGH OUR DESCENDANTS: + + if ( descendants == SC_INCLUDE_DESCENDANTS ) + { + const std::vector<sc_object*> children = get_child_objects(); + int child_n = children.size(); + + for ( int child_i = 0; child_i < child_n; child_i++ ) + { + sc_process_b* child_p = DCAST<sc_process_b*>(children[child_i]); + if ( child_p ) + { + DEBUG_MSG(DEBUG_NAME,child_p,"about to throw user on"); + child_p->throw_user(helper, descendants); + } + } + } + +#if 0 // shouldn't we throw, if we're currently running? + + if ( sc_get_current_process_b() == (sc_process_b*)this ) + { + remove_dynamic_events(); + m_throw_status = THROW_USER; + if ( m_throw_helper_p != 0 ) delete m_throw_helper_p; + m_throw_helper_p = helper.clone(); + m_throw_helper_p->throw_it(); + } + + // throw_it HAS NO EFFECT ON A METHOD, ISSUE A WARNING: + + else + +#endif + { + SC_REPORT_WARNING( SC_ID_THROW_IT_IGNORED_, name() ); + } + + +} + +//------------------------------------------------------------------------------ +//"sc_method_process::trigger_dynamic" +// +// This method sets up a dynamic trigger on an event. +// +// Notes: +// (1) This method is identical to sc_thread_process::trigger_dynamic(), +// but they cannot be combined as sc_process_b::trigger_dynamic() +// because the signatures things like sc_event::remove_dynamic() +// have different overloads for sc_method_process* and sc_thread_process*. +// So if you change code here you'll also need to change it in +// sc_thread_process.cpp. +// +// Result is true if this process should be removed from the event's list, +// false if not. +// +// If the triggering process is the same process, the trigger is +// ignored as well, unless SC_ENABLE_IMMEDIATE_SELF_NOTIFICATIONS +// is defined. +//------------------------------------------------------------------------------ +bool sc_method_process::trigger_dynamic( sc_event* e ) +{ + // No time outs yet, and keep gcc happy. + + m_timed_out = false; + + // Escape cases: + // (a) If this method issued the notify() don't schedule it for + // execution, but leave the sensitivity in place. + // (b) If this method is already runnable can't trigger an event. + +#if ! defined( SC_ENABLE_IMMEDIATE_SELF_NOTIFICATIONS ) + if( SC_UNLIKELY_( sc_get_current_process_b() == this ) ) + { + report_immediate_self_notification(); + return false; + } +#endif // SC_ENABLE_IMMEDIATE_SELF_NOTIFICATIONS + + if( is_runnable() ) + return true; + + // If a process is disabled then we ignore any events, leaving them enabled: + // + // But if this is a time out event we need to remove both it and the + // event that was being waited for. + + if ( m_state & ps_bit_disabled ) + { + if ( e == m_timeout_event_p ) + { + remove_dynamic_events( true ); + return true; + } + else + { + return false; + } + } + + + // Process based on the event type and current process state: + // + // Every case needs to set 'rc' and continue on to the end of + // this method to allow suspend processing to work correctly. + + switch( m_trigger_type ) + { + case EVENT: + m_event_p = 0; + m_trigger_type = STATIC; + break; + + case AND_LIST: + -- m_event_count; + if ( m_event_count == 0 ) + { + m_event_list_p->auto_delete(); + m_event_list_p = 0; + m_trigger_type = STATIC; + } + else + { + return true; + } + break; + + case OR_LIST: + m_event_list_p->remove_dynamic( this, e ); + m_event_list_p->auto_delete(); + m_event_list_p = 0; + m_trigger_type = STATIC; + break; + + case TIMEOUT: + m_trigger_type = STATIC; + break; + + case EVENT_TIMEOUT: + if ( e == m_timeout_event_p ) + { + m_timed_out = true; + m_event_p->remove_dynamic( this ); + m_event_p = 0; + m_trigger_type = STATIC; + } + else + { + m_timeout_event_p->cancel(); + m_timeout_event_p->reset(); + m_event_p = 0; + m_trigger_type = STATIC; + } + break; + + case OR_LIST_TIMEOUT: + if ( e == m_timeout_event_p ) + { + m_timed_out = true; + m_event_list_p->remove_dynamic( this, e ); + m_event_list_p->auto_delete(); + m_event_list_p = 0; + m_trigger_type = STATIC; + } + + else + { + m_timeout_event_p->cancel(); + m_timeout_event_p->reset(); + m_event_list_p->remove_dynamic( this, e ); + m_event_list_p->auto_delete(); + m_event_list_p = 0; + m_trigger_type = STATIC; + } + break; + + case AND_LIST_TIMEOUT: + if ( e == m_timeout_event_p ) + { + m_timed_out = true; + m_event_list_p->remove_dynamic( this, e ); + m_event_list_p->auto_delete(); + m_event_list_p = 0; + m_trigger_type = STATIC; + } + + else + { + -- m_event_count; + if ( m_event_count == 0 ) + { + m_timeout_event_p->cancel(); + m_timeout_event_p->reset(); + // no need to remove_dynamic + m_event_list_p->auto_delete(); + m_event_list_p = 0; + m_trigger_type = STATIC; + } + else + { + return true; + } + } + break; + + case STATIC: { + // we should never get here, but throw_it() can make it happen. + SC_REPORT_WARNING(SC_ID_NOT_EXPECTING_DYNAMIC_EVENT_NOTIFY_, name()); + return true; + } + } + + // If we get here then the method has satisfied its next_trigger, if its + // suspended mark its state as ready to run. If its not suspended then push + // it onto the runnable queue. + + if ( (m_state & ps_bit_suspended) ) + { + m_state = m_state | ps_bit_ready_to_run; + } + else + { + simcontext()->push_runnable_method(this); + } + + return true; +} + +} // namespace sc_core + + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affiliation, date and + changes you are making here. + + Name, Affiliation, Date: + Description of Modification: + + *****************************************************************************/ + +// $Log: sc_method_process.cpp,v $ +// Revision 1.49 2011/08/29 18:24:47 acg +// Andy Goodrich: remove temporary comment flagging new preempt_with() call. +// +// Revision 1.48 2011/08/29 18:04:32 acg +// Philipp A. Hartmann: miscellaneous clean ups. +// +// Revision 1.47 2011/08/24 22:05:50 acg +// Torsten Maehne: initialization changes to remove warnings. +// +// Revision 1.46 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.45 2011/07/29 22:42:45 acg +// Andy Goodrich: added check_for_throws() to fix case where a method is +// deleted by a process it resets or kills so that it can throw itself. +// Philipp A. Hartmann: changes to handle case where a process control +// invocation on a child process causes the list of child processes to change. +// +// Revision 1.44 2011/07/24 11:27:04 acg +// Andy Goodrich: moved the check for unwinding processes until after the +// descendants have been processed in throw_user and kill. +// +// Revision 1.43 2011/07/24 11:20:03 acg +// Philipp A. Hartmann: process control error message improvements: +// (1) Downgrade error to warning for re-kills of processes. +// (2) Add process name to process messages. +// (3) drop some superfluous colons in messages. +// +// Revision 1.42 2011/05/05 17:45:27 acg +// Philip A. Hartmann: changes in WIN64 support. +// Andy Goodrich: additional DEBUG_MSG instances to trace process handling. +// +// Revision 1.41 2011/04/19 19:15:41 acg +// Andy Goodrich: fix so warning message is always issued for a throw_it() +// on a method process. +// +// Revision 1.40 2011/04/19 15:04:27 acg +// Philipp A. Hartmann: clean up SC_ID messages. +// +// Revision 1.39 2011/04/19 02:39:09 acg +// Philipp A. Hartmann: added checks for additional throws during stack unwinds. +// +// Revision 1.38 2011/04/13 02:41:34 acg +// Andy Goodrich: eliminate warning messages generated when the DEBUG_MSG +// macro is used. +// +// Revision 1.37 2011/04/11 22:10:46 acg +// Andy Goodrich: +// (1) Add DEBUG_MSG macro and use it to generate a journal of method +// throws if it is enabled. +// (2) Trim down to the expected behavior of scheduling a method that +// is asynchronously reset in anticipation of IEEE 1666 being revised. +// +// Revision 1.36 2011/04/10 22:15:29 acg +// Andy Goodrich: change to call methods on asynchronous reset. +// +// Revision 1.35 2011/04/08 22:31:40 acg +// Andy Goodrich: removed unused code. +// +// Revision 1.34 2011/04/08 18:24:07 acg +// Andy Goodrich: fix asynchronous reset dispatch and when the reset_event() +// is fired. +// +// Revision 1.33 2011/04/05 20:50:56 acg +// Andy Goodrich: +// (1) changes to make sure that event(), posedge() and negedge() only +// return true if the clock has not moved. +// (2) fixes for method self-resumes. +// (3) added SC_PRERELEASE_VERSION +// (4) removed kernel events from the object hierarchy, added +// sc_hierarchy_name_exists(). +// +// Revision 1.32 2011/04/01 22:30:39 acg +// Andy Goodrich: change hard assertion to warning for trigger_dynamic() +// getting called when there is only STATIC sensitivity. This can result +// because of sc_process_handle::throw_it(). +// +// Revision 1.31 2011/03/28 13:02:51 acg +// Andy Goodrich: Changes for disable() interactions. +// +// Revision 1.30 2011/03/23 16:17:52 acg +// Andy Goodrich: don't emit an error message for a resume on a disabled +// process that is not suspended. +// +// Revision 1.29 2011/03/20 13:43:23 acg +// Andy Goodrich: added async_signal_is() plus suspend() as a corner case. +// +// Revision 1.28 2011/03/08 20:49:30 acg +// Andy Goodrich: implement coarse checking for synchronous reset - suspend +// interaction. +// +// Revision 1.27 2011/03/08 20:32:28 acg +// Andy Goodrich: implemented "coarse" checking for undefined process +// control interactions. +// +// Revision 1.26 2011/03/07 18:25:19 acg +// Andy Goodrich: tightening of check for resume on a disabled process to +// only produce an error if it is ready to run. +// +// Revision 1.25 2011/03/07 17:38:43 acg +// Andy Goodrich: tightening up of checks for undefined interaction between +// synchronous reset and suspend. +// +// Revision 1.24 2011/03/06 23:30:13 acg +// Andy Goodrich: refining suspend - sync reset corner case checking so that +// the following are error situations: +// (1) Calling suspend on a process with a reset_signal_is() specification +// or sync_reset_on() is active. +// (2) Calling sync_reset_on() on a suspended process. +// +// Revision 1.23 2011/03/06 19:57:11 acg +// Andy Goodrich: refinements for the illegal suspend - synchronous reset +// interaction. +// +// Revision 1.22 2011/03/06 16:47:09 acg +// Andy Goodrich: changes for testing sync_reset - suspend corner cases. +// +// Revision 1.21 2011/03/06 15:57:08 acg +// Andy Goodrich: added process control corner case checks. +// +// Revision 1.20 2011/03/05 19:44:20 acg +// Andy Goodrich: changes for object and event naming and structures. +// +// Revision 1.19 2011/02/18 20:27:14 acg +// Andy Goodrich: Updated Copyrights. +// +// Revision 1.18 2011/02/17 19:50:43 acg +// Andy Goodrich: +// (1) Changed signature of trigger_dynamic back to a bool. +// (2) Added run queue processing into trigger dynamic. +// (3) Simplified process control support. +// +// Revision 1.17 2011/02/16 22:37:30 acg +// Andy Goodrich: clean up to remove need for ps_disable_pending. +// +// Revision 1.16 2011/02/13 23:09:58 acg +// Andy Goodrich: only remove dynamic events for asynchronous resets. +// +// Revision 1.15 2011/02/13 21:47:37 acg +// Andy Goodrich: update copyright notice. +// +// Revision 1.14 2011/02/13 21:31:02 acg +// Andy Goodrich: added error messages for throws when simulator has not +// been initialized. Added missing remove_dynamic_events() call to the +// reset code. +// +// Revision 1.13 2011/02/11 13:25:24 acg +// Andy Goodrich: Philipp A. Hartmann's changes: +// (1) Removal of SC_CTHREAD method overloads. +// (2) New exception processing code. +// +// Revision 1.12 2011/02/07 19:17:20 acg +// Andy Goodrich: changes for IEEE 1666 compatibility. +// +// Revision 1.11 2011/02/04 15:27:36 acg +// Andy Goodrich: changes for suspend-resume semantics. +// +// Revision 1.10 2011/02/01 23:01:53 acg +// Andy Goodrich: removed dead code. +// +// Revision 1.9 2011/02/01 21:05:05 acg +// Andy Goodrich: Changes in trigger_dynamic methods to handle new +// process control rules about event sensitivity. +// +// Revision 1.8 2011/01/25 20:50:37 acg +// Andy Goodrich: changes for IEEE 1666 2011. +// +// Revision 1.7 2011/01/18 20:10:44 acg +// Andy Goodrich: changes for IEEE1666_2011 semantics. +// +// Revision 1.6 2011/01/06 18:02:43 acg +// Andy Goodrich: added check for ps_disabled to method_dynamic(). +// +// Revision 1.5 2010/11/20 17:10:56 acg +// Andy Goodrich: reset processing changes for new IEEE 1666 standard. +// +// Revision 1.4 2010/07/22 20:02:33 acg +// Andy Goodrich: bug fixes. +// +// Revision 1.3 2009/05/22 16:06:29 acg +// Andy Goodrich: process control updates. +// +// Revision 1.2 2008/05/22 17:06:25 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.7 2006/04/20 17:08:16 acg +// Andy Goodrich: 3.0 style process changes. +// +// Revision 1.6 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.5 2006/01/26 21:04:54 acg +// Andy Goodrich: deprecation message changes and additional messages. +// +// Revision 1.4 2006/01/24 20:49:05 acg +// Andy Goodrich: changes to remove the use of deprecated features within the +// simulator, and to issue warning messages when deprecated features are used. +// +// Revision 1.3 2006/01/13 18:44:29 acg +// Added $Log to record CVS changes into the source. +// diff --git a/ext/systemc/src/sysc/kernel/sc_method_process.h b/ext/systemc/src/sysc/kernel/sc_method_process.h new file mode 100644 index 000000000..00f6e37e7 --- /dev/null +++ b/ext/systemc/src/sysc/kernel/sc_method_process.h @@ -0,0 +1,467 @@ +/***************************************************************************** + + 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_method_process.h -- Method process declarations + + Original Author: Andy Goodrich, Forte Design Systems, 4 August 2005 + + + CHANGE LOG AT THE END OF THE FILE + *****************************************************************************/ + +// $Log: sc_method_process.h,v $ +// Revision 1.23 2011/09/05 21:20:22 acg +// Andy Goodrich: result of automake invocation. +// +// Revision 1.22 2011/08/29 18:04:32 acg +// Philipp A. Hartmann: miscellaneous clean ups. +// +// Revision 1.21 2011/08/26 20:46:10 acg +// Andy Goodrich: moved the modification log to the end of the file to +// eliminate source line number skew when check-ins are done. +// + +#if !defined(sc_method_process_h_INCLUDED) +#define sc_method_process_h_INCLUDED + +#include "sysc/kernel/sc_process.h" +#include "sysc/kernel/sc_spawn_options.h" +#include "sysc/kernel/sc_cor.h" +#include "sysc/kernel/sc_event.h" +#include "sysc/kernel/sc_except.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 { + +// forward function and class declarations: + +void sc_method_cor_fn( void* ); +void sc_cmethod_cor_fn( void* ); +void sc_set_stack_size( sc_method_handle, std::size_t ); +class sc_event; +class sc_module; +class sc_process_table; +class sc_process_handle; +class sc_simcontext; +class sc_runnable; + +void next_trigger( sc_simcontext* ); +void next_trigger( const sc_event&, sc_simcontext* ); +void next_trigger( const sc_event_or_list&, sc_simcontext* ); +void next_trigger( const sc_event_and_list&, sc_simcontext* ); +void next_trigger( const sc_time&, sc_simcontext* ); +void next_trigger( const sc_time&, const sc_event&, sc_simcontext* ); +void next_trigger( const sc_time&, const sc_event_or_list&, sc_simcontext* ); +void next_trigger( const sc_time&, const sc_event_and_list&, sc_simcontext* ); + +struct sc_invoke_method; +//============================================================================== +// sc_method_process - +// +//============================================================================== +class sc_method_process : public sc_process_b { + friend struct sc_invoke_method; + friend void sc_method_cor_fn( void* ); + friend void sc_cmethod_cor_fn( void* ); + friend void sc_set_stack_size( sc_method_handle, std::size_t ); + friend class sc_event; + friend class sc_module; + friend class sc_process_table; + friend class sc_process_handle; + friend class sc_simcontext; + friend class sc_runnable; + + friend void next_trigger( sc_simcontext* ); + friend void next_trigger( const sc_event&, + sc_simcontext* ); + friend void next_trigger( const sc_event_or_list&, + sc_simcontext* ); + friend void next_trigger( const sc_event_and_list&, + sc_simcontext* ); + friend void next_trigger( const sc_time&, + sc_simcontext* ); + friend void next_trigger( const sc_time&, const sc_event&, + sc_simcontext* ); + friend void next_trigger( const sc_time&, const sc_event_or_list&, + sc_simcontext* ); + friend void next_trigger( const sc_time&, const sc_event_and_list&, + sc_simcontext* ); + + public: + sc_method_process( const char* name_p, bool free_host, + SC_ENTRY_FUNC method_p, sc_process_host* host_p, + const sc_spawn_options* opt_p ); + + virtual const char* kind() const + { return "sc_method_process"; } + + protected: + void check_for_throws(); + virtual void disable_process( + sc_descendant_inclusion_info descendants = SC_NO_DESCENDANTS ); + virtual void enable_process( + sc_descendant_inclusion_info descendants = SC_NO_DESCENDANTS ); + inline bool run_process(); + virtual void kill_process( + sc_descendant_inclusion_info descendants = SC_NO_DESCENDANTS ); + sc_method_handle next_exist(); + sc_method_handle next_runnable(); + void clear_trigger(); + void next_trigger( const sc_event& ); + void next_trigger( const sc_event_or_list& ); + void next_trigger( const sc_event_and_list& ); + void next_trigger( const sc_time& ); + void next_trigger( const sc_time&, const sc_event& ); + void next_trigger( const sc_time&, const sc_event_or_list& ); + void next_trigger( const sc_time&, const sc_event_and_list& ); + virtual void resume_process( + sc_descendant_inclusion_info descendants = SC_NO_DESCENDANTS ); + void set_next_exist( sc_method_handle next_p ); + void set_next_runnable( sc_method_handle next_p ); + void set_stack_size( std::size_t size ); + virtual void suspend_process( + sc_descendant_inclusion_info descendants = SC_NO_DESCENDANTS ); + virtual void throw_reset( bool async ); + virtual void throw_user( const sc_throw_it_helper& helper, + sc_descendant_inclusion_info descendants = SC_NO_DESCENDANTS ); + bool trigger_dynamic( sc_event* ); + inline void trigger_static(); + + protected: + sc_cor* m_cor; // Thread's coroutine. + std::size_t m_stack_size; // Thread stack size. + std::vector<sc_process_monitor*> m_monitor_q; // Thread monitors. + + private: + // may not be deleted manually (called from sc_process_b) + virtual ~sc_method_process(); + + private: // disabled + sc_method_process( const sc_method_process& ); + const sc_method_process& operator = ( const sc_method_process& ); + +}; + +inline +void +sc_method_process::next_trigger( const sc_event& e ) +{ + clear_trigger(); + e.add_dynamic( this ); + m_event_p = &e; + m_trigger_type = EVENT; +} + +inline +void +sc_method_process::next_trigger( const sc_event_or_list& el ) +{ + clear_trigger(); + el.add_dynamic( this ); + m_event_list_p = ⪙ + m_trigger_type = OR_LIST; +} + +inline +void +sc_method_process::next_trigger( const sc_event_and_list& el ) +{ + clear_trigger(); + el.add_dynamic( this ); + m_event_list_p = ⪙ + m_event_count = el.size(); + m_trigger_type = AND_LIST; +} + +inline +void +sc_method_process::next_trigger( const sc_time& t ) +{ + clear_trigger(); + m_timeout_event_p->notify_internal( t ); + m_timeout_event_p->add_dynamic( this ); + m_trigger_type = TIMEOUT; +} + +inline +void +sc_method_process::next_trigger( const sc_time& t, const sc_event& e ) +{ + clear_trigger(); + m_timeout_event_p->notify_internal( t ); + m_timeout_event_p->add_dynamic( this ); + e.add_dynamic( this ); + m_event_p = &e; + m_trigger_type = EVENT_TIMEOUT; +} + +inline +void +sc_method_process::next_trigger( const sc_time& t, const sc_event_or_list& el ) +{ + clear_trigger(); + m_timeout_event_p->notify_internal( t ); + m_timeout_event_p->add_dynamic( this ); + el.add_dynamic( this ); + m_event_list_p = ⪙ + m_trigger_type = OR_LIST_TIMEOUT; +} + +inline +void +sc_method_process::next_trigger( const sc_time& t, const sc_event_and_list& el ) +{ + clear_trigger(); + m_timeout_event_p->notify_internal( t ); + m_timeout_event_p->add_dynamic( this ); + el.add_dynamic( this ); + m_event_list_p = ⪙ + m_event_count = el.size(); + m_trigger_type = AND_LIST_TIMEOUT; +} + +inline +void sc_method_process::set_next_exist(sc_method_handle next_p) +{ + m_exist_p = next_p; +} + +inline +sc_method_handle sc_method_process::next_exist() +{ + return (sc_method_handle)m_exist_p; +} + + +inline +void sc_method_process::set_next_runnable(sc_method_handle next_p) +{ + m_runnable_p = next_p; +} + +inline +sc_method_handle sc_method_process::next_runnable() +{ + return (sc_method_handle)m_runnable_p; +} + +// +---------------------------------------------------------------------------- +// |"sc_method_process::run_process" +// | +// | This method executes this object instance, including fielding exceptions. +// | +// | Result is false if an unfielded exception occurred, true if not. +// +---------------------------------------------------------------------------- +inline bool sc_method_process::run_process() +{ + // Execute this object instance's semantics and catch any exceptions that + // are generated: + + bool restart = false; + do { + try { + DEBUG_MSG(DEBUG_NAME,this,"executing method semantics"); + semantics(); + restart = false; + } + catch( sc_unwind_exception& ex ) { + DEBUG_MSG(DEBUG_NAME,this,"caught unwind exception"); + ex.clear(); + restart = ex.is_reset(); + } + catch( ... ) { + sc_report* err_p = sc_handle_exception(); + simcontext()->set_error( err_p ); + return false; + } + } while( restart ); + + return true; +} + +//------------------------------------------------------------------------------ +//"sc_method_process::trigger_static" +// +// This inline method adds the current method to the queue of runnable +// processes, if required. This is the case if the following criteria +// are met: +// (1) The process is in a runnable state. +// (2) The process is not already on the run queue. +// (3) The process is expecting a static trigger, +// dynamic event waits take priority. +// +// +// If the triggering process is the same process, the trigger is +// ignored as well, unless SC_ENABLE_IMMEDIATE_SELF_NOTIFICATIONS +// is defined. +//------------------------------------------------------------------------------ +inline +void +sc_method_process::trigger_static() +{ + if ( (m_state & ps_bit_disabled) || is_runnable() || + m_trigger_type != STATIC ) + return; + +#if ! defined( SC_ENABLE_IMMEDIATE_SELF_NOTIFICATIONS ) + if( SC_UNLIKELY_( sc_get_current_process_b() == this ) ) + { + report_immediate_self_notification(); + return; + } +#endif // SC_ENABLE_IMMEDIATE_SELF_NOTIFICATIONS + + // If we get here then the method is has satisfied its wait, if its + // suspended mark its state as ready to run. If its not suspended then + // push it onto the runnable queue. + + if ( m_state & ps_bit_suspended ) + { + m_state = m_state | ps_bit_ready_to_run; + } + else + { + simcontext()->push_runnable_method(this); + } +} + +#undef DEBUG_MSG + +} // namespace sc_core + +// Revision 1.20 2011/08/24 22:05:50 acg +// Torsten Maehne: initialization changes to remove warnings. +// +// Revision 1.19 2011/07/29 22:43:15 acg +// Andy Goodrich: addition of check_for_throws() method. +// +// Revision 1.18 2011/07/24 11:18:09 acg +// Philipp A. Hartmann: add code to restart a method process after a +// self-reset. +// +// Revision 1.17 2011/05/09 04:07:48 acg +// Philipp A. Hartmann: +// (1) Restore hierarchy in all phase callbacks. +// (2) Ensure calls to before_end_of_elaboration. +// +// Revision 1.16 2011/04/13 02:41:34 acg +// Andy Goodrich: eliminate warning messages generated when the DEBUG_MSG +// macro is used. +// +// Revision 1.15 2011/04/10 22:12:32 acg +// Andy Goodrich: adding debugging macros. +// +// Revision 1.14 2011/04/08 22:31:21 acg +// Andy Goodrich: added new inline method run_process() to hide the process +// implementation for sc_simcontext. +// +// Revision 1.13 2011/04/05 20:50:56 acg +// Andy Goodrich: +// (1) changes to make sure that event(), posedge() and negedge() only +// return true if the clock has not moved. +// (2) fixes for method self-resumes. +// (3) added SC_PRERELEASE_VERSION +// (4) removed kernel events from the object hierarchy, added +// sc_hierarchy_name_exists(). +// +// Revision 1.12 2011/04/01 21:24:57 acg +// Andy Goodrich: removed unused code. +// +// 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:51:34 acg +// Andy Goodrich: +// (1) Changed the signature of trigger_dynamic back to a bool. +// (2) Removed ready_to_run(). +// (3) Simplified process control usage. +// +// 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:05:05 acg +// Andy Goodrich: Changes in trigger_dynamic methods to handle new +// process control rules about event sensitivity. +// +// Revision 1.5 2011/01/18 20:10:44 acg +// Andy Goodrich: changes for IEEE1666_2011 semantics. +// +// Revision 1.4 2009/07/28 01:10:53 acg +// Andy Goodrich: updates for 2.3 release candidate. +// +// Revision 1.3 2009/05/22 16:06:29 acg +// Andy Goodrich: process control updates. +// +// Revision 1.2 2008/05/22 17:06:25 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.7 2006/05/08 17:57:13 acg +// Andy Goodrich: Added David Long's forward declarations for friend functions +// to keep the Microsoft C++ compiler happy. +// +// Revision 1.6 2006/04/20 17:08:17 acg +// Andy Goodrich: 3.0 style process changes. +// +// Revision 1.5 2006/04/11 23:13:21 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.4 2006/01/24 20:49:05 acg +// Andy Goodrich: changes to remove the use of deprecated features within the +// simulator, and to issue warning messages when deprecated features are used. +// +// Revision 1.3 2006/01/13 18:44:29 acg +// Added $Log to record CVS changes into the source. + +#endif // !defined(sc_method_process_h_INCLUDED) diff --git a/ext/systemc/src/sysc/kernel/sc_module.cpp b/ext/systemc/src/sysc/kernel/sc_module.cpp new file mode 100644 index 000000000..efca2a4dc --- /dev/null +++ b/ext/systemc/src/sysc/kernel/sc_module.cpp @@ -0,0 +1,846 @@ +/***************************************************************************** + + 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_module.cpp -- Base class of all sequential and combinational processes. + + Original Author: Stan Y. Liao, Synopsys, Inc. + + CHANGE LOG AT THE END OF THE FILE + *****************************************************************************/ + + +#include <cassert> +#include <math.h> +#include <stddef.h> +#include <stdio.h> + +#include "sysc/kernel/sc_event.h" +#include "sysc/kernel/sc_kernel_ids.h" +#include "sysc/kernel/sc_module.h" +#include "sysc/kernel/sc_module_registry.h" +#include "sysc/kernel/sc_name_gen.h" +#include "sysc/kernel/sc_object_manager.h" +#include "sysc/kernel/sc_process.h" +#include "sysc/kernel/sc_process_handle.h" +#include "sysc/kernel/sc_simcontext.h" +#include "sysc/kernel/sc_simcontext_int.h" +#include "sysc/kernel/sc_object_int.h" +#include "sysc/kernel/sc_reset.h" +#include "sysc/communication/sc_communication_ids.h" +#include "sysc/communication/sc_interface.h" +#include "sysc/communication/sc_port.h" +#include "sysc/communication/sc_signal.h" +#include "sysc/communication/sc_signal_ports.h" +#include "sysc/utils/sc_utils_ids.h" +#include "sysc/utils/sc_iostream.h" + +namespace sc_core { + +// ---------------------------------------------------------------------------- +// CLASS : sc_module_dynalloc_list +// +// Garbage collection for modules dynamically allocated with SC_NEW. +// ---------------------------------------------------------------------------- + +class sc_module_dynalloc_list +{ +public: + + sc_module_dynalloc_list() : m_list() + {} + + ~sc_module_dynalloc_list(); + + void add( sc_module* p ) + { m_list.push_back( p ); } + +private: + + sc_plist<sc_module*> m_list; +}; + + +//------------------------------------------------------------------------------ +//"~sc_module_dynalloc_list" +// +// Note we clear the m_parent field for the module being deleted. This because +// we process the list front to back so the parent has already been deleted, +// and we don't want ~sc_object() to try to access the parent which may +// contain garbage. +//------------------------------------------------------------------------------ +sc_module_dynalloc_list::~sc_module_dynalloc_list() +{ + sc_plist<sc_module*>::iterator it( m_list ); + while( ! it.empty() ) { + (*it)->m_parent = 0; + delete *it; + it ++; + } +} + + +// ---------------------------------------------------------------------------- + +sc_module* +sc_module_dynalloc( sc_module* module_ ) +{ + static sc_module_dynalloc_list dynalloc_list; + dynalloc_list.add( module_ ); + return module_; +} + + +// ---------------------------------------------------------------------------- +// STRUCT : sc_bind_proxy +// +// Struct for temporarily storing a pointer to an interface or port. +// Used for positional binding. +// ---------------------------------------------------------------------------- + +sc_bind_proxy::sc_bind_proxy() +: iface( 0 ), + port( 0 ) +{} + +sc_bind_proxy::sc_bind_proxy( sc_interface& iface_ ) +: iface( &iface_ ), + port( 0 ) +{} + +sc_bind_proxy::sc_bind_proxy( sc_port_base& port_ ) +: iface( 0 ), + port( &port_ ) +{} + + +const sc_bind_proxy SC_BIND_PROXY_NIL; + + +// ---------------------------------------------------------------------------- +// CLASS : sc_module +// +// Base class for all structural entities. +// ---------------------------------------------------------------------------- + +void +sc_module::sc_module_init() +{ + simcontext()->get_module_registry()->insert( *this ); + simcontext()->hierarchy_push( this ); + m_end_module_called = false; + m_module_name_p = 0; + m_port_vec = new std::vector<sc_port_base*>; + m_port_index = 0; + m_name_gen = new sc_name_gen; +} + +/* + * This form of the constructor assumes that the user has + * used an sc_module_name parameter for his/her constructor. + * That parameter object has been pushed onto the stack, + * and can be looked up by calling the + * top_of_module_name_stack() function of the object manager. + * This technique has two advantages: + * + * 1) The user no longer has to write sc_module(name) in the + * constructor initializer. + * 2) The user no longer has to call end_module() at the end + * of the constructor -- a common negligence. + * + * But it is important to note that sc_module_name may be used + * in the user's constructor's parameter. If it is used anywhere + * else, unexpected things will happen. The error-checking + * mechanism builtin here cannot hope to catch all misuses. + * + */ + +sc_module::sc_module() +: sc_object(::sc_core::sc_get_curr_simcontext() + ->get_object_manager() + ->top_of_module_name_stack() + ->operator const char*()), + sensitive(this), + sensitive_pos(this), + sensitive_neg(this), + m_end_module_called(false), + m_port_vec(), + m_port_index(0), + m_name_gen(0), + m_module_name_p(0) +{ + /* When this form is used, we better have a fresh sc_module_name + on the top of the stack */ + sc_module_name* mod_name = + simcontext()->get_object_manager()->top_of_module_name_stack(); + if (0 == mod_name || 0 != mod_name->m_module_p) + SC_REPORT_ERROR( SC_ID_SC_MODULE_NAME_REQUIRED_, 0 ); + sc_module_init(); + mod_name->set_module( this ); + m_module_name_p = mod_name; // must come after sc_module_init call. +} + +sc_module::sc_module( const sc_module_name& ) +: sc_object(::sc_core::sc_get_curr_simcontext() + ->get_object_manager() + ->top_of_module_name_stack() + ->operator const char*()), + sensitive(this), + sensitive_pos(this), + sensitive_neg(this), + m_end_module_called(false), + m_port_vec(), + m_port_index(0), + m_name_gen(0), + m_module_name_p(0) +{ + /* For those used to the old style of passing a name to sc_module, + this constructor will reduce the chance of making a mistake */ + + /* When this form is used, we better have a fresh sc_module_name + on the top of the stack */ + sc_module_name* mod_name = + simcontext()->get_object_manager()->top_of_module_name_stack(); + if (0 == mod_name || 0 != mod_name->m_module_p) + SC_REPORT_ERROR( SC_ID_SC_MODULE_NAME_REQUIRED_, 0 ); + sc_module_init(); + mod_name->set_module( this ); + m_module_name_p = mod_name; // must come after sc_module_init call. +} + +/* -------------------------------------------------------------------- + * + * Deprecated constructors: + * sc_module( const char* ) + * sc_module( const std::string& ) + */ +sc_module::sc_module( const char* nm ) +: sc_object(nm), + sensitive(this), + sensitive_pos(this), + sensitive_neg(this), + m_end_module_called(false), + m_port_vec(), + m_port_index(0), + m_name_gen(0), + m_module_name_p(0) +{ + SC_REPORT_WARNING( SC_ID_BAD_SC_MODULE_CONSTRUCTOR_, nm ); + sc_module_init(); +} + +sc_module::sc_module( const std::string& s ) +: sc_object( s.c_str() ), + sensitive(this), + sensitive_pos(this), + sensitive_neg(this), + m_end_module_called(false), + m_port_vec(), + m_port_index(0), + m_name_gen(0), + m_module_name_p(0) +{ + SC_REPORT_WARNING( SC_ID_BAD_SC_MODULE_CONSTRUCTOR_, s.c_str() ); + sc_module_init(); +} + +/* -------------------------------------------------------------------- */ + +sc_module::~sc_module() +{ + delete m_port_vec; + delete m_name_gen; + orphan_child_objects(); + if ( m_module_name_p ) + { + m_module_name_p->clear_module( this ); // must be before end_module() + end_module(); + } + simcontext()->get_module_registry()->remove( *this ); +} + + +const ::std::vector<sc_object*>& +sc_module::get_child_objects() const +{ + return m_child_objects; +} + +// set SC_THREAD asynchronous reset sensitivity + +void +sc_module::async_reset_signal_is( const sc_in<bool>& port, bool level ) +{ + sc_reset::reset_signal_is(true, port, level); +} + +void +sc_module::async_reset_signal_is( const sc_inout<bool>& port, bool level ) +{ + sc_reset::reset_signal_is(true, port, level); +} + +void +sc_module::async_reset_signal_is( const sc_out<bool>& port, bool level ) +{ + sc_reset::reset_signal_is(true, port, level); +} + +void +sc_module::async_reset_signal_is(const sc_signal_in_if<bool>& iface, bool level) +{ + sc_reset::reset_signal_is(true, iface, level); +} + +void +sc_module::end_module() +{ + if( ! m_end_module_called ) { + /* TBD: Can check here to alert the user that end_module + was not called for a previous module. */ + (void)sc_get_curr_simcontext()->hierarchy_pop(); + sc_get_curr_simcontext()->reset_curr_proc(); + sensitive.reset(); + sensitive_pos.reset(); + sensitive_neg.reset(); + m_end_module_called = true; + m_module_name_p = 0; // make sure we are not called in ~sc_module(). + } +} + + +// to prevent initialization for SC_METHODs and SC_THREADs + +void +sc_module::dont_initialize() +{ + sc_process_handle last_proc = sc_get_last_created_process_handle(); + last_proc.dont_initialize( true ); +} + +// set SC_THREAD synchronous reset sensitivity + +void +sc_module::reset_signal_is( const sc_in<bool>& port, bool level ) +{ + sc_reset::reset_signal_is(false, port, level); +} + +void +sc_module::reset_signal_is( const sc_inout<bool>& port, bool level ) +{ + sc_reset::reset_signal_is(false, port, level); +} + +void +sc_module::reset_signal_is( const sc_out<bool>& port, bool level ) +{ + sc_reset::reset_signal_is(false, port, level); +} + +void +sc_module::reset_signal_is( const sc_signal_in_if<bool>& iface, bool level ) +{ + sc_reset::reset_signal_is(false, iface, level); +} + +// to generate unique names for objects in an MT-Safe way + +const char* +sc_module::gen_unique_name( const char* basename_, bool preserve_first ) +{ + return m_name_gen->gen_unique_name( basename_, preserve_first ); +} + + +// called by construction_done + +void +sc_module::before_end_of_elaboration() +{} + +// We push the sc_module instance onto the stack of open objects so +// that any objects that are created in before_end_of_elaboration have +// the proper parent. After the call we pop the hierarchy. +void +sc_module::construction_done() +{ + hierarchy_scope scope(this); + before_end_of_elaboration(); +} + +// called by elaboration_done (does nothing by default) + +void +sc_module::end_of_elaboration() +{} + + +// We push the sc_module instance onto the stack of open objects so +// that any objects that are created in end_of_elaboration have +// the proper parent. After the call we pop the hierarchy. +void +sc_module::elaboration_done( bool& error_ ) +{ + if( ! m_end_module_called ) { + char msg[BUFSIZ]; + std::sprintf( msg, "module '%s'", name() ); + SC_REPORT_WARNING( SC_ID_END_MODULE_NOT_CALLED_, msg ); + if( error_ ) { + SC_REPORT_WARNING( SC_ID_HIER_NAME_INCORRECT_, 0 ); + } + error_ = true; + } + hierarchy_scope scope(this); + end_of_elaboration(); +} + +// called by start_simulation (does nothing by default) + +void +sc_module::start_of_simulation() +{} + +void +sc_module::start_simulation() +{ + hierarchy_scope scope(this); + start_of_simulation(); +} + +// called by simulation_done (does nothing by default) + +void +sc_module::end_of_simulation() +{} + +void +sc_module::simulation_done() +{ + hierarchy_scope scope(this); + end_of_simulation(); +} + +void +sc_module::set_stack_size( std::size_t size ) +{ + sc_process_handle proc_h( + sc_is_running() ? + sc_get_current_process_handle() : + sc_get_last_created_process_handle() + ); + sc_thread_handle thread_h; // Current process as thread. + + + thread_h = (sc_thread_handle)proc_h; + if ( thread_h ) + { + thread_h->set_stack_size( size ); + } + else + { + SC_REPORT_WARNING( SC_ID_SET_STACK_SIZE_, 0 ); + } +} + + +int +sc_module::append_port( sc_port_base* port_ ) +{ + int index = m_port_vec->size(); + m_port_vec->push_back( port_ ); + return index; +} + + +// positional binding methods + +static void sc_warn_arrow_arrow_bind() +{ + static bool warn_arrow_arrow_bind=true; + if ( warn_arrow_arrow_bind ) + { + warn_arrow_arrow_bind = false; + SC_REPORT_INFO(SC_ID_IEEE_1666_DEPRECATION_, + "positional binding using << or , is deprecated, use () instead."); + } +} + +sc_module& +sc_module::operator << ( sc_interface& interface_ ) +{ + sc_warn_arrow_arrow_bind(); + positional_bind(interface_); + return *this; +} + +sc_module& +sc_module::operator << ( sc_port_base& port_ ) +{ + sc_warn_arrow_arrow_bind(); + positional_bind(port_); + return *this; +} + + +void +sc_module::positional_bind( sc_interface& interface_ ) +{ + if( m_port_index == (int)m_port_vec->size() ) { + char msg[BUFSIZ]; + if( m_port_index == 0 ) { + std::sprintf( msg, "module `%s' has no ports", name() ); + } else { + std::sprintf( msg, "all ports of module `%s' are bound", name() ); + } + SC_REPORT_ERROR( SC_ID_BIND_IF_TO_PORT_, msg ); + } + int status = (*m_port_vec)[m_port_index]->pbind( interface_ ); + if( status != 0 ) { + char msg[BUFSIZ]; + switch( status ) { + case 1: + std::sprintf( msg, "port %d of module `%s' is already bound", + m_port_index, name() ); + break; + case 2: + std::sprintf( msg, "type mismatch on port %d of module `%s'", + m_port_index, name() ); + break; + default: + std::sprintf( msg, "unknown error" ); + break; + } + SC_REPORT_ERROR( SC_ID_BIND_IF_TO_PORT_, msg ); + } + ++ m_port_index; +} + +void +sc_module::positional_bind( sc_port_base& port_ ) +{ + if( m_port_index == (int)m_port_vec->size() ) { + char msg[BUFSIZ]; + if( m_port_index == 0 ) { + std::sprintf( msg, "module `%s' has no ports", name() ); + } else { + std::sprintf( msg, "all ports of module `%s' are bound", name() ); + } + SC_REPORT_ERROR( SC_ID_BIND_PORT_TO_PORT_, msg ); + } + int status = (*m_port_vec)[m_port_index]->pbind( port_ ); + if( status != 0 ) { + char msg[BUFSIZ]; + switch( status ) { + case 1: + std::sprintf( msg, "port %d of module `%s' is already bound", + m_port_index, name() ); + break; + case 2: + std::sprintf( msg, "type mismatch on port %d of module `%s'", + m_port_index, name() ); + break; + default: + std::sprintf( msg, "unknown error" ); + break; + } + SC_REPORT_ERROR( SC_ID_BIND_PORT_TO_PORT_, msg ); + } + ++ m_port_index; +} + + +#define TRY_BIND( p ) \ + if( (p).iface != 0 ) { \ + positional_bind( *(p).iface ); \ + } else if( (p).port != 0 ) { \ + positional_bind( *(p).port ); \ + } else { \ + return; \ + } + + +void +sc_module::operator () ( const sc_bind_proxy& p001, + const sc_bind_proxy& p002, + const sc_bind_proxy& p003, + const sc_bind_proxy& p004, + const sc_bind_proxy& p005, + const sc_bind_proxy& p006, + const sc_bind_proxy& p007, + const sc_bind_proxy& p008, + const sc_bind_proxy& p009, + const sc_bind_proxy& p010, + const sc_bind_proxy& p011, + const sc_bind_proxy& p012, + const sc_bind_proxy& p013, + const sc_bind_proxy& p014, + const sc_bind_proxy& p015, + const sc_bind_proxy& p016, + const sc_bind_proxy& p017, + const sc_bind_proxy& p018, + const sc_bind_proxy& p019, + const sc_bind_proxy& p020, + const sc_bind_proxy& p021, + const sc_bind_proxy& p022, + const sc_bind_proxy& p023, + const sc_bind_proxy& p024, + const sc_bind_proxy& p025, + const sc_bind_proxy& p026, + const sc_bind_proxy& p027, + const sc_bind_proxy& p028, + const sc_bind_proxy& p029, + const sc_bind_proxy& p030, + const sc_bind_proxy& p031, + const sc_bind_proxy& p032, + const sc_bind_proxy& p033, + const sc_bind_proxy& p034, + const sc_bind_proxy& p035, + const sc_bind_proxy& p036, + const sc_bind_proxy& p037, + const sc_bind_proxy& p038, + const sc_bind_proxy& p039, + const sc_bind_proxy& p040, + const sc_bind_proxy& p041, + const sc_bind_proxy& p042, + const sc_bind_proxy& p043, + const sc_bind_proxy& p044, + const sc_bind_proxy& p045, + const sc_bind_proxy& p046, + const sc_bind_proxy& p047, + const sc_bind_proxy& p048, + const sc_bind_proxy& p049, + const sc_bind_proxy& p050, + const sc_bind_proxy& p051, + const sc_bind_proxy& p052, + const sc_bind_proxy& p053, + const sc_bind_proxy& p054, + const sc_bind_proxy& p055, + const sc_bind_proxy& p056, + const sc_bind_proxy& p057, + const sc_bind_proxy& p058, + const sc_bind_proxy& p059, + const sc_bind_proxy& p060, + const sc_bind_proxy& p061, + const sc_bind_proxy& p062, + const sc_bind_proxy& p063, + const sc_bind_proxy& p064 ) +{ + static bool warn_only_once=true; + if ( m_port_index > 0 && warn_only_once ) + { + warn_only_once = false; + SC_REPORT_INFO(SC_ID_IEEE_1666_DEPRECATION_, + "multiple () binding deprecated, use explicit port binding instead." ); + } + + TRY_BIND( p001 ); + TRY_BIND( p002 ); + TRY_BIND( p003 ); + TRY_BIND( p004 ); + TRY_BIND( p005 ); + TRY_BIND( p006 ); + TRY_BIND( p007 ); + TRY_BIND( p008 ); + TRY_BIND( p009 ); + TRY_BIND( p010 ); + TRY_BIND( p011 ); + TRY_BIND( p012 ); + TRY_BIND( p013 ); + TRY_BIND( p014 ); + TRY_BIND( p015 ); + TRY_BIND( p016 ); + TRY_BIND( p017 ); + TRY_BIND( p018 ); + TRY_BIND( p019 ); + TRY_BIND( p020 ); + TRY_BIND( p021 ); + TRY_BIND( p022 ); + TRY_BIND( p023 ); + TRY_BIND( p024 ); + TRY_BIND( p025 ); + TRY_BIND( p026 ); + TRY_BIND( p027 ); + TRY_BIND( p028 ); + TRY_BIND( p029 ); + TRY_BIND( p030 ); + TRY_BIND( p031 ); + TRY_BIND( p032 ); + TRY_BIND( p033 ); + TRY_BIND( p034 ); + TRY_BIND( p035 ); + TRY_BIND( p036 ); + TRY_BIND( p037 ); + TRY_BIND( p038 ); + TRY_BIND( p039 ); + TRY_BIND( p040 ); + TRY_BIND( p041 ); + TRY_BIND( p042 ); + TRY_BIND( p043 ); + TRY_BIND( p044 ); + TRY_BIND( p045 ); + TRY_BIND( p046 ); + TRY_BIND( p047 ); + TRY_BIND( p048 ); + TRY_BIND( p049 ); + TRY_BIND( p050 ); + TRY_BIND( p051 ); + TRY_BIND( p052 ); + TRY_BIND( p053 ); + TRY_BIND( p054 ); + TRY_BIND( p055 ); + TRY_BIND( p056 ); + TRY_BIND( p057 ); + TRY_BIND( p058 ); + TRY_BIND( p059 ); + TRY_BIND( p060 ); + TRY_BIND( p061 ); + TRY_BIND( p062 ); + TRY_BIND( p063 ); + TRY_BIND( p064 ); +} + +} // namespace sc_core + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affiliation, date and + changes you are making here. + + Name, Affiliation, Date: Ali Dasdan, Synopsys, Inc. + Description of Modification: - Implementation of operator() and operator, + positional connection method. + - Implementation of error checking in + operator<<'s. + - Implementation of the function test_module_prm. + - Implementation of set_stack_size(). + + Name, Affiliation, Date: Andy Goodrich, Forte Design Systems 20 May 2003 + Description of Modification: Inherit from sc_process_host + + Name, Affiliation, Date: Bishnupriya Bhattacharya, Cadence Design Systems, + 25 August, 2003 + Description of Modification: dont_initialize() uses + sc_get_last_created_process_handle() instead of + sc_get_current_process_b() + + Name, Affiliation, Date: Andy Goodrich, Forte Design Systems 25 Mar 2003 + Description of Modification: Fixed bug in SC_NEW, see comments on + ~sc_module_dynalloc_list below. + + + *****************************************************************************/ + + +// $Log: sc_module.cpp,v $ +// Revision 1.14 2011/08/29 18:04:32 acg +// Philipp A. Hartmann: miscellaneous clean ups. +// +// Revision 1.13 2011/08/26 20:46:10 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.12 2011/08/24 22:05:51 acg +// Torsten Maehne: initialization changes to remove warnings. +// +// Revision 1.11 2011/03/05 19:44:20 acg +// Andy Goodrich: changes for object and event naming and structures. +// +// Revision 1.10 2011/02/18 20:27:14 acg +// Andy Goodrich: Updated Copyrights. +// +// Revision 1.9 2011/02/16 22:37:30 acg +// Andy Goodrich: clean up to remove need for ps_disable_pending. +// +// Revision 1.8 2011/02/14 17:51:40 acg +// Andy Goodrich: proper pushing an poppping of the module hierarchy for +// start_of_simulation() and end_of_simulation. +// +// Revision 1.7 2011/02/13 21:47:37 acg +// Andy Goodrich: update copyright notice. +// +// Revision 1.6 2011/01/25 20:50:37 acg +// Andy Goodrich: changes for IEEE 1666 2011. +// +// Revision 1.5 2009/05/22 16:06:29 acg +// Andy Goodrich: process control updates. +// +// Revision 1.4 2008/11/17 15:57:15 acg +// Andy Goodrich: added deprecation message for sc_module(const char*) +// +// Revision 1.3 2008/05/22 17:06:25 acg +// Andy Goodrich: updated copyright notice to include 2008. +// +// Revision 1.2 2007/05/17 20:16:33 acg +// Andy Goodrich: changes for beta release to LWG. +// +// Revision 1.1.1.1 2006/12/15 20:20:05 acg +// SystemC 2.3 +// +// Revision 1.9 2006/12/02 20:58:18 acg +// Andy Goodrich: updates from 2.2 for IEEE 1666 support. +// +// Revision 1.8 2006/03/21 00:00:34 acg +// Andy Goodrich: changed name of sc_get_current_process_base() to be +// sc_get_current_process_b() since its returning an sc_process_b instance. +// +// Revision 1.7 2006/03/14 23:56:58 acg +// Andy Goodrich: This fixes a bug when an exception is thrown in +// sc_module::sc_module() for a dynamically allocated sc_module +// object. We are calling sc_module::end_module() on a module that has +// already been deleted. The scenario runs like this: +// +// a) the sc_module constructor is entered +// b) the exception is thrown +// c) the exception processor deletes the storage for the sc_module +// d) the stack is unrolled causing the sc_module_name instance to be deleted +// e) ~sc_module_name() calls end_module() with its pointer to the sc_module +// f) because the sc_module has been deleted its storage is corrupted, +// either by linking it to a free space chain, or by reuse of some sort +// g) the m_simc field is garbage +// h) the m_object_manager field is also garbage +// i) an exception occurs +// +// This does not happen for automatic sc_module instances since the +// storage for the module is not reclaimed its just part of the stack. +// +// I am fixing this by having the destructor for sc_module clear the +// module pointer in its sc_module_name instance. That cuts things at +// step (e) above, since the pointer will be null if the module has +// already been deleted. To make sure the module stack is okay, I call +// end-module() in ~sc_module in the case where there is an +// sc_module_name pointer lying around. +// +// Revision 1.6 2006/01/26 21:04:54 acg +// Andy Goodrich: deprecation message changes and additional messages. +// +// Revision 1.5 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.4 2006/01/24 20:49:05 acg +// Andy Goodrich: changes to remove the use of deprecated features within the +// simulator, and to issue warning messages when deprecated features are used. +// +// Revision 1.3 2006/01/13 18:44:29 acg +// Added $Log to record CVS changes into the source. +// + +// Taf! diff --git a/ext/systemc/src/sysc/kernel/sc_module.h b/ext/systemc/src/sysc/kernel/sc_module.h new file mode 100644 index 000000000..8a68cb049 --- /dev/null +++ b/ext/systemc/src/sysc/kernel/sc_module.h @@ -0,0 +1,583 @@ +/***************************************************************************** + + 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_module.h -- Base class of all hierarchical modules and channels. + + Original Author: Stan Y. Liao, Synopsys, Inc. + Martin Janssen, Synopsys, Inc. + + CHANGE LOG AT THE END OF THE FILE + *****************************************************************************/ + + +#ifndef SC_MODULE_H +#define SC_MODULE_H + +#include "sysc/kernel/sc_kernel_ids.h" +#include "sysc/kernel/sc_process.h" +#include "sysc/kernel/sc_module_name.h" +#include "sysc/kernel/sc_sensitive.h" +#include "sysc/kernel/sc_time.h" +#include "sysc/kernel/sc_wait.h" +#include "sysc/kernel/sc_wait_cthread.h" +#include "sysc/kernel/sc_process.h" +#include "sysc/kernel/sc_process_handle.h" +#include "sysc/utils/sc_list.h" + +namespace sc_core { + +class sc_name_gen; +template<class T> class sc_in; +template<class T> class sc_inout; +template<class T> class sc_out; + +// ---------------------------------------------------------------------------- +// STRUCT : sc_bind_proxy +// +// Struct for temporarily storing a pointer to an interface or port. +// Used for positional binding. +// ---------------------------------------------------------------------------- + +struct sc_bind_proxy +{ + sc_interface* iface; + sc_port_base* port; + + sc_bind_proxy(); + sc_bind_proxy( sc_interface& ); + sc_bind_proxy( sc_port_base& ); +}; + + +extern const sc_bind_proxy SC_BIND_PROXY_NIL; + + +// ---------------------------------------------------------------------------- +// CLASS : sc_module +// +// Base class for all structural entities. +// ---------------------------------------------------------------------------- + +class sc_module +: public sc_object, public sc_process_host +{ + friend class sc_module_name; + friend class sc_module_registry; + friend class sc_object; + friend class sc_port_registry; + friend class sc_process_b; + friend class sc_simcontext; + +public: + + sc_simcontext* sc_get_curr_simcontext() + { return simcontext(); } + + // to generate unique names for objects in an MT-Safe way + const char* gen_unique_name( const char* basename_, bool preserve_first ); + + virtual const char* kind() const + { return "sc_module"; } + +protected: + + // called by construction_done + virtual void before_end_of_elaboration(); + + void construction_done(); + + // called by elaboration_done (does nothing by default) + virtual void end_of_elaboration(); + + void elaboration_done( bool& ); + + // called by start_simulation (does nothing by default) + virtual void start_of_simulation(); + + void start_simulation(); + + // called by simulation_done (does nothing by default) + virtual void end_of_simulation(); + + void simulation_done(); + + void sc_module_init(); + + // constructor + sc_module(); + sc_module( const sc_module_name& nm ); /* for those used to old style */ + + /* DEPRECATED */ sc_module( const char* nm ); + /* DEPRECATED */ sc_module( const std::string& nm ); + +public: + + // destructor + virtual ~sc_module(); + + // positional binding methods + + sc_module& operator << ( sc_interface& ); + sc_module& operator << ( sc_port_base& ); + + sc_module& operator , ( sc_interface& interface_ ) + { return operator << ( interface_ ); } + + sc_module& operator , ( sc_port_base& port_ ) + { return operator << ( port_ ); } + + // operator() is declared at the end of the class. + + const ::std::vector<sc_object*>& get_child_objects() const; + +protected: + + // this must be called by user-defined modules + void end_module(); + + + // to prevent initialization for SC_METHODs and SC_THREADs + void dont_initialize(); + + // positional binding code - used by operator () + + void positional_bind( sc_interface& ); + void positional_bind( sc_port_base& ); + + // set reset sensitivity for SC_xTHREADs + void async_reset_signal_is( const sc_in<bool>& port, bool level ); + void async_reset_signal_is( const sc_inout<bool>& port, bool level ); + void async_reset_signal_is( const sc_out<bool>& port, bool level ); + void async_reset_signal_is( const sc_signal_in_if<bool>& iface, bool level); + void reset_signal_is( const sc_in<bool>& port, bool level ); + void reset_signal_is( const sc_inout<bool>& port, bool level ); + void reset_signal_is( const sc_out<bool>& port, bool level ); + void reset_signal_is( const sc_signal_in_if<bool>& iface, bool level ); + + // static sensitivity for SC_THREADs and SC_CTHREADs + + void wait() + { ::sc_core::wait( simcontext() ); } + + // dynamic sensitivity for SC_THREADs and SC_CTHREADs + + void wait( const sc_event& e ) + { ::sc_core::wait( e, simcontext() ); } + + void wait( const sc_event_or_list& el ) + { ::sc_core::wait( el, simcontext() ); } + + void wait( const sc_event_and_list& el ) + { ::sc_core::wait( el, simcontext() ); } + + void wait( const sc_time& t ) + { ::sc_core::wait( t, simcontext() ); } + + void wait( double v, sc_time_unit tu ) + { ::sc_core::wait( sc_time( v, tu, simcontext() ), simcontext() ); } + + void wait( const sc_time& t, const sc_event& e ) + { ::sc_core::wait( t, e, simcontext() ); } + + void wait( double v, sc_time_unit tu, const sc_event& e ) + { ::sc_core::wait( + sc_time( v, tu, simcontext() ), e, simcontext() ); } + + void wait( const sc_time& t, const sc_event_or_list& el ) + { ::sc_core::wait( t, el, simcontext() ); } + + void wait( double v, sc_time_unit tu, const sc_event_or_list& el ) + { ::sc_core::wait( sc_time( v, tu, simcontext() ), el, simcontext() ); } + + void wait( const sc_time& t, const sc_event_and_list& el ) + { ::sc_core::wait( t, el, simcontext() ); } + + void wait( double v, sc_time_unit tu, const sc_event_and_list& el ) + { ::sc_core::wait( sc_time( v, tu, simcontext() ), el, simcontext() ); } + + + // static sensitivity for SC_METHODs + + void next_trigger() + { ::sc_core::next_trigger( simcontext() ); } + + + // dynamic sensitivty for SC_METHODs + + void next_trigger( const sc_event& e ) + { ::sc_core::next_trigger( e, simcontext() ); } + + void next_trigger( const sc_event_or_list& el ) + { ::sc_core::next_trigger( el, simcontext() ); } + + void next_trigger( const sc_event_and_list& el ) + { ::sc_core::next_trigger( el, simcontext() ); } + + void next_trigger( const sc_time& t ) + { ::sc_core::next_trigger( t, simcontext() ); } + + void next_trigger( double v, sc_time_unit tu ) + { ::sc_core::next_trigger( + sc_time( v, tu, simcontext() ), simcontext() ); } + + void next_trigger( const sc_time& t, const sc_event& e ) + { ::sc_core::next_trigger( t, e, simcontext() ); } + + void next_trigger( double v, sc_time_unit tu, const sc_event& e ) + { ::sc_core::next_trigger( + sc_time( v, tu, simcontext() ), e, simcontext() ); } + + void next_trigger( const sc_time& t, const sc_event_or_list& el ) + { ::sc_core::next_trigger( t, el, simcontext() ); } + + void next_trigger( double v, sc_time_unit tu, const sc_event_or_list& el ) + { ::sc_core::next_trigger( + sc_time( v, tu, simcontext() ), el, simcontext() ); } + + void next_trigger( const sc_time& t, const sc_event_and_list& el ) + { ::sc_core::next_trigger( t, el, simcontext() ); } + + void next_trigger( double v, sc_time_unit tu, const sc_event_and_list& el ) + { ::sc_core::next_trigger( + sc_time( v, tu, simcontext() ), el, simcontext() ); } + + + // for SC_METHODs and SC_THREADs and SC_CTHREADs + + bool timed_out() + { return ::sc_core::timed_out(); } + + + // for SC_CTHREADs + + void halt() + { ::sc_core::halt( simcontext() ); } + + void wait( int n ) + { ::sc_core::wait( n, simcontext() ); } + + void at_posedge( const sc_signal_in_if<bool>& s ) + { ::sc_core::at_posedge( s, simcontext() ); } + + void at_posedge( const sc_signal_in_if<sc_dt::sc_logic>& s ) + { ::sc_core::at_posedge( s, simcontext() ); } + + void at_negedge( const sc_signal_in_if<bool>& s ) + { ::sc_core::at_negedge( s, simcontext() ); } + + void at_negedge( const sc_signal_in_if<sc_dt::sc_logic>& s ) + { ::sc_core::at_negedge( s, simcontext() ); } + + // Catch uses of watching: + void watching( bool /* expr */ ) + { SC_REPORT_ERROR(SC_ID_WATCHING_NOT_ALLOWED_,""); } + + // These are protected so that user derived classes can refer to them. + sc_sensitive sensitive; + sc_sensitive_pos sensitive_pos; + sc_sensitive_neg sensitive_neg; + + // Function to set the stack size of the current (c)thread process. + void set_stack_size( std::size_t ); + + int append_port( sc_port_base* ); + +private: + sc_module( const sc_module& ); + const sc_module& operator = ( const sc_module& ); + +private: + + bool m_end_module_called; + std::vector<sc_port_base*>* m_port_vec; + int m_port_index; + sc_name_gen* m_name_gen; + sc_module_name* m_module_name_p; + +public: + + void defunct() { } + + // positional binding methods (cont'd) + + void operator () ( const sc_bind_proxy& p001, + const sc_bind_proxy& p002 = SC_BIND_PROXY_NIL, + const sc_bind_proxy& p003 = SC_BIND_PROXY_NIL, + const sc_bind_proxy& p004 = SC_BIND_PROXY_NIL, + const sc_bind_proxy& p005 = SC_BIND_PROXY_NIL, + const sc_bind_proxy& p006 = SC_BIND_PROXY_NIL, + const sc_bind_proxy& p007 = SC_BIND_PROXY_NIL, + const sc_bind_proxy& p008 = SC_BIND_PROXY_NIL, + const sc_bind_proxy& p009 = SC_BIND_PROXY_NIL, + const sc_bind_proxy& p010 = SC_BIND_PROXY_NIL, + const sc_bind_proxy& p011 = SC_BIND_PROXY_NIL, + const sc_bind_proxy& p012 = SC_BIND_PROXY_NIL, + const sc_bind_proxy& p013 = SC_BIND_PROXY_NIL, + const sc_bind_proxy& p014 = SC_BIND_PROXY_NIL, + const sc_bind_proxy& p015 = SC_BIND_PROXY_NIL, + const sc_bind_proxy& p016 = SC_BIND_PROXY_NIL, + const sc_bind_proxy& p017 = SC_BIND_PROXY_NIL, + const sc_bind_proxy& p018 = SC_BIND_PROXY_NIL, + const sc_bind_proxy& p019 = SC_BIND_PROXY_NIL, + const sc_bind_proxy& p020 = SC_BIND_PROXY_NIL, + const sc_bind_proxy& p021 = SC_BIND_PROXY_NIL, + const sc_bind_proxy& p022 = SC_BIND_PROXY_NIL, + const sc_bind_proxy& p023 = SC_BIND_PROXY_NIL, + const sc_bind_proxy& p024 = SC_BIND_PROXY_NIL, + const sc_bind_proxy& p025 = SC_BIND_PROXY_NIL, + const sc_bind_proxy& p026 = SC_BIND_PROXY_NIL, + const sc_bind_proxy& p027 = SC_BIND_PROXY_NIL, + const sc_bind_proxy& p028 = SC_BIND_PROXY_NIL, + const sc_bind_proxy& p029 = SC_BIND_PROXY_NIL, + const sc_bind_proxy& p030 = SC_BIND_PROXY_NIL, + const sc_bind_proxy& p031 = SC_BIND_PROXY_NIL, + const sc_bind_proxy& p032 = SC_BIND_PROXY_NIL, + const sc_bind_proxy& p033 = SC_BIND_PROXY_NIL, + const sc_bind_proxy& p034 = SC_BIND_PROXY_NIL, + const sc_bind_proxy& p035 = SC_BIND_PROXY_NIL, + const sc_bind_proxy& p036 = SC_BIND_PROXY_NIL, + const sc_bind_proxy& p037 = SC_BIND_PROXY_NIL, + const sc_bind_proxy& p038 = SC_BIND_PROXY_NIL, + const sc_bind_proxy& p039 = SC_BIND_PROXY_NIL, + const sc_bind_proxy& p040 = SC_BIND_PROXY_NIL, + const sc_bind_proxy& p041 = SC_BIND_PROXY_NIL, + const sc_bind_proxy& p042 = SC_BIND_PROXY_NIL, + const sc_bind_proxy& p043 = SC_BIND_PROXY_NIL, + const sc_bind_proxy& p044 = SC_BIND_PROXY_NIL, + const sc_bind_proxy& p045 = SC_BIND_PROXY_NIL, + const sc_bind_proxy& p046 = SC_BIND_PROXY_NIL, + const sc_bind_proxy& p047 = SC_BIND_PROXY_NIL, + const sc_bind_proxy& p048 = SC_BIND_PROXY_NIL, + const sc_bind_proxy& p049 = SC_BIND_PROXY_NIL, + const sc_bind_proxy& p050 = SC_BIND_PROXY_NIL, + const sc_bind_proxy& p051 = SC_BIND_PROXY_NIL, + const sc_bind_proxy& p052 = SC_BIND_PROXY_NIL, + const sc_bind_proxy& p053 = SC_BIND_PROXY_NIL, + const sc_bind_proxy& p054 = SC_BIND_PROXY_NIL, + const sc_bind_proxy& p055 = SC_BIND_PROXY_NIL, + const sc_bind_proxy& p056 = SC_BIND_PROXY_NIL, + const sc_bind_proxy& p057 = SC_BIND_PROXY_NIL, + const sc_bind_proxy& p058 = SC_BIND_PROXY_NIL, + const sc_bind_proxy& p059 = SC_BIND_PROXY_NIL, + const sc_bind_proxy& p060 = SC_BIND_PROXY_NIL, + const sc_bind_proxy& p061 = SC_BIND_PROXY_NIL, + const sc_bind_proxy& p062 = SC_BIND_PROXY_NIL, + const sc_bind_proxy& p063 = SC_BIND_PROXY_NIL, + const sc_bind_proxy& p064 = SC_BIND_PROXY_NIL ); + +}; + +extern sc_module* sc_module_dynalloc(sc_module*); +#define SC_NEW(x) ::sc_core::sc_module_dynalloc(new x); + + +// ----------------------------------------------------------------------------- +// SOME MACROS TO SIMPLIFY SYNTAX: +// ----------------------------------------------------------------------------- + +#define SC_MODULE(user_module_name) \ + struct user_module_name : ::sc_core::sc_module + +#define SC_CTOR(user_module_name) \ + typedef user_module_name SC_CURRENT_USER_MODULE; \ + user_module_name( ::sc_core::sc_module_name ) + +// the SC_HAS_PROCESS macro call must be followed by a ; +#define SC_HAS_PROCESS(user_module_name) \ + typedef user_module_name SC_CURRENT_USER_MODULE + +// The this-> construct on sensitive operators in the macros below is +// required for gcc 4.x when a templated class has a templated parent that is +// derived from sc_module: +// +// template<typename X> +// class B : public sc_module; +// template<typename X> +// class A : public B<X> + +#define declare_method_process(handle, name, host_tag, func) \ + { \ + ::sc_core::sc_process_handle handle = \ + sc_core::sc_get_curr_simcontext()->create_method_process( \ + name, false, SC_MAKE_FUNC_PTR( host_tag, func ), \ + this, 0 ); \ + this->sensitive << handle; \ + this->sensitive_pos << handle; \ + this->sensitive_neg << handle; \ + } + +#define declare_thread_process(handle, name, host_tag, func) \ + { \ + ::sc_core::sc_process_handle handle = \ + sc_core::sc_get_curr_simcontext()->create_thread_process( \ + name, false, \ + SC_MAKE_FUNC_PTR( host_tag, func ), this, 0 ); \ + this->sensitive << handle; \ + this->sensitive_pos << handle; \ + this->sensitive_neg << handle; \ + } + +#define declare_cthread_process(handle, name, host_tag, func, edge) \ + { \ + ::sc_core::sc_process_handle handle = \ + sc_core::sc_get_curr_simcontext()->create_cthread_process( \ + name, false, \ + SC_MAKE_FUNC_PTR( host_tag, func ), this, 0 ); \ + this->sensitive.operator() ( handle, edge );\ + } + +#define SC_CTHREAD(func, edge) \ + declare_cthread_process( func ## _handle, \ + #func, \ + SC_CURRENT_USER_MODULE, \ + func, \ + edge ) + +#define SC_METHOD(func) \ + declare_method_process( func ## _handle, \ + #func, \ + SC_CURRENT_USER_MODULE, \ + func ) + +#define SC_THREAD(func) \ + declare_thread_process( func ## _handle, \ + #func, \ + SC_CURRENT_USER_MODULE, \ + func ) + + + +// ---------------------------------------------------------------------------- +// TYPEDEFS +// ---------------------------------------------------------------------------- + +typedef sc_module sc_channel; +typedef sc_module sc_behavior; + +} // namespace sc_core + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affiliation, date and + changes you are making here. + + Name, Affiliation, Date: Ali Dasdan, Synopsys, Inc. + Description of Modification: - Implementation of operator() and operator, + positional connection method. + - Implementation of error checking in + operator<<'s. + - Implementation of the function test_module_prm. + - Implementation of set_stack_size(). + + Name, Affiliation, Date: Gene Bushuyev, Synopsys, Inc. + Description of Modification: - Change implementation for VC6. + + Name, Affiliation, Date: Andy Godorich, Forte + Bishnupriya Bhattacharya, Cadence Design Systems, + 25 August, 2003 + Description of Modification: inherit from sc_process_host as a part of + implementing dynamic processes + + *****************************************************************************/ + +// $Log: sc_module.h,v $ +// Revision 1.11 2011/08/26 20:46:10 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.10 2011/08/15 16:43:24 acg +// Torsten Maehne: changes to remove unused argument warnings. +// +// Revision 1.9 2011/03/05 19:44:20 acg +// Andy Goodrich: changes for object and event naming and structures. +// +// Revision 1.8 2011/02/18 20:27:14 acg +// Andy Goodrich: Updated Copyrights. +// +// Revision 1.7 2011/02/13 21:47:37 acg +// Andy Goodrich: update copyright notice. +// +// Revision 1.6 2011/01/18 20:10:44 acg +// Andy Goodrich: changes for IEEE1666_2011 semantics. +// +// Revision 1.5 2010/12/07 20:09:12 acg +// Andy Goodrich: remove unused signal declaration +// +// Revision 1.4 2009/05/22 16:06:29 acg +// Andy Goodrich: process control updates. +// +// Revision 1.3 2008/05/22 17:06:25 acg +// Andy Goodrich: updated copyright notice to include 2008. +// +// Revision 1.2 2007/01/24 20:14:40 acg +// Andy Goodrich: improved comments about the use of this-> in the macros +// that access sensitive. +// +// Revision 1.1.1.1 2006/12/15 20:20:05 acg +// SystemC 2.3 +// +// Revision 1.10 2006/12/02 20:58:18 acg +// Andy Goodrich: updates from 2.2 for IEEE 1666 support. +// +// Revision 1.7 2006/04/11 23:13:21 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/03/15 17:53:34 acg +// Andy Goodrich, Forte Design +// Reordered includes to pick up <cassert> for use by sc_process_name.h +// +// Revision 1.5 2006/03/14 23:56:58 acg +// Andy Goodrich: This fixes a bug when an exception is thrown in +// sc_module::sc_module() for a dynamically allocated sc_module +// object. We are calling sc_module::end_module() on a module that has +// already been deleted. The scenario runs like this: +// +// a) the sc_module constructor is entered +// b) the exception is thrown +// c) the exception processor deletes the storage for the sc_module +// d) the stack is unrolled causing the sc_module_name instance to be deleted +// e) ~sc_module_name() calls end_module() with its pointer to the sc_module +// f) because the sc_module has been deleted its storage is corrupted, +// either by linking it to a free space chain, or by reuse of some sort +// g) the m_simc field is garbage +// h) the m_object_manager field is also garbage +// i) an exception occurs +// +// This does not happen for automatic sc_module instances since the +// storage for the module is not reclaimed its just part of the stack. +// +// I am fixing this by having the destructor for sc_module clear the +// module pointer in its sc_module_name instance. That cuts things at +// step (e) above, since the pointer will be null if the module has +// already been deleted. To make sure the module stack is okay, I call +// end-module() in ~sc_module in the case where there is an +// sc_module_name pointer lying around. +// +// Revision 1.4 2006/01/24 20:49:05 acg +// Andy Goodrich: changes to remove the use of deprecated features within the +// simulator, and to issue warning messages when deprecated features are used. +// +// Revision 1.3 2006/01/13 18:44:30 acg +// Added $Log to record CVS changes into the source. + +#endif diff --git a/ext/systemc/src/sysc/kernel/sc_module_name.cpp b/ext/systemc/src/sysc/kernel/sc_module_name.cpp new file mode 100644 index 000000000..a5352690f --- /dev/null +++ b/ext/systemc/src/sysc/kernel/sc_module_name.cpp @@ -0,0 +1,123 @@ +/***************************************************************************** + + 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_module_name.cpp -- An object used to help manage object names + and hierarchy + + Original Author: Stan Y. Liao, Synopsys, Inc. + + CHANGE LOG AT THE END OF THE FILE + *****************************************************************************/ + +#include <cstdlib> + +#include "sysc/kernel/sc_kernel_ids.h" +#include "sysc/kernel/sc_module.h" +#include "sysc/kernel/sc_module_name.h" +#include "sysc/kernel/sc_object_manager.h" +#include "sysc/kernel/sc_simcontext.h" +#include "sysc/utils/sc_iostream.h" + +namespace sc_core { + +sc_module_name::sc_module_name( const char* name_ ) +: m_name( name_ ), + m_module_p( 0 ), + m_next( 0 ), + m_simc( sc_get_curr_simcontext() ), + m_pushed( true ) +{ + m_simc->get_object_manager()->push_module_name( this ); +} + +sc_module_name::sc_module_name( const sc_module_name& name_ ) +: m_name( name_.m_name ), + m_module_p( 0 ), + m_next( 0 ), + m_simc( name_.m_simc ), + m_pushed( false ) +{} + +sc_module_name::~sc_module_name() +{ + if( m_pushed ) { + sc_module_name* smn = m_simc->get_object_manager()->pop_module_name(); + if( this != smn ) { + SC_REPORT_ERROR( SC_ID_SC_MODULE_NAME_USE_, 0 ); + } + if ( m_module_p ) m_module_p->end_module(); + } +} + +sc_module_name::operator const char*() const +{ + return m_name; +} + +} // namespace sc_core + +// $Log: sc_module_name.cpp,v $ +// Revision 1.5 2011/08/26 20:46:10 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.4 2011/02/18 20:27:14 acg +// Andy Goodrich: Updated Copyrights. +// +// Revision 1.3 2011/02/13 21:47:37 acg +// Andy Goodrich: update copyright notice. +// +// 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/03/14 23:56:58 acg +// Andy Goodrich: This fixes a bug when an exception is thrown in +// sc_module::sc_module() for a dynamically allocated sc_module +// object. We are calling sc_module::end_module() on a module that has +// already been deleted. The scenario runs like this: +// +// a) the sc_module constructor is entered +// b) the exception is thrown +// c) the exception processor deletes the storage for the sc_module +// d) the stack is unrolled causing the sc_module_name instance to be deleted +// e) ~sc_module_name() calls end_module() with its pointer to the sc_module +// f) because the sc_module has been deleted its storage is corrupted, +// either by linking it to a free space chain, or by reuse of some sort +// g) the m_simc field is garbage +// h) the m_object_manager field is also garbage +// i) an exception occurs +// +// This does not happen for automatic sc_module instances since the +// storage for the module is not reclaimed its just part of the stack. +// +// I am fixing this by having the destructor for sc_module clear the +// module pointer in its sc_module_name instance. That cuts things at +// step (e) above, since the pointer will be null if the module has +// already been deleted. To make sure the module stack is okay, I call +// end-module() in ~sc_module in the case where there is an +// sc_module_name pointer lying around. +// +// Revision 1.3 2006/01/13 18:44:30 acg +// Added $Log to record CVS changes into the source. +// diff --git a/ext/systemc/src/sysc/kernel/sc_module_name.h b/ext/systemc/src/sysc/kernel/sc_module_name.h new file mode 100644 index 000000000..a2149cc6a --- /dev/null +++ b/ext/systemc/src/sysc/kernel/sc_module_name.h @@ -0,0 +1,140 @@ +/***************************************************************************** + + 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_module_name.h -- An object used to help manage object names + and hierarchy. + + Original Author: Stan Y. Liao, Synopsys, Inc. + + CHANGE LOG AT THE END OF THE FILE + *****************************************************************************/ + +// $Log: sc_module_name.h,v $ +// Revision 1.5 2011/08/26 20:46:10 acg +// Andy Goodrich: moved the modification log to the end of the file to +// eliminate source line number skew when check-ins are done. +// + +#ifndef SC_MODULE_NAME_H +#define SC_MODULE_NAME_H + + +namespace sc_core { + +class sc_module; +class sc_simcontext; + + +// ---------------------------------------------------------------------------- +// CLASS : sc_module_name +// +// Module name class. +// ---------------------------------------------------------------------------- + +class sc_module_name +{ + friend class sc_module; + friend class sc_object_manager; + +public: + + sc_module_name( const char* ); + sc_module_name( const sc_module_name& ); + + ~sc_module_name(); + + operator const char*() const; + +protected: + inline void clear_module( sc_module* module_p ); + inline void set_module( sc_module* module_p ); + +private: + + const char* m_name; + sc_module* m_module_p; + sc_module_name* m_next; + sc_simcontext* m_simc; + bool m_pushed; + +private: + + // disabled + sc_module_name(); + sc_module_name& operator = ( const sc_module_name& ); +}; + +inline void sc_module_name::clear_module( sc_module* module_p ) +{ + assert( m_module_p == module_p ); + m_module_p = 0; +} + +inline void sc_module_name::set_module( sc_module* module_p ) +{ + m_module_p = module_p; +} + +} // namespace sc_core + +// Revision 1.4 2011/02/18 20:27:14 acg +// Andy Goodrich: Updated Copyrights. +// +// Revision 1.3 2011/02/13 21:47:37 acg +// Andy Goodrich: update copyright notice. +// +// 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/03/14 23:56:58 acg +// Andy Goodrich: This fixes a bug when an exception is thrown in +// sc_module::sc_module() for a dynamically allocated sc_module +// object. We are calling sc_module::end_module() on a module that has +// already been deleted. The scenario runs like this: +// +// a) the sc_module constructor is entered +// b) the exception is thrown +// c) the exception processor deletes the storage for the sc_module +// d) the stack is unrolled causing the sc_module_name instance to be deleted +// e) ~sc_module_name() calls end_module() with its pointer to the sc_module +// f) because the sc_module has been deleted its storage is corrupted, +// either by linking it to a free space chain, or by reuse of some sort +// g) the m_simc field is garbage +// h) the m_object_manager field is also garbage +// i) an exception occurs +// +// This does not happen for automatic sc_module instances since the +// storage for the module is not reclaimed its just part of the stack. +// +// I am fixing this by having the destructor for sc_module clear the +// module pointer in its sc_module_name instance. That cuts things at +// step (e) above, since the pointer will be null if the module has +// already been deleted. To make sure the module stack is okay, I call +// end-module() in ~sc_module in the case where there is an +// sc_module_name pointer lying around. +// +// Revision 1.3 2006/01/13 18:44:30 acg +// Added $Log to record CVS changes into the source. + +#endif diff --git a/ext/systemc/src/sysc/kernel/sc_module_registry.cpp b/ext/systemc/src/sysc/kernel/sc_module_registry.cpp new file mode 100644 index 000000000..2d8b02c34 --- /dev/null +++ b/ext/systemc/src/sysc/kernel/sc_module_registry.cpp @@ -0,0 +1,184 @@ +/***************************************************************************** + + 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_module_registry.cpp -- Registry for all modules. + FOR INTERNAL USE ONLY. + + Original Author: Martin Janssen, Synopsys, Inc., 2001-05-21 + + CHANGE LOG AT THE END OF THE FILE + *****************************************************************************/ + + +#include "sysc/kernel/sc_kernel_ids.h" +#include "sysc/kernel/sc_module.h" +#include "sysc/kernel/sc_module_registry.h" +#include "sysc/kernel/sc_simcontext.h" + +namespace sc_core { + +// ---------------------------------------------------------------------------- +// CLASS : sc_module_registry +// +// Registry for all modules. +// FOR INTERNAL USE ONLY! +// ---------------------------------------------------------------------------- + +void +sc_module_registry::insert( sc_module& module_ ) +{ + if( sc_is_running() ) { + SC_REPORT_ERROR( SC_ID_INSERT_MODULE_, "simulation running" ); + } + + if( m_simc->elaboration_done() ) { + SC_REPORT_ERROR( SC_ID_INSERT_MODULE_, "elaboration done" ); + } + +#ifdef DEBUG_SYSTEMC + // check if module_ is already inserted + for( int i = size() - 1; i >= 0; -- i ) { + if( &module_ == m_module_vec[i] ) { + SC_REPORT_ERROR( SC_ID_INSERT_MODULE_, "already inserted" ); + } + } +#endif + + // insert + m_module_vec.push_back( &module_ ); +} + +void +sc_module_registry::remove( sc_module& module_ ) +{ + int i; + for( i = 0; i < size(); ++ i ) { + if( &module_ == m_module_vec[i] ) { + break; + } + } + if( i == size() ) { + SC_REPORT_ERROR( SC_ID_REMOVE_MODULE_, 0 ); + } + + // remove + m_module_vec[i] = m_module_vec[size() - 1]; + m_module_vec.resize(m_module_vec.size()-1); +} + + +// constructor + +sc_module_registry::sc_module_registry( sc_simcontext& simc_ ) + : m_construction_done(0), m_module_vec(), m_simc( &simc_ ) +{} + + +// destructor + +sc_module_registry::~sc_module_registry() +{} + +// called when construction is done + +bool +sc_module_registry::construction_done() +{ + if( size() == m_construction_done ) + // nothing has been updated + return true; + + for( ; m_construction_done < size(); ++m_construction_done ) { + m_module_vec[m_construction_done]->construction_done(); + } + return false; +} + +// called when elaboration is done + +void +sc_module_registry::elaboration_done() +{ + bool error = false; + for( int i = 0; i < size(); ++ i ) { + m_module_vec[i]->elaboration_done( error ); + } +} + +// called before simulation begins + +void +sc_module_registry::start_simulation() +{ + for( int i = 0; i < size(); ++ i ) { + m_module_vec[i]->start_simulation(); + } +} + +// called after simulation ends + +void +sc_module_registry::simulation_done() +{ + for( int i = 0; i < size(); ++ i ) { + m_module_vec[i]->simulation_done(); + } +} + +} // namespace sc_core + +// $Log: sc_module_registry.cpp,v $ +// Revision 1.8 2011/08/26 20:46:10 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.7 2011/08/24 22:05:51 acg +// Torsten Maehne: initialization changes to remove warnings. +// +// Revision 1.6 2011/05/09 04:07:49 acg +// Philipp A. Hartmann: +// (1) Restore hierarchy in all phase callbacks. +// (2) Ensure calls to before_end_of_elaboration. +// +// Revision 1.5 2011/02/18 20:27:14 acg +// Andy Goodrich: Updated Copyrights. +// +// Revision 1.4 2011/02/14 17:51:40 acg +// Andy Goodrich: proper pushing an poppping of the module hierarchy for +// start_of_simulation() and end_of_simulation. +// +// Revision 1.3 2011/02/13 21:47:37 acg +// Andy Goodrich: update copyright notice. +// +// 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/01/26 21:04:54 acg +// Andy Goodrich: deprecation message changes and additional messages. +// +// Revision 1.3 2006/01/13 18:44:30 acg +// Added $Log to record CVS changes into the source. +// + +// Taf! diff --git a/ext/systemc/src/sysc/kernel/sc_module_registry.h b/ext/systemc/src/sysc/kernel/sc_module_registry.h new file mode 100644 index 000000000..3e1bb5dff --- /dev/null +++ b/ext/systemc/src/sysc/kernel/sc_module_registry.h @@ -0,0 +1,124 @@ +/***************************************************************************** + + 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_module_registry.h -- Registry for all modules. + FOR INTERNAL USE ONLY. + + Original Author: Martin Janssen, Synopsys, Inc., 2001-05-21 + + CHANGE LOG AT THE END OF THE FILE + *****************************************************************************/ + + +#ifndef SC_MODULE_REGISTRY_H +#define SC_MODULE_REGISTRY_H + + +namespace sc_core { + +class sc_module; +class sc_simcontext; + + +// ---------------------------------------------------------------------------- +// CLASS : sc_module_registry +// +// Registry for all modules. +// FOR INTERNAL USE ONLY! +// ---------------------------------------------------------------------------- + +class sc_module_registry +{ + friend class sc_simcontext; + +public: + + void insert( sc_module& ); + void remove( sc_module& ); + + int size() const + { return m_module_vec.size(); } + +private: + + // constructor + explicit sc_module_registry( sc_simcontext& simc_ ); + + // destructor + ~sc_module_registry(); + + // called when construction is done + bool construction_done(); + + // called when elaboration is done + void elaboration_done(); + + // called before simulation begins + void start_simulation(); + + // called after simulation ends + void simulation_done(); + + +private: + + int m_construction_done; + std::vector<sc_module*> m_module_vec; + sc_simcontext* m_simc; + +private: + + // disabled + sc_module_registry(); + sc_module_registry( const sc_module_registry& ); + sc_module_registry& operator = ( const sc_module_registry& ); +}; + +} // namespace sc_core + +#endif + +// $Log: sc_module_registry.h,v $ +// Revision 1.6 2011/08/26 20:46:10 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.5 2011/05/09 04:07:49 acg +// Philipp A. Hartmann: +// (1) Restore hierarchy in all phase callbacks. +// (2) Ensure calls to before_end_of_elaboration. +// +// Revision 1.4 2011/02/18 20:27:14 acg +// Andy Goodrich: Updated Copyrights. +// +// Revision 1.3 2011/02/13 21:47:37 acg +// Andy Goodrich: update copyright notice. +// +// 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.3 2006/01/13 18:44:30 acg +// Added $Log to record CVS changes into the source. + +// Taf! diff --git a/ext/systemc/src/sysc/kernel/sc_name_gen.cpp b/ext/systemc/src/sysc/kernel/sc_name_gen.cpp new file mode 100644 index 000000000..16f6ad78f --- /dev/null +++ b/ext/systemc/src/sysc/kernel/sc_name_gen.cpp @@ -0,0 +1,109 @@ +/***************************************************************************** + + 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_name_gen.cpp -- Unique name generator. + + Original Author: Martin Janssen, Synopsys, Inc., 2001-05-21 + + CHANGE LOG AT THE END OF THE FILE + *****************************************************************************/ + + +#include "sysc/kernel/sc_kernel_ids.h" +#include "sysc/kernel/sc_name_gen.h" +#include "sysc/utils/sc_iostream.h" + +#if defined(_MSC_VER) && _MSC_VER >= 1310 +// "C4351: new behavior: elements of array will be default initialized" +#pragma warning(disable: 4351) +#endif + +namespace sc_core { + +// ---------------------------------------------------------------------------- +// CLASS : sc_name_gen +// +// Unique name generator class. +// ---------------------------------------------------------------------------- + +sc_name_gen::sc_name_gen() : m_unique_name_map(), m_unique_name() +{} + +sc_name_gen::~sc_name_gen() +{ + sc_strhash<int*>::iterator it( m_unique_name_map ); + for( ; ! it.empty(); it ++ ) { + delete it.contents(); + } + m_unique_name_map.erase(); +} + + +// to generate unique names for objects in an MT-Safe way + +const char* +sc_name_gen::gen_unique_name( const char* basename_, bool preserve_first ) +{ + if( basename_ == 0 ) { + SC_REPORT_ERROR( SC_ID_GEN_UNIQUE_NAME_, 0 ); + } + int* c = m_unique_name_map[basename_]; + if( c == 0 ) { + c = new int( 0 ); + m_unique_name_map.insert( CCAST<char*>( basename_ ), c ); + if (preserve_first) { + std::sprintf( m_unique_name, "%s", basename_ ); + } else { + std::sprintf( m_unique_name, "%s_%d", basename_, *c ); + } + } else { + std::sprintf( m_unique_name, "%s_%d", basename_, ++ (*c) ); + } + return m_unique_name; +} + +} // namespace sc_core + +// $Log: sc_name_gen.cpp,v $ +// Revision 1.6 2011/08/26 20:46:10 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.5 2011/08/24 22:05:51 acg +// Torsten Maehne: initialization changes to remove warnings. +// +// Revision 1.4 2011/02/18 20:27:14 acg +// Andy Goodrich: Updated Copyrights. +// +// Revision 1.3 2011/02/13 21:47:37 acg +// Andy Goodrich: update copyright notice. +// +// 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.3 2006/01/13 18:44:30 acg +// Added $Log to record CVS changes into the source. +// + +// Taf! diff --git a/ext/systemc/src/sysc/kernel/sc_name_gen.h b/ext/systemc/src/sysc/kernel/sc_name_gen.h new file mode 100644 index 000000000..0910e014a --- /dev/null +++ b/ext/systemc/src/sysc/kernel/sc_name_gen.h @@ -0,0 +1,93 @@ +/***************************************************************************** + + 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_name_gen.h -- Unique name generator. + + Original Author: Martin Janssen, Synopsys, Inc., 2001-05-21 + + CHANGE LOG AT THE END OF THE FILE + *****************************************************************************/ + + +#ifndef SC_NAME_GEN +#define SC_NAME_GEN + + +#include <cstdio> + +#include "sysc/utils/sc_hash.h" + +namespace sc_core{ + +// ---------------------------------------------------------------------------- +// CLASS : sc_name_gen +// +// Unique name generator class. +// ---------------------------------------------------------------------------- + +class sc_name_gen +{ +public: + + sc_name_gen(); + ~sc_name_gen(); + + const char* gen_unique_name( const char* basename_, + bool preserve_first = false + ); + +private: + + sc_strhash<int*> m_unique_name_map; + char m_unique_name[BUFSIZ]; + +private: + + // disabled + sc_name_gen( const sc_name_gen& ); + sc_name_gen& operator = ( const sc_name_gen& ); +}; + +} // namespace sc_core + +// $Log: sc_name_gen.h,v $ +// Revision 1.5 2011/08/26 20:46:10 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.4 2011/02/18 20:27:14 acg +// Andy Goodrich: Updated Copyrights. +// +// Revision 1.3 2011/02/13 21:47:37 acg +// Andy Goodrich: update copyright notice. +// +// 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.3 2006/01/13 18:44:30 acg +// Added $Log to record CVS changes into the source. + +#endif + +// Taf! diff --git a/ext/systemc/src/sysc/kernel/sc_object.cpp b/ext/systemc/src/sysc/kernel/sc_object.cpp new file mode 100644 index 000000000..e624d12b5 --- /dev/null +++ b/ext/systemc/src/sysc/kernel/sc_object.cpp @@ -0,0 +1,568 @@ +/***************************************************************************** + + 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_object.cpp -- Abstract base class of all SystemC objects. + + Original Author: Stan Y. Liao, Synopsys, Inc. + + CHANGE LOG AT THE END OF THE FILE + *****************************************************************************/ + + +#include <cstdlib> +#include <cassert> +#include <stddef.h> +#include <cstdio> +#include <string.h> +#include <ctype.h> + +#include "sysc/kernel/sc_externs.h" +#include "sysc/kernel/sc_kernel_ids.h" +#include "sysc/kernel/sc_module.h" +#include "sysc/kernel/sc_object.h" +#include "sysc/kernel/sc_object_manager.h" +#include "sysc/kernel/sc_phase_callback_registry.h" +#include "sysc/kernel/sc_process_handle.h" +#include "sysc/kernel/sc_simcontext.h" +#include "sysc/kernel/sc_event.h" +#include "sysc/utils/sc_hash.h" +#include "sysc/utils/sc_iostream.h" +#include "sysc/utils/sc_list.h" +#include "sysc/utils/sc_utils_ids.h" +#include "sysc/utils/sc_mempool.h" + +namespace sc_core { + +typedef int (*STRCMP)(const void*, const void*); + +const char SC_HIERARCHY_CHAR = '.'; + +/* This will be gotten rid after multiple-processes + are implemented. This is to fix some regression + problems. */ +bool sc_enable_name_checking = true; + + +// ---------------------------------------------------------------------------- +// CLASS : sc_object +// +// Abstract base class of all SystemC `simulation' objects. +// ---------------------------------------------------------------------------- + +void +sc_object::add_child_event( sc_event* event_p ) +{ + // no check if event_p is already in the set + m_child_events.push_back( event_p ); +} + +void +sc_object::add_child_object( sc_object* object_ ) +{ + // no check if object_ is already in the set + m_child_objects.push_back( object_ ); +} + +const char* +sc_object::basename() const +{ + size_t pos; // position of last SC_HIERARCHY_CHAR. + pos = m_name.rfind( (char)SC_HIERARCHY_CHAR ); + return ( pos == m_name.npos ) ? m_name.c_str() : &(m_name.c_str()[pos+1]); +} + +void +sc_object::print(::std::ostream& os) const +{ + os << name(); +} + +void +sc_object::dump(::std::ostream& os) const +{ + os << "name = " << name() << "\n"; + os << "kind = " << kind() << "\n"; +} + +static int sc_object_num = 0; + +static std::string +sc_object_newname() +{ + char buffer[64]; + std::string result; + + std::sprintf(buffer, "{%d}", sc_object_num); + sc_object_num++; + result = buffer; + + return result; +} + +// +---------------------------------------------------------------------------- +// |"sc_object::remove_child_event" +// | +// | This virtual method removes the supplied event from the list of child +// | events if it is present. +// | +// | Arguments: +// | event_p -> event to be removed. +// | Returns true if the event was present, false if not. +// +---------------------------------------------------------------------------- +bool +sc_object::remove_child_event( sc_event* event_p ) +{ + int size = m_child_events.size(); + for( int i = 0; i < size; ++ i ) { + if( event_p == m_child_events[i] ) { + m_child_events[i] = m_child_events[size - 1]; + m_child_events.pop_back(); + return true; + } + } + return false; +} + +// +---------------------------------------------------------------------------- +// |"sc_object::remove_child_object" +// | +// | This virtual method removes the supplied object from the list of child +// | objects if it is present. +// | +// | Arguments: +// | object_p -> object to be removed. +// | Returns true if the object was present, false if not. +// +---------------------------------------------------------------------------- +bool +sc_object::remove_child_object( sc_object* object_p ) +{ + int size = m_child_objects.size(); + for( int i = 0; i < size; ++ i ) { + if( object_p == m_child_objects[i] ) { + m_child_objects[i] = m_child_objects[size - 1]; + m_child_objects.pop_back(); + object_p->m_parent = NULL; + return true; + } + } + return false; +} + +// +---------------------------------------------------------------------------- +// |"sc_object::sc_object_init" +// | +// | This method initializes this object instance and places it in to the +// | object hierarchy if the supplied name is not NULL. +// | +// | Arguments: +// | nm = leaf name for the object. +// +---------------------------------------------------------------------------- +void +sc_object::sc_object_init(const char* nm) +{ + // SET UP POINTERS TO OBJECT MANAGER, PARENT, AND SIMULATION CONTEXT: + // + // Make the current simcontext the simcontext for this object + + m_simc = sc_get_curr_simcontext(); + m_attr_cltn_p = 0; + sc_object_manager* object_manager = m_simc->get_object_manager(); + m_parent = m_simc->active_object(); + + // CONSTRUCT PATHNAME TO OBJECT BEING CREATED: + // + // If there is not a leaf name generate one. + + m_name = object_manager->create_name(nm ? nm : sc_object_newname().c_str()); + + + // PLACE THE OBJECT INTO THE HIERARCHY + + object_manager->insert_object(m_name, this); + if ( m_parent ) + m_parent->add_child_object( this ); + else + m_simc->add_child_object( this ); +} + +sc_object::sc_object() : + m_attr_cltn_p(0), m_child_events(), m_child_objects(), m_name(), + m_parent(0), m_simc(0) +{ + sc_object_init( sc_gen_unique_name("object") ); +} + +sc_object::sc_object( const sc_object& that ) : + m_attr_cltn_p(0), m_child_events(), m_child_objects(), m_name(), + m_parent(0), m_simc(0) +{ + sc_object_init( sc_gen_unique_name( that.basename() ) ); +} + + +static bool +object_name_illegal_char(char ch) +{ + return (ch == SC_HIERARCHY_CHAR) || isspace(ch); +} + +sc_object::sc_object(const char* nm) : + m_attr_cltn_p(0), m_child_events(), m_child_objects(), m_name(), + m_parent(0), m_simc(0) +{ + int namebuf_alloc = 0; + char* namebuf = 0; + const char* p; + + // null name or "" uses machine generated name. + + if ( !nm || !*nm ) + nm = sc_gen_unique_name("object"); + p = nm; + + if (nm && sc_enable_name_checking) { + namebuf_alloc = 1 + strlen(nm); + namebuf = (char*) sc_mempool::allocate(namebuf_alloc); + char* q = namebuf; + const char* r = nm; + bool has_illegal_char = false; + while (*r) { + if (object_name_illegal_char(*r)) { + has_illegal_char = true; + *q = '_'; + } else { + *q = *r; + } + r++; + q++; + } + *q = '\0'; + p = namebuf; + if (has_illegal_char) + { + std::string message = nm; + message += " substituted by "; + message += namebuf; + SC_REPORT_WARNING( SC_ID_ILLEGAL_CHARACTERS_, message.c_str()); + } + } + sc_object_init(p); + sc_mempool::release( namebuf, namebuf_alloc ); +} + +sc_object::~sc_object() +{ +#if SC_HAS_PHASE_CALLBACKS_ + unregister_simulation_phase_callback( SC_STATUS_ANY ); +#endif + detach(); + delete m_attr_cltn_p; +} + +//------------------------------------------------------------------------------ +//"sc_object::detach" +// +// This method detaches this object instance from the object hierarchy. +// It is called in two places: ~sc_object() and sc_process_b::kill_process(). +//------------------------------------------------------------------------------ +void sc_object::detach() +{ + if (m_simc) { + + // REMOVE OBJECT FROM THE OBJECT MANAGER: + + sc_object_manager* object_manager = m_simc->get_object_manager(); + object_manager->remove_object(m_name); + + // REMOVE OBJECT FROM PARENT'S LIST OF OBJECTS: + + if ( m_parent ) + m_parent->remove_child_object( this ); + else + m_simc->remove_child_object( this ); + + // ORPHAN THIS OBJECT'S CHILDREN: + +#if 0 // #### + ::std::<sc_object*> children_p = &get_child_objects(); + int child_n = children_p->size(); + sc_object* parent_p; + + for ( int child_i = 0; child_i < child_n; child_i++ ) + { + (*children_p)[child_i]->m_parent = 0; + } +#endif + + } +} + +// +---------------------------------------------------------------------------- +// |"sc_object::orphan_child_events" +// | +// | This method moves the children of this object instance to be children +// | of the simulator. +// +---------------------------------------------------------------------------- +void sc_object::orphan_child_events() +{ + std::vector< sc_event* > const & events = get_child_events(); + + std::vector< sc_event* >::const_iterator + it = events.begin(), end = events.end(); + + for( ; it != end; ++it ) + { + (*it)->m_parent_p = NULL; + simcontext()->add_child_event(*it); + } +} + +// +---------------------------------------------------------------------------- +// |"sc_object::orphan_child_objects" +// | +// | This method moves the children of this object instance to be children +// | of the simulator. +// +---------------------------------------------------------------------------- +void sc_object::orphan_child_objects() +{ + std::vector< sc_object* > const & children = get_child_objects(); + + std::vector< sc_object* >::const_iterator + it = children.begin(), end = children.end(); + + for( ; it != end; ++it ) + { + (*it)->m_parent = NULL; + simcontext()->add_child_object(*it); + } +} + +void +sc_object::trace( sc_trace_file * /* unused */) const +{ + /* This space is intentionally left blank */ +} + + +// add attribute + +bool +sc_object::add_attribute( sc_attr_base& attribute_ ) +{ + if ( !m_attr_cltn_p ) m_attr_cltn_p = new sc_attr_cltn; + return ( m_attr_cltn_p->push_back( &attribute_ ) ); +} + + +// get attribute by name + +sc_attr_base* +sc_object::get_attribute( const std::string& name_ ) +{ + if ( !m_attr_cltn_p ) m_attr_cltn_p = new sc_attr_cltn; + return ( (*m_attr_cltn_p)[name_] ); +} + +const sc_attr_base* +sc_object::get_attribute( const std::string& name_ ) const +{ + if ( !m_attr_cltn_p ) m_attr_cltn_p = new sc_attr_cltn; + return ( (*m_attr_cltn_p)[name_] ); +} + + +// remove attribute by name + +sc_attr_base* +sc_object::remove_attribute( const std::string& name_ ) +{ + if ( m_attr_cltn_p ) + return ( m_attr_cltn_p->remove( name_ ) ); + else + return 0; +} + + +// remove all attributes + +void +sc_object::remove_all_attributes() +{ + if ( m_attr_cltn_p ) + m_attr_cltn_p->remove_all(); +} + + +// get the number of attributes + +int +sc_object::num_attributes() const +{ + if ( m_attr_cltn_p ) + return ( m_attr_cltn_p->size() ); + else + return 0; +} + + +// get the attribute collection + +sc_attr_cltn& +sc_object::attr_cltn() +{ + if ( !m_attr_cltn_p ) m_attr_cltn_p = new sc_attr_cltn; + return *m_attr_cltn_p; +} + +const sc_attr_cltn& +sc_object::attr_cltn() const +{ + if ( !m_attr_cltn_p ) m_attr_cltn_p = new sc_attr_cltn; + return *m_attr_cltn_p; +} + +sc_object* +sc_object::get_parent() const +{ + static bool warn_sc_get_parent_deprecated=true; + if ( warn_sc_get_parent_deprecated ) + { + warn_sc_get_parent_deprecated=false; + SC_REPORT_INFO(sc_core::SC_ID_IEEE_1666_DEPRECATION_, + "sc_object::get_parent() is deprecated, " + "use get_parent_object() instead"); + } + return get_parent_object(); +} + +// ---------------------------------------------------------------------------- +// simulation phase callbacks + + +sc_object::phase_cb_mask +sc_object::register_simulation_phase_callback( phase_cb_mask mask ) +{ + mask = simcontext()->m_phase_cb_registry + ->register_callback(*this, mask); + return mask; +} + + +sc_object::phase_cb_mask +sc_object::unregister_simulation_phase_callback( phase_cb_mask mask ) +{ + mask = simcontext()->m_phase_cb_registry + ->unregister_callback(*this, mask); + return mask; +} + + +void +sc_object::simulation_phase_callback() +{ + SC_REPORT_WARNING( SC_ID_PHASE_CALLBACK_NOT_IMPLEMENTED_, name() ); +} + + +} // namespace sc_core + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affiliation, date and + changes you are making here. + + Name, Affiliation, Date: Bishnupriya Bhattacharya, Cadence Design Systems, + 25 August, 2003 + Description of Modification: if module name hierarchy is empty, sc_object + ctor assumes the currently executing process + as the parent object to support dynamic process + creation similar to other sc_objects + + Name, Affiliation, Date: Andy Goodrich, Forte Design Systems + 5 September 2003 + Description of Modification: - Made creation of attributes structure + conditional on its being used. This eliminates + 100 bytes of storage for each normal sc_object. + + *****************************************************************************/ + + +// $Log: sc_object.cpp,v $ +// Revision 1.16 2011/08/29 18:04:32 acg +// Philipp A. Hartmann: miscellaneous clean ups. +// +// Revision 1.15 2011/08/26 20:46:10 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.14 2011/08/24 22:05:51 acg +// Torsten Maehne: initialization changes to remove warnings. +// +// Revision 1.13 2011/04/01 21:24:57 acg +// Andy Goodrich: removed unused code. +// +// Revision 1.12 2011/03/06 15:55:11 acg +// Andy Goodrich: Changes for named events. +// +// Revision 1.11 2011/03/05 19:44:20 acg +// Andy Goodrich: changes for object and event naming and structures. +// +// Revision 1.10 2011/03/05 04:45:16 acg +// Andy Goodrich: moved active process calculation to the sc_simcontext class. +// +// Revision 1.9 2011/03/05 01:39:21 acg +// Andy Goodrich: changes for named events. +// +// Revision 1.8 2011/02/18 20:27:14 acg +// Andy Goodrich: Updated Copyrights. +// +// Revision 1.7 2011/02/13 21:47:37 acg +// Andy Goodrich: update copyright notice. +// +// Revision 1.6 2011/01/25 20:50:37 acg +// Andy Goodrich: changes for IEEE 1666 2011. +// +// Revision 1.5 2011/01/18 20:10:44 acg +// Andy Goodrich: changes for IEEE1666_2011 semantics. +// +// Revision 1.4 2010/08/03 17:02:39 acg +// Andy Goodrich: formatting changes. +// +// 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.5 2006/04/20 17:08:17 acg +// Andy Goodrich: 3.0 style process changes. +// +// Revision 1.4 2006/03/21 00:00:34 acg +// Andy Goodrich: changed name of sc_get_current_process_base() to be +// sc_get_current_process_b() since its returning an sc_process_b instance. +// +// Revision 1.3 2006/01/13 18:44:30 acg +// Added $Log to record CVS changes into the source. +// diff --git a/ext/systemc/src/sysc/kernel/sc_object.h b/ext/systemc/src/sysc/kernel/sc_object.h new file mode 100644 index 000000000..c6e0957a8 --- /dev/null +++ b/ext/systemc/src/sysc/kernel/sc_object.h @@ -0,0 +1,244 @@ +/***************************************************************************** + + 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_object.h -- Abstract base class of all SystemC `simulation' objects. + + Original Author: Stan Y. Liao, Synopsys, Inc. + + CHANGE LOG AT THE END OF THE FILE + *****************************************************************************/ + + +#ifndef SC_OBJECT_H +#define SC_OBJECT_H + + +#include "sysc/utils/sc_iostream.h" +#include "sysc/kernel/sc_attribute.h" + +namespace sc_core { + +class sc_event; +class sc_module; +class sc_phase_callback_registry; +class sc_runnable; +class sc_simcontext; +class sc_trace_file; +class sc_trace_file_base; + +// ---------------------------------------------------------------------------- +// CLASS : sc_object +// +// Abstract base class of all SystemC `simulation' objects. +// ---------------------------------------------------------------------------- + +class sc_object +{ + friend class sc_event; + friend class sc_module; + friend struct sc_invoke_method; + friend class sc_module_dynalloc_list; + friend class sc_object_manager; + friend class sc_phase_callback_registry; + friend class sc_process_b; + friend class sc_runnable; + friend class sc_simcontext; + friend class sc_trace_file_base; + +public: + typedef unsigned phase_cb_mask; + + const char* name() const + { return m_name.c_str(); } + + const char* basename() const; + + virtual void print(::std::ostream& os=::std::cout ) const; + + // dump() is more detailed than print() + virtual void dump(::std::ostream& os=::std::cout ) const; + + virtual void trace( sc_trace_file* tf ) const; + + virtual const char* kind() const { return "sc_object"; } + + sc_simcontext* simcontext() const + { return m_simc; } + + // add attribute + bool add_attribute( sc_attr_base& ); + + // get attribute by name + sc_attr_base* get_attribute( const std::string& name_ ); + const sc_attr_base* get_attribute( const std::string& name_ ) const; + + // remove attribute by name + sc_attr_base* remove_attribute( const std::string& name_ ); + + // remove all attributes + void remove_all_attributes(); + + // get the number of attributes + int num_attributes() const; + + // get the attribute collection + sc_attr_cltn& attr_cltn(); + const sc_attr_cltn& attr_cltn() const; + + virtual const std::vector<sc_event*>& get_child_events() const + { return m_child_events; } + + virtual const std::vector<sc_object*>& get_child_objects() const + { return m_child_objects; } + + sc_object* get_parent() const; + sc_object* get_parent_object() const { return m_parent; } + +protected: + + sc_object(); + sc_object(const char* nm); + + sc_object( const sc_object& ); + sc_object& operator=( const sc_object& ); + + + virtual ~sc_object(); + + virtual void add_child_event( sc_event* event_p ); + virtual void add_child_object( sc_object* object_p ); + virtual bool remove_child_event( sc_event* event_p ); + virtual bool remove_child_object( sc_object* object_p ); + + phase_cb_mask register_simulation_phase_callback( phase_cb_mask ); + phase_cb_mask unregister_simulation_phase_callback( phase_cb_mask ); + + class hierarchy_scope; + +private: + void do_simulation_phase_callback(); + virtual void simulation_phase_callback(); + + void detach(); + virtual void orphan_child_events(); + virtual void orphan_child_objects(); + void sc_object_init(const char* nm); + +private: + + /* Each simulation object is associated with a simulation context */ + mutable sc_attr_cltn* m_attr_cltn_p; // attributes for this object. + std::vector<sc_event*> m_child_events; // list of child events. + std::vector<sc_object*> m_child_objects; // list of child objects. + std::string m_name; // name of this object. + sc_object* m_parent; // parent for this object. + sc_simcontext* m_simc; // simcontext ptr / empty indicator +}; + +inline +sc_object& +sc_object::operator=( sc_object const & ) +{ + // deliberately do nothing + return *this; +} + +// ---------------------------------------------------------------------------- + +extern const char SC_HIERARCHY_CHAR; +extern bool sc_enable_name_checking; + + +inline +sc_object* sc_get_parent( const sc_object* obj_p ) +{ + return obj_p->get_parent_object(); +} + +} // namespace sc_core + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affiliation, date and + changes you are making here. + + Name, Affiliation, Date: Andy Goodrich, Forte Design Systems + 5 September 2003 + Description of Modification: - Made creation of attributes structure + conditional on its being used. This eliminates + 100 bytes of storage for each normal sc_object. + + *****************************************************************************/ + +// $Log: sc_object.h,v $ +// Revision 1.13 2011/08/29 18:04:32 acg +// Philipp A. Hartmann: miscellaneous clean ups. +// +// Revision 1.12 2011/08/26 20:46:10 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.11 2011/03/06 15:55:11 acg +// Andy Goodrich: Changes for named events. +// +// Revision 1.10 2011/03/05 19:44:20 acg +// Andy Goodrich: changes for object and event naming and structures. +// +// Revision 1.9 2011/03/05 01:39:21 acg +// Andy Goodrich: changes for named events. +// +// Revision 1.8 2011/02/18 20:27:14 acg +// Andy Goodrich: Updated Copyrights. +// +// Revision 1.7 2011/02/13 21:47:37 acg +// Andy Goodrich: update copyright notice. +// +// Revision 1.6 2011/01/25 20:50:37 acg +// Andy Goodrich: changes for IEEE 1666 2011. +// +// Revision 1.5 2011/01/18 20:10:44 acg +// Andy Goodrich: changes for IEEE1666_2011 semantics. +// +// 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.5 2006/04/20 17:08:17 acg +// Andy Goodrich: 3.0 style process changes. +// +// Revision 1.4 2006/04/11 23:13:21 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.3 2006/01/13 18:44:30 acg +// Added $Log to record CVS changes into the source. + +#endif // SC_OBJECT_H diff --git a/ext/systemc/src/sysc/kernel/sc_object_int.h b/ext/systemc/src/sysc/kernel/sc_object_int.h new file mode 100644 index 000000000..aca230f8b --- /dev/null +++ b/ext/systemc/src/sysc/kernel/sc_object_int.h @@ -0,0 +1,99 @@ +/***************************************************************************** + + 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_object_int.h -- For inline definitions of some utility functions. + DO NOT EXPORT THIS INCLUDE FILE. + + Original Author: Philipp A. Hartmann, OFFIS, 2013-02-10 + + *****************************************************************************/ + +#ifndef SC_OBJECT_INT_H_INCLUDED_ +#define SC_OBJECT_INT_H_INCLUDED_ + +#include "sysc/kernel/sc_object.h" +#include "sysc/kernel/sc_module.h" +#include "sysc/kernel/sc_simcontext_int.h" +#include "sysc/kernel/sc_phase_callback_registry.h" + +namespace sc_core { + +class sc_object::hierarchy_scope +{ +public: + explicit hierarchy_scope(sc_object* obj); + explicit hierarchy_scope(sc_module* mod); + ~hierarchy_scope(); + +private: + sc_module * scope_; + +private: + hierarchy_scope( hierarchy_scope const & other ) /* = delete */; + hierarchy_scope& operator=(hierarchy_scope const&) /* = delete */; +}; + + +inline +sc_object::hierarchy_scope::hierarchy_scope( sc_object* obj ) + : scope_(0) +{ + if( !obj ) return; + + scope_ = dynamic_cast<sc_module*>(obj); + if( !scope_ ) + scope_ = dynamic_cast<sc_module*>(obj->get_parent_object()); + if( scope_ ) + scope_->simcontext()->hierarchy_push(scope_); +} + + +inline +sc_object::hierarchy_scope::hierarchy_scope( sc_module* mod ) + : scope_(mod) +{ + if( scope_ ) + scope_->simcontext()->hierarchy_push(scope_); +} + + +inline +sc_object::hierarchy_scope::~hierarchy_scope() +{ + if( scope_ ) + scope_->simcontext()->hierarchy_pop(); +} + + +// ----------------------------------------------------------------------- + +inline void +sc_object::do_simulation_phase_callback() +{ + simulation_phase_callback(); +} + +// ----------------------------------------------------------------------- + +} // namespace sc_core + +#endif // SC_OBJECT_INT_H_INCLUDED_ +// Taf! diff --git a/ext/systemc/src/sysc/kernel/sc_object_manager.cpp b/ext/systemc/src/sysc/kernel/sc_object_manager.cpp new file mode 100644 index 000000000..e46413928 --- /dev/null +++ b/ext/systemc/src/sysc/kernel/sc_object_manager.cpp @@ -0,0 +1,462 @@ +/***************************************************************************** + + 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_object_manager.cpp -- Manager of objects (naming, &c.) + + Original Author: Stan Y. Liao, Synopsys, Inc. + + CHANGE LOG AT THE END OF THE FILE + *****************************************************************************/ + + +#include <stdio.h> +#include <cstdlib> +#include <cassert> +#include <ctype.h> +#include <stddef.h> +#include <algorithm> // pick up std::sort. + +#include "sysc/utils/sc_iostream.h" +#include "sysc/kernel/sc_object.h" +#include "sysc/utils/sc_hash.h" +#include "sysc/utils/sc_list.h" +#include "sysc/utils/sc_mempool.h" +#include "sysc/kernel/sc_simcontext.h" +#include "sysc/kernel/sc_object_manager.h" +#include "sysc/kernel/sc_kernel_ids.h" +#include "sysc/kernel/sc_process.h" +#include "sysc/kernel/sc_module_name.h" + +namespace sc_core { + +// ---------------------------------------------------------------------------- +// CLASS : sc_object_manager +// +// Manager of objects. +// ---------------------------------------------------------------------------- + +sc_object_manager::sc_object_manager() : + m_event_it(), + m_event_walk_ok(0), + m_instance_table(), + m_module_name_stack(0), + m_object_it(), + m_object_stack(), + m_object_walk_ok() +{ +} + +// +---------------------------------------------------------------------------- +// |"sc_object_manager::~sc_object_manager" +// | +// | This is the object instance destructor for this class. It goes through +// | each sc_object instance in the instance table and sets its m_simc field +// | to NULL. +// +---------------------------------------------------------------------------- +sc_object_manager::~sc_object_manager() +{ + instance_table_t::iterator it; // instance table iterator. + + for ( it = m_instance_table.begin(); it != m_instance_table.end(); it++) + { + sc_object* obj_p = it->second.m_object_p; + if ( obj_p ) obj_p->m_simc = 0; + } +} + +// +---------------------------------------------------------------------------- +// |"sc_object_manager::create_name" +// | +// | This method creates a hierarchical name based on the name of the active +// | object and the supplied leaf name. If the resultant name is not unique it +// | will be made unique and a warning message issued. +// | +// | Arguments: +// | leaf_name = name to use for the leaf of the hierarchy. +// | Result is an std::string containing the name. +// +---------------------------------------------------------------------------- +std::string sc_object_manager::create_name(const char* leaf_name) +{ + bool clash; // true if path name exists in obj table + std::string leafname_string; // string containing the leaf name. + std::string parentname_string; // parent path name + sc_object* parent_p; // parent for this instance or NULL. + std::string result_orig_string; // save for warning message. + std::string result_string; // name to return. + + // CONSTRUCT PATHNAME TO THE NAME TO BE RETURNED: + // + // If there is not a leaf name generate one. + + parent_p = sc_get_curr_simcontext()->active_object(); + parentname_string = parent_p ? parent_p->name() : ""; + leafname_string = leaf_name; + if (parent_p) { + result_string = parentname_string; + result_string += SC_HIERARCHY_CHAR; + result_string += leafname_string; + } else { + result_string = leafname_string; + } + + // SAVE the original path name + + result_orig_string = result_string; + + // MAKE SURE THE ENTITY NAME IS UNIQUE: + // + // If not use unique name generator to make it unique. + + clash = false; + for (;;) + { + instance_table_t::iterator it = m_instance_table.find(result_string); + if ( it == m_instance_table.end() || + (it->second.m_event_p == NULL && it->second.m_object_p == NULL ) ) + { + break; + } + clash = true; + leafname_string = sc_gen_unique_name(leafname_string.c_str(), false); + if (parent_p) { + result_string = parentname_string; + result_string += SC_HIERARCHY_CHAR; + result_string += leafname_string; + } else { + result_string = leafname_string; + } + } + if (clash) { + std::string message = result_orig_string; + message += ". Latter declaration will be renamed to "; + message += result_string; + SC_REPORT_WARNING( SC_ID_INSTANCE_EXISTS_, message.c_str()); + } + + return result_string; +} + +// +---------------------------------------------------------------------------- +// |"sc_object_manager::find_event" +// | +// | This method returns the sc_event with the supplied name, or a NULL if +// | the event does not exist. +// | +// | Arguments: +// | name = name of the event +// | Result is a pointer to the event or NULL if it does not exist. +// +---------------------------------------------------------------------------- +sc_event* +sc_object_manager::find_event(const char* name) +{ + instance_table_t::iterator it; + it = m_instance_table.find(name); + return it == m_instance_table.end() ? NULL : it->second.m_event_p; +} + +// +---------------------------------------------------------------------------- +// |"sc_object_manager::find_object" +// | +// | This method returns the sc_object with the supplied name, or a NULL if +// | the object does not exist. +// | +// | Arguments: +// | name = name of the object +// | Result is a pointer to the object or NULL if it does not exist. +// +---------------------------------------------------------------------------- +sc_object* +sc_object_manager::find_object(const char* name) +{ + instance_table_t::iterator it; + it = m_instance_table.find(name); + return it == m_instance_table.end() ? NULL : it->second.m_object_p; +} + + +// +---------------------------------------------------------------------------- +// |"sc_object_manager::first_object" +// | +// | This method initializes the object iterator to point to the first object +// | in the instance table, and returns its address. If there are no objects +// | in the table a NULL value is returned. +// +---------------------------------------------------------------------------- +sc_object* +sc_object_manager::first_object() +{ + sc_object* result_p; // result to return. + + m_object_walk_ok = true; + result_p = NULL; + for ( m_object_it = m_instance_table.begin(); + m_object_it != m_instance_table.end(); + m_object_it++ ) + { + result_p = m_object_it->second.m_object_p; + if ( result_p ) break; + } + return result_p; +} + +// +---------------------------------------------------------------------------- +// |"sc_object_manager::hierarchy_curr" +// | +// | This method returns the current object in the object hierarchy or NULL +// | if it does not exist. +// +---------------------------------------------------------------------------- +sc_object* +sc_object_manager::hierarchy_curr() +{ + size_t hierarchy_n; // current size of the hierarchy. + + hierarchy_n = m_object_stack.size(); + return hierarchy_n ? m_object_stack[hierarchy_n-1] : 0; +} + +// +---------------------------------------------------------------------------- +// |"sc_object_manager::hierarchy_pop" +// | +// | This method pops the current object off the object hierarchy and returns +// | it. +// +---------------------------------------------------------------------------- +sc_object* +sc_object_manager::hierarchy_pop() +{ + size_t hierarchy_n; // current size of the hierarchy. + sc_object* result_p; // object to return. + + hierarchy_n = m_object_stack.size(); + if ( hierarchy_n == 0 ) return NULL; + hierarchy_n--; + result_p = m_object_stack[hierarchy_n]; + m_object_stack.pop_back(); + return result_p; +} + +// +---------------------------------------------------------------------------- +// |"sc_object_manager::hierarchy_push" +// | +// | This method pushes down the sc_object hierarchy to make the supplied +// | object the current object in the hierarchy. +// | +// | Arguments: +// | object_p -> object to become the new current object in the hierarchy. +// +---------------------------------------------------------------------------- +void +sc_object_manager::hierarchy_push(sc_object* object_p) +{ + m_object_stack.push_back(object_p); +} + + +// +---------------------------------------------------------------------------- +// |"sc_object_manager::hierarchy_size" +// | +// | This method returns the current size of the object hierarchy stack. +// +---------------------------------------------------------------------------- +int +sc_object_manager::hierarchy_size() +{ + return m_object_stack.size(); +} + +// +---------------------------------------------------------------------------- +// |"sc_object_manager::insert_event" +// | +// | This method inserts the supplied sc_event instance into the instance +// | table using the supplied name. +// | +// | Arguments: +// | name = name of the event to be inserted. +// | event_p -> event to be inserted. +// +---------------------------------------------------------------------------- +void +sc_object_manager::insert_event(const std::string& name, sc_event* event_p) +{ + m_instance_table[name].m_event_p = event_p; +} + +// +---------------------------------------------------------------------------- +// |"sc_object_manager::insert_object" +// | +// | This method inserts the supplied sc_object instance into the instance +// | table using the supplied name. +// | +// | Arguments: +// | name = name of the event to be inserted. +// | object_p -> object to be inserted. +// +---------------------------------------------------------------------------- +void +sc_object_manager::insert_object(const std::string& name, sc_object* object_p) +{ + m_instance_table[name].m_object_p = object_p; +} + +// +---------------------------------------------------------------------------- +// |"sc_object_manager::next_object" +// | +// | This method returns the next object pointed to by the instance iterator. +// +---------------------------------------------------------------------------- +sc_object* +sc_object_manager::next_object() +{ + sc_object* result_p; // result to return. + + assert( m_object_walk_ok ); + + if ( m_object_it == m_instance_table.end() ) return NULL; + m_object_it++; + + for ( result_p = NULL; m_object_it != m_instance_table.end(); + m_object_it++ ) + { + result_p = m_object_it->second.m_object_p; + if ( result_p ) break; + } + return result_p; +} + +// +---------------------------------------------------------------------------- +// |"sc_object_manager::pop_module_name" +// | +// | This method pops an entry off the module name stack and returns it. +// +---------------------------------------------------------------------------- +sc_module_name* +sc_object_manager::pop_module_name() +{ + sc_module_name* mod_name = m_module_name_stack; + m_module_name_stack = m_module_name_stack->m_next; + mod_name->m_next = 0; + return mod_name; +} + +// +---------------------------------------------------------------------------- +// |"sc_object_manager::push_module_name" +// | +// | This method pushes the supplied entry onto the module name stack. +// | +// | Arguments: +// | mod_name_p -> entry to push onto the module name stack. +// +---------------------------------------------------------------------------- +void +sc_object_manager::push_module_name(sc_module_name* mod_name_p) +{ + mod_name_p->m_next = m_module_name_stack; + m_module_name_stack = mod_name_p; +} + +// +---------------------------------------------------------------------------- +// |"sc_object_manager::top_of_module_name_stack" +// | +// | This method returns the module name that is on the top of the module +// | name stack. +// +---------------------------------------------------------------------------- +sc_module_name* +sc_object_manager::top_of_module_name_stack() +{ + if( m_module_name_stack == 0 ) { + SC_REPORT_ERROR( SC_ID_MODULE_NAME_STACK_EMPTY_, 0 ); + } + return m_module_name_stack; +} + +// +---------------------------------------------------------------------------- +// |"sc_object_manager::remove_event" +// | +// | This method removes the sc_event instance with the supplied name from +// | the table of instances. Note we just clear the pointer since if the name +// | was for an sc_object the m_event_p pointer will be null anyway. +// | +// | Arguments: +// | name = name of the event to be removed. +// +---------------------------------------------------------------------------- +void +sc_object_manager::remove_event(const std::string& name) +{ + instance_table_t::iterator it; // instance table iterator. + it = m_instance_table.find(name); + if ( it != m_instance_table.end() ) it->second.m_event_p = NULL; +} + +// +---------------------------------------------------------------------------- +// |"sc_object_manager::remove_object" +// | +// | This method removes the sc_object instance with the supplied name from +// | the table of instances. Note we just clear the pointer since if the name +// | was for an sc_event the m_object_p pointer will be null anyway. +// | +// | Arguments: +// | name = name of the object to be removed. +// +---------------------------------------------------------------------------- +void +sc_object_manager::remove_object(const std::string& name) +{ + instance_table_t::iterator it; // instance table iterator. + it = m_instance_table.find(name); + if ( it != m_instance_table.end() ) it->second.m_object_p = NULL; +} + +} // namespace sc_core + +// $Log: sc_object_manager.cpp,v $ +// Revision 1.13 2011/08/26 20:46:10 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.12 2011/08/24 22:05:51 acg +// Torsten Maehne: initialization changes to remove warnings. +// +// Revision 1.11 2011/06/25 17:08:39 acg +// Andy Goodrich: Jerome Cornet's changes to use libtool to build the +// library. +// +// Revision 1.10 2011/04/01 21:27:54 acg +// Andy Goodrich: documentation of event and object insertion methods. +// +// Revision 1.9 2011/03/06 15:55:11 acg +// Andy Goodrich: Changes for named events. +// +// Revision 1.8 2011/03/05 19:44:20 acg +// Andy Goodrich: changes for object and event naming and structures. +// +// Revision 1.7 2011/03/05 04:45:16 acg +// Andy Goodrich: moved active process calculation to the sc_simcontext class. +// +// Revision 1.6 2011/03/05 01:39:21 acg +// Andy Goodrich: changes for named events. +// +// Revision 1.5 2011/02/18 20:27:14 acg +// Andy Goodrich: Updated Copyrights. +// +// Revision 1.4 2011/02/13 21:47:37 acg +// Andy Goodrich: update copyright notice. +// +// Revision 1.3 2010/07/22 20:02:33 acg +// Andy Goodrich: bug fixes. +// +// 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.3 2006/01/13 18:44:30 acg +// Added $Log to record CVS changes into the source. +// diff --git a/ext/systemc/src/sysc/kernel/sc_object_manager.h b/ext/systemc/src/sysc/kernel/sc_object_manager.h new file mode 100644 index 000000000..753252c33 --- /dev/null +++ b/ext/systemc/src/sysc/kernel/sc_object_manager.h @@ -0,0 +1,139 @@ +/***************************************************************************** + + 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_object_manager.h -- Manager of objects (naming, &c.) + + Original Author: Stan Y. Liao, Synopsys, Inc. + + CHANGE LOG AT THE END OF THE FILE + *****************************************************************************/ + + +#ifndef SC_OBJECT_MANAGER_H +#define SC_OBJECT_MANAGER_H + +#include <map> +#include <vector> + +namespace sc_core { + +class sc_event; +class sc_object; +class sc_module_name; + + +// ---------------------------------------------------------------------------- +// CLASS : sc_object_manager +// +// Manager of objects. +// ---------------------------------------------------------------------------- + +class sc_object_manager +{ + friend class sc_event; + friend class sc_object; + friend class sc_simcontext; + +protected: + struct table_entry + { + table_entry() : m_event_p(NULL), m_object_p(NULL) {} + + sc_event* m_event_p; // if non-null this is an sc_event. + sc_object* m_object_p; // if non-null this is an sc_object. + }; + +public: + typedef std::map<std::string,table_entry> instance_table_t; + typedef std::vector<sc_object*> object_vector_t; + + sc_object_manager(); + ~sc_object_manager(); + + sc_event* find_event(const char* name); + + sc_object* find_object(const char* name); + sc_object* first_object(); + sc_object* next_object(); + + void hierarchy_push(sc_object* mdl); + sc_object* hierarchy_pop(); + sc_object* hierarchy_curr(); + int hierarchy_size(); + + void push_module_name(sc_module_name* mod_name); + sc_module_name* pop_module_name(); + sc_module_name* top_of_module_name_stack(); + + +private: + std::string create_name( const char* leaf_name ); + void insert_event(const std::string& name, sc_event* obj); + void insert_object(const std::string& name, sc_object* obj); + void remove_event(const std::string& name); + void remove_object(const std::string& name); + +private: + + instance_table_t::iterator m_event_it; // event instance iterator. + bool m_event_walk_ok; // true if can walk events. + instance_table_t m_instance_table; // table of instances. + sc_module_name* m_module_name_stack; // sc_module_name stack. + instance_table_t::iterator m_object_it; // object instance iterator. + object_vector_t m_object_stack; // sc_object stack. + bool m_object_walk_ok; // true if can walk objects. +}; + +} // namespace sc_core + +// $Log: sc_object_manager.h,v $ +// Revision 1.9 2011/08/26 20:46:10 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.8 2011/03/06 15:55:11 acg +// Andy Goodrich: Changes for named events. +// +// Revision 1.7 2011/03/05 19:44:20 acg +// Andy Goodrich: changes for object and event naming and structures. +// +// Revision 1.6 2011/03/05 01:39:21 acg +// Andy Goodrich: changes for named events. +// +// Revision 1.5 2011/02/18 20:27:14 acg +// Andy Goodrich: Updated Copyrights. +// +// Revision 1.4 2011/02/13 21:47:37 acg +// Andy Goodrich: update copyright notice. +// +// Revision 1.3 2010/07/22 20:02:33 acg +// Andy Goodrich: bug fixes. +// +// 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.3 2006/01/13 18:44:30 acg +// Added $Log to record CVS changes into the source. + +#endif diff --git a/ext/systemc/src/sysc/kernel/sc_phase_callback_registry.cpp b/ext/systemc/src/sysc/kernel/sc_phase_callback_registry.cpp new file mode 100644 index 000000000..84f15c93f --- /dev/null +++ b/ext/systemc/src/sysc/kernel/sc_phase_callback_registry.cpp @@ -0,0 +1,301 @@ +/***************************************************************************** + + 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_phase_callback_registry.cpp -- Implementation of phase callback registry + + Original Author: Philipp A. Hartmann, OFFIS, 2013-02-15 + + CHANGE LOG AT END OF FILE + *****************************************************************************/ + +#include "sysc/kernel/sc_object.h" +#include "sysc/kernel/sc_phase_callback_registry.h" +#include "sysc/kernel/sc_kernel_ids.h" +#include "sysc/utils/sc_report.h" + +#include <algorithm> +#include <functional> + +namespace sc_core { + +#if SC_HAS_PHASE_CALLBACKS_ + +sc_phase_callback_registry::sc_phase_callback_registry( sc_simcontext& simc ) + : m_simc( &simc ) +#if 0 + , m_cb_eval_vec() +#endif + , m_cb_update_vec() + , m_cb_timestep_vec() +{} + +sc_phase_callback_registry::~sc_phase_callback_registry() +{} + +static const sc_phase_callback_registry::mask_type + SC_PHASE_CALLBACK_MASK = SC_STATUS_ANY; + +namespace /* anonymous */ { + +struct entry_match + : std::unary_function< sc_phase_callback_registry::entry, bool > +{ + typedef sc_phase_callback_registry::cb_type* ref_type; + + explicit + entry_match( ref_type ref ) + : ref_(ref) + {} + + result_type operator()( argument_type e ) + { return e.target == ref_; } +private: + sc_phase_callback_registry::cb_type * ref_; + +}; // entry_match + +template< typename T > +inline void +erase_remove( std::vector<T>* vec, T const& t ) +{ + vec->erase( std::remove( vec->begin(), vec->end(), t ) ); +} + +} // namespace anonymous + + +sc_phase_callback_registry::mask_type +sc_phase_callback_registry::validate_mask( cb_type& cb + , mask_type m + , bool warn = false ) +{ + if( SC_UNLIKELY_(m & ~SC_PHASE_CALLBACK_MASK) ) + { + if( warn ) + { + std::stringstream ss; + ss << cb.name() << ": invalid phase callback mask: " + << (sc_status)m; + SC_REPORT_WARNING( SC_ID_PHASE_CALLBACK_REGISTER_ + , ss.str().c_str() ); + } + m &= SC_PHASE_CALLBACK_MASK; + } + + mask_type check_mask; + + // elaboration callbacks + check_mask = ( SC_ELABORATION + | SC_BEFORE_END_OF_ELABORATION + | SC_END_OF_ELABORATION ); + if( SC_UNLIKELY_( (m & check_mask ) && m_simc->elaboration_done() ) ) + { + if( warn ) + { + std::stringstream ss; + ss << cb.name() << ": elaboration done\n\t " + << (sc_status)( m & check_mask ) << " callback(s) ignored"; + SC_REPORT_WARNING(SC_ID_PHASE_CALLBACK_REGISTER_ + , ss.str().c_str() ); + } + m &= ~check_mask; + } + + check_mask = (SC_BEFORE_END_OF_ELABORATION | SC_END_OF_ELABORATION); + if( SC_UNLIKELY_(m & SC_ELABORATION) ) + { + if( warn ) + { + std::stringstream ss; + ss << cb.name() << ": " << SC_ELABORATION + << ":\n\t substituted by " << (sc_status)(check_mask); + SC_REPORT_WARNING( SC_ID_PHASE_CALLBACK_REGISTER_ + , ss.str().c_str() ); + } + m &= ~SC_ELABORATION; + m |= check_mask; + } + + check_mask = ( SC_END_OF_INITIALIZATION +#if 0 + | SC_END_OF_EVALUATION +#endif + | SC_END_OF_UPDATE + | SC_BEFORE_TIMESTEP ); + if( SC_UNLIKELY_(m & SC_RUNNING) ) + { + if( warn ) + { + std::stringstream ss; + ss << cb.name() << ": " << SC_RUNNING + << ":\n\t substituted by " << (sc_status)(check_mask); + SC_REPORT_WARNING( SC_ID_PHASE_CALLBACK_REGISTER_ + , ss.str().c_str() ); + } + m &= ~SC_RUNNING; + m |= check_mask; + } + return m; +} + + +sc_phase_callback_registry::mask_type +sc_phase_callback_registry::register_callback( cb_type& cb, mask_type m ) +{ + storage_type::iterator it = + find_if( m_cb_vec.begin(), m_cb_vec.end(), entry_match(&cb) ); + + m = validate_mask(cb, m, /* warn */ true ); + + mask_type diff_mask = m; + mask_type new_mask = m; + + if( it != m_cb_vec.end() ) // update existing entry + { + // update masks + new_mask = (*it).mask | m; + diff_mask = ~(*it).mask & m; + (*it).mask = new_mask; + } + else // new entry + { + if( !m ) // empty, do nothing + return SC_UNITIALIZED; + + entry new_entry = { &cb, new_mask }; + m_cb_vec.push_back( new_entry ); + } + + // add to callback shortcut sets +#if 0 + if( diff_mask & SC_END_OF_EVALUATION ) + m_cb_eval_vec.push_back( &cb ); +#endif + if( diff_mask & SC_END_OF_UPDATE ) + m_cb_update_vec.push_back( &cb ); + if( diff_mask & SC_BEFORE_TIMESTEP ) + m_cb_timestep_vec.push_back( &cb ); + + return new_mask; +} + + +sc_phase_callback_registry::mask_type +sc_phase_callback_registry::unregister_callback( cb_type& cb, mask_type m ) +{ + storage_type::iterator it = + find_if( m_cb_vec.begin(), m_cb_vec.end(), entry_match(&cb) ); + + m = validate_mask(cb, m); + + mask_type diff_mask = m; + mask_type new_mask = m; + + if( it == m_cb_vec.end() ) { // not registered + return SC_UNITIALIZED; + } + + // update masks + new_mask = (*it).mask & ~m; + diff_mask = (*it).mask & m; + (*it).mask = new_mask; + + if( !new_mask ) + m_cb_vec.erase(it); + + // drop from callback shortcut sets +#if 0 + if( diff_mask & SC_END_OF_EVALUATION ) + erase_remove( &m_cb_eval_vec, &cb ); +#endif + if( diff_mask & SC_END_OF_UPDATE ) + erase_remove( &m_cb_update_vec, &cb ); + if( diff_mask & SC_BEFORE_TIMESTEP ) + erase_remove( &m_cb_timestep_vec, &cb ); + + return new_mask; +} + + +// generic implementation (for non-critical callbacks) +// - also restores hierarchy around callback object +void +sc_phase_callback_registry::do_callback( sc_status s ) const +{ + typedef storage_type::const_iterator it_type; + storage_type const & vec = m_cb_vec; + + for(it_type it = vec.begin(), end = vec.end(); it != end; ++it) { + if( s & it->mask ) { + sc_object::hierarchy_scope scope(it->target); + it->target->do_simulation_phase_callback(); + } + } +} + +#else // ! SC_HAS_PHASE_CALLBACKS_ + +sc_phase_callback_registry::sc_phase_callback_registry( sc_simcontext& ){} +sc_phase_callback_registry::~sc_phase_callback_registry(){} + +static inline void +warn_phase_callbacks( sc_core::sc_object const& obj ) +{ + static bool warned = false; + if (!warned) + { + std::stringstream ss; + ss << obj.name() << ".\n" + << "Please recompile SystemC with " + "\"SC_ENABLE_SIMULATION_PHASE_CALLBACKS\" defined."; + SC_REPORT_WARNING( SC_ID_PHASE_CALLBACKS_UNSUPPORTED_ + , ss.str().c_str() ); + } +} + +sc_phase_callback_registry::mask_type +sc_phase_callback_registry::register_callback( cb_type& cb, mask_type ) +{ + warn_phase_callbacks( cb ); + return SC_UNITIALIZED; +} + +sc_phase_callback_registry::mask_type +sc_phase_callback_registry::unregister_callback( cb_type& cb, mask_type ) +{ + warn_phase_callbacks( cb ); + return SC_UNITIALIZED; +} + +#endif // ! SC_HAS_PHASE_CALLBACKS_ + +} // namespace sc_core + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affiliation, date and + changes you are making here. + + Name, Affiliation, Date: + Description of Modification: + + *****************************************************************************/ +// Taf! diff --git a/ext/systemc/src/sysc/kernel/sc_phase_callback_registry.h b/ext/systemc/src/sysc/kernel/sc_phase_callback_registry.h new file mode 100644 index 000000000..9510c0d3f --- /dev/null +++ b/ext/systemc/src/sysc/kernel/sc_phase_callback_registry.h @@ -0,0 +1,276 @@ +/***************************************************************************** + + 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_phase_callback_registry.h -- Definition of the simulation phase callbacks + + The most critical functions are defined inline in this file. Only active, + if SC_ENABLE_SIMULATION_PHASE_CALLBACKS[_TRACING] is defined during the + SystemC library build. + + Original Author: Philipp A. Hartmann, OFFIS, 2013-02-15 + + CHANGE LOG AT END OF FILE + *****************************************************************************/ + +#ifndef SC_PHASE_CALLBACK_REGISTRY_H_INCLUDED_ +#define SC_PHASE_CALLBACK_REGISTRY_H_INCLUDED_ + +#if defined( SC_ENABLE_SIMULATION_PHASE_CALLBACKS ) \ + || defined( SC_ENABLE_SIMULATION_PHASE_CALLBACKS_TRACING ) +# define SC_HAS_PHASE_CALLBACKS_ 1 +#else +# define SC_HAS_PHASE_CALLBACKS_ 0 +#endif + +#include "sysc/kernel/sc_simcontext.h" +#include "sysc/kernel/sc_object_int.h" +#include "sysc/kernel/sc_status.h" + +#include <vector> + +namespace sc_core { + +class sc_simcontext; +class sc_object; + +class sc_phase_callback_registry +{ +public: + typedef sc_phase_callback_registry this_type; + typedef sc_object cb_type; + typedef cb_type::phase_cb_mask mask_type; + + struct entry + { + cb_type* target; + mask_type mask; + }; + + friend class sc_simcontext; + friend class sc_object; + +private: // interface completely internal + + explicit + sc_phase_callback_registry( sc_simcontext& simc ); + + ~sc_phase_callback_registry(); + + // --- callback forwarders + + bool construction_done() const; //< returns false + void elaboration_done() const; + void initialization_done() const; + void start_simulation() const; + + void evaluation_done() const; + void update_done() const; + void before_timestep() const; + + void simulation_paused() const; + void simulation_stopped() const; + void simulation_done() const; + + + // --- callback registration and implementation + + mask_type register_callback( cb_type&, mask_type mask ); + mask_type unregister_callback( cb_type&, mask_type mask ); + + // generic caller + void do_callback( sc_status ) const; + +private: + typedef std::vector<entry> storage_type; + typedef std::vector<cb_type*> single_storage_type; + +#if SC_HAS_PHASE_CALLBACKS_ + + // set and restore simulation status + struct scoped_status + { + scoped_status( sc_status& ref, sc_status s ) + : ref_(ref), prev_(ref) { ref_ = s;} + ~scoped_status() { ref_ = prev_; } + private: + sc_status& ref_; + sc_status prev_; + }; // scoped_status + + mask_type validate_mask( cb_type&, mask_type, bool warn ); + +private: + + sc_simcontext* m_simc; + storage_type m_cb_vec; // all callbacks +#if 0 + single_storage_type m_cb_eval_vec; // - eval cb shortcut +#endif + single_storage_type m_cb_update_vec; // - update cb shortcut + single_storage_type m_cb_timestep_vec; // - timestep cb shortcut + +#endif // SC_HAS_PHASE_CALLBACKS_ + +private: + // disabled + sc_phase_callback_registry( const this_type& ); + this_type& operator=(const this_type&); + +}; // sc_phase_callback_registry + + +// -------------------- callback implementations -------------------- +// (empty, if feature is disabled) + +inline bool +sc_phase_callback_registry::construction_done() const +{ +#if SC_HAS_PHASE_CALLBACKS_ + do_callback( SC_BEFORE_END_OF_ELABORATION ); +#endif + return false; +} + +inline void +sc_phase_callback_registry::elaboration_done() const +{ +#if SC_HAS_PHASE_CALLBACKS_ + do_callback( SC_END_OF_ELABORATION ); +#endif +} + +inline void +sc_phase_callback_registry::start_simulation() const +{ +#if SC_HAS_PHASE_CALLBACKS_ + do_callback( SC_START_OF_SIMULATION ); +#endif +} + +inline void +sc_phase_callback_registry::initialization_done() const +{ +#if SC_HAS_PHASE_CALLBACKS_ + scoped_status scope( m_simc->m_simulation_status + , SC_END_OF_INITIALIZATION ); + + do_callback( SC_END_OF_INITIALIZATION ); +#endif +} + +inline void +sc_phase_callback_registry::simulation_paused() const +{ +#if SC_HAS_PHASE_CALLBACKS_ + do_callback( SC_PAUSED ); +#endif +} + +inline void +sc_phase_callback_registry::simulation_stopped() const +{ +#if SC_HAS_PHASE_CALLBACKS_ + do_callback( SC_STOPPED ); +#endif +} + +inline void +sc_phase_callback_registry::simulation_done() const +{ +#if SC_HAS_PHASE_CALLBACKS_ + do_callback( SC_END_OF_SIMULATION ); +#endif +} + +// -------------- specialized callback implementations -------------- + +#if 0 +inline void +sc_phase_callback_registry::evaluation_done() const +{ +#if SC_HAS_PHASE_CALLBACKS_ + + if( !m_cb_eval_vec.size() ) return; + + typedef single_storage_type::const_iterator it_type; + single_storage_type const & vec = m_cb_eval_vec; + + scoped_status scope( m_simc->m_simulation_status + , SC_END_OF_EVALUATION ); + + for(it_type it = vec.begin(), end = vec.end(); it != end; ++it) + (*it)->do_simulation_phase_callback(); +#endif +} +#endif + +inline void +sc_phase_callback_registry::update_done() const +{ +#if SC_HAS_PHASE_CALLBACKS_ + + if( !m_cb_update_vec.size() ) return; + + typedef single_storage_type::const_iterator it_type; + single_storage_type const & vec = m_cb_update_vec; + + scoped_status scope( m_simc->m_simulation_status + , SC_END_OF_UPDATE ); + + for(it_type it = vec.begin(), end = vec.end(); it != end; ++it) + (*it)->do_simulation_phase_callback(); +#endif +} + +inline void +sc_phase_callback_registry::before_timestep() const +{ +#if SC_HAS_PHASE_CALLBACKS_ + + if( !m_cb_timestep_vec.size() ) return; + + typedef single_storage_type::const_iterator it_type; + single_storage_type const & vec = m_cb_timestep_vec; + + scoped_status scope( m_simc->m_simulation_status + , SC_BEFORE_TIMESTEP ); + + for(it_type it = vec.begin(), end = vec.end(); it != end; ++it) + (*it)->do_simulation_phase_callback(); +#endif +} + +// ------------------------------------------------------------------ + +} // namespace sc_core + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affiliation, date and + changes you are making here. + + Name, Affiliation, Date: + Description of Modification: + + *****************************************************************************/ +#endif /* SC_PHASE_CALLBACK_REGISTRY_H_INCLUDED_ */ +// Taf! + diff --git a/ext/systemc/src/sysc/kernel/sc_process.cpp b/ext/systemc/src/sysc/kernel/sc_process.cpp new file mode 100644 index 000000000..353eddd6a --- /dev/null +++ b/ext/systemc/src/sysc/kernel/sc_process.cpp @@ -0,0 +1,854 @@ +/***************************************************************************** + + 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_process.cpp -- Base process implementation. + + Original Authors: Andy Goodrich, Forte Design Systems, 17 June 2003 + Stuart Swan, Cadence + Bishnupriya Bhattacharya, Cadence Design Systems, + 25 August, 2003 + + CHANGE LOG AT THE END OF THE FILE + *****************************************************************************/ + +#include "sysc/kernel/sc_name_gen.h" +#include "sysc/kernel/sc_cthread_process.h" +#include "sysc/kernel/sc_method_process.h" +#include "sysc/kernel/sc_thread_process.h" +#include "sysc/kernel/sc_sensitive.h" +#include "sysc/kernel/sc_process_handle.h" +#include "sysc/kernel/sc_event.h" +#include <sstream> + +namespace sc_core { + +// sc_process_handle entities that are returned for null pointer instances: +// +// Note the special name for 'non_event' - this makes sure it does not +// appear as a named event. + +std::vector<sc_event*> sc_process_handle::empty_event_vector; +std::vector<sc_object*> sc_process_handle::empty_object_vector; +sc_event sc_process_handle::non_event(SC_KERNEL_EVENT_PREFIX); + +// Last process that was created: + +sc_process_b* sc_process_b::m_last_created_process_p = 0; + +//------------------------------------------------------------------------------ +//"sc_process_b::add_static_event" +// +// This method adds an event to the list of static events, and sets the +// event up to call back this process when it fires. +//------------------------------------------------------------------------------ +void sc_process_b::add_static_event( const sc_event& e ) +{ + sc_method_handle method_h; // This process as a method. + sc_thread_handle thread_h; // This process as a thread. + + + // CHECK TO SEE IF WE ARE ALREADY REGISTERED WITH THE EVENT: + + for( int i = m_static_events.size() - 1; i >= 0; -- i ) { + if( &e == m_static_events[i] ) { + return; + } + } + + // REMEMBER THE EVENT AND THEN REGISTER OUR OBJECT INSTANCE WITH IT: + + m_static_events.push_back( &e ); + + switch ( m_process_kind ) + { + case SC_THREAD_PROC_: + case SC_CTHREAD_PROC_: + thread_h = SCAST<sc_thread_handle>( this ); + e.add_static( thread_h ); + break; + case SC_METHOD_PROC_: + method_h = SCAST<sc_method_handle>( this ); + e.add_static( method_h ); + break; + default: + assert( false ); + break; + } +} + +//------------------------------------------------------------------------------ +//"sc_process_b::disconnect_process" +// +// This method removes this object instance from use. It will be called by +// the kill_process() methods of classes derived from it. This object instance +// will be removed from any data structures it resides, other than existence. +//------------------------------------------------------------------------------ +void sc_process_b::disconnect_process() +{ + int mon_n; // monitor queue size. + sc_thread_handle thread_h; // This process as a thread. + + // IF THIS OBJECT IS PINING FOR THE FJORDS WE ARE DONE: + + if ( m_state & ps_bit_zombie ) return; + + // IF THIS IS A THREAD SIGNAL ANY MONITORS WAITING FOR IT TO EXIT: + + switch ( m_process_kind ) + { + case SC_THREAD_PROC_: + case SC_CTHREAD_PROC_: + thread_h = SCAST<sc_thread_handle>(this); + mon_n = thread_h->m_monitor_q.size(); + if ( mon_n ) + { + for ( int mon_i = 0; mon_i < mon_n; mon_i++ ) + { + thread_h->m_monitor_q[mon_i]->signal( thread_h, + sc_process_monitor::spm_exit); + } + } + break; + default: + break; + } + + // REMOVE EVENT WAITS, AND REMOVE THE PROCESS FROM ITS SC_RESET: + + remove_dynamic_events(); + remove_static_events(); + + for ( std::vector<sc_reset*>::size_type rst_i = 0; rst_i < m_resets.size(); rst_i++ ) + { + m_resets[rst_i]->remove_process( this ); + } + m_resets.resize(0); + + + // FIRE THE TERMINATION EVENT, MARK AS TERMINATED, AND DECREMENT THE COUNT: + // + // (1) We wait to set the process kind until after doing the removals + // above. + // (2) Decrementing the reference count will result in actual object + // deletion if we hit zero. + + m_state = ps_bit_zombie; + if ( m_term_event_p ) m_term_event_p->notify(); + reference_decrement(); +} + +//------------------------------------------------------------------------------ +//"sc_process_b::delete_process" +// +// This method deletes the current instance, if it is not the running +// process. Otherwise, it is put in the simcontext's process deletion +// queue. +// +// The reason for the two step deletion process is that the process from which +// reference_decrement() is called may be the running process, so we may need +// to wait until it goes idle. +//------------------------------------------------------------------------------ +void sc_process_b::delete_process() +{ + assert( m_references_n == 0 ); + + // Immediate deletion: + + if ( this != sc_get_current_process_b() ) + { + delete this; + } + + // Deferred deletion: note we set the reference count to one for the call + // to reference_decrement that occurs in sc_simcontext::crunch(). + + else + { + m_references_n = 1; + detach(); + simcontext()->mark_to_collect_process( this ); + } +} + + +//------------------------------------------------------------------------------ +//"sc_process_b::dont_initialize" +// +// This virtual method sets the initialization switch for this object instance. +//------------------------------------------------------------------------------ +void sc_process_b::dont_initialize( bool dont ) +{ + m_dont_init = dont; +} + +//------------------------------------------------------------------------------ +//"sc_process_b::dump_state" +// +// This method returns the process state as a string. +//------------------------------------------------------------------------------ +std::string sc_process_b::dump_state() const +{ + std::string result; + result = "["; + if ( m_state == ps_normal ) + { + result += " normal"; + } + else + { + if ( m_state & ps_bit_disabled ) + result += "disabled "; + if ( m_state & ps_bit_suspended ) + result += "suspended "; + if ( m_state & ps_bit_ready_to_run ) + result += "ready_to_run "; + if ( m_state & ps_bit_zombie ) + result += "zombie "; + } + result += "]"; + return result; +} + + +//------------------------------------------------------------------------------ +//"sc_process_b::gen_unique_name" +// +// This method generates a unique name within this object instance's namespace. +//------------------------------------------------------------------------------ +const char* sc_process_b::gen_unique_name( const char* basename_, + bool preserve_first ) +{ + if ( ! m_name_gen_p ) m_name_gen_p = new sc_name_gen; + return m_name_gen_p->gen_unique_name( basename_, preserve_first ); +} + +//------------------------------------------------------------------------------ +//"sc_process_b::remove_dynamic_events" +// +// This method removes this object instance from the events in its dynamic +// event lists. +// +// Arguments: +// skip_timeout = skip cleaning up the timeout event, it will be done +// by sc_event_notify(). +//------------------------------------------------------------------------------ +void +sc_process_b::remove_dynamic_events( bool skip_timeout ) +{ + sc_method_handle method_h; // This process as a method. + sc_thread_handle thread_h; // This process as a thread. + + m_trigger_type = STATIC; + switch ( m_process_kind ) + { + case SC_THREAD_PROC_: + case SC_CTHREAD_PROC_: + thread_h = SCAST<sc_thread_handle>(this); + if ( thread_h->m_timeout_event_p && !skip_timeout ) { + thread_h->m_timeout_event_p->remove_dynamic(thread_h); + thread_h->m_timeout_event_p->cancel(); + } + if ( m_event_p ) m_event_p->remove_dynamic( thread_h ); + if ( m_event_list_p ) + { + m_event_list_p->remove_dynamic( thread_h, 0 ); + m_event_list_p->auto_delete(); + m_event_list_p = 0; + } + break; + case SC_METHOD_PROC_: + method_h = SCAST<sc_method_handle>(this); + if ( method_h->m_timeout_event_p && !skip_timeout ) { + method_h->m_timeout_event_p->remove_dynamic(method_h); + method_h->m_timeout_event_p->cancel(); + } + if ( m_event_p ) m_event_p->remove_dynamic( method_h ); + if ( m_event_list_p ) + { + m_event_list_p->remove_dynamic( method_h, 0 ); + m_event_list_p->auto_delete(); + m_event_list_p = 0; + } + break; + default: // Some other type, it needs to clean up itself. + // std::cout << "Check " << __FILE__ << ":" << __LINE__ << std::endl; + break; + } +} + +//------------------------------------------------------------------------------ +//"sc_process_b::remove_static_events" +// +// This method removes this object instance from the events in its static +// event list. +//------------------------------------------------------------------------------ +void +sc_process_b::remove_static_events() +{ + sc_method_handle method_h; // This process as a method. + sc_thread_handle thread_h; // This process as a thread. + + switch ( m_process_kind ) + { + case SC_THREAD_PROC_: + case SC_CTHREAD_PROC_: + thread_h = SCAST<sc_thread_handle>( this ); + for( int i = m_static_events.size() - 1; i >= 0; -- i ) { + m_static_events[i]->remove_static( thread_h ); + } + m_static_events.resize(0); + break; + case SC_METHOD_PROC_: + method_h = DCAST<sc_method_handle>( this ); + assert( method_h != 0 ); + for( int i = m_static_events.size() - 1; i >= 0; -- i ) { + m_static_events[i]->remove_static( method_h ); + } + m_static_events.resize(0); + break; + default: // Some other type, it needs to clean up itself. + // std::cout << "Check " << __FILE__ << ":" << __LINE__ << std::endl; + break; + } +} + +//------------------------------------------------------------------------------ +// "sc_process_b::report_error" +// +// This method can be used to issue a report from within a process. +// The error of the given ID is reported with the given message and +// the process' name() appended to the report. +//------------------------------------------------------------------------------ +void +sc_process_b::report_error( const char* msgid, const char* msg ) const +{ + std::stringstream sstr; + if( msg && msg[0] ) + sstr << msg << ": "; + sstr << name(); + SC_REPORT_ERROR( msgid, sstr.str().c_str() ); +} + + +//------------------------------------------------------------------------------ +// "sc_process_b::report_immediate_self_notification" +// +// This method is used to report an immediate self-notification +// that used to trigger the process before the clarification in 1666-2011. +// The warning is only reported once. +//------------------------------------------------------------------------------ +void +sc_process_b::report_immediate_self_notification() const +{ + static bool once = false; + if( !once ) { + SC_REPORT_WARNING( SC_ID_IMMEDIATE_SELF_NOTIFICATION_, name() ); + once = true; + } +} + +//------------------------------------------------------------------------------ +//"sc_process_b::reset_changed" +// +// This method is called when there is a change in the value of the +// signal that was specified via reset_signal_is, or the value of the +// m_sticky_reset field. We get called any time m_sticky_reset changes +// or a signal value changes since, since we may need to throw an exception +// or clear one. Note that this method may be called when there is no +// active process, but rather the main simulator is executing so we must +// check for that case. +// +// Arguments: +// async = true if this is an asynchronous reset. +// asserted = true if reset being asserted, false if being deasserted. +//------------------------------------------------------------------------------ +void sc_process_b::reset_changed( bool async, bool asserted ) +{ + + // Error out on the corner case: + + if ( !sc_allow_process_control_corners && !async && + (m_state & ps_bit_suspended) ) + { + report_error( SC_ID_PROCESS_CONTROL_CORNER_CASE_, + "synchronous reset changed on a suspended process" ); + } + + // IF THIS OBJECT IS PUSHING UP DAISIES WE ARE DONE: + + if ( m_state & ps_bit_zombie ) return; + + // Reset is being asserted: + + if ( asserted ) + { + // if ( m_reset_event_p ) m_reset_event_p->notify(); + if ( async ) + { + m_active_areset_n++; + if ( sc_is_running() ) throw_reset(true); + } + else + { + m_active_reset_n++; + if ( sc_is_running() ) throw_reset(false); + } + } + + // Reset is being deasserted: + + else + { + if ( async ) + { + m_active_areset_n--; + } + else + { + m_active_reset_n--; + } + } + + // Clear the throw type if there are no active resets. + + if ( (m_throw_status == THROW_SYNC_RESET || + m_throw_status == THROW_ASYNC_RESET) && + m_active_areset_n == 0 && m_active_reset_n == 0 && !m_sticky_reset ) + { + m_throw_status = THROW_NONE; + } +} + +//------------------------------------------------------------------------------ +//"sc_process_b::reset_event" +// +// This method returns a reference to the reset event for this object +// instance. If no event exists one is allocated. +//------------------------------------------------------------------------------ +sc_event& sc_process_b::reset_event() +{ + if ( !m_reset_event_p ) + { + m_reset_event_p = new sc_event( + (std::string(SC_KERNEL_EVENT_PREFIX)+"_reset_event").c_str() ); + } + return *m_reset_event_p; +} + +//------------------------------------------------------------------------------ +//"sc_process_b::reset_process" +// +// This inline method changes the reset state of this object instance and +// conditionally its descendants. +// +// Notes: +// (1) It is called for sync_reset_on() and sync_reset_off(). It is not used +// for signal sensitive resets, though all reset flow ends up in +// reset_changed(). +// +// Arguments: +// rt = source of the reset: +// * reset_asynchronous - sc_process_handle::reset() +// * reset_synchronous_off - sc_process_handle::sync_reset_off() +// * reset_synchronous_on - sc_process_handle::sync_reset_on() +// descendants = indication of how to process descendants. +//------------------------------------------------------------------------------ +void sc_process_b::reset_process( reset_type rt, + sc_descendant_inclusion_info descendants ) +{ + + // PROCESS THIS OBJECT INSTANCE'S DESCENDANTS IF REQUESTED TO: + + if ( descendants == SC_INCLUDE_DESCENDANTS ) + { + const std::vector<sc_object*> children = get_child_objects(); + int child_n = children.size(); + + for ( int child_i = 0; child_i < child_n; child_i++ ) + { + sc_process_b* child_p = DCAST<sc_process_b*>(children[child_i]); + if ( child_p ) child_p->reset_process(rt, descendants); + } + } + + // PROCESS THIS OBJECT INSTANCE: + + switch (rt) + { + // One-shot asynchronous reset: remove dynamic sensitivity and throw: + // + // If this is an sc_method only throw if it is active. + + case reset_asynchronous: + if ( sc_get_status() != SC_RUNNING ) + { + report_error(SC_ID_RESET_PROCESS_WHILE_NOT_RUNNING_); + } + else + { + remove_dynamic_events(); + throw_reset(true); + } + break; + + // Turn on sticky synchronous reset: use standard reset mechanism. + + case reset_synchronous_on: + if ( m_sticky_reset == false ) + { + m_sticky_reset = true; + reset_changed( false, true ); + } + break; + + // Turn off sticky synchronous reset: use standard reset mechanism. + + default: + if ( m_sticky_reset == true ) + { + m_sticky_reset = false; + reset_changed( false, false ); + } + break; + } +} + +//------------------------------------------------------------------------------ +//"sc_process_b::sc_process_b" +// +// This is the object instance constructor for this class. +//------------------------------------------------------------------------------ +sc_process_b::sc_process_b( const char* name_p, bool is_thread, bool free_host, + SC_ENTRY_FUNC method_p, sc_process_host* host_p, + const sc_spawn_options* /* opt_p */ +) : + sc_object( name_p ), + file(0), + lineno(0), + proc_id( simcontext()->next_proc_id()), + m_active_areset_n(0), + m_active_reset_n(0), + m_dont_init( false ), + m_dynamic_proc( simcontext()->elaboration_done() ), + m_event_p(0), + m_event_count(0), + m_event_list_p(0), + m_exist_p(0), + m_free_host( free_host ), + m_has_reset_signal( false ), + m_has_stack(false), + m_is_thread(is_thread), + m_last_report_p(0), + m_name_gen_p(0), + m_process_kind(SC_NO_PROC_), + m_references_n(1), + m_resets(), + m_reset_event_p(0), + m_resume_event_p(0), + m_runnable_p(0), + m_semantics_host_p( host_p ), + m_semantics_method_p ( method_p ), + m_state(ps_normal), + m_static_events(), + m_sticky_reset(false), + m_term_event_p(0), + m_throw_helper_p(0), + m_throw_status( THROW_NONE ), + m_timed_out(false), + m_timeout_event_p(0), + m_trigger_type(STATIC), + m_unwinding(false) +{ + + // THIS OBJECT INSTANCE IS NOW THE LAST CREATED PROCESS: + + m_last_created_process_p = this; + m_timeout_event_p = new sc_event( + (std::string(SC_KERNEL_EVENT_PREFIX)+"_free_event").c_str() ); +} + +//------------------------------------------------------------------------------ +//"sc_process_b::~sc_process_b" +// +// This is the object instance destructor for this class. +//------------------------------------------------------------------------------ +sc_process_b::~sc_process_b() +{ + + // REDIRECT ANY CHILDREN AS CHILDREN OF THE SIMULATION CONTEXT: + + orphan_child_objects(); + + + // DELETE SEMANTICS OBJECTS IF NEED BE: + + if ( m_free_host ) delete m_semantics_host_p; +# if !defined(SC_USE_MEMBER_FUNC_PTR) // Remove invocation object. + delete m_semantics_method_p; +# endif + + + // REMOVE ANY STRUCTURES THAT MAY HAVE BEEN BUILT: + + delete m_last_report_p; + delete m_name_gen_p; + delete m_reset_event_p; + delete m_resume_event_p; + delete m_term_event_p; + delete m_throw_helper_p; + delete m_timeout_event_p; + +} + +//------------------------------------------------------------------------------ +//"sc_process_b::terminated_event" +// +// This method returns a reference to the terminated event for this object +// instance. If no event exists one is allocated. +//------------------------------------------------------------------------------ +sc_event& sc_process_b::terminated_event() +{ + if ( !m_term_event_p ) + { + m_term_event_p = new sc_event( + (std::string(SC_KERNEL_EVENT_PREFIX)+"_term_event").c_str() ); + } + return *m_term_event_p; +} + +// +---------------------------------------------------------------------------- +// |"sc_process_b::trigger_reset_event" +// | +// | This method triggers the notify event. It exists because we can't get +// | sc_event context in sc_process.h because the includes would be +// | circular... sigh... +// +---------------------------------------------------------------------------- +void sc_process_b::trigger_reset_event() +{ + if ( m_reset_event_p ) m_reset_event_p->notify(); +} + +//------------------------------------------------------------------------------ +//"sc_process_handle::operator sc_cthread_handle" +// +//------------------------------------------------------------------------------ +sc_process_handle::operator sc_cthread_handle() +{ + return DCAST<sc_cthread_handle>(m_target_p); +} + +//------------------------------------------------------------------------------ +//"sc_process_handle::sc_method_handle" +// +//------------------------------------------------------------------------------ +sc_process_handle::operator sc_method_handle() +{ + return DCAST<sc_method_handle>(m_target_p); +} + +//------------------------------------------------------------------------------ +//"sc_process_handle::sc_thread_handle" +// +//------------------------------------------------------------------------------ +sc_process_handle::operator sc_thread_handle() +{ + return DCAST<sc_thread_handle>(m_target_p); +} + +} // namespace sc_core + + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affiliation, date and + changes you are making here. + + Name, Affiliation, Date: Andy Goodrich, Forte Design Systems, 12 Aug 05 + Description of Modification: This is the rewrite of process support. It + contains some code from the now-defunct + sc_process_b.cpp, as well as the former + version of sc_process_b.cpp. + + Name, Affiliation, Date: + Description of Modification: + + *****************************************************************************/ + +// $Log: sc_process.cpp,v $ +// Revision 1.37 2011/08/24 22:05:51 acg +// Torsten Maehne: initialization changes to remove warnings. +// +// Revision 1.36 2011/08/15 16:43:24 acg +// Torsten Maehne: changes to remove unused argument warnings. +// +// Revision 1.35 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.34 2011/07/29 22:55:01 acg +// Philipp A. Hartmann: add missing include. +// +// Revision 1.33 2011/07/29 22:43:41 acg +// Philipp A. Hartmann: changes to handle case where a process control +// invocation on a child process causes the list of child processes to change. +// +// Revision 1.32 2011/07/24 11:20:03 acg +// Philipp A. Hartmann: process control error message improvements: +// (1) Downgrade error to warning for re-kills of processes. +// (2) Add process name to process messages. +// (3) drop some superfluous colons in messages. +// +// Revision 1.31 2011/04/19 15:04:27 acg +// Philipp A. Hartmann: clean up SC_ID messages. +// +// Revision 1.30 2011/04/14 22:33:43 acg +// Andy Goodrich: added missing checks for a process being a zombie. +// +// Revision 1.29 2011/04/13 05:00:43 acg +// Andy Goodrich: removed check for method process in termination_event() +// since with the new IEEE 1666 2011 its legal. +// +// Revision 1.28 2011/04/13 02:44:26 acg +// Andy Goodrich: added m_unwinding flag in place of THROW_NOW because the +// throw status will be set back to THROW_*_RESET if reset is active and +// the check for an unwind being complete was expecting THROW_NONE as the +// clearing of THROW_NOW. +// +// Revision 1.27 2011/04/10 22:17:35 acg +// Andy Goodrich: added trigger_reset_event() to allow sc_process.h to +// contain the run_process() inline method. sc_process.h cannot have +// sc_simcontext information because of recursive includes. +// +// Revision 1.26 2011/04/08 22:33:08 acg +// Andy Goodrich: moved the semantics() method to the header file and made +// it an inline method. +// +// Revision 1.25 2011/04/08 18:24:48 acg +// Andy Goodrich: moved reset_changed() to .cpp since it needs visibility +// to sc_simcontext. +// +// Revision 1.24 2011/04/05 20:50:57 acg +// Andy Goodrich: +// (1) changes to make sure that event(), posedge() and negedge() only +// return true if the clock has not moved. +// (2) fixes for method self-resumes. +// (3) added SC_PRERELEASE_VERSION +// (4) removed kernel events from the object hierarchy, added +// sc_hierarchy_name_exists(). +// +// Revision 1.23 2011/04/05 06:25:38 acg +// Andy Goodrich: new checks for simulation running in reset_process(). +// +// Revision 1.22 2011/03/20 13:43:23 acg +// Andy Goodrich: added async_signal_is() plus suspend() as a corner case. +// +// Revision 1.21 2011/03/12 21:07:51 acg +// Andy Goodrich: changes to kernel generated event support. +// +// Revision 1.20 2011/03/07 17:38:43 acg +// Andy Goodrich: tightening up of checks for undefined interaction between +// synchronous reset and suspend. +// +// Revision 1.19 2011/03/06 23:30:13 acg +// Andy Goodrich: refining suspend - sync reset corner case checking so that +// the following are error situations: +// (1) Calling suspend on a process with a reset_signal_is() specification +// or sync_reset_on() is active. +// (2) Calling sync_reset_on() on a suspended process. +// +// Revision 1.18 2011/03/06 19:57:11 acg +// Andy Goodrich: refinements for the illegal suspend - synchronous reset +// interaction. +// +// Revision 1.17 2011/03/06 16:47:09 acg +// Andy Goodrich: changes for testing sync_reset - suspend corner cases. +// +// Revision 1.16 2011/03/06 15:57:57 acg +// Andy Goodrich: added process control corner case checks. Changes for +// named events. +// +// Revision 1.15 2011/02/18 20:27:14 acg +// Andy Goodrich: Updated Copyrights. +// +// Revision 1.14 2011/02/17 19:52:13 acg +// Andy Goodrich: +// (1) Simplfied process control usage. +// (2) Changed dump_status() to dump_state with new signature. +// +// Revision 1.13 2011/02/13 21:47:37 acg +// Andy Goodrich: update copyright notice. +// +// Revision 1.12 2011/02/13 21:41:34 acg +// Andy Goodrich: get the log messages for the previous check in correct. +// +// Revision 1.11 2011/02/13 21:32:24 acg +// Andy Goodrich: moved sc_process_b::reset_process() from header file +// to cpp file. Added dump_status() to print out the status of a +// process. +// +// Revision 1.10 2011/02/04 15:27:36 acg +// Andy Goodrich: changes for suspend-resume semantics. +// +// Revision 1.9 2011/02/01 21:06:12 acg +// Andy Goodrich: new layout for the process_state enum. +// +// Revision 1.8 2011/01/25 20:50:37 acg +// Andy Goodrich: changes for IEEE 1666 2011. +// +// Revision 1.7 2011/01/19 23:21:50 acg +// Andy Goodrich: changes for IEEE 1666 2011 +// +// Revision 1.6 2011/01/18 20:10:45 acg +// Andy Goodrich: changes for IEEE1666_2011 semantics. +// +// Revision 1.5 2010/07/22 20:02:33 acg +// Andy Goodrich: bug fixes. +// +// Revision 1.4 2009/05/22 16:06:29 acg +// Andy Goodrich: process control updates. +// +// Revision 1.3 2008/05/22 17:06:26 acg +// Andy Goodrich: updated copyright notice to include 2008. +// +// Revision 1.2 2007/09/20 20:32:35 acg +// Andy Goodrich: changes to the semantics of throw_it() to match the +// specification. A call to throw_it() will immediately suspend the calling +// thread until all the throwees have executed. At that point the calling +// thread will be restarted before the execution of any other threads. +// +// Revision 1.1.1.1 2006/12/15 20:20:05 acg +// SystemC 2.3 +// +// Revision 1.6 2006/04/20 17:08:17 acg +// Andy Goodrich: 3.0 style process changes. +// +// Revision 1.5 2006/04/11 23:13:21 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.4 2006/01/24 20:49:05 acg +// Andy Goodrich: changes to remove the use of deprecated features within the +// simulator, and to issue warning messages when deprecated features are used. +// +// Revision 1.3 2006/01/13 18:44:30 acg +// Added $Log to record CVS changes into the source. +// diff --git a/ext/systemc/src/sysc/kernel/sc_process.h b/ext/systemc/src/sysc/kernel/sc_process.h new file mode 100644 index 000000000..298e2462f --- /dev/null +++ b/ext/systemc/src/sysc/kernel/sc_process.h @@ -0,0 +1,887 @@ +/***************************************************************************** + + 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_process.h -- Process base class support. + + Original Author: Andy Goodrich, Forte Design Systems, 04 August 2005 + + + CHANGE LOG AT THE END OF THE FILE + *****************************************************************************/ + + +#if !defined(sc_process_h_INCLUDED) +#define sc_process_h_INCLUDED + +#include <cassert> +#include "sysc/utils/sc_iostream.h" +#include "sysc/kernel/sc_constants.h" +#include "sysc/kernel/sc_object.h" +#include "sysc/kernel/sc_kernel_ids.h" +#include "sysc/communication/sc_export.h" + +namespace sc_core { + +// Forward declarations: +class sc_process_handle; +class sc_thread_process; +class sc_reset; + +const char* sc_gen_unique_name( const char*, bool preserve_first ); +sc_process_handle sc_get_current_process_handle(); +void sc_thread_cor_fn( void* arg ); +bool timed_out( sc_simcontext* ); + +extern bool sc_allow_process_control_corners; // see sc_simcontext.cpp. + + +// Process handles as forward references: + +typedef class sc_cthread_process* sc_cthread_handle; +typedef class sc_method_process* sc_method_handle; +typedef class sc_thread_process* sc_thread_handle; + + +// Standard process types: + +enum sc_curr_proc_kind +{ + SC_NO_PROC_, + SC_METHOD_PROC_, + SC_THREAD_PROC_, + SC_CTHREAD_PROC_ +}; + +// Descendant information for process hierarchy operations: + +enum sc_descendant_inclusion_info { + SC_NO_DESCENDANTS=0, + SC_INCLUDE_DESCENDANTS, + SC_INVALID_DESCENDANTS +}; + +//============================================================================== +// CLASS sc_process_host +// +// This is the base class for objects which may have processes defined for +// their methods (e.g., sc_module) +//============================================================================== + +class sc_process_host +{ + public: + sc_process_host() {} + virtual ~sc_process_host() { } // Needed for cast check for sc_module. + void defunct() {} +}; + + +//============================================================================== +// CLASS sc_process_monitor +// +// This class provides a way of monitoring a process' status (e.g., waiting +// for a thread to complete its execution.) This class is intended to be a base +// class for classes which need to monitor a process or processes (e.g., +// sc_join.) Its methods should be overloaded where notifications are desired. +//============================================================================== + +class sc_process_monitor { + public: + enum { + spm_exit = 0 + }; + virtual ~sc_process_monitor() {} + virtual void signal(sc_thread_handle thread_p, int type); +}; +inline void sc_process_monitor::signal(sc_thread_handle , int ) {} + +//------------------------------------------------------------------------------ +// PROCESS INVOCATION METHOD OR FUNCTION: +// +// Define SC_USE_MEMBER_FUNC_PTR if we want to use member function pointers +// to implement process dispatch. Otherwise, we'll use a hack that involves +// creating a templated invocation object which will invoke the member +// function. This should not be necessary, but some compilers (e.g., VC++) +// do not allow the conversion from `void (callback_tag::*)()' to +// `void (sc_process_host::*)()'. This is supposed to be OK as long as the +// dynamic type is correct. C++ Standard 5.4 "Explicit type conversion", +// clause 7: a pointer to member of derived class type may be explicitly +// converted to a pointer to member of an unambiguous non-virtual base class +// type. +//----------------------------------------------------------------------------- + +#if defined(_MSC_VER) +#if ( _MSC_VER > 1200 ) +# define SC_USE_MEMBER_FUNC_PTR +#endif +#else +# define SC_USE_MEMBER_FUNC_PTR +#endif + + +// COMPILER DOES SUPPORT CAST TO void (sc_process_host::*)() from (T::*)(): + +#if defined(SC_USE_MEMBER_FUNC_PTR) + + typedef void (sc_process_host::*SC_ENTRY_FUNC)(); +# define SC_DECL_HELPER_STRUCT(callback_tag, func) /*EMPTY*/ +# define SC_MAKE_FUNC_PTR(callback_tag, func) \ + static_cast<sc_core::SC_ENTRY_FUNC>(&callback_tag::func) + + +// COMPILER NOT DOES SUPPORT CAST TO void (sc_process_host::*)() from (T::*)(): + +#else // !defined(SC_USE_MEMBER_FUNC_PTR) + class sc_process_call_base { + public: + inline sc_process_call_base() + { + } + + virtual ~sc_process_call_base() + { + } + + virtual void invoke(sc_process_host* host_p) + { + } + }; + extern sc_process_call_base sc_process_defunct; + + template<class T> + class sc_process_call : public sc_process_call_base { + public: + sc_process_call( void (T::*method_p)() ) : + sc_process_call_base() + { + m_method_p = method_p; + } + + virtual ~sc_process_call() + { + } + + virtual void invoke(sc_process_host* host_p) + { + (((T*)host_p)->*m_method_p)(); + } + + protected: + void (T::*m_method_p)(); // Method implementing the process. + }; + + typedef sc_process_call_base* SC_ENTRY_FUNC; +# define SC_DECL_HELPER_STRUCT(callback_tag, func) /*EMPTY*/ +# define SC_MAKE_FUNC_PTR(callback_tag, func) \ + (::sc_core::SC_ENTRY_FUNC) (new \ + ::sc_core::sc_process_call<callback_tag>(&callback_tag::func)) + +#endif // !defined(SC_USE_MEMBER_FUNC_PTR) + + +extern void sc_set_stack_size( sc_thread_handle, std::size_t ); + +class sc_event; +class sc_event_list; +class sc_name_gen; +class sc_spawn_options; +class sc_unwind_exception; + +//============================================================================== +// CLASS sc_throw_it<EXCEPT> - ARBITRARY EXCEPTION CLASS +// +// This class serves as a way of throwing an execption for an aribtrary type +// without knowing what that type is. A true virtual method in the base +// class is used to actually throw the execption. A pointer to the base +// class is used internally removing the necessity of knowing what the type +// of EXCEPT is for code internal to the library. +// +// Note the clone() true virtual method. This is used to allow instances +// of the sc_throw_it<EXCEPT> class to be easily garbage collected. Since +// an exception may be propogated to more than one process knowing when +// to garbage collect is non-trivial. So when a call is made to +// sc_process_handle::throw_it() an instance of sc_throw_it<EXCEPT> is +// allocated on the stack. For each process throwing the exception a copy is +// made via clone(). That allows those objects to be deleted by the individual +// processes when they are no longer needed (in this implementation of SystemC +// that deletion will occur each time a new exception is thrown ( see +// sc_thread_process::suspend_me() ). +//============================================================================== +class sc_throw_it_helper { + public: + virtual sc_throw_it_helper* clone() const = 0; + virtual void throw_it() = 0; + sc_throw_it_helper() {} + virtual ~sc_throw_it_helper() {} +}; + +template<typename EXCEPT> +class sc_throw_it : public sc_throw_it_helper +{ + typedef sc_throw_it<EXCEPT> this_type; + public: + sc_throw_it( const EXCEPT& value ) : m_value(value) { } + virtual ~sc_throw_it() {} + virtual inline this_type* clone() const { return new this_type(m_value); } + virtual inline void throw_it() { throw m_value; } + protected: + EXCEPT m_value; // value to be thrown. +}; + +//============================================================================== +// CLASS sc_process_b - USER INITIATED DYNAMIC PROCESS SUPPORT: +// +// This class implements the base class for a threaded process_base process +// whose semantics are provided by the true virtual method semantics(). +// Classes derived from this one will provide a version of semantics which +// implements the desired semantics. See the sc_spawn_xxx classes below. +// +// Notes: +// (1) Object instances of this class maintain a reference count of +// outstanding handles. When the handle count goes to zero the +// object will be deleted. +// (2) Descriptions of the methods and operators in this class appear with +// their implementations. +// (3) The m_sticky_reset field is used to handle synchronous resets that +// are enabled via the sc_process_handle::sync_reset_on() method. These +// resets are not generated by a signal, but rather are modal by +// method call: sync_reset_on - sync_reset_off. +// +//============================================================================== +class sc_process_b : public sc_object { + friend class sc_simcontext; // Allow static processes to have base. + friend class sc_cthread_process; // Child can access parent. + friend class sc_method_process; // Child can access parent. + friend class sc_process_handle; // Allow handles to modify ref. count. + friend class sc_thread_process; // Child can access parent. + + friend class sc_object; + friend class sc_port_base; + friend class sc_runnable; + friend class sc_sensitive; + friend class sc_sensitive_pos; + friend class sc_sensitive_neg; + friend class sc_module; + friend class sc_report_handler; + friend class sc_reset; + friend class sc_reset_finder; + friend class sc_unwind_exception; + + friend const char* sc_gen_unique_name( const char*, bool preserve_first ); + friend sc_process_handle sc_get_current_process_handle(); + friend void sc_thread_cor_fn( void* arg ); + friend bool timed_out( sc_simcontext* ); + + public: + enum process_throw_type { + THROW_NONE = 0, + THROW_KILL, + THROW_USER, + THROW_ASYNC_RESET, + THROW_SYNC_RESET + }; + + enum process_state { + ps_bit_disabled = 1, // process is disabled. + ps_bit_ready_to_run = 2, // process is ready to run. + ps_bit_suspended = 4, // process is suspended. + ps_bit_zombie = 8, // process is a zombie. + ps_normal = 0 // must be zero. + }; + + enum reset_type { // types for sc_process_b::reset_process() + reset_asynchronous = 0, // asynchronous reset. + reset_synchronous_off, // turn off synchronous reset sticky bit. + reset_synchronous_on // turn on synchronous reset sticky bit. + }; + + enum trigger_t + { + STATIC, + EVENT, + OR_LIST, + AND_LIST, + TIMEOUT, + EVENT_TIMEOUT, + OR_LIST_TIMEOUT, + AND_LIST_TIMEOUT + }; + + public: + sc_process_b( const char* name_p, bool is_thread, bool free_host, + SC_ENTRY_FUNC method_p, sc_process_host* host_p, + const sc_spawn_options* opt_p ); + + protected: + // may not be deleted manually (called from destroy_process()) + virtual ~sc_process_b(); + + public: + inline int current_state() { return m_state; } + bool dont_initialize() const { return m_dont_init; } + virtual void dont_initialize( bool dont ); + std::string dump_state() const; + const ::std::vector<sc_object*>& get_child_objects() const; + inline sc_curr_proc_kind proc_kind() const; + sc_event& reset_event(); + sc_event& terminated_event(); + + public: + static inline sc_process_handle last_created_process_handle(); + + protected: + virtual void add_child_object( sc_object* ); + void add_static_event( const sc_event& ); + bool dynamic() const { return m_dynamic_proc; } + const char* gen_unique_name( const char* basename_, bool preserve_first ); + inline sc_report* get_last_report() { return m_last_report_p; } + inline bool is_disabled() const; + inline bool is_runnable() const; + static inline sc_process_b* last_created_process_base(); + virtual bool remove_child_object( sc_object* ); + void remove_dynamic_events( bool skip_timeout = false ); + void remove_static_events(); + inline void set_last_report( sc_report* last_p ) + { + delete m_last_report_p; + m_last_report_p = last_p; + } + inline bool timed_out() const; + void report_error( const char* msgid, const char* msg = "" ) const; + void report_immediate_self_notification() const; + + protected: // process control methods: + virtual void disable_process( + sc_descendant_inclusion_info descendants = SC_NO_DESCENDANTS ) = 0; + void disconnect_process(); + virtual void enable_process( + sc_descendant_inclusion_info descendants = SC_NO_DESCENDANTS ) = 0; + inline void initially_in_reset( bool async ); + inline bool is_unwinding() const; + inline bool start_unwinding(); + inline bool clear_unwinding(); + virtual void kill_process( + sc_descendant_inclusion_info descendants = SC_NO_DESCENDANTS ) = 0; + void reset_changed( bool async, bool asserted ); + void reset_process( reset_type rt, + sc_descendant_inclusion_info descendants = SC_NO_DESCENDANTS ); + virtual void resume_process( + sc_descendant_inclusion_info descendants = SC_NO_DESCENDANTS ) = 0; + virtual void suspend_process( + sc_descendant_inclusion_info descendants = SC_NO_DESCENDANTS ) = 0; + virtual void throw_user( const sc_throw_it_helper& helper, + sc_descendant_inclusion_info descendants = SC_NO_DESCENDANTS ) = 0; + virtual void throw_reset( bool async ) = 0; + virtual bool terminated() const; + void trigger_reset_event(); + + private: + void delete_process(); + inline void reference_decrement(); + inline void reference_increment(); + + protected: + inline void semantics(); + + // debugging stuff: + + public: + const char* file; + int lineno; + int proc_id; + + protected: + int m_active_areset_n; // number of aresets active. + int m_active_reset_n; // number of resets active. + bool m_dont_init; // true: no initialize call. + bool m_dynamic_proc; // true: after elaboration. + const sc_event* m_event_p; // Dynamic event waiting on. + int m_event_count; // number of events. + const sc_event_list* m_event_list_p; // event list waiting on. + sc_process_b* m_exist_p; // process existence link. + bool m_free_host; // free sc_semantic_host_p. + bool m_has_reset_signal; // has reset_signal_is. + bool m_has_stack; // true is stack present. + bool m_is_thread; // true if this is thread. + sc_report* m_last_report_p; // last report this process. + sc_name_gen* m_name_gen_p; // subprocess name generator + sc_curr_proc_kind m_process_kind; // type of process. + int m_references_n; // outstanding handles. + std::vector<sc_reset*> m_resets; // resets for process. + sc_event* m_reset_event_p; // reset event. + sc_event* m_resume_event_p; // resume event. + sc_process_b* m_runnable_p; // sc_runnable link + sc_process_host* m_semantics_host_p; // host for semantics. + SC_ENTRY_FUNC m_semantics_method_p; // method for semantics. + int m_state; // process state. + std::vector<const sc_event*> m_static_events; // static events waiting on. + bool m_sticky_reset; // see note 3 above. + sc_event* m_term_event_p; // terminated event. + sc_throw_it_helper* m_throw_helper_p; // what to throw. + process_throw_type m_throw_status; // exception throwing status + bool m_timed_out; // true if we timed out. + sc_event* m_timeout_event_p; // timeout event. + trigger_t m_trigger_type; // type of trigger using. + bool m_unwinding; // true if unwinding stack. + + protected: + static sc_process_b* m_last_created_process_p; // Last process created. +}; + +typedef sc_process_b sc_process_b; // For compatibility. + + +//------------------------------------------------------------------------------ +//"sc_process_b::XXXX_child_YYYYY" +// +// These methods provide child object support. +//------------------------------------------------------------------------------ +inline void +sc_process_b::add_child_object( sc_object* object_p ) +{ + sc_object::add_child_object( object_p ); + reference_increment(); +} + +inline bool +sc_process_b::remove_child_object( sc_object* object_p ) +{ + if ( sc_object::remove_child_object( object_p ) ) { + reference_decrement(); + return true; + } + else + { + return false; + } +} + +inline const ::std::vector<sc_object*>& +sc_process_b::get_child_objects() const +{ + return m_child_objects; +} + + +//------------------------------------------------------------------------------ +//"sc_process_b::initially_in_reset" +// +// This inline method is a callback to indicate that a reset is active at +// start up. This is because the signal will have been initialized before +// a reset linkage for it is set up, so we won't get a reset_changed() +// callback. +// async = true if this an asynchronous reset. +//------------------------------------------------------------------------------ +inline void sc_process_b::initially_in_reset( bool async ) +{ + if ( async ) + m_active_areset_n++; + else + m_active_reset_n++; +} + +//------------------------------------------------------------------------------ +//"sc_process_b::is_disabled" +// +// This method returns true if this process is disabled. +//------------------------------------------------------------------------------ +inline bool sc_process_b::is_disabled() const +{ + return (m_state & ps_bit_disabled) ? true : false; +} + +//------------------------------------------------------------------------------ +//"sc_process_b::is_runnable" +// +// This method returns true if this process is runnable. That is indicated +// by a non-zero m_runnable_p field. +//------------------------------------------------------------------------------ +inline bool sc_process_b::is_runnable() const +{ + return m_runnable_p != 0; +} + +//------------------------------------------------------------------------------ +//"sc_process_b::is_unwinding" +// +// This method returns true if this process is unwinding from a kill or reset. +//------------------------------------------------------------------------------ +inline bool sc_process_b::is_unwinding() const +{ + return m_unwinding; +} + +//------------------------------------------------------------------------------ +//"sc_process_b::start_unwinding" +// +// This method flags that this object instance should start unwinding if the +// current throw status requires an unwind. +// +// Result is true if the flag is set, false if the flag is already set. +//------------------------------------------------------------------------------ +inline bool sc_process_b::start_unwinding() +{ + if ( !m_unwinding ) + { + switch( m_throw_status ) + { + case THROW_KILL: + case THROW_ASYNC_RESET: + case THROW_SYNC_RESET: + m_unwinding = true; + return true; + case THROW_USER: + default: + break; + } + } + return false; +} + +//------------------------------------------------------------------------------ +//"sc_process_b::clear_unwinding" +// +// This method clears this object instance's throw status and always returns +// true. +//------------------------------------------------------------------------------ +inline bool sc_process_b::clear_unwinding() +{ + m_unwinding = false; + return true; +} + + +//------------------------------------------------------------------------------ +//"sc_process_b::last_created_process_base" +// +// This virtual method returns the sc_process_b pointer for the last +// created process. It is only used internally by the simulator. +//------------------------------------------------------------------------------ +inline sc_process_b* sc_process_b::last_created_process_base() +{ + return m_last_created_process_p; +} + + + +//------------------------------------------------------------------------------ +//"sc_process_b::proc_kind" +// +// This method returns the kind of this process. +//------------------------------------------------------------------------------ +inline sc_curr_proc_kind sc_process_b::proc_kind() const +{ + return m_process_kind; +} + + +//------------------------------------------------------------------------------ +//"sc_process_b::reference_decrement" +// +// This inline method decrements the number of outstanding references to this +// object instance. If the number of references goes to zero, this object +// can be deleted in "sc_process_b::delete_process()". +//------------------------------------------------------------------------------ +inline void sc_process_b::reference_decrement() +{ + m_references_n--; + if ( m_references_n == 0 ) delete_process(); +} + + +//------------------------------------------------------------------------------ +//"sc_process_b::reference_increment" +// +// This inline method increments the number of outstanding references to this +// object instance. +//------------------------------------------------------------------------------ +inline void sc_process_b::reference_increment() +{ + assert(m_references_n != 0); + m_references_n++; +} + +//------------------------------------------------------------------------------ +//"sc_process_b::semantics" +// +// This inline method invokes the semantics for this object instance. +// We check to see if we are initially in reset and then invoke the +// process semantics. +// +// Notes: +// (1) For a description of the process reset mechanism see the top of +// the file sc_reset.cpp. +//------------------------------------------------------------------------------ +struct scoped_flag +{ + scoped_flag( bool& b ) : ref(b){ ref = true; } + ~scoped_flag() { ref = false; } + bool& ref; +}; +inline void sc_process_b::semantics() +{ + + // within this function, the process has a stack associated + + scoped_flag scoped_stack_flag( m_has_stack ); + + assert( m_process_kind != SC_NO_PROC_ ); + + // Determine the reset status of this object instance and potentially + // trigger its notify event: + + // See if we need to trigger the notify event: + + if ( m_reset_event_p && + ( (m_throw_status == THROW_SYNC_RESET) || + (m_throw_status == THROW_ASYNC_RESET) ) + ) { + trigger_reset_event(); + } + + // Set the new reset status of this object based on the reset counts: + + m_throw_status = m_active_areset_n ? THROW_ASYNC_RESET : + ( m_active_reset_n ? THROW_SYNC_RESET : THROW_NONE); + + // Dispatch the actual semantics for the process: + +# ifndef SC_USE_MEMBER_FUNC_PTR + m_semantics_method_p->invoke( m_semantics_host_p ); +# else + (m_semantics_host_p->*m_semantics_method_p)(); +# endif +} + + +//------------------------------------------------------------------------------ +//"sc_process_b::terminated" +// +// This inline method returns true if this object has terminated. +//------------------------------------------------------------------------------ +inline bool sc_process_b::terminated() const +{ + return (m_state & ps_bit_zombie) != 0; +} + + +//------------------------------------------------------------------------------ +//"sc_process_b::timed_out" +// +// This inline method returns true if this object instance timed out. +//------------------------------------------------------------------------------ +inline bool sc_process_b::timed_out() const +{ + return m_timed_out; +} + +} // namespace sc_core + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affiliation, date and + changes you are making here. + + Name, Affiliation, Date: Andy Goodrich, Forte Design Systems, 12 Aug 05 + Description of Modification: This is the rewrite of process support. It + contains some code from the original + sc_process.h by Stan Liao, and the now-defunct + sc_process_b.h by Stan Liao and Martin + Janssen, all of Synopsys, Inc., It also contains + code from the original sc_process_b.h by + Andy Goodrich of Forte Design Systems and + Bishnupriya Bhattacharya of Cadence Design + Systems. + + Name, Affiliation, Date: + Description of Modification: + + *****************************************************************************/ + +// $Log: sc_process.h,v $ +// Revision 1.36 2011/08/26 22:44:30 acg +// Torsten Maehne: eliminate unused argument warning. +// +// Revision 1.35 2011/08/26 20:46:10 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.34 2011/08/24 22:05:51 acg +// Torsten Maehne: initialization changes to remove warnings. +// +// Revision 1.33 2011/08/15 16:43:24 acg +// Torsten Maehne: changes to remove unused argument warnings. +// +// Revision 1.32 2011/07/24 11:20:03 acg +// Philipp A. Hartmann: process control error message improvements: +// (1) Downgrade error to warning for re-kills of processes. +// (2) Add process name to process messages. +// (3) drop some superfluous colons in messages. +// +// Revision 1.31 2011/04/13 02:44:26 acg +// Andy Goodrich: added m_unwinding flag in place of THROW_NOW because the +// throw status will be set back to THROW_*_RESET if reset is active and +// the check for an unwind being complete was expecting THROW_NONE as the +// clearing of THROW_NOW. +// +// Revision 1.30 2011/04/11 22:07:27 acg +// Andy Goodrich: check for reset event notification before resetting the +// throw_status value. +// +// Revision 1.29 2011/04/10 22:17:36 acg +// Andy Goodrich: added trigger_reset_event() to allow sc_process.h to +// contain the run_process() inline method. sc_process.h cannot have +// sc_simcontext information because of recursive includes. +// +// Revision 1.28 2011/04/08 22:34:06 acg +// Andy Goodrich: moved the semantics() method to this file and made it +// an inline method. Added reset processing to the semantics() method. +// +// Revision 1.27 2011/04/08 18:24:48 acg +// Andy Goodrich: moved reset_changed() to .cpp since it needs visibility +// to sc_simcontext. +// +// Revision 1.26 2011/04/01 21:24:57 acg +// Andy Goodrich: removed unused code. +// +// Revision 1.25 2011/03/28 13:02:51 acg +// Andy Goodrich: Changes for disable() interactions. +// +// Revision 1.24 2011/03/20 13:43:23 acg +// Andy Goodrich: added async_signal_is() plus suspend() as a corner case. +// +// Revision 1.23 2011/03/12 21:07:51 acg +// Andy Goodrich: changes to kernel generated event support. +// +// Revision 1.22 2011/03/08 20:49:31 acg +// Andy Goodrich: implement coarse checking for synchronous reset - suspend +// interaction. +// +// Revision 1.21 2011/03/07 17:38:43 acg +// Andy Goodrich: tightening up of checks for undefined interaction between +// synchronous reset and suspend. +// +// Revision 1.20 2011/03/06 19:57:11 acg +// Andy Goodrich: refinements for the illegal suspend - synchronous reset +// interaction. +// +// Revision 1.19 2011/03/05 19:44:20 acg +// Andy Goodrich: changes for object and event naming and structures. +// +// Revision 1.18 2011/02/19 08:30:53 acg +// Andy Goodrich: Moved process queueing into trigger_static from +// sc_event::notify. +// +// Revision 1.17 2011/02/18 20:27:14 acg +// Andy Goodrich: Updated Copyrights. +// +// Revision 1.16 2011/02/18 20:10:44 acg +// Philipp A. Hartmann: force return expression to be a bool to keep MSVC +// happy. +// +// Revision 1.15 2011/02/17 19:52:45 acg +// Andy Goodrich: +// (1) Simplified process control usage. +// (2) Changed dump_status() to dump_state() with new signature. +// +// Revision 1.14 2011/02/16 22:37:30 acg +// Andy Goodrich: clean up to remove need for ps_disable_pending. +// +// Revision 1.13 2011/02/13 21:47:37 acg +// Andy Goodrich: update copyright notice. +// +// Revision 1.12 2011/02/13 21:41:34 acg +// Andy Goodrich: get the log messages for the previous check in correct. +// +// Revision 1.11 2011/02/13 21:32:24 acg +// Andy Goodrich: moved sc_process_b::reset_process() implementation +// from header to cpp file . Added dump_status() to print out the status of a +// process. +// +// Revision 1.10 2011/02/11 13:25:24 acg +// Andy Goodrich: Philipp A. Hartmann's changes: +// (1) Removal of SC_CTHREAD method overloads. +// (2) New exception processing code. +// +// Revision 1.9 2011/02/04 15:27:36 acg +// Andy Goodrich: changes for suspend-resume semantics. +// +// Revision 1.8 2011/02/01 21:06:12 acg +// Andy Goodrich: new layout for the process_state enum. +// +// Revision 1.7 2011/01/25 20:50:37 acg +// Andy Goodrich: changes for IEEE 1666 2011. +// +// Revision 1.6 2011/01/19 23:21:50 acg +// Andy Goodrich: changes for IEEE 1666 2011 +// +// Revision 1.5 2011/01/18 20:10:45 acg +// Andy Goodrich: changes for IEEE1666_2011 semantics. +// +// Revision 1.4 2010/07/22 20:02:33 acg +// Andy Goodrich: bug fixes. +// +// Revision 1.3 2009/05/22 16:06:29 acg +// Andy Goodrich: process control updates. +// +// 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.11 2006/05/08 17:58:10 acg +// Andy Goodrich: added David Long's forward declarations for friend +// functions, methods, and operators to keep the Microsoft compiler happy. +// +// Revision 1.10 2006/04/28 23:29:01 acg +// Andy Goodrich: added an sc_core:: prefix to SC_FUNC_PTR in the +// SC_MAKE_FUNC_PTR macro to allow its transpareuse outside of the sc_core +// namespace. +// +// Revision 1.9 2006/04/28 21:52:57 acg +// Andy Goodrich: changed SC_MAKE_FUNC_PTR to use a static cast to address +// and AIX issue wrt sc_module's inherited classes. +// +// Revision 1.8 2006/04/20 17:08:17 acg +// Andy Goodrich: 3.0 style process changes. +// +// Revision 1.7 2006/04/11 23:13:21 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/03/13 20:26:50 acg +// Andy Goodrich: Addition of forward class declarations, e.g., +// sc_reset, to keep gcc 4.x happy. +// +// Revision 1.5 2006/01/31 20:09:10 acg +// Andy Goodrich: added explaination of static vs dynamic waits to +// sc_process_b::trigger_static. +// +// Revision 1.4 2006/01/24 20:49:05 acg +// Andy Goodrich: changes to remove the use of deprecated features within the +// simulator, and to issue warning messages when deprecated features are used. +// +// Revision 1.3 2006/01/13 18:44:30 acg +// Added $Log to record CVS changes into the source. + +#endif // !defined(sc_process_h_INCLUDED) diff --git a/ext/systemc/src/sysc/kernel/sc_process_handle.h b/ext/systemc/src/sysc/kernel/sc_process_handle.h new file mode 100644 index 000000000..c219f5fad --- /dev/null +++ b/ext/systemc/src/sysc/kernel/sc_process_handle.h @@ -0,0 +1,608 @@ +/***************************************************************************** + + 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_process_handle.h -- Process access support. + + Original Author: Andy Goodrich, Forte Design Systems, 17 June 2003 + + + CHANGE LOG AT THE END OF THE FILE + *****************************************************************************/ + +// $Log: sc_process_handle.h,v $ +// Revision 1.21 2011/08/26 21:54:04 acg +// Torsten Maehne: Simplify use of dynamic_cast<> for initializing m_target. +// +// Revision 1.20 2011/08/26 20:46:10 acg +// Andy Goodrich: moved the modification log to the end of the file to +// eliminate source line number skew when check-ins are done. +// + +#if !defined(sc_process_handle_h_INCLUDED) +#define sc_process_handle_h_INCLUDED + +#include "sysc/kernel/sc_module.h" + +namespace sc_core { + +// forward operator declarations: + +class sc_process_handle; +bool +operator == ( const sc_process_handle& left, const sc_process_handle& right ); +bool +operator != ( const sc_process_handle& left, const sc_process_handle& right ); +bool +operator < ( const sc_process_handle& left, const sc_process_handle& right ); + + + +//============================================================================= +// CLASS sc_process_handle +// +// This class provides access to an sc_process_b object instance in a +// manner which allows some persistence after the deletion of the actual +// process. +//============================================================================= +class sc_simcontext; +class sc_process_handle { + typedef sc_process_handle this_type; + + friend bool operator == ( const this_type& left, const this_type& right ); + friend bool operator != ( const this_type& left, const this_type& right ); + friend bool operator < ( const this_type& left, const this_type& right ); + friend class sc_object; + friend class sc_join; + friend class sc_module; + friend class sc_reset; + friend class sc_sensitive; + friend class sc_sensitive_pos; + friend class sc_sensitive_neg; + friend class sc_thread_process; + + public: + inline sc_process_handle(); + inline explicit sc_process_handle( sc_object* object_p ); + inline explicit sc_process_handle( sc_process_b* process_p ); + inline sc_process_handle( const sc_process_handle& orig ); + inline ~sc_process_handle(); + inline sc_process_handle& operator = ( sc_process_handle src ); + inline void swap( sc_process_handle& other ); + + public: + inline void disable( + sc_descendant_inclusion_info descendants=SC_NO_DESCENDANTS ); + inline bool dynamic() const; + inline void enable( + sc_descendant_inclusion_info descendants=SC_NO_DESCENDANTS ); + inline const std::vector<sc_event*>& get_child_events() const; + inline const std::vector<sc_object*>& get_child_objects() const; + inline sc_object* get_parent_object() const; + inline sc_object* get_process_object() const; + inline bool is_unwinding() const; + inline void kill( + sc_descendant_inclusion_info descendants=SC_NO_DESCENDANTS ); + inline const char* name() const; + inline sc_curr_proc_kind proc_kind() const; + inline void reset( + sc_descendant_inclusion_info descendants=SC_NO_DESCENDANTS ); + inline sc_event& reset_event() const; + inline void resume( + sc_descendant_inclusion_info descendants=SC_NO_DESCENDANTS ); + inline void suspend( + sc_descendant_inclusion_info descendants=SC_NO_DESCENDANTS ); + inline void sync_reset_off( + sc_descendant_inclusion_info descendants=SC_NO_DESCENDANTS ); + inline void sync_reset_on( + sc_descendant_inclusion_info descendants=SC_NO_DESCENDANTS ); + inline sc_event& terminated_event(); + inline bool terminated() const; + template<typename EXCEPT> + inline void throw_it( const EXCEPT& exception, + sc_descendant_inclusion_info descendants=SC_NO_DESCENDANTS ); + inline bool valid() const; + + public: // implementation specific methods: + inline std::string dump_state() const; + + protected: + inline bool dont_initialize() const + { return m_target_p ? m_target_p->dont_initialize() : false; } + inline void dont_initialize( bool dont ); + + public: + operator sc_process_b* () + { return m_target_p; } + operator sc_cthread_handle (); + operator sc_method_handle (); + operator sc_thread_handle (); + + protected: + sc_process_b* m_target_p; // Target for this object instance. + + protected: + static std::vector<sc_event*> empty_event_vector; // If m_target_p == 0. + static std::vector<sc_object*> empty_object_vector; // If m_target_p == 0. + static sc_event non_event; // If m_target_p == 0. +}; + +inline bool operator == ( + const sc_process_handle& left, const sc_process_handle& right ) +{ + return (left.m_target_p != 0) && (right.m_target_p != 0) && + (left.m_target_p == right.m_target_p); +} + +inline bool operator != ( + const sc_process_handle& left, const sc_process_handle& right ) +{ + return (left.m_target_p == 0) || (right.m_target_p == 0) || + (left.m_target_p != right.m_target_p); +} + +inline bool operator < ( + const sc_process_handle& left, const sc_process_handle& right ) +{ + return left.m_target_p < right.m_target_p; +} + +//------------------------------------------------------------------------------ +//"sc_process_handle::sc_process_handle - non-pointer constructor" +// +// This version of the object instance constructor for this class creates +// an object instance whose target needs to be supplied via an assignment. +//------------------------------------------------------------------------------ +inline sc_process_handle::sc_process_handle() : m_target_p(0) +{ +} + +//------------------------------------------------------------------------------ +//"sc_process_handle::sc_process_handle - pointer constructor" +// +// This version of the object instance constructor for this class creates +// an object instance whose target is the supplied sc_object instance. +// The supplied sc_object must in fact be an sc_process_b instance. +// object_p -> sc_object instance this is handle for. +//------------------------------------------------------------------------------ +inline sc_process_handle::sc_process_handle( sc_object* object_p ) : + m_target_p(DCAST<sc_process_b*>(object_p)) +{ + if ( m_target_p ) m_target_p->reference_increment(); +} + +//------------------------------------------------------------------------------ +//"sc_process_handle::sc_process_handle - pointer constructor" +// +// This version of the object instance constructor for this class creates +// an object instance whose target is the supplied sc_process_b instance. +// This saves a dynamic cast compared to the sc_object* case. +// process_p -> process instance this is handle for. +//------------------------------------------------------------------------------ +inline sc_process_handle::sc_process_handle( sc_process_b* process_p ) : + m_target_p(process_p) +{ + if ( m_target_p ) m_target_p->reference_increment(); +} + +//------------------------------------------------------------------------------ +//"sc_process_handle::sc_process_handle - copy constructor" +// +// This version of the object instance constructor for this class provides +// the copy constructor for the class. It clones the supplied original +// handle and increments the references to its target. +// orig = sc_process_handle object instance to be copied from. +//------------------------------------------------------------------------------ +inline sc_process_handle::sc_process_handle( const sc_process_handle& orig ) : + m_target_p(orig.m_target_p) +{ + if ( m_target_p ) m_target_p->reference_increment(); +} + + +//------------------------------------------------------------------------------ +//"sc_process_handle::operator =" +// +// This assignment operator signature is call by value rather than reference. +// This means that an sc_process_handle instance will be created and the +// target for that instance will be incremented before the assignment is done. +// The assignment is done using the swap() method, which simply swaps the +// targets of 'orig' and this object instance. We don't need to increment +// the reference count for our new target since that was done when 'orig' +// was created. Our old target's reference count will be decremented when +// 'orig' is deleted. +// orig = sc_process_handle object instance to be copied from. +// Result is a reference for this object instance. +//------------------------------------------------------------------------------ +inline sc_process_handle& +sc_process_handle::operator = ( sc_process_handle orig ) +{ + swap( orig ); + return *this; +} + + +//------------------------------------------------------------------------------ +//"sc_process_handle::~sc_process_handle" +// +// This is the object instance destructor for this class. It decrements +// the reference count for its target. +//------------------------------------------------------------------------------ +inline sc_process_handle::~sc_process_handle() +{ + if ( m_target_p ) m_target_p->reference_decrement(); +} + +//------------------------------------------------------------------------------ +//"sc_process_handle::inline methods" +// +// These are short inline methods. +//------------------------------------------------------------------------------ + +// disable this object instance's target. + +inline void sc_process_handle::disable(sc_descendant_inclusion_info descendants) +{ + if ( m_target_p ) + m_target_p->disable_process(descendants); + else + SC_REPORT_WARNING( SC_ID_EMPTY_PROCESS_HANDLE_, "disable()"); +} + +// call dont_initialize() on this object instance's target. + +inline void sc_process_handle::dont_initialize( bool dont ) +{ + if ( m_target_p ) + m_target_p->dont_initialize( dont ); + else + SC_REPORT_WARNING( SC_ID_EMPTY_PROCESS_HANDLE_, "dont_initialize()"); +} + +// dump the status of this object instance's target: + +inline std::string sc_process_handle::dump_state() const +{ + return m_target_p ? m_target_p->dump_state() : std::string("NO TARGET"); +} + +// return whether this object instance's target is dynamic or not. + +inline bool sc_process_handle::dynamic() const +{ + return m_target_p ? m_target_p->dynamic() : false; +} + +// enable this object instance's target. + +inline void sc_process_handle::enable(sc_descendant_inclusion_info descendants) +{ + if ( m_target_p ) + m_target_p->enable_process(descendants); + else + SC_REPORT_WARNING( SC_ID_EMPTY_PROCESS_HANDLE_, "enable()"); +} + +// return the child objects for this object instance's target. + +inline +const std::vector<sc_event*>& sc_process_handle::get_child_events() const +{ + return m_target_p ? m_target_p->get_child_events() : empty_event_vector; +} + +// return the child objects for this object instance's target. + +inline +const std::vector<sc_object*>& sc_process_handle::get_child_objects() const +{ + return m_target_p ? m_target_p->get_child_objects() : empty_object_vector; +} + +// return the parent object for this object instance's target. + +inline sc_object* sc_process_handle::get_parent_object() const +{ + return m_target_p ? m_target_p->get_parent_object() : NULL; +} + +// return this object instance's target. + +inline sc_object* sc_process_handle::get_process_object() const +{ + return m_target_p; +} + +// return whether this object instance is unwinding or not. + +inline bool sc_process_handle::is_unwinding() const +{ + if ( m_target_p ) + return m_target_p->is_unwinding(); + else { + SC_REPORT_WARNING( SC_ID_EMPTY_PROCESS_HANDLE_, "is_unwinding()"); + return false; + } +} + +// kill this object instance's target. + +inline void sc_process_handle::kill( sc_descendant_inclusion_info descendants ) +{ + if ( m_target_p ) + m_target_p->kill_process( descendants ); + else + SC_REPORT_WARNING( SC_ID_EMPTY_PROCESS_HANDLE_, "kill()"); +} + +// return the name of this object instance's target. + +inline const char* sc_process_handle::name() const +{ + return m_target_p ? m_target_p->name() : ""; +} + +// return the process kind for this object instance's target. + +inline sc_curr_proc_kind sc_process_handle::proc_kind() const +{ + return m_target_p ? m_target_p->proc_kind() : SC_NO_PROC_; +} + +// reset this object instance's target. + +inline void sc_process_handle::reset( sc_descendant_inclusion_info descendants ) +{ + if ( m_target_p ) + m_target_p->reset_process( sc_process_b::reset_asynchronous, + descendants ); + else + SC_REPORT_WARNING( SC_ID_EMPTY_PROCESS_HANDLE_, "reset()"); +} + +// return the reset event for this object instance's target. + +inline sc_event& sc_process_handle::reset_event() const +{ + if ( m_target_p ) + return m_target_p->reset_event(); + else + { + SC_REPORT_WARNING( SC_ID_EMPTY_PROCESS_HANDLE_, "reset()"); + return sc_process_handle::non_event; + } +} + +// resume this object instance's target. + +inline void sc_process_handle::resume(sc_descendant_inclusion_info descendants) +{ + if ( m_target_p ) + m_target_p->resume_process(descendants); + else + SC_REPORT_WARNING( SC_ID_EMPTY_PROCESS_HANDLE_, "resume()"); +} + +// suspend this object instance's target. + +inline void sc_process_handle::suspend(sc_descendant_inclusion_info descendants) +{ + if ( m_target_p ) + m_target_p->suspend_process(descendants); + else + SC_REPORT_WARNING( SC_ID_EMPTY_PROCESS_HANDLE_, "suspend()"); +} + +// swap targets of this process handle with the supplied one. + +inline void sc_process_handle::swap( sc_process_handle& other ) +{ + sc_process_b* tmp = m_target_p; + m_target_p = other.m_target_p; + other.m_target_p = tmp; +} + +// turn sync_reset off for this object instance's target. + +inline void sc_process_handle::sync_reset_off( + sc_descendant_inclusion_info descendants) +{ + if ( m_target_p ) + m_target_p->reset_process( sc_process_b::reset_synchronous_off, + descendants); + else + SC_REPORT_WARNING( SC_ID_EMPTY_PROCESS_HANDLE_, "sync_reset_off()"); +} + +// turn sync_reset on for this object instance's target. + +inline void sc_process_handle::sync_reset_on( + sc_descendant_inclusion_info descendants) +{ + if ( m_target_p ) + { + m_target_p->reset_process(sc_process_b::reset_synchronous_on, + descendants); + } + else + { + SC_REPORT_WARNING( SC_ID_EMPTY_PROCESS_HANDLE_, "sync_reset_on()"); + } +} + +// terminate this object instance's target. + +inline bool sc_process_handle::terminated() const +{ + return m_target_p ? m_target_p->terminated() : false; +} + +// return the termination event for this object instance's target. + +inline sc_event& sc_process_handle::terminated_event() +{ + if ( m_target_p ) + return m_target_p->terminated_event(); + else + { + SC_REPORT_WARNING( SC_ID_EMPTY_PROCESS_HANDLE_, "terminated_event()"); + return sc_process_handle::non_event; + } +} + +// return true if this object instance has a target, false it not. + +inline bool sc_process_handle::valid() const +{ + return m_target_p ? true : false; +} + +//------------------------------------------------------------------------------ +//"sc_process_handle::sc_throw_it" +// +// This method throws the supplied exception to the process whose handle this +// object instance is, and optionally to the process' descendants. Once the +// exception is thrown the currently executed process will suspend to allow +// the exception to be propagated. Once the propagation has occurred the +// current process will be resumed. +// +// Notes: +// (1) We allocate the helper function on the stack, see the description of +// sc_throw_it<EXCEPT>, in sc_process.h, for why. +// +// Arguments: +// exception = exception to be thrown +// descendants = indication of whether descendant processes should also +// receive the throw. +//------------------------------------------------------------------------------ +template<typename EXCEPT> +inline void sc_process_handle::throw_it( const EXCEPT& exception, + sc_descendant_inclusion_info descendants) +{ + sc_throw_it<EXCEPT> helper(exception); // helper to throw the exception. + + if ( !m_target_p ) + { + SC_REPORT_WARNING( SC_ID_EMPTY_PROCESS_HANDLE_, "throw_it()"); + return; + } + m_target_p->throw_user(helper, descendants); +} + + +//------------------------------------------------------------------------------ +//"sc_process_b::last_created_process_handle" +// +// This method returns the kind of this process. +//------------------------------------------------------------------------------ +inline sc_process_handle sc_process_b::last_created_process_handle() +{ + return sc_process_handle(m_last_created_process_p); +} + +inline sc_process_handle sc_get_last_created_process_handle() +{ + return sc_process_b::last_created_process_handle(); +} + +} // namespace sc_core + +// Revision 1.19 2011/08/24 22:05:51 acg +// Torsten Maehne: initialization changes to remove warnings. +// +// Revision 1.18 2011/04/01 22:08:26 acg +// Andy Goodrich: remove unused variable. +// +// Revision 1.17 2011/03/12 21:07:51 acg +// Andy Goodrich: changes to kernel generated event support. +// +// Revision 1.16 2011/02/18 20:27:14 acg +// Andy Goodrich: Updated Copyrights. +// +// Revision 1.15 2011/02/17 19:53:03 acg +// Andy Goodrich: changed dump_status() to dump_state() with new signature. +// +// Revision 1.14 2011/02/13 21:47:37 acg +// Andy Goodrich: update copyright notice. +// +// Revision 1.13 2011/02/13 21:33:30 acg +// Andy Goodrich: added dump_status() to allow the dumping of the status +// of a process handle's target. +// +// Revision 1.12 2011/02/01 23:01:53 acg +// Andy Goodrich: removed dead code. +// +// Revision 1.11 2011/02/01 21:07:36 acg +// Andy Goodrich: defering of run queue manipulations to the +// sc_thread_process::throw_it() method. +// +// Revision 1.10 2011/01/25 20:50:37 acg +// Andy Goodrich: changes for IEEE 1666 2011. +// +// Revision 1.9 2011/01/20 16:52:20 acg +// Andy Goodrich: changes for IEEE 1666 2011. +// +// Revision 1.8 2011/01/19 23:21:50 acg +// Andy Goodrich: changes for IEEE 1666 2011 +// +// Revision 1.7 2011/01/18 20:10:45 acg +// Andy Goodrich: changes for IEEE1666_2011 semantics. +// +// Revision 1.6 2010/07/30 05:21:22 acg +// Andy Goodrich: release 2.3 fixes. +// +// Revision 1.5 2010/07/22 20:02:33 acg +// Andy Goodrich: bug fixes. +// +// Revision 1.4 2009/05/22 16:06:29 acg +// Andy Goodrich: process control updates. +// +// Revision 1.3 2008/05/22 17:06:26 acg +// Andy Goodrich: updated copyright notice to include 2008. +// +// Revision 1.2 2007/09/20 20:32:35 acg +// Andy Goodrich: changes to the semantics of throw_it() to match the +// specification. A call to throw_it() will immediately suspend the calling +// thread until all the throwees have executed. At that point the calling +// thread will be restarted before the execution of any other threads. +// +// Revision 1.1.1.1 2006/12/15 20:20:05 acg +// SystemC 2.3 +// +// Revision 1.7 2006/05/08 17:58:24 acg +// Andy Goodrich: added David Long's forward declarations for friend +// functions, methods, and operators to keep the Microsoft compiler happy. +// +// Revision 1.6 2006/04/20 17:08:17 acg +// Andy Goodrich: 3.0 style process changes. +// +// Revision 1.5 2006/04/11 23:13:21 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.4 2006/01/24 20:49:05 acg +// Andy Goodrich: changes to remove the use of deprecated features within the +// simulator, and to issue warning messages when deprecated features are used. +// +// Revision 1.3 2006/01/13 18:44:30 acg +// Added $Log to record CVS changes into the source. + +#endif // !defined(sc_spawn_h_INCLUDED) diff --git a/ext/systemc/src/sysc/kernel/sc_reset.cpp b/ext/systemc/src/sysc/kernel/sc_reset.cpp new file mode 100644 index 000000000..2e4bc6c6e --- /dev/null +++ b/ext/systemc/src/sysc/kernel/sc_reset.cpp @@ -0,0 +1,440 @@ +/***************************************************************************** + + 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_reset.cpp -- Support for reset. + + Original Author: Andy Goodrich, Forte Design Systems + + CHANGE LOG AT THE END OF THE FILE + *****************************************************************************/ + + +#include "sysc/kernel/sc_simcontext.h" +#include "sysc/kernel/sc_reset.h" +#include "sysc/kernel/sc_process_handle.h" +#include "sysc/communication/sc_signal.h" +#include "sysc/communication/sc_signal_ports.h" + + +// THE SYSTEMC PROOF OF CONCEPT SIMULATOR RESET SIGNAL IMPLEMENTATION: +// +// (1) An instance of the sc_reset class is attached to each sc_signal<bool> +// that is used as a reset signal. +// +// (2) Each process that is senstive to a reset signal will be registered in the +// sc_reset class attached to that reset signal. +// +// (3) When a change in the value of a reset signal occurs it invokes the +// notify_processes() method of its sc_reset object instance. The +// notify_processes() method will call the reset_changed() method of each +// process that is registered with it to inform the process that +// state of the reset signal has changed. +// +// (4) A process may have multiple reset signals, so counters are kept for the +// number of active asynchronous, and synchronous, reset signals that are +// active. Those counters are incremented and decremented in the process' +// reset_changed() method. +// +// (5) When a process' semantics() method is called the current reset state is +// checked, and a reset sequence is initiated if the process is in reset. +// This will occur every time an SC_METHOD is dispatched. SC_CTHREAD and +// and SC_THREAD instances, only go through the semantics() method they +// initially start up. So the reset check is duplicated in the suspend_me() +// method, the tail of which will execute each time the thread is +// dispatched. + +namespace sc_core { + +class sc_reset_finder; +static sc_reset_finder* reset_finder_q=0; // Q of reset finders to reconcile. + +//============================================================================== +// sc_reset_finder - place holder class for a port reset signal until it is +// bound and an interface class is available. When the port +// has been bound the information in this class will be used +// to initialize its sc_reset object instance. +//============================================================================== +class sc_reset_finder { + friend class sc_reset; + public: + sc_reset_finder( bool async, const sc_in<bool>* port_p, bool level, + sc_process_b* target_p); + sc_reset_finder( bool async, const sc_inout<bool>* port_p, bool level, + sc_process_b* target_p); + sc_reset_finder( bool async, const sc_out<bool>* port_p, bool level, + sc_process_b* target_p); + + protected: + bool m_async; // True if asynchronous reset. + bool m_level; // Level for reset. + sc_reset_finder* m_next_p; // Next reset finder in list. + const sc_in<bool>* m_in_p; // Port for which reset is needed. + const sc_inout<bool>* m_inout_p; // Port for which reset is needed. + const sc_out<bool>* m_out_p; // Port for which reset is needed. + sc_process_b* m_target_p; // Process to reset. + + private: // disabled + sc_reset_finder( const sc_reset_finder& ); + const sc_reset_finder& operator = ( const sc_reset_finder& ); +}; + +inline sc_reset_finder::sc_reset_finder( + bool async, const sc_in<bool>* port_p, bool level, sc_process_b* target_p) : + m_async(async), m_level(level), m_next_p(0), m_in_p(port_p), m_inout_p(0), + m_out_p(0), m_target_p(target_p) +{ + m_next_p = reset_finder_q; + reset_finder_q = this; +} + +inline sc_reset_finder::sc_reset_finder( + bool async, const sc_inout<bool>* port_p, bool level, sc_process_b* target_p +) : + m_async(async), m_level(level), m_next_p(0), m_in_p(0), m_inout_p(port_p), + m_out_p(0), m_target_p(target_p) +{ + m_next_p = reset_finder_q; + reset_finder_q = this; +} + +inline sc_reset_finder::sc_reset_finder( + bool async, const sc_out<bool>* port_p, bool level, sc_process_b* target_p +) : + m_async(async), m_level(level), m_next_p(0), m_in_p(0), m_inout_p(0), + m_out_p(port_p), m_target_p(target_p) +{ + m_next_p = reset_finder_q; + reset_finder_q = this; +} + + +//------------------------------------------------------------------------------ +//"sc_reset::notify_processes" +// +// Notify processes that there is a change in the reset signal value. +//------------------------------------------------------------------------------ +void sc_reset::notify_processes() +{ + bool active; // true if reset is active. + sc_reset_target* entry_p; // reset entry processing. + std::vector<sc_reset_target>::size_type process_i; // index of process resetting. + std::vector<sc_reset_target>::size_type process_n; // # of processes to reset. + bool value; // value of our signal. + + value = m_iface_p->read(); + process_n = m_targets.size(); + for ( process_i = 0; process_i < process_n; process_i++ ) + { + entry_p = &m_targets[process_i]; + active = ( entry_p->m_level == value ); + entry_p->m_process_p->reset_changed( entry_p->m_async, active ); + } +} + + +//------------------------------------------------------------------------------ +//"sc_reset::reconcile_resets" +// +// This static method processes the sc_reset_finders to establish the actual +// reset connections. +// +// Notes: +// (1) If reset is asserted we tell the process that it is in reset. +//------------------------------------------------------------------------------ +void sc_reset::reconcile_resets() +{ + const sc_signal_in_if<bool>* iface_p; // Interface to reset signal. + sc_reset_finder* next_p; // Next finder to process. + sc_reset_finder* now_p; // Finder currently processing. + sc_reset_target reset_target; // Target's reset entry. + sc_reset* reset_p; // Reset object to use. + + for ( now_p = reset_finder_q; now_p; now_p = next_p ) + { + next_p = now_p->m_next_p; + if ( now_p->m_in_p ) + { + iface_p = DCAST<const sc_signal_in_if<bool>*>( + now_p->m_in_p->get_interface()); + } + else if ( now_p->m_inout_p ) + { + iface_p = DCAST<const sc_signal_in_if<bool>*>( + now_p->m_inout_p->get_interface()); + } + else + { + iface_p = DCAST<const sc_signal_in_if<bool>*>( + now_p->m_out_p->get_interface()); + } + assert( iface_p != 0 ); + reset_p = iface_p->is_reset(); + now_p->m_target_p->m_resets.push_back(reset_p); + reset_target.m_async = now_p->m_async; + reset_target.m_level = now_p->m_level; + reset_target.m_process_p = now_p->m_target_p; + reset_p->m_targets.push_back(reset_target); + if ( iface_p->read() == now_p->m_level ) // see note 1 above + now_p->m_target_p->initially_in_reset( now_p->m_async ); + delete now_p; + } +} + + +//------------------------------------------------------------------------------ +//"sc_reset::remove_process" +// +// This method removes the supplied process from the list of processes that +// should be notified when there is a change in the value of the reset signal. +// +// Arguments: +// process_p -> process to be removed. +//------------------------------------------------------------------------------ +void sc_reset::remove_process( sc_process_b* process_p ) +{ + int process_i; // Index of process resetting. + int process_n; // # of processes to reset. + + process_n = m_targets.size(); + for ( process_i = 0; process_i < process_n; ) + { + if ( m_targets[process_i].m_process_p == process_p ) + { + m_targets[process_i] = m_targets[process_n-1]; + process_n--; + m_targets.resize(process_n); + } + else + { + process_i++; + } + } +} + +//------------------------------------------------------------------------------ +//"sc_reset::reset_signal_is - ports" +// +// These overloads of the reset_signal_is() method will register the active +// process with the sc_reset object instance associated with the supplied port. +// If the port does not yet have a pointer to its sc_signal<bool> instance it +// will create an sc_reset_finder class object instance that will be used +// to set the process' reset information when the port has been bound. +// +// Arguments: +// async = true if the reset signal is asynchronous, false if not. +// port = port for sc_signal<bool> that will provide the reset signal. +// level = level at which reset is active, either true or false. +//------------------------------------------------------------------------------ +void sc_reset::reset_signal_is( bool async, const sc_in<bool>& port, bool level) +{ + const sc_signal_in_if<bool>* iface_p; + sc_process_b* process_p; + + process_p = (sc_process_b*)sc_get_current_process_handle(); + assert( process_p ); + process_p->m_has_reset_signal = true; + switch ( process_p->proc_kind() ) + { + case SC_THREAD_PROC_: + case SC_METHOD_PROC_: + case SC_CTHREAD_PROC_: + iface_p = DCAST<const sc_signal_in_if<bool>*>(port.get_interface()); + if ( iface_p ) + reset_signal_is( async, *iface_p, level ); + else + new sc_reset_finder( async, &port, level, process_p ); + break; + default: + SC_REPORT_ERROR(SC_ID_UNKNOWN_PROCESS_TYPE_, process_p->name()); + break; + } +} + +void sc_reset::reset_signal_is( + bool async, const sc_inout<bool>& port, bool level ) +{ + const sc_signal_in_if<bool>* iface_p; + sc_process_b* process_p; + + process_p = (sc_process_b*)sc_get_current_process_handle(); + assert( process_p ); + process_p->m_has_reset_signal = true; + switch ( process_p->proc_kind() ) + { + case SC_THREAD_PROC_: + case SC_METHOD_PROC_: + case SC_CTHREAD_PROC_: + iface_p = DCAST<const sc_signal_in_if<bool>*>(port.get_interface()); + if ( iface_p ) + reset_signal_is( async, *iface_p, level ); + else + new sc_reset_finder( async, &port, level, process_p ); + break; + default: + SC_REPORT_ERROR(SC_ID_UNKNOWN_PROCESS_TYPE_, process_p->name()); + break; + } +} + +void sc_reset::reset_signal_is( + bool async, const sc_out<bool>& port, bool level ) +{ + const sc_signal_in_if<bool>* iface_p; + sc_process_b* process_p; + + process_p = (sc_process_b*)sc_get_current_process_handle(); + assert( process_p ); + process_p->m_has_reset_signal = true; + switch ( process_p->proc_kind() ) + { + case SC_THREAD_PROC_: + case SC_METHOD_PROC_: + case SC_CTHREAD_PROC_: + iface_p = DCAST<const sc_signal_in_if<bool>*>(port.get_interface()); + if ( iface_p ) + reset_signal_is( async, *iface_p, level ); + else + new sc_reset_finder( async, &port, level, process_p ); + break; + default: + SC_REPORT_ERROR(SC_ID_UNKNOWN_PROCESS_TYPE_, process_p->name()); + break; + } +} + +//------------------------------------------------------------------------------ +//"sc_reset::reset_signal_is" +// +// This static method will register the active process instance as being +// reset by the sc_signal<bool> whose interface has been supplied. If no +// sc_reset object instance has been attached to the sc_signal<bool> yet, it +// will be created and attached. The active process instance is pushed into +// the list of processes that the sc_reset object instance should notify if +// the value of the reset signal changes. +// +// Arguments: +// async = true if the reset signal is asynchronous, false if not. +// iface = interface for the reset signal. +// level = is the level at which reset is active, either true or false. +// Notes: +// (1) If reset is asserted we tell the process that it is in reset +// initially. +//------------------------------------------------------------------------------ +void sc_reset::reset_signal_is( + bool async, const sc_signal_in_if<bool>& iface, bool level ) +{ + sc_process_b* process_p; // process adding reset for. + sc_reset_target reset_target; // entry to build for the process. + sc_reset* reset_p; // reset object. + + process_p = sc_process_b::last_created_process_base(); + assert( process_p ); + process_p->m_has_reset_signal = true; + switch ( process_p->proc_kind() ) + { + case SC_METHOD_PROC_: + case SC_CTHREAD_PROC_: + case SC_THREAD_PROC_: + reset_p = iface.is_reset(); + process_p->m_resets.push_back(reset_p); + reset_target.m_async = async; + reset_target.m_level = level; + reset_target.m_process_p = process_p; + reset_p->m_targets.push_back(reset_target); + if ( iface.read() == level ) process_p->initially_in_reset( async ); + break; + default: + SC_REPORT_ERROR(SC_ID_UNKNOWN_PROCESS_TYPE_, process_p->name()); + break; + } +} + +} // namespace sc_core + +// $Log: sc_reset.cpp,v $ +// Revision 1.16 2011/08/26 20:46:10 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.15 2011/08/24 22:05:51 acg +// Torsten Maehne: initialization changes to remove warnings. +// +// Revision 1.14 2011/04/08 22:37:34 acg +// Andy Goodrich: documentation of the reset mechanism and additional +// documentation of methods. Removal of check for SC_METHODs in +// sc_reset_signal_is() that should not have been there. +// +// Revision 1.13 2011/03/20 15:13:01 acg +// Andy Goodrich: set the reset flag for async_reset_signal_is to catch +// the suspend() corner case. +// +// Revision 1.12 2011/03/20 13:43:23 acg +// Andy Goodrich: added async_signal_is() plus suspend() as a corner case. +// +// Revision 1.11 2011/03/06 19:57:11 acg +// Andy Goodrich: refinements for the illegal suspend - synchronous reset +// interaction. +// +// Revision 1.10 2011/02/18 20:27:14 acg +// Andy Goodrich: Updated Copyrights. +// +// Revision 1.9 2011/02/13 21:47:37 acg +// Andy Goodrich: update copyright notice. +// +// Revision 1.8 2011/02/01 21:08:26 acg +// Andy Goodrich: new multiple reset support. +// +// Revision 1.7 2011/01/06 18:04:38 acg +// Andy Goodrich: removed commented out code. +// +// Revision 1.6 2010/12/07 20:09:13 acg +// Andy Goodrich: removed sc_signal overloads since already have sc_signal_in_if overloads. +// +// Revision 1.5 2010/11/20 17:10:56 acg +// Andy Goodrich: reset processing changes for new IEEE 1666 standard. +// +// Revision 1.4 2009/05/22 16:06:29 acg +// Andy Goodrich: process control updates. +// +// Revision 1.3 2009/03/12 22:59:58 acg +// Andy Goodrich: updates for 2.4 stuff. +// +// 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.7 2006/12/02 20:58:19 acg +// Andy Goodrich: updates from 2.2 for IEEE 1666 support. +// +// Revision 1.5 2006/04/11 23:13:21 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.4 2006/01/24 20:49:05 acg +// Andy Goodrich: changes to remove the use of deprecated features within the +// simulator, and to issue warning messages when deprecated features are used. +// +// Revision 1.3 2006/01/13 18:44:30 acg +// Added $Log to record CVS changes into the source. +// diff --git a/ext/systemc/src/sysc/kernel/sc_reset.h b/ext/systemc/src/sysc/kernel/sc_reset.h new file mode 100644 index 000000000..f0992bb16 --- /dev/null +++ b/ext/systemc/src/sysc/kernel/sc_reset.h @@ -0,0 +1,164 @@ +/***************************************************************************** + + 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_reset.h -- Process reset support. + + Original Author: Andy Goodrich, Forte Design Systems, 17 June 2003 + + CHANGE LOG AT THE END OF THE FILE + *****************************************************************************/ + +#if !defined(sc_reset_h_INCLUDED) +#define sc_reset_h_INCLUDED + +#include "sysc/communication/sc_writer_policy.h" + +namespace sc_core { + +// FORWARD CLASS REFERENCES: + +template<typename DATA> class sc_signal_in_if; +template<typename IF, sc_writer_policy POL> class sc_signal; +template<typename DATA> class sc_in; +template<typename DATA> class sc_inout; +template<typename DATA> class sc_out; +template<typename SOURCE> class sc_spawn_reset; +class sc_reset; +class sc_process_b; + +//============================================================================== +// CLASS sc_reset_target - RESET ENTRY FOR AN sc_process_b TARGET +// +// This class describes a reset condition associated with an sc_process_b +// instance. +//============================================================================== +class sc_reset_target { + public: + bool m_async; // true asynchronous reset, false synchronous. + bool m_level; // level for reset. + sc_process_b* m_process_p; // process this reset entry is for. +}; + +inline std::ostream& operator << ( std::ostream& os, + const sc_reset_target& target ) +{ + os << "["; + os << target.m_async << ","; + os << target.m_level << ","; + os << target.m_process_p << ","; + return os; +} + +//============================================================================== +// CLASS sc_reset - RESET INFORMATION FOR A RESET SIGNAL +// +// See the top of sc_reset.cpp for an explaination of how the reset mechanism +// is implemented. +//============================================================================== +class sc_reset { + friend class sc_cthread_process; + friend class sc_method_process; + friend class sc_module; + friend class sc_process_b; + friend class sc_signal<bool, SC_ONE_WRITER>; + friend class sc_signal<bool, SC_MANY_WRITERS>; + friend class sc_signal<bool, SC_UNCHECKED_WRITERS>; + friend class sc_simcontext; + template<typename SOURCE> friend class sc_spawn_reset; + friend class sc_thread_process; + + protected: + static void reconcile_resets(); + static void + reset_signal_is(bool async, const sc_signal_in_if<bool>& iface, + bool level); + static void + reset_signal_is( bool async, const sc_in<bool>& iface, bool level); + static void + reset_signal_is( bool async, const sc_inout<bool>& iface, bool level); + static void + reset_signal_is( bool async, const sc_out<bool>& iface, bool level); + + protected: + sc_reset( const sc_signal_in_if<bool>* iface_p ) : + m_iface_p(iface_p), m_targets() {} + void notify_processes(); + void remove_process( sc_process_b* ); + + protected: + const sc_signal_in_if<bool>* m_iface_p; // Interface to read. + std::vector<sc_reset_target> m_targets; // List of processes to reset. + + private: // disabled + sc_reset( const sc_reset& ); + const sc_reset& operator = ( const sc_reset& ); +}; + +// $Log: sc_reset.h,v $ +// Revision 1.11 2011/08/26 20:46:10 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.10 2011/08/24 22:05:51 acg +// Torsten Maehne: initialization changes to remove warnings. +// +// Revision 1.9 2011/04/08 22:38:30 acg +// Andy Goodrich: added comment pointing to the description of how the +// reset mechanism works that is in sc_reset.cpp. +// +// Revision 1.8 2011/02/18 20:27:14 acg +// Andy Goodrich: Updated Copyrights. +// +// Revision 1.7 2011/02/13 21:47:37 acg +// Andy Goodrich: update copyright notice. +// +// Revision 1.6 2011/01/06 18:00:32 acg +// Andy Goodrich: Removed commented out code. +// +// Revision 1.5 2010/12/07 20:09:14 acg +// Andy Goodrich: removed sc_signal signatures since already have sc_signal_in_if signatures. +// +// Revision 1.4 2010/11/20 17:10:57 acg +// Andy Goodrich: reset processing changes for new IEEE 1666 standard. +// +// Revision 1.3 2009/05/22 16:06:29 acg +// Andy Goodrich: process control updates. +// +// 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.6 2006/12/02 20:58:19 acg +// Andy Goodrich: updates from 2.2 for IEEE 1666 support. +// +// Revision 1.4 2006/04/11 23:13:21 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.3 2006/01/13 18:44:30 acg +// Added $Log to record CVS changes into the source. + +} // namespace sc_core + +#endif // !defined(sc_reset_h_INCLUDED) diff --git a/ext/systemc/src/sysc/kernel/sc_runnable.h b/ext/systemc/src/sysc/kernel/sc_runnable.h new file mode 100644 index 000000000..028a9b311 --- /dev/null +++ b/ext/systemc/src/sysc/kernel/sc_runnable.h @@ -0,0 +1,144 @@ +/***************************************************************************** + + 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.h -- + + Original Author: Martin Janssen, Synopsys, Inc., 2001-05-21 + + CHANGE LOG AT THE END OF THE FILE + *****************************************************************************/ + + +#ifndef SC_RUNNABLE_H +#define SC_RUNNABLE_H + + +#include "sysc/kernel/sc_process.h" + +namespace sc_core { + +//============================================================================= +// CLASS : sc_runnable +// +// Class that manages the ready-to-run queues. +//============================================================================= + +class sc_runnable +{ + + public: + sc_runnable(); + ~sc_runnable(); + + inline void init(); + inline void toggle_methods(); + inline void toggle_threads(); + + inline void remove_method( sc_method_handle ); + inline void remove_thread( sc_thread_handle ); + + inline void execute_method_next( sc_method_handle ); + inline void execute_thread_next( sc_thread_handle ); + + inline void push_back_method( sc_method_handle ); + inline void push_back_thread( sc_thread_handle ); + inline void push_front_method( sc_method_handle ); + inline void push_front_thread( sc_thread_handle ); + + inline bool is_initialized() const; + inline bool is_empty() const; + + inline sc_method_handle pop_method(); + inline sc_thread_handle pop_thread(); + + public: // diagnostics: + void dump() const; + + private: + sc_method_handle m_methods_push_head; + sc_method_handle m_methods_push_tail; + sc_method_handle m_methods_pop; + sc_thread_handle m_threads_push_head; + sc_thread_handle m_threads_push_tail; + sc_thread_handle m_threads_pop; + + private: + // disabled + sc_runnable( const sc_runnable& ); + sc_runnable& operator = ( const sc_runnable& ); +}; + +} // namespace sc_core + +#endif + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affiliation, date and + changes you are making here. + + Name, Affiliation, Date: Andy Goodrich, 30 June 2003, Forte Design Systems + Description of Modification: Total rewrite using linked list rather than + fixed vector. + + + Name, Affiliation, Date: Bishnupriya Bhattacharya, Cadence Design Systems, + 25 August, 2003 + Description of Modification: Add tail pointers for m_methods_push and + m_threads_push to maintain the same scheduler + ordering as 2.0.1 + + *****************************************************************************/ + +// $Log: sc_runnable.h,v $ +// Revision 1.9 2011/08/26 20:46:10 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.8 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.7 2011/02/18 20:27:14 acg +// Andy Goodrich: Updated Copyrights. +// +// Revision 1.6 2011/02/13 21:47:38 acg +// Andy Goodrich: update copyright notice. +// +// Revision 1.5 2011/02/02 06:37:03 acg +// Andy Goodrich: removed toggle() method since it is no longer used. +// +// Revision 1.4 2011/02/01 21:09:13 acg +// Andy Goodrich: addition of toggle_methods() and toggle_threads() calls. +// +// Revision 1.3 2011/01/25 20:50:37 acg +// Andy Goodrich: changes for IEEE 1666 2011. +// +// 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.3 2006/01/13 18:44:30 acg +// Added $Log to record CVS changes into the source. + +// Taf! 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! diff --git a/ext/systemc/src/sysc/kernel/sc_sensitive.cpp b/ext/systemc/src/sysc/kernel/sc_sensitive.cpp new file mode 100644 index 000000000..210c2670e --- /dev/null +++ b/ext/systemc/src/sysc/kernel/sc_sensitive.cpp @@ -0,0 +1,959 @@ +/***************************************************************************** + + 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_sensitive.cpp -- + + Original Author: Stan Y. Liao, Synopsys, Inc. + Martin Janssen, Synopsys, Inc. + + CHANGE LOG AT THE END OF THE FILE + *****************************************************************************/ + + +#include "sysc/kernel/sc_event.h" +#include "sysc/kernel/sc_kernel_ids.h" +#include "sysc/kernel/sc_module.h" +#include "sysc/kernel/sc_cthread_process.h" +#include "sysc/kernel/sc_method_process.h" +#include "sysc/kernel/sc_thread_process.h" +#include "sysc/kernel/sc_process_handle.h" +#include "sysc/kernel/sc_sensitive.h" +#include "sysc/communication/sc_signal_ports.h" +#include "sysc/utils/sc_utils_ids.h" + +namespace sc_core { + +// support functions + +static +sc_method_handle +as_method_handle( sc_process_b* handle_ ) +{ + return DCAST<sc_method_handle>( handle_ ); +} + +static +sc_thread_handle +as_thread_handle( sc_process_b* handle_ ) +{ + return DCAST<sc_thread_handle>( handle_ ); +} + +static +void +warn_no_parens() +{ + static bool warn_no_parentheses=true; + if ( warn_no_parentheses ) + { + warn_no_parentheses=false; + SC_REPORT_INFO(SC_ID_IEEE_1666_DEPRECATION_, + "use of () to specify sensitivity is deprecated, use << instead" ); + } +} + +// ---------------------------------------------------------------------------- +// CLASS : sc_sensitive +// +// Static sensitivity class for events. +// ---------------------------------------------------------------------------- + +// constructor + +sc_sensitive::sc_sensitive( sc_module* module_ ) +: m_module( module_ ), + m_mode( SC_NONE_ ), + m_handle( 0 ) +{} + + +// destructor + +sc_sensitive::~sc_sensitive() +{} + + +// changing between process handles + +sc_sensitive& +sc_sensitive::operator << ( sc_process_handle handle_ ) +{ + switch ( handle_.proc_kind() ) + { + case SC_CTHREAD_PROC_: + case SC_THREAD_PROC_: + m_mode = SC_THREAD_; + break; + case SC_METHOD_PROC_: + m_mode = SC_METHOD_; + break; + default: + assert(0); + } + m_handle = (sc_process_b*)handle_; + return *this; +} + +sc_sensitive& +sc_sensitive::operator << ( const sc_event& event_ ) +{ + // check + if( sc_is_running() ) { + SC_REPORT_ERROR( SC_ID_MAKE_SENSITIVE_, "simulation running" ); + } + + // make sensitive + switch( m_mode ) { + case SC_METHOD_: + case SC_THREAD_: { + m_handle->add_static_event( event_ ); + break; + } + case SC_NONE_: + /* do nothing */ + break; + } + + return *this; +} + +void +sc_sensitive::make_static_sensitivity( + sc_process_b* handle_, const sc_event& event_) +{ + handle_->add_static_event( event_ ); +} + + +sc_sensitive& +sc_sensitive::operator << ( const sc_interface& interface_ ) +{ + // check + if( sc_is_running() ) { + SC_REPORT_ERROR( SC_ID_MAKE_SENSITIVE_, "simulation running" ); + } + + // make sensitive + switch( m_mode ) { + case SC_METHOD_: + case SC_THREAD_: { + m_handle->add_static_event( interface_.default_event() ); + break; + } + case SC_NONE_: + /* do nothing */ + break; + } + + return *this; +} + +void +sc_sensitive::make_static_sensitivity( + sc_process_b* handle_, const sc_interface& interface_) +{ + handle_->add_static_event( interface_.default_event() ); +} + +sc_sensitive& +sc_sensitive::operator << ( const sc_port_base& port_ ) +{ + // check + if( sc_is_running() ) { + SC_REPORT_ERROR( SC_ID_MAKE_SENSITIVE_, "simulation running" ); + } + + // make sensitive + switch( m_mode ) { + case SC_METHOD_: { + port_.make_sensitive( as_method_handle( m_handle ) ); + break; + } + case SC_THREAD_: { + port_.make_sensitive( as_thread_handle( m_handle ) ); + break; + } + case SC_NONE_: + /* do nothing */ + break; + } + + return *this; +} + +void +sc_sensitive::make_static_sensitivity( + sc_process_b* handle_, const sc_port_base& port_) +{ + sc_method_handle handle_m = as_method_handle( handle_ ); + if ( handle_m ) { + port_.make_sensitive( handle_m ); + return; + } + sc_thread_handle handle_t = as_thread_handle( handle_ ); + // assert(handle_t); + port_.make_sensitive( handle_t ); +} + +sc_sensitive& +sc_sensitive::operator << ( sc_event_finder& event_finder_ ) +{ + // check + if( sc_is_running() ) { + SC_REPORT_ERROR( SC_ID_MAKE_SENSITIVE_, "simulation running" ); + } + + // make sensitive + switch( m_mode ) { + case SC_METHOD_: { + event_finder_.port().make_sensitive( as_method_handle( m_handle ), + &event_finder_ ); + break; + } + case SC_THREAD_: { + event_finder_.port().make_sensitive( as_thread_handle( m_handle ), + &event_finder_ ); + break; + } + case SC_NONE_: + /* do nothing */ + break; + } + + return *this; +} + +void +sc_sensitive::make_static_sensitivity( + sc_process_b* handle_, sc_event_finder& event_finder_) +{ + if (sc_is_running()) { + handle_->add_static_event( event_finder_.find_event() ); + } else { + sc_method_handle handle_m = as_method_handle( handle_ ); + if ( handle_m ) { + event_finder_.port().make_sensitive( handle_m, &event_finder_ ); + return; + } + sc_thread_handle handle_t = as_thread_handle( handle_ ); + // assert(handle_t); + event_finder_.port().make_sensitive( handle_t, &event_finder_); + } +} + + +sc_sensitive& +sc_sensitive::operator () ( const sc_event& event_ ) +{ + warn_no_parens(); + return operator << ( event_ ); +} + +sc_sensitive& +sc_sensitive::operator () ( const sc_interface& interface_ ) +{ + warn_no_parens(); + return operator << ( interface_ ); +} + +sc_sensitive& +sc_sensitive::operator () ( const sc_port_base& port_ ) +{ + warn_no_parens(); + return operator << ( port_ ); +} + +sc_sensitive& +sc_sensitive::operator () ( sc_event_finder& event_finder_ ) +{ + warn_no_parens(); + return operator << ( event_finder_ ); +} + + +sc_sensitive& +sc_sensitive::operator () ( sc_cthread_handle handle_, + sc_event_finder& event_finder_ ) +{ + event_finder_.port().make_sensitive( handle_, &event_finder_ ); + return *this; +} + +sc_sensitive& +sc_sensitive::operator () ( sc_cthread_handle handle_, + const in_if_b_type& interface_ ) +{ + handle_->add_static_event( interface_.posedge_event() ); + return *this; +} + +sc_sensitive& +sc_sensitive::operator () ( sc_cthread_handle handle_, + const in_if_l_type& interface_ ) +{ + handle_->add_static_event( interface_.posedge_event() ); + return *this; +} + +sc_sensitive& +sc_sensitive::operator () ( sc_cthread_handle handle_, + const in_port_b_type& port_ ) +{ + port_.make_sensitive( handle_, &port_.pos() ); + return *this; +} + +sc_sensitive& +sc_sensitive::operator () ( sc_cthread_handle handle_, + const in_port_l_type& port_ ) +{ + port_.make_sensitive( handle_, &port_.pos() ); + return *this; +} + +sc_sensitive& +sc_sensitive::operator () ( sc_cthread_handle handle_, + const inout_port_b_type& port_ ) +{ + port_.make_sensitive( handle_, &port_.pos() ); + return *this; +} + +sc_sensitive& +sc_sensitive::operator () ( sc_cthread_handle handle_, + const inout_port_l_type& port_ ) +{ + port_.make_sensitive( handle_, &port_.pos() ); + return *this; +} + +void sc_sensitive::reset() +{ + m_mode = SC_NONE_; +} + + +// ---------------------------------------------------------------------------- +// CLASS : sc_sensitive_pos +// +// Static sensitivity class for positive edge events. +// ---------------------------------------------------------------------------- + +static void sc_deprecated_sensitive_pos() +{ + static bool warn_sensitive_pos=true; + if ( warn_sensitive_pos ) + { + warn_sensitive_pos=false; + SC_REPORT_INFO(SC_ID_IEEE_1666_DEPRECATION_, + "sc_sensitive_pos is deprecated use sc_sensitive << with pos() instead" ); + } +} + +// constructor + +sc_sensitive_pos::sc_sensitive_pos( sc_module* module_ ) +: m_module( module_ ), + m_mode( SC_NONE_ ), + m_handle( 0 ) +{} + + +// destructor + +sc_sensitive_pos::~sc_sensitive_pos() +{} + + +// changing between process handles + +sc_sensitive_pos& +sc_sensitive_pos::operator << ( sc_process_handle handle_ ) +{ + switch ( handle_.proc_kind() ) + { + case SC_CTHREAD_PROC_: + case SC_THREAD_PROC_: + m_mode = SC_THREAD_; + break; + case SC_METHOD_PROC_: + m_mode = SC_METHOD_; + break; + default: + assert(0); + } + m_handle = (sc_process_b*)handle_; + return *this; +} + +sc_sensitive_pos& +sc_sensitive_pos::operator << ( sc_method_handle handle_ ) +{ + m_mode = SC_METHOD_; + m_handle = handle_; + return *this; +} + +sc_sensitive_pos& +sc_sensitive_pos::operator << ( sc_thread_handle handle_ ) +{ + m_mode = SC_THREAD_; + m_handle = handle_; + return *this; +} + + +sc_sensitive_pos& +sc_sensitive_pos::operator << ( const in_if_b_type& interface_ ) +{ + sc_deprecated_sensitive_pos(); + // check + if( sc_is_running() ) { + SC_REPORT_ERROR( SC_ID_MAKE_SENSITIVE_POS_, "simulation running" ); + } + + // make sensitive + switch( m_mode ) { + case SC_METHOD_: + case SC_THREAD_: { + m_handle->add_static_event( interface_.posedge_event() ); + break; + } + case SC_NONE_: + /* do nothing */ + break; + } + + return *this; +} + +sc_sensitive_pos& +sc_sensitive_pos::operator << ( const in_if_l_type& interface_ ) +{ + sc_deprecated_sensitive_pos(); + // check + if( sc_is_running() ) { + SC_REPORT_ERROR( SC_ID_MAKE_SENSITIVE_POS_, "simulation running" ); + } + + // make sensitive + switch( m_mode ) { + case SC_METHOD_: + case SC_THREAD_: { + m_handle->add_static_event( interface_.posedge_event() ); + break; + } + case SC_NONE_: + /* do nothing */ + break; + } + + return *this; +} + +sc_sensitive_pos& +sc_sensitive_pos::operator << ( const in_port_b_type& port_ ) +{ + sc_deprecated_sensitive_pos(); + // check + if( sc_is_running() ) { + SC_REPORT_ERROR( SC_ID_MAKE_SENSITIVE_POS_, "simulation running" ); + } + + // make sensitive + switch( m_mode ) { + case SC_METHOD_: { + port_.make_sensitive( as_method_handle( m_handle ), &port_.pos() ); + break; + } + case SC_THREAD_: { + port_.make_sensitive( as_thread_handle( m_handle ), &port_.pos() ); + break; + } + case SC_NONE_: + /* do nothing */ + break; + } + + return *this; +} + +sc_sensitive_pos& +sc_sensitive_pos::operator << ( const in_port_l_type& port_ ) +{ + sc_deprecated_sensitive_pos(); + // check + if( sc_is_running() ) { + SC_REPORT_ERROR( SC_ID_MAKE_SENSITIVE_POS_, "simulation running" ); + } + + // make sensitive + switch( m_mode ) { + case SC_METHOD_: { + port_.make_sensitive( as_method_handle( m_handle ), &port_.pos() ); + break; + } + case SC_THREAD_: { + port_.make_sensitive( as_thread_handle( m_handle ), &port_.pos() ); + break; + } + case SC_NONE_: + /* do nothing */ + break; + } + + return *this; +} + +sc_sensitive_pos& +sc_sensitive_pos::operator << ( const inout_port_b_type& port_ ) +{ + sc_deprecated_sensitive_pos(); + // check + if( sc_is_running() ) { + SC_REPORT_ERROR( SC_ID_MAKE_SENSITIVE_POS_, "simulation running" ); + } + + // make sensitive + switch( m_mode ) { + case SC_METHOD_: { + port_.make_sensitive( as_method_handle( m_handle ), &port_.pos() ); + break; + } + case SC_THREAD_: { + port_.make_sensitive( as_thread_handle( m_handle ), &port_.pos() ); + break; + } + case SC_NONE_: + /* do nothing */ + break; + } + + return *this; +} + +sc_sensitive_pos& +sc_sensitive_pos::operator << ( const inout_port_l_type& port_ ) +{ + sc_deprecated_sensitive_pos(); + // check + if( sc_is_running() ) { + SC_REPORT_ERROR( SC_ID_MAKE_SENSITIVE_POS_, "simulation running" ); + } + + // make sensitive + switch( m_mode ) { + case SC_METHOD_: { + port_.make_sensitive( as_method_handle( m_handle ), &port_.pos() ); + break; + } + case SC_THREAD_: { + port_.make_sensitive( as_thread_handle( m_handle ), &port_.pos() ); + break; + } + case SC_NONE_: + /* do nothing */ + break; + } + + return *this; +} + + +sc_sensitive_pos& +sc_sensitive_pos::operator () ( const in_if_b_type& interface_ ) +{ + warn_no_parens(); + return operator << ( interface_ ); +} + +sc_sensitive_pos& +sc_sensitive_pos::operator () ( const in_if_l_type& interface_ ) +{ + warn_no_parens(); + return operator << ( interface_ ); +} + +sc_sensitive_pos& +sc_sensitive_pos::operator () ( const in_port_b_type& port_ ) +{ + warn_no_parens(); + return operator << ( port_ ); +} + +sc_sensitive_pos& +sc_sensitive_pos::operator () ( const in_port_l_type& port_ ) +{ + warn_no_parens(); + return operator << ( port_ ); +} + +sc_sensitive_pos& +sc_sensitive_pos::operator () ( const inout_port_b_type& port_ ) +{ + warn_no_parens(); + return operator << ( port_ ); +} + +sc_sensitive_pos& +sc_sensitive_pos::operator () ( const inout_port_l_type& port_ ) +{ + warn_no_parens(); + return operator << ( port_ ); +} + +void sc_sensitive_pos::reset() +{ + m_mode = SC_NONE_; +} + + +// ---------------------------------------------------------------------------- +// CLASS : sc_sensitive_neg +// +// Static sensitivity class for negative edge events. +// ---------------------------------------------------------------------------- + +static void sc_deprecated_sensitive_neg() +{ + static bool warn_sensitive_neg=true; + if ( warn_sensitive_neg ) + { + warn_sensitive_neg=false; + SC_REPORT_INFO(SC_ID_IEEE_1666_DEPRECATION_, + "sc_sensitive_neg is deprecated use sc_sensitive << with neg() instead" ); + } +} + +// constructor + +sc_sensitive_neg::sc_sensitive_neg( sc_module* module_ ) +: m_module( module_ ), + m_mode( SC_NONE_ ), + m_handle( 0 ) +{} + + +// destructor + +sc_sensitive_neg::~sc_sensitive_neg() +{} + + +// changing between process handles + +sc_sensitive_neg& +sc_sensitive_neg::operator << ( sc_process_handle handle_ ) +{ + switch ( handle_.proc_kind() ) + { + case SC_CTHREAD_PROC_: + case SC_THREAD_PROC_: + m_mode = SC_THREAD_; + break; + case SC_METHOD_PROC_: + m_mode = SC_METHOD_; + break; + default: + assert(0); + } + m_handle = (sc_process_b*)handle_; + return *this; +} + +sc_sensitive_neg& +sc_sensitive_neg::operator << ( sc_method_handle handle_ ) +{ + m_mode = SC_METHOD_; + m_handle = handle_; + return *this; +} + +sc_sensitive_neg& +sc_sensitive_neg::operator << ( sc_thread_handle handle_ ) +{ + m_mode = SC_THREAD_; + m_handle = handle_; + return *this; +} + + +sc_sensitive_neg& +sc_sensitive_neg::operator << ( const in_if_b_type& interface_ ) +{ + sc_deprecated_sensitive_neg(); + // check + if( sc_is_running() ) { + SC_REPORT_ERROR( SC_ID_MAKE_SENSITIVE_NEG_, "simulation running" ); + } + + // make sensitive + switch( m_mode ) { + case SC_METHOD_: + case SC_THREAD_: { + m_handle->add_static_event( interface_.negedge_event() ); + break; + } + case SC_NONE_: + /* do nothing */ + break; + } + + return *this; +} + +sc_sensitive_neg& +sc_sensitive_neg::operator << ( const in_if_l_type& interface_ ) +{ + sc_deprecated_sensitive_neg(); + // check + if( sc_is_running() ) { + SC_REPORT_ERROR( SC_ID_MAKE_SENSITIVE_NEG_, "simulation running" ); + } + + // make sensitive + switch( m_mode ) { + case SC_METHOD_: + case SC_THREAD_: { + m_handle->add_static_event( interface_.negedge_event() ); + break; + } + case SC_NONE_: + /* do nothing */ + break; + } + + return *this; +} + +sc_sensitive_neg& +sc_sensitive_neg::operator << ( const in_port_b_type& port_ ) +{ + sc_deprecated_sensitive_neg(); + // check + if( sc_is_running() ) { + SC_REPORT_ERROR( SC_ID_MAKE_SENSITIVE_NEG_, "simulation running" ); + } + + // make sensitive + switch( m_mode ) { + case SC_METHOD_: { + port_.make_sensitive( as_method_handle( m_handle ), &port_.neg() ); + break; + } + case SC_THREAD_: { + port_.make_sensitive( as_thread_handle( m_handle ), &port_.neg() ); + break; + } + case SC_NONE_: + /* do nothing */ + break; + } + + return *this; +} + +sc_sensitive_neg& +sc_sensitive_neg::operator << ( const in_port_l_type& port_ ) +{ + sc_deprecated_sensitive_neg(); + // check + if( sc_is_running() ) { + SC_REPORT_ERROR( SC_ID_MAKE_SENSITIVE_NEG_, "simulation running" ); + } + + // make sensitive + switch( m_mode ) { + case SC_METHOD_: { + port_.make_sensitive( as_method_handle( m_handle ), &port_.neg() ); + break; + } + case SC_THREAD_: { + port_.make_sensitive( as_thread_handle( m_handle ), &port_.neg() ); + break; + } + case SC_NONE_: + /* do nothing */ + break; + } + + return *this; +} + +sc_sensitive_neg& +sc_sensitive_neg::operator << ( const inout_port_b_type& port_ ) +{ + sc_deprecated_sensitive_neg(); + // check + if( sc_is_running() ) { + SC_REPORT_ERROR( SC_ID_MAKE_SENSITIVE_NEG_, "simulation running" ); + } + + // make sensitive + switch( m_mode ) { + case SC_METHOD_: { + port_.make_sensitive( as_method_handle( m_handle ), &port_.neg() ); + break; + } + case SC_THREAD_: { + port_.make_sensitive( as_thread_handle( m_handle ), &port_.neg() ); + break; + } + case SC_NONE_: + /* do nothing */ + break; + } + + return *this; +} + +sc_sensitive_neg& +sc_sensitive_neg::operator << ( const inout_port_l_type& port_ ) +{ + sc_deprecated_sensitive_neg(); + // check + if( sc_is_running() ) { + SC_REPORT_ERROR( SC_ID_MAKE_SENSITIVE_NEG_, "simulation running" ); + } + + // make sensitive + switch( m_mode ) { + case SC_METHOD_: { + port_.make_sensitive( as_method_handle( m_handle ), &port_.neg() ); + break; + } + case SC_THREAD_: { + port_.make_sensitive( as_thread_handle( m_handle ), &port_.neg() ); + break; + } + case SC_NONE_: + /* do nothing */ + break; + } + + return *this; +} + + +sc_sensitive_neg& +sc_sensitive_neg::operator () ( const in_if_b_type& interface_ ) +{ + warn_no_parens(); + return operator << ( interface_ ); +} + +sc_sensitive_neg& +sc_sensitive_neg::operator () ( const in_if_l_type& interface_ ) +{ + warn_no_parens(); + return operator << ( interface_ ); +} + +sc_sensitive_neg& +sc_sensitive_neg::operator () ( const in_port_b_type& port_ ) +{ + warn_no_parens(); + return operator << ( port_ ); +} + +sc_sensitive_neg& +sc_sensitive_neg::operator () ( const in_port_l_type& port_ ) +{ + warn_no_parens(); + return operator << ( port_ ); +} + +sc_sensitive_neg& +sc_sensitive_neg::operator () ( const inout_port_b_type& port_ ) +{ + warn_no_parens(); + return operator << ( port_ ); +} + +sc_sensitive_neg& +sc_sensitive_neg::operator () ( const inout_port_l_type& port_ ) +{ + warn_no_parens(); + return operator << ( port_ ); +} + +void sc_sensitive_neg::reset() +{ + m_mode = SC_NONE_; +} + +} // namespace sc_core + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affiliation, date and + changes you are making here. + + Name, Affiliation, Date: Bishnupriya Bhattacharya, Cadence Design Systems, + 25 August, 2003 + Description of Modification: add make_static_sensitivity() routines to support + dynamic method process creation with static + sensitivity + + *****************************************************************************/ + +// $Log: sc_sensitive.cpp,v $ +// Revision 1.5 2011/08/26 20:46:10 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.4 2011/02/18 20:27:14 acg +// Andy Goodrich: Updated Copyrights. +// +// Revision 1.3 2011/02/13 21:47:38 acg +// Andy Goodrich: update copyright notice. +// +// 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.8 2006/04/11 23:13:21 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.7 2006/01/27 17:31:24 acg +// Andy Goodrich: removed debugging comments from << operator code for types +// that are deprecated. +// +// Revision 1.6 2006/01/26 21:04:54 acg +// Andy Goodrich: deprecation message changes and additional messages. +// +// Revision 1.5 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.4 2006/01/24 20:49:05 acg +// Andy Goodrich: changes to remove the use of deprecated features within the +// simulator, and to issue warning messages when deprecated features are used. +// +// Revision 1.3 2006/01/13 18:44:30 acg +// Added $Log to record CVS changes into the source. +// + +// Taf! diff --git a/ext/systemc/src/sysc/kernel/sc_sensitive.h b/ext/systemc/src/sysc/kernel/sc_sensitive.h new file mode 100644 index 000000000..9d07bd03a --- /dev/null +++ b/ext/systemc/src/sysc/kernel/sc_sensitive.h @@ -0,0 +1,306 @@ +/***************************************************************************** + + 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_sensitive.h -- Sensitivity classes. Requires "sc_process.h" + for declarations of sc_method_handle, &.c. + + Original Author: Stan Y. Liao, Synopsys, Inc. + Martin Janssen, Synopsys, Inc. + + CHANGE LOG AT THE END OF THE FILE + *****************************************************************************/ + + +#ifndef SC_SENSITIVE_H +#define SC_SENSITIVE_H + +#include "sysc/kernel/sc_process.h" + +namespace sc_dt +{ + class sc_logic; +} + +namespace sc_core { + +class sc_process_handle; +class sc_event; +class sc_event_finder; +class sc_interface; +class sc_module; +class sc_port_base; +template <class T> class sc_in; +template <class T> class sc_inout; +template <class T> class sc_signal_in_if; + + +// ---------------------------------------------------------------------------- +// CLASS : sc_sensitive +// +// Static sensitivity class for events. +// ---------------------------------------------------------------------------- + +class sc_sensitive +{ + friend class sc_module; + +public: + + // typedefs + typedef sc_signal_in_if<bool> in_if_b_type; + typedef sc_signal_in_if<sc_dt::sc_logic> in_if_l_type; + typedef sc_in<bool> in_port_b_type; + typedef sc_in<sc_dt::sc_logic> in_port_l_type; + typedef sc_inout<bool> inout_port_b_type; + typedef sc_inout<sc_dt::sc_logic> inout_port_l_type; + +private: + + // constructor + explicit sc_sensitive( sc_module* ); + + // destructor + ~sc_sensitive(); + +public: + + // changing between process handles + sc_sensitive& operator << ( sc_process_handle ); +#if 0 + sc_sensitive& operator << ( sc_method_handle ); + sc_sensitive& operator << ( sc_thread_handle ); +#endif // 0 + + sc_sensitive& operator () ( const sc_event& ); + sc_sensitive& operator () ( const sc_interface& ); + sc_sensitive& operator () ( const sc_port_base& ); + sc_sensitive& operator () ( sc_event_finder& ); + + sc_sensitive& operator << ( const sc_event& ); + sc_sensitive& operator << ( const sc_interface& ); + sc_sensitive& operator << ( const sc_port_base& ); + sc_sensitive& operator << ( sc_event_finder& ); + + sc_sensitive& operator () ( sc_cthread_handle, sc_event_finder& ); + sc_sensitive& operator () ( sc_cthread_handle, const in_if_b_type& ); + sc_sensitive& operator () ( sc_cthread_handle, const in_if_l_type& ); + sc_sensitive& operator () ( sc_cthread_handle, const in_port_b_type& ); + sc_sensitive& operator () ( sc_cthread_handle, const in_port_l_type& ); + sc_sensitive& operator () ( sc_cthread_handle, const inout_port_b_type& ); + sc_sensitive& operator () ( sc_cthread_handle, const inout_port_l_type& ); + + static void make_static_sensitivity( sc_process_b*, const sc_event& ); + static void make_static_sensitivity( sc_process_b*, const sc_interface& ); + static void make_static_sensitivity( sc_process_b*, const sc_port_base&); + static void make_static_sensitivity( sc_process_b*, sc_event_finder& ); + + void reset(); + +private: + + sc_module* m_module; + enum { SC_NONE_, SC_METHOD_, SC_THREAD_ } m_mode; + sc_process_b* m_handle; + +private: + + // disabled + + sc_sensitive(); + sc_sensitive( const sc_sensitive& ); + sc_sensitive& operator = ( const sc_sensitive& ); +}; + + +// ---------------------------------------------------------------------------- +// CLASS : sc_sensitive_pos +// +// Static sensitivity class for positive edge events. +// ---------------------------------------------------------------------------- + +class sc_sensitive_pos +{ + friend class sc_module; + +public: + + // typedefs + typedef sc_signal_in_if<bool> in_if_b_type; + typedef sc_signal_in_if<sc_dt::sc_logic> in_if_l_type; + typedef sc_in<bool> in_port_b_type; + typedef sc_in<sc_dt::sc_logic> in_port_l_type; + typedef sc_inout<bool> inout_port_b_type; + typedef sc_inout<sc_dt::sc_logic> inout_port_l_type; + +private: + + // constructor + explicit sc_sensitive_pos( sc_module* ); + + // destructor + ~sc_sensitive_pos(); + +public: + + // changing between process handles + sc_sensitive_pos& operator << ( sc_process_handle ); + sc_sensitive_pos& operator << ( sc_method_handle ); + sc_sensitive_pos& operator << ( sc_thread_handle ); + + sc_sensitive_pos& operator () ( const in_if_b_type& ); + sc_sensitive_pos& operator () ( const in_if_l_type& ); + sc_sensitive_pos& operator () ( const in_port_b_type& ); + sc_sensitive_pos& operator () ( const in_port_l_type& ); + sc_sensitive_pos& operator () ( const inout_port_b_type& ); + sc_sensitive_pos& operator () ( const inout_port_l_type& ); + + sc_sensitive_pos& operator << ( const in_if_b_type& ); + sc_sensitive_pos& operator << ( const in_if_l_type& ); + sc_sensitive_pos& operator << ( const in_port_b_type& ); + sc_sensitive_pos& operator << ( const in_port_l_type& ); + sc_sensitive_pos& operator << ( const inout_port_b_type& ); + sc_sensitive_pos& operator << ( const inout_port_l_type& ); + + void reset(); + +private: + + sc_module* m_module; + enum { SC_NONE_, SC_METHOD_, SC_THREAD_ } m_mode; + sc_process_b* m_handle; + +private: + + // disabled + sc_sensitive_pos(); + sc_sensitive_pos( const sc_sensitive_pos& ); + sc_sensitive_pos& operator = ( const sc_sensitive_pos& ); +}; + + +// ---------------------------------------------------------------------------- +// CLASS : sc_sensitive_neg +// +// Static sensitivity class for negative edge events. +// ---------------------------------------------------------------------------- + +class sc_sensitive_neg +{ + friend class sc_module; + +public: + + // typedefs + typedef sc_signal_in_if<bool> in_if_b_type; + typedef sc_signal_in_if<sc_dt::sc_logic> in_if_l_type; + typedef sc_in<bool> in_port_b_type; + typedef sc_in<sc_dt::sc_logic> in_port_l_type; + typedef sc_inout<bool> inout_port_b_type; + typedef sc_inout<sc_dt::sc_logic> inout_port_l_type; + +private: + + // constructor + explicit sc_sensitive_neg( sc_module* ); + + // destructor + ~sc_sensitive_neg(); + +public: + + // changing between process handles + sc_sensitive_neg& operator << ( sc_process_handle ); + sc_sensitive_neg& operator << ( sc_method_handle ); + sc_sensitive_neg& operator << ( sc_thread_handle ); + + sc_sensitive_neg& operator () ( const in_if_b_type& ); + sc_sensitive_neg& operator () ( const in_if_l_type& ); + sc_sensitive_neg& operator () ( const in_port_b_type& ); + sc_sensitive_neg& operator () ( const in_port_l_type& ); + sc_sensitive_neg& operator () ( const inout_port_b_type& ); + sc_sensitive_neg& operator () ( const inout_port_l_type& ); + + sc_sensitive_neg& operator << ( const in_if_b_type& ); + sc_sensitive_neg& operator << ( const in_if_l_type& ); + sc_sensitive_neg& operator << ( const in_port_b_type& ); + sc_sensitive_neg& operator << ( const in_port_l_type& ); + sc_sensitive_neg& operator << ( const inout_port_b_type& ); + sc_sensitive_neg& operator << ( const inout_port_l_type& ); + + void reset(); + +private: + + sc_module* m_module; + enum { SC_NONE_, SC_METHOD_, SC_THREAD_ } m_mode; + sc_process_b* m_handle; + +private: + + // disabled + sc_sensitive_neg(); + sc_sensitive_neg( const sc_sensitive_neg& ); + sc_sensitive_neg& operator = ( const sc_sensitive_neg& ); +}; + +} // namespace sc_core + +#endif + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affiliation, date and + changes you are making here. + + Name, Affiliation, Date: Bishnupriya Bhattacharya, Cadence Design Systems, + 25 August, 2003 + Description of Modification: Add make_static_sensitivity() methods to enable + dynamic method process creation with static + sensitivity. + + *****************************************************************************/ + +// $Log: sc_sensitive.h,v $ +// Revision 1.5 2011/08/26 20:46:10 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.4 2011/02/18 20:27:14 acg +// Andy Goodrich: Updated Copyrights. +// +// Revision 1.3 2011/02/13 21:47:38 acg +// Andy Goodrich: update copyright notice. +// +// 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/11 23:13:21 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.3 2006/01/13 18:44:30 acg +// Added $Log to record CVS changes into the source. + +// Taf! diff --git a/ext/systemc/src/sysc/kernel/sc_simcontext.cpp b/ext/systemc/src/sysc/kernel/sc_simcontext.cpp new file mode 100644 index 000000000..104f7c984 --- /dev/null +++ b/ext/systemc/src/sysc/kernel/sc_simcontext.cpp @@ -0,0 +1,2284 @@ +/***************************************************************************** + + 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_simcontext.cpp -- Provides a simulation context for use with multiple + simulations. + + Original Author: Stan Y. Liao, Synopsys, Inc. + Martin Janssen, Synopsys, Inc. + + CHANGE LOG AT THE END OF THE FILE + *****************************************************************************/ + +#include <algorithm> + +#define SC_DISABLE_API_VERSION_CHECK // for in-library sc_ver.h inclusion + +#include "sysc/kernel/sc_cor_fiber.h" +#include "sysc/kernel/sc_cor_pthread.h" +#include "sysc/kernel/sc_cor_qt.h" +#include "sysc/kernel/sc_event.h" +#include "sysc/kernel/sc_kernel_ids.h" +#include "sysc/kernel/sc_module.h" +#include "sysc/kernel/sc_module_registry.h" +#include "sysc/kernel/sc_name_gen.h" +#include "sysc/kernel/sc_object_manager.h" +#include "sysc/kernel/sc_cthread_process.h" +#include "sysc/kernel/sc_method_process.h" +#include "sysc/kernel/sc_thread_process.h" +#include "sysc/kernel/sc_process_handle.h" +#include "sysc/kernel/sc_simcontext.h" +#include "sysc/kernel/sc_simcontext_int.h" +#include "sysc/kernel/sc_reset.h" +#include "sysc/kernel/sc_ver.h" +#include "sysc/kernel/sc_boost.h" +#include "sysc/kernel/sc_spawn.h" +#include "sysc/kernel/sc_phase_callback_registry.h" +#include "sysc/communication/sc_port.h" +#include "sysc/communication/sc_export.h" +#include "sysc/communication/sc_prim_channel.h" +#include "sysc/tracing/sc_trace.h" +#include "sysc/utils/sc_mempool.h" +#include "sysc/utils/sc_list.h" +#include "sysc/utils/sc_utils_ids.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 + +#if SC_HAS_PHASE_CALLBACKS_ +# define SC_DO_PHASE_CALLBACK_( Kind ) \ + m_phase_cb_registry->Kind() +#else +# define SC_DO_PHASE_CALLBACK_( Kind ) \ + ((void)0) /* do nothing */ +#endif + +#if defined( SC_ENABLE_SIMULATION_PHASE_CALLBACKS_TRACING ) +// use callback based tracing +# define SC_SIMCONTEXT_TRACING_ 0 +#else +// enable tracing via explicit trace_cycle calls from simulator loop +# define SC_SIMCONTEXT_TRACING_ 1 +#endif + +namespace sc_core { + +sc_stop_mode stop_mode = SC_STOP_FINISH_DELTA; + +// ---------------------------------------------------------------------------- +// CLASS : sc_process_table +// +// Container class that keeps track of all method processes, +// (c)thread processes. +// ---------------------------------------------------------------------------- + +class sc_process_table +{ + public: + + sc_process_table(); + ~sc_process_table(); + void push_front( sc_method_handle ); + void push_front( sc_thread_handle ); + sc_method_handle method_q_head(); + sc_method_handle remove( sc_method_handle ); + sc_thread_handle thread_q_head(); + sc_thread_handle remove( sc_thread_handle ); + + + private: + + sc_method_handle m_method_q; // Queue of existing method processes. + sc_thread_handle m_thread_q; // Queue of existing thread processes. +}; + + +// IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII + +sc_process_table::sc_process_table() : m_method_q(0), m_thread_q(0) +{} + +sc_process_table::~sc_process_table() +{ + + sc_method_handle method_next_p; // Next method to delete. + sc_method_handle method_now_p; // Method now deleting. + + for( method_now_p = m_method_q; method_now_p; method_now_p = method_next_p ) + { + method_next_p = method_now_p->next_exist(); + delete method_now_p; + } + + if ( m_thread_q ) + { + ::std::cout << ::std::endl + << "WATCH OUT!! In sc_process_table destructor. " + << "Threads and cthreads are not actually getting deleted here. " + << "Some memory may leak. Look at the comments here in " + << "kernel/sc_simcontext.cpp for more details." + << ::std::endl; + } + + // don't delete threads and cthreads. If a (c)thread + // has died, then it has already been deleted. Only (c)threads created + // before simulation-start are in this table. Due to performance + // reasons, we don't look up the dying thread in the process table + // and remove it from there. simcontext::reset and ~simcontext invoke this + // destructor. At present none of these routines are ever invoked. + // We can delete threads and cthreads here if a dying thread figured out + // it was created before simulation-start and took itself off the + // process_table. + +#if 0 + sc_thread_handle thread_next_p; // Next thread to delete. + sc_thread_handle thread_now_p; // Thread now deleting. + + for( thread_now_p=m_thread_q; thread_now_p; thread_now_p=thread_next_p ) + { + thread_next_p = thread_now_p->next_exist(); + delete thread_now_p; + } +#endif // 0 +} + +inline +sc_method_handle +sc_process_table::method_q_head() +{ + return m_method_q; +} + +inline +void +sc_process_table::push_front( sc_method_handle handle_ ) +{ + handle_->set_next_exist(m_method_q); + m_method_q = handle_; +} + +inline +void +sc_process_table::push_front( sc_thread_handle handle_ ) +{ + handle_->set_next_exist(m_thread_q); + m_thread_q = handle_; +} + +sc_method_handle +sc_process_table::remove( sc_method_handle handle_ ) +{ + sc_method_handle now_p; // Entry now examining. + sc_method_handle prior_p; // Entry prior to one now examining. + + prior_p = 0; + for ( now_p = m_method_q; now_p; now_p = now_p->next_exist() ) + { + if ( now_p == handle_ ) + { + if ( prior_p ) + prior_p->set_next_exist( now_p->next_exist() ); + else + m_method_q = now_p->next_exist(); + return handle_; + } + } + return 0; +} + +sc_thread_handle +sc_process_table::remove( sc_thread_handle handle_ ) +{ + sc_thread_handle now_p; // Entry now examining. + sc_thread_handle prior_p; // Entry prior to one now examining. + + prior_p = 0; + for ( now_p = m_thread_q; now_p; now_p = now_p->next_exist() ) + { + if ( now_p == handle_ ) + { + if ( prior_p ) + prior_p->set_next_exist( now_p->next_exist() ); + else + m_thread_q = now_p->next_exist(); + return handle_; + } + } + return 0; +} + +inline +sc_thread_handle +sc_process_table::thread_q_head() +{ + return m_thread_q; +} + +int +sc_notify_time_compare( const void* p1, const void* p2 ) +{ + const sc_event_timed* et1 = static_cast<const sc_event_timed*>( p1 ); + const sc_event_timed* et2 = static_cast<const sc_event_timed*>( p2 ); + + const sc_time& t1 = et1->notify_time(); + const sc_time& t2 = et2->notify_time(); + + if( t1 < t2 ) { + return 1; + } else if( t1 > t2 ) { + return -1; + } else { + return 0; + } +} + + +// +============================================================================ +// | CLASS sc_invoke_method - class to invoke sc_method's to support +// | sc_simcontext::preempt_with(). +// +============================================================================ +SC_MODULE(sc_invoke_method) +{ + SC_CTOR(sc_invoke_method) + { + // remove from object hierarchy + detach(); + } + + virtual ~sc_invoke_method() + { + m_invokers.resize(0); + } + + // Method to call to execute a method's semantics. + + void invoke_method( sc_method_handle method_h ) + { + sc_process_handle invoker_h; // handle for invocation thread to use. + std::vector<sc_process_handle>::size_type invokers_n; // number of invocation threads available. + + m_method = method_h; + + // There is not an invocation thread to use, so allocate one. + + invokers_n = m_invokers.size(); + if ( invokers_n == 0 ) + { + sc_spawn_options options; + options.dont_initialize(); + options.set_stack_size(0x100000); + options.set_sensitivity(&m_dummy); + invoker_h = sc_spawn(sc_bind(&sc_invoke_method::invoker,this), + sc_gen_unique_name("invoker"), &options); + ((sc_process_b*)invoker_h)->detach(); + } + + // There is an invocation thread to use, use the last one on the list. + + else + { + invoker_h = m_invokers[invokers_n-1]; + m_invokers.pop_back(); + } + + // Fire off the invocation thread to invoke the method's semantics, + // When it blocks put it onto the list of invocation threads that + // are available. + + sc_get_curr_simcontext()->preempt_with( (sc_thread_handle)invoker_h ); + DEBUG_MSG( DEBUG_NAME, m_method, "back from preemption" ); + m_invokers.push_back(invoker_h); + } + + // Thread to call method from: + + void invoker() + { + sc_simcontext* csc_p = sc_get_curr_simcontext(); + sc_process_b* me = sc_get_current_process_b(); + + DEBUG_MSG( DEBUG_NAME, me, "invoker initialization" ); + for (;; ) + { + DEBUG_MSG( DEBUG_NAME, m_method, "invoker executing method" ); + csc_p->set_curr_proc( (sc_process_b*)m_method ); + csc_p->get_active_invokers().push_back((sc_thread_handle)me); + m_method->run_process(); + csc_p->set_curr_proc( me ); + csc_p->get_active_invokers().pop_back(); + DEBUG_MSG( DEBUG_NAME, m_method, "back from executing method" ); + wait(); + } + } + + sc_event m_dummy; // dummy event to wait on. + sc_method_handle m_method; // method to be invoked. + std::vector<sc_process_handle> m_invokers; // list of invoking threads. +}; + +// ---------------------------------------------------------------------------- +// CLASS : sc_simcontext +// +// The simulation context. +// ---------------------------------------------------------------------------- + +void +sc_simcontext::init() +{ + + // ALLOCATE VARIOUS MANAGERS AND REGISTRIES: + + m_object_manager = new sc_object_manager; + m_module_registry = new sc_module_registry( *this ); + m_port_registry = new sc_port_registry( *this ); + m_export_registry = new sc_export_registry( *this ); + m_prim_channel_registry = new sc_prim_channel_registry( *this ); + m_phase_cb_registry = new sc_phase_callback_registry( *this ); + m_name_gen = new sc_name_gen; + m_process_table = new sc_process_table; + m_current_writer = 0; + + + // CHECK FOR ENVIRONMENT VARIABLES THAT MODIFY SIMULATOR EXECUTION: + + const char* write_check = std::getenv("SC_SIGNAL_WRITE_CHECK"); + m_write_check = ( (write_check==0) || strcmp(write_check,"DISABLE") ) ? + true : false; + + + // FINISH INITIALIZATIONS: + + reset_curr_proc(); + m_next_proc_id = -1; + m_timed_events = new sc_ppq<sc_event_timed*>( 128, sc_notify_time_compare ); + m_something_to_trace = false; + m_runnable = new sc_runnable; + m_collectable = new sc_process_list; + m_time_params = new sc_time_params; + m_curr_time = SC_ZERO_TIME; + m_max_time = SC_ZERO_TIME; + m_change_stamp = 0; + m_delta_count = 0; + m_forced_stop = false; + m_paused = false; + m_ready_to_simulate = false; + m_elaboration_done = false; + m_execution_phase = phase_initialize; + m_error = NULL; + m_cor_pkg = 0; + m_method_invoker_p = NULL; + m_cor = 0; + m_in_simulator_control = false; + m_start_of_simulation_called = false; + m_end_of_simulation_called = false; + m_simulation_status = SC_ELABORATION; +} + +void +sc_simcontext::clean() +{ + delete m_object_manager; + delete m_module_registry; + delete m_port_registry; + delete m_export_registry; + delete m_prim_channel_registry; + delete m_phase_cb_registry; + delete m_name_gen; + delete m_process_table; + m_child_objects.resize(0); + m_delta_events.resize(0); + delete m_timed_events; + for( int i = m_trace_files.size() - 1; i >= 0; -- i ) { + delete m_trace_files[i]; + } + m_trace_files.resize(0); + delete m_runnable; + delete m_collectable; + delete m_time_params; + delete m_cor_pkg; + delete m_error; +} + + +sc_simcontext::sc_simcontext() : + m_object_manager(0), m_module_registry(0), m_port_registry(0), + m_export_registry(0), m_prim_channel_registry(0), + m_phase_cb_registry(0), m_name_gen(0), + m_process_table(0), m_curr_proc_info(), m_current_writer(0), + m_write_check(false), m_next_proc_id(-1), m_child_events(), + m_child_objects(), m_delta_events(), m_timed_events(0), m_trace_files(), + m_something_to_trace(false), m_runnable(0), m_collectable(0), + m_time_params(), m_curr_time(SC_ZERO_TIME), m_max_time(SC_ZERO_TIME), + m_change_stamp(0), m_delta_count(0), m_forced_stop(false), m_paused(false), + m_ready_to_simulate(false), m_elaboration_done(false), + m_execution_phase(phase_initialize), m_error(0), + m_in_simulator_control(false), m_end_of_simulation_called(false), + m_simulation_status(SC_ELABORATION), m_start_of_simulation_called(false), + m_cor_pkg(0), m_cor(0) +{ + init(); +} + +sc_simcontext::~sc_simcontext() +{ + clean(); +} + +// +---------------------------------------------------------------------------- +// |"sc_simcontext::active_object" +// | +// | This method returns the currently active object with respect to +// | additions to the hierarchy. It will be the top of the object hierarchy +// | stack if it is non-empty, or it will be the active process, or NULL +// | if there is no active process. +// +---------------------------------------------------------------------------- +sc_object* +sc_simcontext::active_object() +{ + sc_object* result_p; // pointer to return. + + result_p = m_object_manager->hierarchy_curr(); + if ( !result_p ) + result_p = (sc_object*)get_curr_proc_info()->process_handle; + return result_p; +} + +// +---------------------------------------------------------------------------- +// |"sc_simcontext::crunch" +// | +// | This method implements the simulator's execution of processes. It performs +// | one or more "delta" cycles. Each delta cycle consists of an evaluation, +// | an update phase, and a notification phase. During the evaluation phase any +// | processes that are ready to run are executed. After all the processes have +// | been executed the update phase is entered. During the update phase the +// | values of any signals that have changed are updated. After the updates +// | have been performed the notification phase is entered. During that phase +// | any notifications that need to occur because of of signal values changes +// | are performed. This will result in the queueing of processes for execution +// | that are sensitive to those notifications. At that point a delta cycle +// | is complete, and the process is started again unless 'once' is true. +// | +// | Arguments: +// | once = true if only one delta cycle is to be performed. +// +---------------------------------------------------------------------------- +inline void +sc_simcontext::crunch( bool once ) +{ +#ifdef DEBUG_SYSTEMC + int num_deltas = 0; // number of delta cycles +#endif + + while ( true ) + { + + // EVALUATE PHASE + + m_execution_phase = phase_evaluate; + bool empty_eval_phase = true; + while( true ) + { + + // execute method processes + + m_runnable->toggle_methods(); + sc_method_handle method_h = pop_runnable_method(); + while( method_h != 0 ) { + empty_eval_phase = false; + if ( !method_h->run_process() ) + { + goto out; + } + method_h = pop_runnable_method(); + } + + // execute (c)thread processes + + m_runnable->toggle_threads(); + sc_thread_handle thread_h = pop_runnable_thread(); + while( thread_h != 0 ) { + if ( thread_h->m_cor_p != NULL ) break; + thread_h = pop_runnable_thread(); + } + + if( thread_h != 0 ) { + empty_eval_phase = false; + m_cor_pkg->yield( thread_h->m_cor_p ); + } + if( m_error ) { + goto out; + } + + // check for call(s) to sc_stop + if( m_forced_stop ) { + if ( stop_mode == SC_STOP_IMMEDIATE ) goto out; + } + + // no more runnable processes + + if( m_runnable->is_empty() ) { + break; + } + } + + // remove finally dead zombies: + + while( ! m_collectable->empty() ) + { + sc_process_b* del_p = m_collectable->front(); + m_collectable->pop_front(); + del_p->reference_decrement(); + } + + + // UPDATE PHASE + // + // The change stamp must be updated first so that event_occurred() + // will work. + + m_execution_phase = phase_update; + if ( !empty_eval_phase ) + { +// SC_DO_PHASE_CALLBACK_(evaluation_done); + m_change_stamp++; + m_delta_count ++; + } + m_prim_channel_registry->perform_update(); + SC_DO_PHASE_CALLBACK_(update_done); + m_execution_phase = phase_notify; + +#if SC_SIMCONTEXT_TRACING_ + if( m_something_to_trace ) { + trace_cycle( /* delta cycle? */ true ); + } +#endif + + // check for call(s) to sc_stop + if( m_forced_stop ) { + break; + } + +#ifdef DEBUG_SYSTEMC + // check for possible infinite loops + if( ++ num_deltas > SC_MAX_NUM_DELTA_CYCLES ) { + ::std::cerr << "SystemC warning: " + << "the number of delta cycles exceeds the limit of " + << SC_MAX_NUM_DELTA_CYCLES + << ", defined in sc_constants.h.\n" + << "This is a possible sign of an infinite loop.\n" + << "Increase the limit if this warning is invalid.\n"; + break; + } +#endif + + // NOTIFICATION PHASE: + // + // Process delta notifications which will queue processes for + // subsequent execution. + + int size = m_delta_events.size(); + if ( size != 0 ) + { + sc_event** l_events = &m_delta_events[0]; + int i = size - 1; + do { + l_events[i]->trigger(); + } while( -- i >= 0 ); + m_delta_events.resize(0); + } + + if( m_runnable->is_empty() ) { + // no more runnable processes + break; + } + + // if sc_pause() was called we are done. + + if ( m_paused ) break; + + // IF ONLY DOING ONE CYCLE, WE ARE DONE. OTHERWISE EXECUTE NEW CALLBACKS + + if ( once ) break; + } + + // When this point is reached the processing of delta cycles is complete, + // if the completion was because of an error throw the exception specified + // by '*m_error'. +out: + this->reset_curr_proc(); + if( m_error ) throw *m_error; // re-throw propagated error +} + +inline +void +sc_simcontext::cycle( const sc_time& t) +{ + sc_time next_event_time; + + m_in_simulator_control = true; + crunch(); + SC_DO_PHASE_CALLBACK_(before_timestep); +#if SC_SIMCONTEXT_TRACING_ + if( m_something_to_trace ) { + trace_cycle( /* delta cycle? */ false ); + } +#endif + m_curr_time += t; + if ( next_time(next_event_time) && next_event_time <= m_curr_time) { + SC_REPORT_WARNING(SC_ID_CYCLE_MISSES_EVENTS_, ""); + } + m_in_simulator_control = false; + SC_DO_PHASE_CALLBACK_(simulation_paused); +} + +void +sc_simcontext::elaborate() +{ + if( m_elaboration_done || sim_status() != SC_SIM_OK ) { + return; + } + + // Instantiate the method invocation module + // (not added to public object hierarchy) + + m_method_invoker_p = + new sc_invoke_method("$$$$kernel_module$$$$_invoke_method" ); + + m_simulation_status = SC_BEFORE_END_OF_ELABORATION; + for( int cd = 0; cd != 4; /* empty */ ) + { + cd = m_port_registry->construction_done(); + cd += m_export_registry->construction_done(); + cd += m_prim_channel_registry->construction_done(); + cd += m_module_registry->construction_done(); + + // check for call(s) to sc_stop + if( m_forced_stop ) { + do_sc_stop_action(); + return; + } + + } + SC_DO_PHASE_CALLBACK_(construction_done); + + // SIGNAL THAT ELABORATION IS DONE + // + // We set the switch before the calls in case someone creates a process + // in an end_of_elaboration callback. We need the information to flag + // the process as being dynamic. + + m_elaboration_done = true; + m_simulation_status = SC_END_OF_ELABORATION; + + m_port_registry->elaboration_done(); + m_export_registry->elaboration_done(); + m_prim_channel_registry->elaboration_done(); + m_module_registry->elaboration_done(); + SC_DO_PHASE_CALLBACK_(elaboration_done); + sc_reset::reconcile_resets(); + + // check for call(s) to sc_stop + if( m_forced_stop ) { + do_sc_stop_action(); + return; + } +} + +void +sc_simcontext::prepare_to_simulate() +{ + sc_method_handle method_p; // Pointer to method process accessing. + sc_thread_handle thread_p; // Pointer to thread process accessing. + + if( m_ready_to_simulate || sim_status() != SC_SIM_OK ) { + return; + } + + // instantiate the coroutine package + m_cor_pkg = new sc_cor_pkg_t( this ); + m_cor = m_cor_pkg->get_main(); + + // NOTIFY ALL OBJECTS THAT SIMULATION IS ABOUT TO START: + + m_simulation_status = SC_START_OF_SIMULATION; + m_port_registry->start_simulation(); + m_export_registry->start_simulation(); + m_prim_channel_registry->start_simulation(); + m_module_registry->start_simulation(); + SC_DO_PHASE_CALLBACK_(start_simulation); + m_start_of_simulation_called = true; + + // CHECK FOR CALL(S) TO sc_stop + + if( m_forced_stop ) { + do_sc_stop_action(); + return; + } + + // PREPARE ALL (C)THREAD PROCESSES FOR SIMULATION: + + for ( thread_p = m_process_table->thread_q_head(); + thread_p; thread_p = thread_p->next_exist() ) + { + thread_p->prepare_for_simulation(); + } + + m_simulation_status = SC_RUNNING; + m_ready_to_simulate = true; + m_runnable->init(); + + // update phase + + m_execution_phase = phase_update; + m_prim_channel_registry->perform_update(); + m_execution_phase = phase_notify; + + int size; + + // make all method processes runnable + + for ( method_p = m_process_table->method_q_head(); + method_p; method_p = method_p->next_exist() ) + { + if ( ((method_p->m_state & sc_process_b::ps_bit_disabled) != 0) || + method_p->dont_initialize() ) + { + if ( method_p->m_static_events.size() == 0 ) + { + SC_REPORT_WARNING( SC_ID_DISABLE_WILL_ORPHAN_PROCESS_, + method_p->name() ); + } + } + else if ( (method_p->m_state & sc_process_b::ps_bit_suspended) == 0) + { + push_runnable_method_front( method_p ); + } + else + { + method_p->m_state |= sc_process_b::ps_bit_ready_to_run; + } + } + + // make thread processes runnable + // (cthread processes always have the dont_initialize flag set) + + for ( thread_p = m_process_table->thread_q_head(); + thread_p; thread_p = thread_p->next_exist() ) + { + if ( ((thread_p->m_state & sc_process_b::ps_bit_disabled) != 0) || + thread_p->dont_initialize() ) + { + if ( thread_p->m_static_events.size() == 0 ) + { + SC_REPORT_WARNING( SC_ID_DISABLE_WILL_ORPHAN_PROCESS_, + thread_p->name() ); + } + } + else if ( (thread_p->m_state & sc_process_b::ps_bit_suspended) == 0) + { + push_runnable_thread_front( thread_p ); + } + else + { + thread_p->m_state |= sc_process_b::ps_bit_ready_to_run; + } + } + + + // process delta notifications + + if( ( size = m_delta_events.size() ) != 0 ) { + sc_event** l_delta_events = &m_delta_events[0]; + int i = size - 1; + do { + l_delta_events[i]->trigger(); + } while( -- i >= 0 ); + m_delta_events.resize(0); + } + + SC_DO_PHASE_CALLBACK_(initialization_done); +} + +void +sc_simcontext::initial_crunch( bool no_crunch ) +{ + if( no_crunch || m_runnable->is_empty() ) { + return; + } + + // run the delta cycle loop + + crunch(); + if( m_error ) { + return; + } + +#if SC_SIMCONTEXT_TRACING_ + if( m_something_to_trace ) { + trace_cycle( false ); + } +#endif + + // check for call(s) to sc_stop + if( m_forced_stop ) { + do_sc_stop_action(); + } +} + +void +sc_simcontext::initialize( bool no_crunch ) +{ + m_in_simulator_control = true; + elaborate(); + + prepare_to_simulate(); + initial_crunch(no_crunch); + m_in_simulator_control = false; +} + +// +---------------------------------------------------------------------------- +// |"sc_simcontext::simulate" +// | +// | This method runs the simulation for the specified amount of time. +// | +// | Notes: +// | (1) This code always run with an SC_EXIT_ON_STARVATION starvation policy, +// | so the simulation time on return will be the minimum of the +// | simulation on entry plus the duration, and the maximum time of any +// | event present in the simulation. If the simulation policy is +// | SC_RUN_TO_TIME starvation it is implemented by the caller of this +// | method, e.g., sc_start(), by artificially setting the simulation +// | time forward after this method completes. +// | +// | Arguments: +// | duration = amount of time to simulate. +// +---------------------------------------------------------------------------- +void +sc_simcontext::simulate( const sc_time& duration ) +{ + initialize( true ); + + if (sim_status() != SC_SIM_OK) { + return; + } + + sc_time non_overflow_time = sc_max_time() - m_curr_time; + if ( duration > non_overflow_time ) + { + SC_REPORT_ERROR(SC_ID_SIMULATION_TIME_OVERFLOW_, ""); + return; + } + else if ( duration < SC_ZERO_TIME ) + { + SC_REPORT_ERROR(SC_ID_NEGATIVE_SIMULATION_TIME_,""); + } + + m_in_simulator_control = true; + m_paused = false; + + sc_time until_t = m_curr_time + duration; + sc_time t; // current simulaton time. + + // IF DURATION WAS ZERO WE ONLY CRUNCH ONCE: + // + // We duplicate the code so that we don't add the overhead of the + // check to each loop in the do below. + if ( duration == SC_ZERO_TIME ) + { + m_in_simulator_control = true; + crunch( true ); + if( m_error ) { + m_in_simulator_control = false; + return; + } +#if SC_SIMCONTEXT_TRACING_ + if( m_something_to_trace ) + trace_cycle( /* delta cycle? */ false ); +#endif + if( m_forced_stop ) { + do_sc_stop_action(); + return; + } + // return via implicit pause + goto exit_pause; + } + + // NON-ZERO DURATION: EXECUTE UP TO THAT TIME, OR UNTIL EVENT STARVATION: + + do { + + crunch(); + if( m_error ) { + m_in_simulator_control = false; + return; + } +#if SC_SIMCONTEXT_TRACING_ + if( m_something_to_trace ) { + trace_cycle( false ); + } +#endif + // check for call(s) to sc_stop() or sc_pause(). + if( m_forced_stop ) { + do_sc_stop_action(); + return; + } + if( m_paused ) goto exit_pause; // return explicit pause + + t = m_curr_time; + + do { + // See note 1 above: + + if ( !next_time(t) || (t > until_t ) ) goto exit_time; + if ( t > m_curr_time ) + { + SC_DO_PHASE_CALLBACK_(before_timestep); + m_curr_time = t; + m_change_stamp++; + } + + // PROCESS TIMED NOTIFICATIONS AT THE CURRENT TIME + + do { + sc_event_timed* et = m_timed_events->extract_top(); + sc_event* e = et->event(); + delete et; + if( e != 0 ) { + e->trigger(); + } + } while( m_timed_events->size() && + m_timed_events->top()->notify_time() == t ); + + } while( m_runnable->is_empty() ); + } while ( t < until_t ); // hold off on the delta for the until_t time. + +exit_time: // final simulation time update, if needed + if ( t > m_curr_time && t <= until_t ) + { + SC_DO_PHASE_CALLBACK_(before_timestep); + m_curr_time = t; + m_change_stamp++; + } +exit_pause: // call pause callback upon implicit or explicit pause + m_execution_phase = phase_evaluate; + m_in_simulator_control = false; + SC_DO_PHASE_CALLBACK_(simulation_paused); +} + +void +sc_simcontext::do_sc_stop_action() +{ + SC_REPORT_INFO("/OSCI/SystemC","Simulation stopped by user."); + if (m_start_of_simulation_called) { + end(); + m_in_simulator_control = false; + } + m_simulation_status = SC_STOPPED; + SC_DO_PHASE_CALLBACK_(simulation_stopped); +} + +void +sc_simcontext::mark_to_collect_process( sc_process_b* zombie ) +{ + m_collectable->push_back( zombie ); +} + + +//------------------------------------------------------------------------------ +//"sc_simcontext::stop" +// +// This method stops the simulator after some amount of further processing. +// How much processing is done depends upon the value of the global variable +// stop_mode: +// SC_STOP_IMMEDIATE - aborts the execution phase of the current delta +// cycle and performs whatever updates are pending. +// SC_STOP_FINISH_DELTA - finishes the current delta cycle - both execution +// and updates. +// If sc_stop is called outside of the purview of the simulator kernel +// (e.g., directly from sc_main), the end of simulation notifications +// are performed. From within the purview of the simulator kernel, these +// will be performed at a later time. +//------------------------------------------------------------------------------ + +void +sc_simcontext::stop() +{ + static bool stop_warning_issued = false; + if (m_forced_stop) + { + if ( !stop_warning_issued ) + { + stop_warning_issued = true; // This must be before the WARNING!!! + SC_REPORT_WARNING(SC_ID_SIMULATION_STOP_CALLED_TWICE_, ""); + } + return; + } + if ( stop_mode == SC_STOP_IMMEDIATE ) m_runnable->init(); + m_forced_stop = true; + if ( !m_in_simulator_control ) + { + do_sc_stop_action(); + } +} + +void +sc_simcontext::reset() +{ + clean(); + init(); +} + +void +sc_simcontext::end() +{ + m_simulation_status = SC_END_OF_SIMULATION; + m_ready_to_simulate = false; + m_port_registry->simulation_done(); + m_export_registry->simulation_done(); + m_prim_channel_registry->simulation_done(); + m_module_registry->simulation_done(); + SC_DO_PHASE_CALLBACK_(simulation_done); + m_end_of_simulation_called = true; +} + +void +sc_simcontext::hierarchy_push( sc_module* mod ) +{ + m_object_manager->hierarchy_push( mod ); +} + +sc_module* +sc_simcontext::hierarchy_pop() +{ + return static_cast<sc_module*>( m_object_manager->hierarchy_pop() ); +} + +sc_module* +sc_simcontext::hierarchy_curr() const +{ + return static_cast<sc_module*>( m_object_manager->hierarchy_curr() ); +} + +sc_object* +sc_simcontext::first_object() +{ + return m_object_manager->first_object(); +} + +sc_object* +sc_simcontext::next_object() +{ + return m_object_manager->next_object(); +} + +sc_object* +sc_simcontext::find_object( const char* name ) +{ + static bool warn_find_object=true; + if ( warn_find_object ) + { + warn_find_object = false; + SC_REPORT_INFO(SC_ID_IEEE_1666_DEPRECATION_, + "sc_simcontext::find_object() is deprecated,\n" \ + " use sc_find_object()" ); + } + return m_object_manager->find_object( name ); +} + +// to generate unique names for objects in an MT-Safe way + +const char* +sc_simcontext::gen_unique_name( const char* basename_, bool preserve_first ) +{ + return m_name_gen->gen_unique_name( basename_, preserve_first ); +} + + +sc_process_handle +sc_simcontext::create_cthread_process( + const char* name_p, bool free_host, SC_ENTRY_FUNC method_p, + sc_process_host* host_p, const sc_spawn_options* opt_p ) +{ + sc_thread_handle handle = + new sc_cthread_process(name_p, free_host, method_p, host_p, opt_p); + if ( m_ready_to_simulate ) + { + handle->prepare_for_simulation(); + } else { + m_process_table->push_front( handle ); + } + return sc_process_handle(handle); +} + + +sc_process_handle +sc_simcontext::create_method_process( + const char* name_p, bool free_host, SC_ENTRY_FUNC method_p, + sc_process_host* host_p, const sc_spawn_options* opt_p ) +{ + sc_method_handle handle = + new sc_method_process(name_p, free_host, method_p, host_p, opt_p); + if ( m_ready_to_simulate ) { // dynamic process + if ( !handle->dont_initialize() ) + { +#ifdef SC_HAS_PHASE_CALLBACKS_ + if( SC_UNLIKELY_( m_simulation_status + & (SC_END_OF_UPDATE|SC_BEFORE_TIMESTEP) ) ) + { + std::stringstream msg; + msg << m_simulation_status + << ":\n\t immediate method spawning of " + "`" << handle->name() << "' ignored"; + SC_REPORT_WARNING( SC_ID_PHASE_CALLBACK_FORBIDDEN_ + , msg.str().c_str() ); + } + else +#endif // SC_HAS_PHASE_CALLBACKS_ + { + push_runnable_method( handle ); + } + } + else if ( handle->m_static_events.size() == 0 ) + { + SC_REPORT_WARNING( SC_ID_DISABLE_WILL_ORPHAN_PROCESS_, + handle->name() ); + } + + } else { + m_process_table->push_front( handle ); + } + return sc_process_handle(handle); +} + + +sc_process_handle +sc_simcontext::create_thread_process( + const char* name_p, bool free_host, SC_ENTRY_FUNC method_p, + sc_process_host* host_p, const sc_spawn_options* opt_p ) +{ + sc_thread_handle handle = + new sc_thread_process(name_p, free_host, method_p, host_p, opt_p); + if ( m_ready_to_simulate ) { // dynamic process + handle->prepare_for_simulation(); + if ( !handle->dont_initialize() ) + { +#ifdef SC_HAS_PHASE_CALLBACKS_ + if( SC_UNLIKELY_( m_simulation_status + & (SC_END_OF_UPDATE|SC_BEFORE_TIMESTEP) ) ) + { + std::stringstream msg; + msg << m_simulation_status + << ":\n\t immediate thread spawning of " + "`" << handle->name() << "' ignored"; + SC_REPORT_WARNING( SC_ID_PHASE_CALLBACK_FORBIDDEN_ + , msg.str().c_str() ); + } + else +#endif // SC_HAS_PHASE_CALLBACKS_ + { + push_runnable_thread( handle ); + } + } + else if ( handle->m_static_events.size() == 0 ) + { + SC_REPORT_WARNING( SC_ID_DISABLE_WILL_ORPHAN_PROCESS_, + handle->name() ); + } + + } else { + m_process_table->push_front( handle ); + } + return sc_process_handle(handle); +} + +void +sc_simcontext::add_trace_file( sc_trace_file* tf ) +{ + m_trace_files.push_back( tf ); + m_something_to_trace = true; +} + +void +sc_simcontext::remove_trace_file( sc_trace_file* tf ) +{ + m_trace_files.erase( + std::remove( m_trace_files.begin(), m_trace_files.end(), tf ) + ); + m_something_to_trace = ( m_trace_files.size() > 0 ); +} + +sc_cor* +sc_simcontext::next_cor() +{ + if( m_error ) { + return m_cor; + } + + sc_thread_handle thread_h = pop_runnable_thread(); + while( thread_h != 0 ) { + if ( thread_h->m_cor_p != NULL ) break; + thread_h = pop_runnable_thread(); + } + + if( thread_h != 0 ) { + return thread_h->m_cor_p; + } else { + return m_cor; + } +} + +const ::std::vector<sc_object*>& +sc_simcontext::get_child_objects() const +{ + static bool warn_get_child_objects=true; + if ( warn_get_child_objects ) + { + warn_get_child_objects = false; + SC_REPORT_INFO(SC_ID_IEEE_1666_DEPRECATION_, + "sc_simcontext::get_child_objects() is deprecated,\n" \ + " use sc_get_top_level_objects()" ); + } + return m_child_objects; +} + +void +sc_simcontext::add_child_event( sc_event* event_ ) +{ + // no check if object_ is already in the set + m_child_events.push_back( event_ ); +} + +void +sc_simcontext::add_child_object( sc_object* object_ ) +{ + // no check if object_ is already in the set + m_child_objects.push_back( object_ ); +} + +void +sc_simcontext::remove_child_event( sc_event* event_ ) +{ + int size = m_child_events.size(); + for( int i = 0; i < size; ++ i ) { + if( event_ == m_child_events[i] ) { + m_child_events[i] = m_child_events[size - 1]; + m_child_events.resize(size-1); + return; + } + } + // no check if event_ is really in the set +} + +void +sc_simcontext::remove_child_object( sc_object* object_ ) +{ + int size = m_child_objects.size(); + for( int i = 0; i < size; ++ i ) { + if( object_ == m_child_objects[i] ) { + m_child_objects[i] = m_child_objects[size - 1]; + m_child_objects.resize(size-1); + return; + } + } + // no check if object_ is really in the set +} + +sc_dt::uint64 +sc_simcontext::delta_count() const +{ + static bool warn_delta_count=true; + if ( warn_delta_count ) + { + warn_delta_count = false; + SC_REPORT_INFO(SC_ID_IEEE_1666_DEPRECATION_, + "sc_simcontext::delta_count() is deprecated, use sc_delta_count()" ); + } + return m_delta_count; +} + +bool +sc_simcontext::is_running() const +{ + static bool warn_is_running=true; + if ( warn_is_running ) + { + warn_is_running = false; + SC_REPORT_INFO(SC_ID_IEEE_1666_DEPRECATION_, + "sc_simcontext::is_running() is deprecated, use sc_is_running()" ); + } + return m_ready_to_simulate; +} + +// +---------------------------------------------------------------------------- +// |"sc_simcontext::next_time" +// | +// | This method returns the time of the next event. If there are no events +// | it returns false. +// | +// | Arguments: +// | result = where to place time of the next event, if no event is +// | found this value will not be changed. +// | Result is true if an event is found, false if not. +// +---------------------------------------------------------------------------- +bool +sc_simcontext::next_time( sc_time& result ) const +{ + while( m_timed_events->size() ) { + sc_event_timed* et = m_timed_events->top(); + if( et->event() != 0 ) { + result = et->notify_time(); + return true; + } + delete m_timed_events->extract_top(); + } + return false; +} + +void +sc_simcontext::remove_delta_event( sc_event* e ) +{ + int i = e->m_delta_event_index; + int j = m_delta_events.size() - 1; + assert( i >= 0 && i <= j ); + if( i != j ) { + sc_event** l_delta_events = &m_delta_events[0]; + l_delta_events[i] = l_delta_events[j]; + l_delta_events[i]->m_delta_event_index = i; + } + m_delta_events.resize(m_delta_events.size()-1); + e->m_delta_event_index = -1; +} + +// +---------------------------------------------------------------------------- +// |"sc_simcontext::preempt_with" +// | +// | This method executes the supplied method immediately, suspending the +// | caller. After executing the supplied method the caller's execution will +// | be restored. It is used to allow a method to immediately throw an +// | exception, e.g., when the method's kill_process() method was called. +// | There are three cases to consider: +// | (1) The caller is a method, e.g., murder by method. +// | (2) The caller is a thread instance, e.g., murder by thread. +// | (3) The caller is this method instance, e.g., suicide. +// | +// | Arguments: +// | method_h -> method to be executed. +// +---------------------------------------------------------------------------- +void +sc_simcontext::preempt_with( sc_method_handle method_h ) +{ + sc_curr_proc_info caller_info; // process info for caller. + sc_method_handle active_method_h; // active method or null. + sc_thread_handle active_thread_h; // active thread or null. + + // Determine the active process and take the thread to be run off the + // run queue, if its there, since we will be explicitly causing its + // execution. + + active_method_h = DCAST<sc_method_handle>(sc_get_current_process_b()); + active_thread_h = DCAST<sc_thread_handle>(sc_get_current_process_b()); + if ( method_h->next_runnable() != NULL ) + remove_runnable_method( method_h ); + + // CALLER IS THE METHOD TO BE RUN: + // + // Should never get here, ignore it unless we are debugging. + + if ( method_h == active_method_h ) + { + DEBUG_MSG(DEBUG_NAME,method_h,"self preemption of active method"); + } + + // THE CALLER IS A METHOD: + // + // (a) Set the current process information to our method. + // (b) Invoke our method directly by-passing the run queue. + // (c) Restore the process info to the caller. + // (d) Check to see if the calling method should throw an exception + // because of activity that occurred during the preemption. + + else if ( active_method_h != NULL ) + { + caller_info = m_curr_proc_info; + DEBUG_MSG( DEBUG_NAME, method_h, + "preempting active method with method" ); + sc_get_curr_simcontext()->set_curr_proc( (sc_process_b*)method_h ); + method_h->run_process(); + sc_get_curr_simcontext()->set_curr_proc((sc_process_b*)active_method_h); + active_method_h->check_for_throws(); + } + + // CALLER IS A THREAD: + // + // (a) Use an invocation thread to execute the method. + + else if ( active_thread_h != NULL ) + { + DEBUG_MSG( DEBUG_NAME, method_h, + "preempting active thread with method" ); + m_method_invoker_p->invoke_method(method_h); + } + + // CALLER IS THE SIMULATOR: + // + // That is not allowed. + + else + { + caller_info = m_curr_proc_info; + DEBUG_MSG( DEBUG_NAME, method_h, + "preempting no active process with method" ); + sc_get_curr_simcontext()->set_curr_proc( (sc_process_b*)method_h ); + method_h->run_process(); + m_curr_proc_info = caller_info; + } +} + +//------------------------------------------------------------------------------ +//"sc_simcontext::requeue_current_process" +// +// This method requeues the current process at the beginning of the run queue +// if it is a thread. This is called by sc_process_handle::throw_it() to assure +// that a thread that is issuing a throw will execute immediately after the +// processes it notifies via the throw. +//------------------------------------------------------------------------------ +void sc_simcontext::requeue_current_process() +{ + sc_thread_handle thread_p; + thread_p = DCAST<sc_thread_handle>(get_curr_proc_info()->process_handle); + if ( thread_p ) + { + execute_thread_next( thread_p ); + } +} + +//------------------------------------------------------------------------------ +//"sc_simcontext::suspend_current_process" +// +// This method suspends the current process if it is a thread. This is called +// by sc_process_handle::throw_it() to allow the processes that have received +// a throw to execute. +//------------------------------------------------------------------------------ +void sc_simcontext::suspend_current_process() +{ + sc_thread_handle thread_p; + thread_p = DCAST<sc_thread_handle>(get_curr_proc_info()->process_handle); + if ( thread_p ) + { + thread_p->suspend_me(); + } +} + +void +sc_simcontext::trace_cycle( bool delta_cycle ) +{ + int size; + if( ( size = m_trace_files.size() ) != 0 ) { + sc_trace_file** l_trace_files = &m_trace_files[0]; + int i = size - 1; + do { + l_trace_files[i]->cycle( delta_cycle ); + } while( -- i >= 0 ); + } +} + +// ---------------------------------------------------------------------------- + +#if 1 +#ifdef PURIFY + static sc_simcontext sc_default_global_context; + sc_simcontext* sc_curr_simcontext = &sc_default_global_context; +#else + sc_simcontext* sc_curr_simcontext = 0; + sc_simcontext* sc_default_global_context = 0; +#endif +#else +// Not MT-safe! +static sc_simcontext* sc_curr_simcontext = 0; + + +sc_simcontext* +sc_get_curr_simcontext() +{ + if( sc_curr_simcontext == 0 ) { +#ifdef PURIFY + static sc_simcontext sc_default_global_context; + sc_curr_simcontext = &sc_default_global_context; +#else + static sc_simcontext* sc_default_global_context = new sc_simcontext; + sc_curr_simcontext = sc_default_global_context; +#endif + } + return sc_curr_simcontext; +} +#endif // 0 + +// Generates unique names within each module. + +const char* +sc_gen_unique_name( const char* basename_, bool preserve_first ) +{ + sc_simcontext* simc = sc_get_curr_simcontext(); + sc_module* curr_module = simc->hierarchy_curr(); + if( curr_module != 0 ) { + return curr_module->gen_unique_name( basename_, preserve_first ); + } else { + sc_process_b* curr_proc_p = sc_get_current_process_b(); + if ( curr_proc_p ) + { + return curr_proc_p->gen_unique_name( basename_, preserve_first ); + } + else + { + return simc->gen_unique_name( basename_, preserve_first ); + } + } +} + +// Get a handle for the current process +// +// Note that this method should not be called if the current process is +// in the act of being deleted, it will mess up the reference count management +// of sc_process_b instance the handle represents. Instead, use the a +// pointer to the raw sc_process_b instance, which may be acquired via +// sc_get_current_process_b(). + +sc_process_handle +sc_get_current_process_handle() +{ + return ( sc_is_running() ) ? + sc_process_handle(sc_get_current_process_b()) : + sc_get_last_created_process_handle(); +} + +// THE FOLLOWING FUNCTION IS DEPRECATED IN 2.1 +sc_process_b* +sc_get_curr_process_handle() +{ + static bool warn=true; + if ( warn ) + { + warn = false; + SC_REPORT_INFO(SC_ID_IEEE_1666_DEPRECATION_, + "sc_get_curr_process_handle deprecated use sc_get_current_process_handle" + ); + } + + return sc_get_curr_simcontext()->get_curr_proc_info()->process_handle; +} + +// Return indication if there are more processes to execute in this delta phase + +bool +sc_simcontext::pending_activity_at_current_time() const +{ + return ( m_delta_events.size() != 0) || + ( m_runnable->is_initialized() && !m_runnable->is_empty() ) || + m_prim_channel_registry->pending_updates(); +} + +// Return time of next activity. + +sc_time sc_time_to_pending_activity( const sc_simcontext* simc_p ) +{ + // If there is an activity pending at the current time + // return a delta of zero. + + sc_time result=SC_ZERO_TIME; // time of pending activity. + + if ( simc_p->pending_activity_at_current_time() ) + { + return result; + } + + // Any activity will take place in the future pick up the next event's time. + + else + { + result = simc_p->max_time(); + simc_p->next_time(result); + result -= sc_time_stamp(); + } + return result; +} + +// Set the random seed for controlled randomization -- not yet implemented + +void +sc_set_random_seed( unsigned int ) +{ + SC_REPORT_WARNING( SC_ID_NOT_IMPLEMENTED_, + "void sc_set_random_seed( unsigned int )" ); +} + + +// +---------------------------------------------------------------------------- +// |"sc_start" +// | +// | This function starts, or restarts, the execution of the simulator. +// | +// | Arguments: +// | duration = the amount of time the simulator should execute. +// | p = event starvation policy. +// +---------------------------------------------------------------------------- +void +sc_start( const sc_time& duration, sc_starvation_policy p ) +{ + sc_simcontext* context_p; // current simulation context. + sc_time entry_time; // simulation time upon entry. + sc_time exit_time; // simulation time to set upon exit. + sc_dt::uint64 starting_delta; // delta count upon entry. + int status; // current simulation status. + + // Set up based on the arguments passed to us: + + context_p = sc_get_curr_simcontext(); + starting_delta = sc_delta_count(); + entry_time = context_p->m_curr_time; + if ( p == SC_RUN_TO_TIME ) + exit_time = context_p->m_curr_time + duration; + + // called with duration = SC_ZERO_TIME for the first time + static bool init_delta_or_pending_updates = + ( starting_delta == 0 && exit_time == SC_ZERO_TIME ); + + // If the simulation status is bad issue the appropriate message: + + status = context_p->sim_status(); + if( status != SC_SIM_OK ) + { + if ( status == SC_SIM_USER_STOP ) + SC_REPORT_ERROR(SC_ID_SIMULATION_START_AFTER_STOP_, ""); + if ( status == SC_SIM_ERROR ) + SC_REPORT_ERROR(SC_ID_SIMULATION_START_AFTER_ERROR_, ""); + return; + } + + if ( context_p->m_prim_channel_registry->pending_updates() ) + init_delta_or_pending_updates = true; + + // If the simulation status is good perform the simulation: + + context_p->simulate( duration ); + + // Re-check the status: + + status = context_p->sim_status(); + + // Update the current time to the exit time if that is the starvation + // policy: + + if ( p == SC_RUN_TO_TIME && !context_p->m_paused && status == SC_SIM_OK ) + { + context_p->m_curr_time = exit_time; + } + + // If there was no activity and the simulation clock did not move warn + // the user, except if we're in a first sc_start(SC_ZERO_TIME) for + // initialisation (only) or there have been pending updates: + + if ( !init_delta_or_pending_updates && + starting_delta == sc_delta_count() && + context_p->m_curr_time == entry_time && + status == SC_SIM_OK ) + { + SC_REPORT_WARNING(SC_ID_NO_SC_START_ACTIVITY_, ""); + } + + // reset init/update flag for subsequent calls + init_delta_or_pending_updates = false; +} + +void +sc_start() +{ + sc_start( sc_max_time() - sc_time_stamp(), + SC_EXIT_ON_STARVATION ); +} + +// for backward compatibility with 1.0 +#if 0 +void +sc_start( double duration ) // in default time units +{ + static bool warn_sc_start=true; + if ( warn_sc_start ) + { + warn_sc_start = false; + SC_REPORT_INFO(SC_ID_IEEE_1666_DEPRECATION_, + "sc_start(double) deprecated, use sc_start(sc_time) or sc_start()"); + } + + if( duration == -1 ) // simulate forever + { + sc_start( + sc_time(~sc_dt::UINT64_ZERO, false) - sc_time_stamp() ); + } + else + { + sc_start( sc_time( duration, true ) ); + } +} +#endif // + +void +sc_stop() +{ + sc_get_curr_simcontext()->stop(); +} + + +// The following function is deprecated in favor of sc_start(SC_ZERO_TIME): + +void +sc_initialize() +{ + static bool warning_initialize = true; + + if ( warning_initialize ) + { + warning_initialize = false; + SC_REPORT_INFO(SC_ID_IEEE_1666_DEPRECATION_, + "sc_initialize() is deprecated: use sc_start(SC_ZERO_TIME)" ); + } + sc_get_curr_simcontext()->initialize(); +} + +// The following function has been deprecated in favor of sc_start(duration): + +void +sc_cycle( const sc_time& duration ) +{ + static bool warning_cycle = true; + + if ( warning_cycle ) + { + warning_cycle = false; + SC_REPORT_INFO(SC_ID_IEEE_1666_DEPRECATION_, + "sc_cycle is deprecated: use sc_start(sc_time)" ); + } + sc_get_curr_simcontext()->cycle( duration ); +} + +sc_event* sc_find_event( const char* name ) +{ + return sc_get_curr_simcontext()->get_object_manager()->find_event( name ); +} + +sc_object* sc_find_object( const char* name ) +{ + return sc_get_curr_simcontext()->get_object_manager()->find_object( name ); +} + + +const sc_time& +sc_max_time() +{ + return sc_get_curr_simcontext()->max_time(); +} + +const sc_time& +sc_time_stamp() +{ + return sc_get_curr_simcontext()->time_stamp(); +} + +double +sc_simulation_time() +{ + static bool warn_simulation_time=true; + if ( warn_simulation_time ) + { + warn_simulation_time=false; + SC_REPORT_INFO(SC_ID_IEEE_1666_DEPRECATION_, + "sc_simulation_time() is deprecated use sc_time_stamp()" ); + } + return sc_get_curr_simcontext()->time_stamp().to_default_time_units(); +} + +void +sc_defunct_process_function( sc_module* ) +{ + // This function is pointed to by defunct sc_thread_process'es and + // sc_cthread_process'es. In a correctly constructed world, this + // function should never be called; hence the assert. + assert( false ); +} + +//------------------------------------------------------------------------------ +//"sc_set_stop_mode" +// +// This function sets the mode of operation when sc_stop() is called. +// mode = SC_STOP_IMMEDIATE or SC_STOP_FINISH_DELTA. +//------------------------------------------------------------------------------ +void sc_set_stop_mode(sc_stop_mode mode) +{ + if ( sc_is_running() ) + { + SC_REPORT_ERROR(SC_ID_STOP_MODE_AFTER_START_,""); + } + else + { + switch( mode ) + { + case SC_STOP_IMMEDIATE: + case SC_STOP_FINISH_DELTA: + stop_mode = mode; + break; + default: + break; + } + } +} + +sc_stop_mode +sc_get_stop_mode() +{ + return stop_mode; +} + +bool sc_is_unwinding() +{ + return sc_get_current_process_handle().is_unwinding(); +} + +// The IEEE 1666 Standard for 2011 designates that the treatment of +// certain process control interactions as being "implementation dependent". +// These interactions are: +// (1) What happens when a resume() call is performed on a disabled, +// suspended process. +// (2) What happens when sync_reset_on() or sync_reset_off() is called +// on a suspended process. +// (3) What happens when the value specified in a reset_signal_is() +// call changes value while a process is suspended. +// +// By default this Proof of Concept implementation reports an error +// for these interactions. However, the implementation also provides +// a non-error treatment. The non-error treatment for the interactions is: +// (1) A resume() call performed on a disabled, suspended process will +// mark the process as no longer suspended, and if it is capable +// of execution (not waiting on any events) it will be placed on +// the queue of runnable processes. See the state diagram below. +// (2) A call to sync_reset_on() or sync_reset_off() will set or clear +// the synchronous reset flag. Whether the process is in reset or +// not will be determined when the process actually executes by +// looking at the flag's value at that time. +// (3) If a suspended process has a reset_signal_is() specification +// the value of the reset variable at the time of its next execution +// will determine whether it is in reset or not. +// +// TO GET THE NON-ERROR BEHAVIOR SET THE VARIABLE BELOW TO TRUE. +// +// This can be done in this source before you build the library, or you +// can use an assignment as the first statement in your sc_main() function: +// sc_core::sc_allow_process_control_corners = true; + +bool sc_allow_process_control_corners = false; + +// The state transition diagram for the interaction of disable and suspend +// when sc_allow_process_control_corners is true is shown below: +// +// ...................................................................... +// . ENABLED . DISABLED . +// . . . +// . +----------+ disable +----------+ . +// . +------------>| |-------.-------->| | . +// . | | runnable | . | runnable | . +// . | +-------| |<------.---------| |------+ . +// . | | +----------+ enable +----------+ | . +// . | | | ^ . | ^ | . +// . | | suspend | | resume . suspend | | resume | . +// . | | V | . V | | . +// . | | +----------+ disable +----------+ | . +// . | | | suspend |-------.-------->| suspend | | . +// . t | r | | | . | | | r . +// . r | u | | ready |<------.---------| ready | | u . +// . i | n | +----------+ enable +----------+ | n . +// . g | / | ^ . | / . +// . g | w | trigger| . | w . +// . e | a | | . | a . +// . r | i | +----------+ disable +----------+ | i . +// . | t | | suspend |-------.-------->| suspend | | t . +// . | | | | . | | | . +// . | | | waiting |<------.---------| waiting | | . +// . | | +----------+ enable +----------+ | . +// . | | | ^ . | ^ | . +// . | | suspend | | resume . suspend | | resume | . +// . | | V | . V | | . +// . | | +----------+ disable +----------+ | . +// . | +------>| |-------.-------->| | | . +// . | | waiting | . | waiting | | . +// . +-------------| |<------.---------| |<-----+ . +// . +----------+ enable +----------+ . +// . . . +// ...................................................................... + +// ---------------------------------------------------------------------------- + +static std::ostream& +print_status_expression( std::ostream& os, sc_status s ); + +// utility helper to print a simulation status +std::ostream& operator << ( std::ostream& os, sc_status s ) +{ + // print primitive values + switch(s) + { +# define PRINT_STATUS( Status ) \ + case Status: { os << #Status; } break + + PRINT_STATUS( SC_UNITIALIZED ); + PRINT_STATUS( SC_ELABORATION ); + PRINT_STATUS( SC_BEFORE_END_OF_ELABORATION ); + PRINT_STATUS( SC_END_OF_ELABORATION ); + PRINT_STATUS( SC_START_OF_SIMULATION ); + + PRINT_STATUS( SC_RUNNING ); + PRINT_STATUS( SC_PAUSED ); + PRINT_STATUS( SC_STOPPED ); + PRINT_STATUS( SC_END_OF_SIMULATION ); + + PRINT_STATUS( SC_END_OF_INITIALIZATION ); +// PRINT_STATUS( SC_END_OF_EVALUATION ); + PRINT_STATUS( SC_END_OF_UPDATE ); + PRINT_STATUS( SC_BEFORE_TIMESTEP ); + + PRINT_STATUS( SC_STATUS_ANY ); + +# undef PRINT_STATUS + default: + + if( s & SC_STATUS_ANY ) // combination of status bits + print_status_expression( os, s ); + else // invalid number, print hex value + os << "0x" << std::hex << +s; + } + + return os; +} + +// pretty-print a combination of sc_status bits (i.e. a callback mask) +static std::ostream& +print_status_expression( std::ostream& os, sc_status s ) +{ + std::vector<sc_status> bits; + unsigned is_set = SC_ELABORATION; + + // collect bits + while( is_set <= SC_STATUS_LAST ) + { + if( s & is_set ) + bits.push_back( (sc_status)is_set ); + is_set <<= 1; + } + if( s & ~SC_STATUS_ANY ) // remaining bits + bits.push_back( (sc_status)( s & ~SC_STATUS_ANY ) ); + + // print expression + std::vector<sc_status>::size_type i=0, n=bits.size(); + if ( n>1 ) + os << "("; + for( ; i<n-1; ++i ) + os << bits[i] << "|"; + os << bits[i]; + if ( n>1 ) + os << ")"; + return os; +} + +} // namespace sc_core + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affiliation, date and + changes you are making here. + + Name, Affiliation, Date: Ali Dasdan, Synopsys, Inc. + Description of Modification: - Added sc_stop() detection into initial_crunch + and crunch. This makes it possible to exit out + of a combinational loop using sc_stop(). + + Name, Affiliation, Date: Andy Goodrich, Forte Design Systems 20 May 2003 + Description of Modification: - sc_stop mode + - phase callbacks + + Name, Affiliation, Date: Bishnupriya Bhattacharya, Cadence Design Systems, + 25 August 2003 + Description of Modification: - support for dynamic process + - support for sc export registry + - new member methods elaborate(), + prepare_to_simulate(), and initial_crunch() + that are invoked by initialize() in that order + - implement sc_get_last_created_process_handle() for use + before simulation starts + - remove "set_curr_proc(handle)" from + register_method_process and + register_thread_process - led to bugs + + Name, Affiliation, Date: Andy Goodrich, Forte Design Systems 04 Sep 2003 + Description of Modification: - changed process existence structures to + linked lists to eliminate exponential + execution problem with using sc_pvector. + *****************************************************************************/ +// $Log: sc_simcontext.cpp,v $ +// Revision 1.37 2011/08/29 18:04:32 acg +// Philipp A. Hartmann: miscellaneous clean ups. +// +// Revision 1.36 2011/08/26 20:46:10 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.35 2011/08/24 22:05:51 acg +// Torsten Maehne: initialization changes to remove warnings. +// +// Revision 1.34 2011/08/04 17:15:28 acg +// Andy Goodrich: added documentation to crunch() routine. +// +// Revision 1.32 2011/07/24 11:16:36 acg +// Philipp A. Hartmann: fix reference counting on deferred deletions of +// processes. +// +// Revision 1.31 2011/07/01 18:49:07 acg +// Andy Goodrich: moved pln() from sc_simcontext.cpp to sc_ver.cpp. +// +// Revision 1.30 2011/05/09 04:07:49 acg +// Philipp A. Hartmann: +// (1) Restore hierarchy in all phase callbacks. +// (2) Ensure calls to before_end_of_elaboration. +// +// Revision 1.29 2011/04/08 22:39:09 acg +// Andy Goodrich: moved method invocation code to sc_method.h so that the +// details are hidden from sc_simcontext. +// +// Revision 1.28 2011/04/05 20:50:57 acg +// Andy Goodrich: +// (1) changes to make sure that event(), posedge() and negedge() only +// return true if the clock has not moved. +// (2) fixes for method self-resumes. +// (3) added SC_PRERELEASE_VERSION +// (4) removed kernel events from the object hierarchy, added +// sc_hierarchy_name_exists(). +// +// Revision 1.27 2011/04/05 06:14:15 acg +// Andy Goodrich: fix typo. +// +// Revision 1.26 2011/04/05 06:03:32 acg +// Philipp A. Hartmann: added code to set ready to run bit for a suspended +// process that does not have dont_initialize specified at simulation +// start up. +// +// Revision 1.25 2011/04/01 21:31:55 acg +// Andy Goodrich: make sure processes suspended before the start of execution +// don't get scheduled for initial execution. +// +// Revision 1.24 2011/03/28 13:02:52 acg +// Andy Goodrich: Changes for disable() interactions. +// +// Revision 1.23 2011/03/12 21:07:51 acg +// Andy Goodrich: changes to kernel generated event support. +// +// Revision 1.22 2011/03/07 17:38:43 acg +// Andy Goodrich: tightening up of checks for undefined interaction between +// synchronous reset and suspend. +// +// Revision 1.21 2011/03/06 19:57:11 acg +// Andy Goodrich: refinements for the illegal suspend - synchronous reset +// interaction. +// +// Revision 1.20 2011/03/06 15:58:50 acg +// Andy Goodrich: added escape to turn off process control corner case +// checks. +// +// Revision 1.19 2011/03/05 04:45:16 acg +// Andy Goodrich: moved active process calculation to the sc_simcontext class. +// +// Revision 1.18 2011/03/05 01:39:21 acg +// Andy Goodrich: changes for named events. +// +// Revision 1.17 2011/02/18 20:27:14 acg +// Andy Goodrich: Updated Copyrights. +// +// Revision 1.16 2011/02/17 19:53:28 acg +// Andy Goodrich: eliminated use of ready_to_run() as part of process control +// simplification. +// +// Revision 1.15 2011/02/13 21:47:38 acg +// Andy Goodrich: update copyright notice. +// +// Revision 1.14 2011/02/11 13:25:24 acg +// Andy Goodrich: Philipp A. Hartmann's changes: +// (1) Removal of SC_CTHREAD method overloads. +// (2) New exception processing code. +// +// Revision 1.13 2011/02/08 08:42:50 acg +// Andy Goodrich: fix ordering of check for stopped versus paused. +// +// Revision 1.12 2011/02/07 19:17:20 acg +// Andy Goodrich: changes for IEEE 1666 compatibility. +// +// Revision 1.11 2011/02/02 07:18:11 acg +// Andy Goodrich: removed toggle() calls for the new crunch() toggle usage. +// +// Revision 1.10 2011/02/01 23:01:53 acg +// Andy Goodrich: removed dead code. +// +// Revision 1.9 2011/02/01 21:11:59 acg +// Andy Goodrich: +// (1) Use of new toggle_methods() and toggle_threads() run queue methods +// to make sure the thread run queue does not execute when allow preempt_me() +// is called from an SC_METHOD. +// (2) Use of execute_thread_next() to allow thread execution in the current +// delta cycle() rather than push_runnable_thread_front which executed +// in the following cycle. +// +// Revision 1.8 2011/01/25 20:50:37 acg +// Andy Goodrich: changes for IEEE 1666 2011. +// +// Revision 1.7 2011/01/19 23:21:50 acg +// Andy Goodrich: changes for IEEE 1666 2011 +// +// Revision 1.6 2011/01/18 20:10:45 acg +// Andy Goodrich: changes for IEEE1666_2011 semantics. +// +// Revision 1.5 2010/11/20 17:10:57 acg +// Andy Goodrich: reset processing changes for new IEEE 1666 standard. +// +// Revision 1.4 2010/07/22 20:02:33 acg +// Andy Goodrich: bug fixes. +// +// Revision 1.3 2008/05/22 17:06:26 acg +// Andy Goodrich: updated copyright notice to include 2008. +// +// Revision 1.2 2007/09/20 20:32:35 acg +// Andy Goodrich: changes to the semantics of throw_it() to match the +// specification. A call to throw_it() will immediately suspend the calling +// thread until all the throwees have executed. At that point the calling +// thread will be restarted before the execution of any other threads. +// +// Revision 1.1.1.1 2006/12/15 20:20:05 acg +// SystemC 2.3 +// +// Revision 1.21 2006/08/29 23:37:13 acg +// Andy Goodrich: Added check for negative time. +// +// Revision 1.20 2006/05/26 20:33:16 acg +// Andy Goodrich: changes required by additional platform compilers (i.e., +// Microsoft VC++, Sun Forte, HP aCC). +// +// Revision 1.19 2006/05/08 17:59:52 acg +// Andy Goodrich: added a check before m_curr_time is set to make sure it +// is not set to a time before its current value. This will treat +// sc_event.notify( ) calls with negative times as calls with a zero time. +// +// Revision 1.18 2006/04/20 17:08:17 acg +// Andy Goodrich: 3.0 style process changes. +// +// Revision 1.17 2006/04/11 23:13:21 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.16 2006/03/21 00:00:34 acg +// Andy Goodrich: changed name of sc_get_current_process_base() to be +// sc_get_current_process_b() since its returning an sc_process_b instance. +// +// Revision 1.15 2006/03/13 20:26:50 acg +// Andy Goodrich: Addition of forward class declarations, e.g., +// sc_reset, to keep gcc 4.x happy. +// +// Revision 1.14 2006/02/02 23:42:41 acg +// Andy Goodrich: implemented a much better fix to the sc_event_finder +// proliferation problem. This new version allocates only a single event +// finder for each port for each type of event, e.g., pos(), neg(), and +// value_change(). The event finder persists as long as the port does, +// which is what the LRM dictates. Because only a single instance is +// allocated for each event type per port there is not a potential +// explosion of storage as was true in the 2.0.1/2.1 versions. +// +// Revision 1.13 2006/02/02 21:29:10 acg +// Andy Goodrich: removed the call to sc_event_finder::free_instances() that +// was in end_of_elaboration(), leaving only the call in clean(). This is +// because the LRM states that sc_event_finder instances are persistent as +// long as the sc_module hierarchy is valid. +// +// Revision 1.12 2006/02/02 21:09:50 acg +// Andy Goodrich: added call to sc_event_finder::free_instances in the clean() +// method. +// +// Revision 1.11 2006/02/02 20:43:14 acg +// Andy Goodrich: Added an existence linked list to sc_event_finder so that +// the dynamically allocated instances can be freed after port binding +// completes. This replaces the individual deletions in ~sc_bind_ef, as these +// caused an exception if an sc_event_finder instance was used more than +// once, due to a double freeing of the instance. +// +// Revision 1.10 2006/01/31 21:43:26 acg +// Andy Goodrich: added comments in constructor to highlight environmental +// overrides section. +// +// Revision 1.9 2006/01/26 21:04:54 acg +// Andy Goodrich: deprecation message changes and additional messages. +// +// Revision 1.8 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.7 2006/01/24 20:49:05 acg +// Andy Goodrich: changes to remove the use of deprecated features within the +// simulator, and to issue warning messages when deprecated features are used. +// +// Revision 1.6 2006/01/19 00:29:52 acg +// Andy Goodrich: Yet another implementation for signal write checking. This +// one uses an environment variable SC_SIGNAL_WRITE_CHECK, that when set to +// DISABLE will disable write checking on signals. +// +// Revision 1.5 2006/01/13 18:44:30 acg +// Added $Log to record CVS changes into the source. +// +// Revision 1.4 2006/01/03 23:18:44 acg +// Changed copyright to include 2006. +// +// Revision 1.3 2005/12/20 22:11:10 acg +// Fixed $Log lines. +// +// Revision 1.2 2005/12/20 22:02:30 acg +// Changed where delta cycles are incremented to match IEEE 1666. Added the +// event_occurred() method to hide how delta cycle comparisions are done within +// sc_simcontext. Changed the boolean update_phase to an enum that shows all +// the phases. +// Taf! diff --git a/ext/systemc/src/sysc/kernel/sc_simcontext.h b/ext/systemc/src/sysc/kernel/sc_simcontext.h new file mode 100644 index 000000000..997a3f49c --- /dev/null +++ b/ext/systemc/src/sysc/kernel/sc_simcontext.h @@ -0,0 +1,903 @@ +/***************************************************************************** + + 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_simcontext.h -- Definition of the simulation context class. + + Original Author: Stan Y. Liao, Synopsys, Inc. + Martin Janssen, Synopsys, Inc. + + CHANGE LOG AT THE END OF THE FILE + *****************************************************************************/ + +#ifndef SC_SIMCONTEXT_H +#define SC_SIMCONTEXT_H + +#include "sysc/kernel/sc_cmnhdr.h" +#include "sysc/kernel/sc_process.h" +#include "sysc/kernel/sc_status.h" +#include "sysc/kernel/sc_time.h" +#include "sysc/utils/sc_hash.h" +#include "sysc/utils/sc_pq.h" + +namespace sc_core { + +// forward declarations + +class sc_cor; +class sc_cor_pkg; +class sc_event; +class sc_event_timed; +class sc_export_registry; +class sc_module; +class sc_module_name; +class sc_module_registry; +class sc_name_gen; +class sc_object; +class sc_object_manager; +class sc_phase_callback_registry; +class sc_process_handle; +class sc_port_registry; +class sc_prim_channel_registry; +class sc_process_table; +class sc_signal_bool_deval; +class sc_trace_file; +class sc_runnable; +class sc_process_host; +class sc_method_process; +class sc_cthread_process; +class sc_thread_process; + +template< typename > class sc_plist; +typedef sc_plist< sc_process_b* > sc_process_list; + +struct sc_curr_proc_info +{ + sc_process_b* process_handle; + sc_curr_proc_kind kind; + sc_curr_proc_info() : process_handle( 0 ), kind( SC_NO_PROC_ ) {} +}; + +typedef const sc_curr_proc_info* sc_curr_proc_handle; + +enum sc_stop_mode { // sc_stop modes: + SC_STOP_FINISH_DELTA, + SC_STOP_IMMEDIATE +}; +extern void sc_set_stop_mode( sc_stop_mode mode ); +extern sc_stop_mode sc_get_stop_mode(); + +enum sc_starvation_policy +{ + SC_EXIT_ON_STARVATION, + SC_RUN_TO_TIME +}; +extern void sc_start(); +extern void sc_start( const sc_time& duration, + sc_starvation_policy p=SC_RUN_TO_TIME ); +inline void sc_start( int duration, sc_time_unit unit, + sc_starvation_policy p=SC_RUN_TO_TIME ) +{ + sc_start( sc_time((double)duration,unit), p ); +} + +inline void sc_start( double duration, sc_time_unit unit, + sc_starvation_policy p=SC_RUN_TO_TIME ) +{ + sc_start( sc_time(duration,unit), p ); +} + +extern void sc_stop(); + +// friend function declarations + +sc_dt::uint64 sc_delta_count(); +const std::vector<sc_event*>& sc_get_top_level_events( + const sc_simcontext* simc_p); +const std::vector<sc_object*>& sc_get_top_level_objects( + const sc_simcontext* simc_p); +bool sc_is_running( const sc_simcontext* simc_p ); +void sc_pause(); +bool sc_end_of_simulation_invoked(); +void sc_start( const sc_time&, sc_starvation_policy ); +bool sc_start_of_simulation_invoked(); +void sc_set_time_resolution( double, sc_time_unit ); +sc_time sc_get_time_resolution(); +void sc_set_default_time_unit( double, sc_time_unit ); +sc_time sc_get_default_time_unit(); +bool sc_pending_activity_at_current_time( const sc_simcontext* ); +bool sc_pending_activity_at_future_time( const sc_simcontext* ); +sc_time sc_time_to_pending_activity( const sc_simcontext* ); + +struct sc_invoke_method; + +// ---------------------------------------------------------------------------- +// CLASS : sc_simcontext +// +// The simulation context. +// ---------------------------------------------------------------------------- + +class sc_simcontext +{ + friend struct sc_invoke_method; + friend class sc_event; + friend class sc_module; + friend class sc_object; + friend class sc_time; + friend class sc_clock; + friend class sc_method_process; + friend class sc_phase_callback_registry; + friend class sc_process_b; + friend class sc_process_handle; + friend class sc_prim_channel; + friend class sc_cthread_process; + friend class sc_thread_process; + friend sc_dt::uint64 sc_delta_count(); + friend const std::vector<sc_event*>& sc_get_top_level_events( + const sc_simcontext* simc_p); + friend const std::vector<sc_object*>& sc_get_top_level_objects( + const sc_simcontext* simc_p); + friend bool sc_is_running( const sc_simcontext* simc_p ); + friend void sc_pause(); + friend bool sc_end_of_simulation_invoked(); + friend void sc_start( const sc_time&, sc_starvation_policy ); + friend bool sc_start_of_simulation_invoked(); + friend void sc_thread_cor_fn(void*); + friend sc_time sc_time_to_pending_activity( const sc_simcontext* ); + friend bool sc_pending_activity_at_current_time( const sc_simcontext* ); + friend bool sc_pending_activity_at_future_time( const sc_simcontext* ); + + + void init(); + void clean(); + +public: + + sc_simcontext(); + ~sc_simcontext(); + + void initialize( bool = false ); + void cycle( const sc_time& ); + void simulate( const sc_time& duration ); + void stop(); + void end(); + void reset(); + + int sim_status() const; + bool elaboration_done() const; + + std::vector<sc_thread_handle>& get_active_invokers(); + + sc_object_manager* get_object_manager(); + + inline sc_status get_status() const; + + sc_object* active_object(); + + void hierarchy_push( sc_module* ); + sc_module* hierarchy_pop(); + sc_module* hierarchy_curr() const; + sc_object* first_object(); + sc_object* next_object(); + sc_object* find_object( const char* name ); + + sc_module_registry* get_module_registry(); + sc_port_registry* get_port_registry(); + sc_export_registry* get_export_registry(); + sc_prim_channel_registry* get_prim_channel_registry(); + + // to generate unique names for objects in an MT-Safe way + const char* gen_unique_name( const char* basename_, + bool preserve_first = false + ); + + // process creation + sc_process_handle create_cthread_process( + const char* name_p, bool free_host, SC_ENTRY_FUNC method_p, + sc_process_host* host_p, const sc_spawn_options* opt_p ); + + sc_process_handle create_method_process( + const char* name_p, bool free_host, SC_ENTRY_FUNC method_p, + sc_process_host* host_p, const sc_spawn_options* opt_p ); + + sc_process_handle create_thread_process( + const char* name_p, bool free_host, SC_ENTRY_FUNC method_p, + sc_process_host* host_p, const sc_spawn_options* opt_p ); + + sc_curr_proc_handle get_curr_proc_info(); + sc_object* get_current_writer() const; + bool write_check() const; + void set_curr_proc( sc_process_b* ); + void reset_curr_proc(); + + int next_proc_id(); + + void add_trace_file( sc_trace_file* ); + void remove_trace_file( sc_trace_file* ); + + friend void sc_set_time_resolution( double, sc_time_unit ); + friend sc_time sc_get_time_resolution(); + friend void sc_set_default_time_unit( double, sc_time_unit ); + friend sc_time sc_get_default_time_unit(); + + const sc_time& max_time() const; + const sc_time& time_stamp() const; + + sc_dt::uint64 change_stamp() const; + sc_dt::uint64 delta_count() const; + bool event_occurred( sc_dt::uint64 last_change_count ) const; + bool evaluation_phase() const; + bool is_running() const; + bool update_phase() const; + bool notify_phase() const; + bool get_error(); + void set_error( sc_report* ); + + sc_cor_pkg* cor_pkg() + { return m_cor_pkg; } + sc_cor* next_cor(); + + const ::std::vector<sc_object*>& get_child_objects() const; + + void elaborate(); + void prepare_to_simulate(); + inline void initial_crunch( bool no_crunch ); + bool next_time( sc_time& t ) const; + bool pending_activity_at_current_time() const; + +private: + + void add_child_event( sc_event* ); + void add_child_object( sc_object* ); + void remove_child_event( sc_event* ); + void remove_child_object( sc_object* ); + + void crunch( bool once=false ); + + int add_delta_event( sc_event* ); + void remove_delta_event( sc_event* ); + void add_timed_event( sc_event_timed* ); + + void trace_cycle( bool delta_cycle ); + + const ::std::vector<sc_event*>& get_child_events_internal() const; + const ::std::vector<sc_object*>& get_child_objects_internal() const; + + void execute_method_next( sc_method_handle ); + void execute_thread_next( sc_thread_handle ); + + sc_method_handle pop_runnable_method(); + sc_thread_handle pop_runnable_thread(); + + void preempt_with( sc_method_handle ); + inline void preempt_with( sc_thread_handle ); + + void push_runnable_method( sc_method_handle ); + void push_runnable_thread( sc_thread_handle ); + + void push_runnable_method_front( sc_method_handle ); + void push_runnable_thread_front( sc_thread_handle ); + + void remove_runnable_method( sc_method_handle ); + void remove_runnable_thread( sc_thread_handle ); + + void requeue_current_process(); + void suspend_current_process(); + + void do_sc_stop_action(); + void mark_to_collect_process( sc_process_b* zombie_p ); + +private: + + enum execution_phases { + phase_initialize = 0, + phase_evaluate, + phase_update, + phase_notify + }; + sc_object_manager* m_object_manager; + + sc_module_registry* m_module_registry; + sc_port_registry* m_port_registry; + sc_export_registry* m_export_registry; + sc_prim_channel_registry* m_prim_channel_registry; + sc_phase_callback_registry* m_phase_cb_registry; + + sc_name_gen* m_name_gen; + + sc_process_table* m_process_table; + sc_curr_proc_info m_curr_proc_info; + sc_object* m_current_writer; + bool m_write_check; + int m_next_proc_id; + + std::vector<sc_thread_handle> m_active_invokers; + + std::vector<sc_event*> m_child_events; + std::vector<sc_object*> m_child_objects; + + std::vector<sc_event*> m_delta_events; + sc_ppq<sc_event_timed*>* m_timed_events; + + std::vector<sc_trace_file*> m_trace_files; + bool m_something_to_trace; + + sc_runnable* m_runnable; + sc_process_list* m_collectable; + + sc_time_params* m_time_params; + sc_time m_curr_time; + mutable sc_time m_max_time; + + sc_invoke_method* m_method_invoker_p; + sc_dt::uint64 m_change_stamp; // "time" change occurred. + sc_dt::uint64 m_delta_count; + bool m_forced_stop; + bool m_paused; + bool m_ready_to_simulate; + bool m_elaboration_done; + execution_phases m_execution_phase; + sc_report* m_error; + bool m_in_simulator_control; + bool m_end_of_simulation_called; + sc_status m_simulation_status; + bool m_start_of_simulation_called; + + sc_cor_pkg* m_cor_pkg; // the simcontext's coroutine package + sc_cor* m_cor; // the simcontext's coroutine + +private: + + // disabled + sc_simcontext( const sc_simcontext& ); + sc_simcontext& operator = ( const sc_simcontext& ); +}; + +// IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII + +// Not MT safe. + +#if 1 +extern sc_simcontext* sc_curr_simcontext; +extern sc_simcontext* sc_default_global_context; + +inline sc_simcontext* +sc_get_curr_simcontext() +{ + if( sc_curr_simcontext == 0 ) { + sc_default_global_context = new sc_simcontext; + sc_curr_simcontext = sc_default_global_context; + } + return sc_curr_simcontext; +} +#else + extern sc_simcontext* sc_get_curr_simcontext(); +#endif // 0 +inline sc_status sc_get_status() +{ + return sc_get_curr_simcontext()->get_status(); +} + + +// IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII + +inline +bool +sc_simcontext::elaboration_done() const +{ + return m_elaboration_done; +} + + +inline sc_status sc_simcontext::get_status() const +{ + return m_simulation_status != SC_RUNNING ? + m_simulation_status : + (m_in_simulator_control ? SC_RUNNING : SC_PAUSED); +} + +inline +int +sc_simcontext::sim_status() const +{ + if( m_error ) { + return SC_SIM_ERROR; + } + if( m_forced_stop ) { + return SC_SIM_USER_STOP; + } + return SC_SIM_OK; +} + + +inline +sc_object_manager* +sc_simcontext::get_object_manager() +{ + return m_object_manager; +} + +inline +sc_module_registry* +sc_simcontext::get_module_registry() +{ + return m_module_registry; +} + +inline +sc_port_registry* +sc_simcontext::get_port_registry() +{ + return m_port_registry; +} + +inline +sc_export_registry* +sc_simcontext::get_export_registry() +{ + return m_export_registry; +} + +inline +sc_prim_channel_registry* +sc_simcontext::get_prim_channel_registry() +{ + return m_prim_channel_registry; +} + + +inline +sc_curr_proc_handle +sc_simcontext::get_curr_proc_info() +{ + return &m_curr_proc_info; +} + + +inline +int +sc_simcontext::next_proc_id() +{ + return ( ++ m_next_proc_id ); +} + + +inline +const sc_time& +sc_simcontext::max_time() const +{ + if ( m_max_time == SC_ZERO_TIME ) + { + m_max_time = sc_time::from_value( ~sc_dt::UINT64_ZERO ); + } + return m_max_time; +} + +inline +sc_dt::uint64 +sc_simcontext::change_stamp() const +{ + return m_change_stamp; +} + +inline +const sc_time& +sc_simcontext::time_stamp() const +{ + return m_curr_time; +} + + +inline +bool +sc_simcontext::event_occurred(sc_dt::uint64 last_change_stamp) const +{ + return m_change_stamp == last_change_stamp; +} + +inline +bool +sc_simcontext::evaluation_phase() const +{ + return (m_execution_phase == phase_evaluate) && + m_ready_to_simulate; +} + +inline +bool +sc_simcontext::update_phase() const +{ + return m_execution_phase == phase_update; +} + +inline +bool +sc_simcontext::notify_phase() const +{ + return m_execution_phase == phase_notify; +} + +inline +void +sc_simcontext::set_error( sc_report* err ) +{ + delete m_error; + m_error = err; +} + + +inline +bool +sc_simcontext::get_error() +{ + return m_error != NULL; +} + +inline +int +sc_simcontext::add_delta_event( sc_event* e ) +{ + m_delta_events.push_back( e ); + return ( m_delta_events.size() - 1 ); +} + +inline +void +sc_simcontext::add_timed_event( sc_event_timed* et ) +{ + m_timed_events->insert( et ); +} + +inline sc_object* +sc_simcontext::get_current_writer() const +{ + return m_current_writer; +} + +inline bool +sc_simcontext::write_check() const +{ + return m_write_check; +} + +// ---------------------------------------------------------------------------- + +class sc_process_handle; +sc_process_handle sc_get_current_process_handle(); + +// Get the current object hierarchy context +// +// Returns a pointer the the sc_object (module or process) that +// would become the parent object of a newly created element +// of the SystemC object hierarchy, or NULL. +// +inline sc_object* +sc_get_current_object() +{ + return sc_get_curr_simcontext()->active_object(); +} + +inline +sc_process_b* +sc_get_current_process_b() +{ + return sc_get_curr_simcontext()->get_curr_proc_info()->process_handle; +} + +// THE FOLLOWING FUNCTION IS DEPRECATED IN 2.1 +extern sc_process_b* sc_get_curr_process_handle(); + +inline +sc_curr_proc_kind +sc_get_curr_process_kind() +{ + return sc_get_curr_simcontext()->get_curr_proc_info()->kind; +} + + +inline int sc_get_simulator_status() +{ + return sc_get_curr_simcontext()->sim_status(); +} + + +// Generates unique names within each module. +extern +const char* +sc_gen_unique_name( const char* basename_, bool preserve_first = false ); + + +// Set the random seed for controlled randomization -- not yet implemented +extern +void +sc_set_random_seed( unsigned int seed_ ); + + +extern void sc_initialize(); + +extern const sc_time& sc_max_time(); // Get maximum time value. +extern const sc_time& sc_time_stamp(); // Current simulation time. +extern double sc_simulation_time(); // Current time in default time units. + +inline +const std::vector<sc_event*>& sc_get_top_level_events( + const sc_simcontext* simc_p = sc_get_curr_simcontext() ) +{ + return simc_p->m_child_events; +} + +inline +const std::vector<sc_object*>& sc_get_top_level_objects( + const sc_simcontext* simc_p = sc_get_curr_simcontext() ) +{ + return simc_p->m_child_objects; +} + +extern sc_event* sc_find_event( const char* name ); + +extern sc_object* sc_find_object( const char* name ); + +inline +sc_dt::uint64 sc_delta_count() +{ + return sc_get_curr_simcontext()->m_delta_count; +} + +inline +bool sc_is_running( const sc_simcontext* simc_p = sc_get_curr_simcontext() ) +{ + return simc_p->m_ready_to_simulate; +} + +bool sc_is_unwinding(); + +inline void sc_pause() +{ + sc_get_curr_simcontext()->m_paused = true; +} + +// Return indication if there are more processes to execute in this delta phase + +inline bool sc_pending_activity_at_current_time + ( const sc_simcontext* simc_p = sc_get_curr_simcontext() ) +{ + return simc_p->pending_activity_at_current_time(); +} + +// Return indication if there are timed notifications in the future + +inline bool sc_pending_activity_at_future_time + ( const sc_simcontext* simc_p = sc_get_curr_simcontext() ) +{ + sc_time ignored; + return simc_p->next_time( ignored ); +} + +// Return indication if there are processes to run, +// or notifications in the future + +inline bool sc_pending_activity + ( const sc_simcontext* simc_p = sc_get_curr_simcontext() ) +{ + return sc_pending_activity_at_current_time( simc_p ) + || sc_pending_activity_at_future_time( simc_p ); +} + +sc_time +sc_time_to_pending_activity + ( const sc_simcontext* simc_p = sc_get_curr_simcontext() ); + + +inline +bool +sc_end_of_simulation_invoked() +{ + return sc_get_curr_simcontext()->m_end_of_simulation_called; +} + +inline bool sc_hierarchical_name_exists( const char* name ) +{ + return sc_find_object(name) || sc_find_event(name); +} + +inline +bool +sc_start_of_simulation_invoked() +{ + return sc_get_curr_simcontext()->m_start_of_simulation_called; +} + +// The following variable controls whether process control corners should +// be considered errors or not. See sc_simcontext.cpp for details on what +// happens if this value is set to true. + +extern bool sc_allow_process_control_corners; + +} // namespace sc_core + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affiliation, date and + changes you are making here. + + Name, Affiliation, Date: Andy Goodrich, Forte Design Systems 20 May 2003 + Description of Modification: - phase callbacks + - sc_stop mode + + Name, Affiliation, Date: Bishnupriya Bhattacharya, Cadence Design Systems, + 25 August, 2003 + Description of Modification: - support for dynamic process + - support for sc export registry + - new member methods elaborate(), + prepare_to_simulate(), and initial_crunch() + that are invoked by initialize() in that order + - add sc_get_last_created_process_handle() for + use before simulation starts + + Name, Affiliation, Date: Bishnupriya Bhattacharya, Cadence Design Systems, + 3 March, 2004 + Description of Modification: add sc_get_curr_process_kind() + + Name, Affiliation, Date: + Description of Modification: + + *****************************************************************************/ +// $Log: sc_simcontext.h,v $ +// Revision 1.26 2011/09/05 21:20:22 acg +// Andy Goodrich: result of automake invocation. +// +// Revision 1.25 2011/09/01 15:28:10 acg +// Andy Goodrich: the aftermath of automake. +// +// Revision 1.24 2011/08/29 18:04:32 acg +// Philipp A. Hartmann: miscellaneous clean ups. +// +// Revision 1.23 2011/08/26 20:46:10 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.22 2011/08/24 22:05:51 acg +// Torsten Maehne: initialization changes to remove warnings. +// +// Revision 1.21 2011/05/09 04:07:49 acg +// Philipp A. Hartmann: +// (1) Restore hierarchy in all phase callbacks. +// (2) Ensure calls to before_end_of_elaboration. +// +// Revision 1.20 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.19 2011/04/05 20:50:57 acg +// Andy Goodrich: +// (1) changes to make sure that event(), posedge() and negedge() only +// return true if the clock has not moved. +// (2) fixes for method self-resumes. +// (3) added SC_PRERELEASE_VERSION +// (4) removed kernel events from the object hierarchy, added +// sc_hierarchical_name_exists(). +// +// Revision 1.18 2011/03/20 13:43:23 acg +// Andy Goodrich: added async_signal_is() plus suspend() as a corner case. +// +// Revision 1.17 2011/03/07 18:25:19 acg +// Andy Goodrich: tightening of check for resume on a disabled process to +// only produce an error if it is ready to run. +// +// Revision 1.16 2011/03/06 15:58:50 acg +// Andy Goodrich: added escape to turn off process control corner case +// checks. +// +// Revision 1.15 2011/03/05 04:45:16 acg +// Andy Goodrich: moved active process calculation to the sc_simcontext class. +// +// Revision 1.14 2011/03/05 01:39:21 acg +// Andy Goodrich: changes for named events. +// +// Revision 1.13 2011/02/18 20:27:14 acg +// Andy Goodrich: Updated Copyrights. +// +// Revision 1.12 2011/02/13 21:47:38 acg +// Andy Goodrich: update copyright notice. +// +// Revision 1.11 2011/02/13 21:34:35 acg +// Andy Goodrich: added SC_UNITIALIZED enum value to process status so +// its possible to detect throws before initialization. +// +// Revision 1.10 2011/02/11 13:25:24 acg +// Andy Goodrich: Philipp A. Hartmann's changes: +// (1) Removal of SC_CTHREAD method overloads. +// (2) New exception processing code. +// +// Revision 1.9 2011/02/01 21:18:56 acg +// Andy Goodrich: addition of new preempt_with() method used to immediately +// throw exceptions from threads. +// +// Revision 1.8 2011/01/25 20:50:37 acg +// Andy Goodrich: changes for IEEE 1666 2011. +// +// Revision 1.7 2011/01/19 23:21:50 acg +// Andy Goodrich: changes for IEEE 1666 2011 +// +// Revision 1.6 2011/01/18 20:10:45 acg +// Andy Goodrich: changes for IEEE1666_2011 semantics. +// +// Revision 1.5 2010/07/22 20:02:33 acg +// Andy Goodrich: bug fixes. +// +// Revision 1.4 2009/05/22 16:06:29 acg +// Andy Goodrich: process control updates. +// +// Revision 1.3 2008/05/22 17:06:26 acg +// Andy Goodrich: updated copyright notice to include 2008. +// +// Revision 1.2 2007/09/20 20:32:35 acg +// Andy Goodrich: changes to the semantics of throw_it() to match the +// specification. A call to throw_it() will immediately suspend the calling +// thread until all the throwees have executed. At that point the calling +// thread will be restarted before the execution of any other threads. +// +// Revision 1.1.1.1 2006/12/15 20:20:05 acg +// SystemC 2.3 +// +// Revision 1.13 2006/05/08 18:00:06 acg +// Andy Goodrich: added David Long's forward declarations for friend +// functions, methods, and operators to keep the Microsoft compiler happy. +// +// Revision 1.11 2006/04/11 23:13:21 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.10 2006/03/21 00:00:34 acg +// Andy Goodrich: changed name of sc_get_current_process_base() to be +// sc_get_current_process_b() since its returning an sc_process_b instance. +// +// Revision 1.9 2006/01/26 21:04:54 acg +// Andy Goodrich: deprecation message changes and additional messages. +// +// Revision 1.8 2006/01/24 20:49:05 acg +// Andy Goodrich: changes to remove the use of deprecated features within the +// simulator, and to issue warning messages when deprecated features are used. +// +// Revision 1.7 2006/01/19 00:29:52 acg +// Andy Goodrich: Yet another implementation for signal write checking. This +// one uses an environment variable SC_SIGNAL_WRITE_CHECK, that when set to +// DISABLE will disable write checking on signals. +// +// Revision 1.6 2006/01/18 21:42:37 acg +// Andy Goodrich: Changes for check writer support. +// +// Revision 1.5 2006/01/13 18:44:30 acg +// Added $Log to record CVS changes into the source. +// +// Revision 1.4 2006/01/03 23:18:44 acg +// Changed copyright to include 2006. +// +// Revision 1.3 2005/12/20 22:11:10 acg +// Fixed $Log lines. +// +// Revision 1.2 2005/12/20 22:02:30 acg +// Changed where delta cycles are incremented to match IEEE 1666. Added the +// event_occurred() method to hide how delta cycle comparisions are done within +// sc_simcontext. Changed the boolean update_phase to an enum that shows all +// the phases. + +#endif diff --git a/ext/systemc/src/sysc/kernel/sc_simcontext_int.h b/ext/systemc/src/sysc/kernel/sc_simcontext_int.h new file mode 100644 index 000000000..039237f4a --- /dev/null +++ b/ext/systemc/src/sysc/kernel/sc_simcontext_int.h @@ -0,0 +1,365 @@ +/***************************************************************************** + + 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_simcontext_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: Stan Y. Liao, Synopsys, Inc. + + CHANGE LOG AT THE END OF THE FILE + *****************************************************************************/ + +#ifndef SC_SIMCONTEXT_INT_H +#define SC_SIMCONTEXT_INT_H + +#include "sysc/kernel/sc_simcontext.h" +#include "sysc/kernel/sc_runnable.h" +#include "sysc/kernel/sc_runnable_int.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 { + +inline +const char* +sc_get_current_process_name() +{ + sc_process_b* active_p; // active process to get name of. + const char* result; // name of active process. + + active_p = sc_get_curr_simcontext()->get_curr_proc_info()->process_handle; + if ( active_p ) + result = active_p->name(); + else + result = "** NONE **"; + return result; +} + +// We use m_current_writer rather than m_curr_proc_info.process_handle to +// return the active process for sc_signal<T>::check_write since that lets +// us turn it off a library compile time, and only incur the overhead at +// the time of process switches rather than having to interrogate an +// additional switch every time a signal is written. + +inline +void +sc_simcontext::set_curr_proc( sc_process_b* process_h ) +{ + m_curr_proc_info.process_handle = process_h; + m_curr_proc_info.kind = process_h->proc_kind(); + m_current_writer = m_write_check ? process_h : (sc_object*)0; +} + +inline +void +sc_simcontext::reset_curr_proc() +{ + m_curr_proc_info.process_handle = 0; + m_curr_proc_info.kind = SC_NO_PROC_; + m_current_writer = 0; + sc_process_b::m_last_created_process_p = 0; +} + +inline +void +sc_simcontext::execute_method_next( sc_method_handle method_h ) +{ + m_runnable->execute_method_next( method_h ); +} + +inline +void +sc_simcontext::execute_thread_next( sc_thread_handle thread_h ) +{ + m_runnable->execute_thread_next( thread_h ); +} + +// +---------------------------------------------------------------------------- +// |"sc_simcontext::preempt_with" +// | +// | This method executes the supplied thread immediately, suspending the +// | caller. After executing the supplied thread the caller's execution will +// | be restored. It is used to allow a thread to immediately throw an +// | exception, e.g., when the thread's kill_process() method was called. +// | There are three cases to consider: +// | (1) The caller is a method, e.g., murder by method. +// | (2) The caller is another thread instance, e.g., murder by thread. +// | (3) The caller is this thread instance, e.g., suicide. +// | +// | Arguments: +// | thread_h -> thread to be executed. +// +---------------------------------------------------------------------------- +inline +void +sc_simcontext::preempt_with( sc_thread_handle thread_h ) +{ + sc_thread_handle active_p; // active thread or null. + sc_curr_proc_info caller_info; // process info for caller. + + // Determine the active process and take the thread to be run off the + // run queue, if its there, since we will be explicitly causing its + // execution. + + active_p = DCAST<sc_thread_handle>(sc_get_current_process_b()); + if ( thread_h->next_runnable() != NULL ) + remove_runnable_thread( thread_h ); + + // THE CALLER IS A METHOD: + // + // (a) Set the current process information to our thread. + // (b) If the method was called by an invoker thread push that thread + // onto the front of the run queue, this will cause the method + // to be resumed after this thread waits. + // (c) Invoke our thread directly by-passing the run queue. + // (d) Restore the process info to the caller. + // (e) Check to see if the calling method should throw an exception + // because of activity that occurred during the preemption. + + if ( active_p == NULL ) + { + std::vector<sc_thread_handle>* invokers_p; // active invokers stack. + sc_thread_handle invoke_thread_p; // latest invocation thread. + sc_method_handle method_p; // active method. + + method_p = DCAST<sc_method_handle>(sc_get_current_process_b()); + invokers_p = &get_active_invokers(); + caller_info = m_curr_proc_info; + if ( invokers_p->size() != 0 ) + { + invoke_thread_p = invokers_p->back(); + DEBUG_MSG( DEBUG_NAME, invoke_thread_p, + "queueing invocation thread to execute next" ); + execute_thread_next(invoke_thread_p); + } + DEBUG_MSG( DEBUG_NAME, thread_h, "preempting method with thread" ); + set_curr_proc( (sc_process_b*)thread_h ); + m_cor_pkg->yield( thread_h->m_cor_p ); + m_curr_proc_info = caller_info; + DEBUG_MSG(DEBUG_NAME, thread_h, "back from preempting method w/thread"); + method_p->check_for_throws(); + } + + // CALLER IS A THREAD, BUT NOT THE THREAD TO BE RUN: + // + // (a) Push the calling thread onto the front of the runnable queue + // so it be the first thread to be run after this thread. + // (b) Push the thread to be run onto the front of the runnable queue so + // it will execute when we suspend the calling thread. + // (c) Suspend the active thread. + + else if ( active_p != thread_h ) + { + DEBUG_MSG( DEBUG_NAME, thread_h, + "preempting active thread with thread" ); + execute_thread_next( active_p ); + execute_thread_next( thread_h ); + active_p->suspend_me(); + } + + // CALLER IS THE THREAD TO BE RUN: + // + // (a) Push the thread to be run onto the front of the runnable queue so + // it will execute when we suspend the calling thread. + // (b) Suspend the active thread. + + else + { + DEBUG_MSG(DEBUG_NAME,thread_h,"self preemption of active thread"); + execute_thread_next( thread_h ); + active_p->suspend_me(); + } +} + + +inline +void +sc_simcontext::push_runnable_method( sc_method_handle method_h ) +{ + m_runnable->push_back_method( method_h ); +} + +inline +void +sc_simcontext::push_runnable_method_front( sc_method_handle method_h ) +{ + m_runnable->push_front_method( method_h ); +} + +inline +void +sc_simcontext::push_runnable_thread( sc_thread_handle thread_h ) +{ + m_runnable->push_back_thread( thread_h ); +} + +inline +void +sc_simcontext::push_runnable_thread_front( sc_thread_handle thread_h ) +{ + m_runnable->push_front_thread( thread_h ); +} + + +inline +sc_method_handle +sc_simcontext::pop_runnable_method() +{ + sc_method_handle method_h = m_runnable->pop_method(); + if( method_h == 0 ) { + reset_curr_proc(); + return 0; + } + set_curr_proc( (sc_process_b*)method_h ); + return method_h; +} + +inline +sc_thread_handle +sc_simcontext::pop_runnable_thread() +{ + sc_thread_handle thread_h = m_runnable->pop_thread(); + if( thread_h == 0 ) { + reset_curr_proc(); + return 0; + } + set_curr_proc( (sc_process_b*)thread_h ); + return thread_h; +} + +inline +void +sc_simcontext::remove_runnable_method( sc_method_handle method_h ) +{ + m_runnable->remove_method( method_h ); +} + +inline +void +sc_simcontext::remove_runnable_thread( sc_thread_handle thread_h ) +{ + m_runnable->remove_thread( thread_h ); +} + +inline +std::vector<sc_thread_handle>& +sc_simcontext::get_active_invokers() +{ + return m_active_invokers; +} + +// ---------------------------------------------------------------------------- + +extern void sc_defunct_process_function( sc_module* ); + + +} // namespace sc_core + +#undef DEBUG_MSG +#undef DEBUG_NAME + +// $Log: sc_simcontext_int.h,v $ +// Revision 1.14 2011/08/29 18:04:32 acg +// Philipp A. Hartmann: miscellaneous clean ups. +// +// Revision 1.13 2011/08/26 20:46:11 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.12 2011/07/29 22:45:06 acg +// Andy Goodrich: added invocation of sc_method_process::check_for_throws() +// to the preempt_with() code to handle case where the preempting process +// causes a throw on the invoking method process. +// +// Revision 1.11 2011/04/13 02:45:11 acg +// Andy Goodrich: eliminated warning message that occurred if the DEBUG_MSG +// macro was used. +// +// Revision 1.10 2011/04/11 22:05:48 acg +// Andy Goodrich: use the DEBUG_NAME macro in DEBUG_MSG invocations. +// +// Revision 1.9 2011/04/10 22:12:32 acg +// Andy Goodrich: adding debugging macros. +// +// Revision 1.8 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.7 2011/02/18 20:27:14 acg +// Andy Goodrich: Updated Copyrights. +// +// Revision 1.6 2011/02/13 21:47:38 acg +// Andy Goodrich: update copyright notice. +// +// Revision 1.5 2011/02/08 08:17:50 acg +// Andy Goodrich: fixed bug in preempt_with() where I was resetting the +// process context rather than saving and restoring it. +// +// Revision 1.4 2011/02/01 21:12:56 acg +// Andy Goodrich: addition of preempt_with() method to allow immediate +// execution of threads for throws. +// +// Revision 1.3 2011/01/25 20:50:37 acg +// Andy Goodrich: changes for IEEE 1666 2011. +// +// 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.6 2006/05/26 20:33:16 acg +// Andy Goodrich: changes required by additional platform compilers (i.e., +// Microsoft VC++, Sun Forte, HP aCC). +// +// Revision 1.5 2006/01/19 00:29:52 acg +// Andy Goodrich: Yet another implementation for signal write checking. This +// one uses an environment variable SC_SIGNAL_WRITE_CHECK, that when set to +// DISABLE will disable write checking on signals. +// +// Revision 1.4 2006/01/18 21:42:37 acg +// Andy Goodrich: Changes for check writer support. +// +// Revision 1.3 2006/01/13 18:44:30 acg +// Added $Log to record CVS changes into the source. + +#endif diff --git a/ext/systemc/src/sysc/kernel/sc_spawn.h b/ext/systemc/src/sysc/kernel/sc_spawn.h new file mode 100644 index 000000000..e54886929 --- /dev/null +++ b/ext/systemc/src/sysc/kernel/sc_spawn.h @@ -0,0 +1,337 @@ +/***************************************************************************** + + 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_spawn.h -- Process spawning support. + + Original Authors: Andy Goodrich, Forte Design Systems, 17 June 2003 + Stuart Swan, Cadence, + Bishnupriya Bhattacharya, Cadence Design Systems, + 25 August, 2003 + + CHANGE LOG AT THE END OF THE FILE + *****************************************************************************/ + + +#if !defined(sc_spawn_h_INCLUDED) +#define sc_spawn_h_INCLUDED + +#include "sysc/kernel/sc_process_handle.h" +#include "sysc/kernel/sc_spawn_options.h" + +namespace sc_core { + +class sc_event; +class sc_port_base; +class sc_interface; +class sc_event_finder; +class sc_process_b; + +//============================================================================= +// CLASS sc_spawn_object<T> +// +// This templated helper class allows an object to provide the execution +// semantics for a process via its () operator. An instance of the supplied +// execution object will be kept to provide the semantics when the process is +// scheduled for execution. The () operator does not return a value. An example +// of an object that might be used for this helper function would be void +// SC_BOOST bound function or method. +// +// This class is derived from sc_process_host and overloads +// sc_process_host::semantics to provide the actual semantic content. +// +// sc_spawn_object(T object, const char* name, const sc_spawn_options* opt_p) +// This is the object instance constructor for this class. It makes a +// copy of the supplied object. The tp_call constructor is called +// with an indication that this object instance should be reclaimed when +// execution completes. +// object = object whose () operator will be called to provide +// the process semantics. +// name_p = optional name for object instance, or zero. +// opt_p -> spawn options or zero. +// +// virtual void semantics() +// This virtual method provides the execution semantics for its process. +// It performs a () operation on m_object. +//============================================================================= +template<typename T> +class sc_spawn_object : public sc_process_host { + public: + sc_spawn_object( T object) : m_object(object) + { + } + + virtual void semantics() + { + m_object(); + } + + protected: + T m_object; +}; + + +//------------------------------------------------------------------------------ +//"sc_spawn - semantic object with no return value" +// +// This inline function spawns a process for execution. The execution semantics +// for the process being spawned will be provided by the supplied object +// instance via its () operator. (E.g., a SC_BOOST bound function) +// After creating the process it is registered with the simulator. +// object = object instance providing the execution semantics via its +// () operator. +// name_p = optional name for object instance, or zero. +// opt_p -> optional spawn options for process, or zero for the default. +//------------------------------------------------------------------------------ +template <typename T> +inline sc_process_handle sc_spawn( + T object, + const char* name_p = 0, + const sc_spawn_options* opt_p = 0) +{ + sc_simcontext* context_p; + sc_spawn_object<T>* spawn_p; + + context_p = sc_get_curr_simcontext(); + spawn_p = new sc_spawn_object<T>(object); + if ( !opt_p || !opt_p->is_method() ) + { + sc_process_handle thread_handle = context_p->create_thread_process( + name_p, true, + SC_MAKE_FUNC_PTR(sc_spawn_object<T>,semantics), + spawn_p, opt_p + ); + return thread_handle; + } + else + { + sc_process_handle method_handle = context_p->create_method_process( + name_p, true, + SC_MAKE_FUNC_PTR(sc_spawn_object<T>,semantics), + spawn_p, opt_p + ); + return method_handle; + } +} + +//============================================================================= +// CLASS sc_spawn_object_v<T> for all compilers except HP aCC +// or +// CLASS sc_spawn_object_v<T, R> for HP aCC which tries to match this +// one template argument class when the sc_spawn() declared above is +// invoked with 3 arguments or 2 arguments, and generates compiler errors. +// +// This templated helper class allows an object to provide the execution +// semantics for a process via its () operator. An instance of the supplied +// object will be kept to provide the semantics when the process is scheduled +// for execution. The () operator returns a value, which will be stored at the +// location specified by the supplied pointer. An example of an object that +// might be used for this helper function would be valued SC_BOOST bound +// function or method. +// +// sc_spawn_object_v( typename F::result_type* r_p, T f, const char* name_p, +// const sc_spawn_options* opt_p ) +// r_p -> where to place the result of the function invocation. +// f = information to be executed. +// name_p = optional name for object instance, or zero. +// opt_p -> optional spawn options for process, or zero for the default +// This is the object instance constructor for this class. It makes a +// copy of the supplied object. The tp_call constructor is called +// with an indication that this object instance should be reclaimed when +// execution completes. +// result_p -> where to place the value of the () operator. +// object = object whose () operator will be called to provide +// the process semantics. +// +// virtual void semantics() +// This virtual method provides the execution semantics for its process. +// It performs a () operation on m_object, placing the result at m_result_p. +//============================================================================= + +//------------------------------------------------------------------------------ +//"sc_spawn_object_v - semantic object with return value" +// +// This inline function spawns a process for execution. The execution semantics +// for the process being spawned will be provided by the supplied object +// instance via its () operator. (E.g., a SC_BOOST bound function) That +// operator returns a value, which will be placed in the supplied return +// location. +// After creating the process it is registered with the simulator. +// object = object instance providing the execution semantics via its () +// operator. +// r_p -> where to place the value of the () operator. +// name_p = optional name for object instance, or zero. +// opt_p -> optional spawn options for process, or zero for the default. +//------------------------------------------------------------------------------ + +#if !defined (__HP_aCC) + +template<typename T> +class sc_spawn_object_v : public sc_process_host { + public: + sc_spawn_object_v( typename T::result_type* r_p, T object ) : + m_object(object), m_result_p(r_p) + { + } + + virtual void semantics() + { + *m_result_p = m_object(); + } + + protected: + T m_object; + typename T::result_type* m_result_p; +}; + +template <typename T> +inline sc_process_handle sc_spawn( + typename T::result_type* r_p, + T object, + const char* name_p = 0, + const sc_spawn_options* opt_p = 0) +{ + sc_simcontext* context_p; + sc_spawn_object_v<T>* spawn_p; + + context_p = sc_get_curr_simcontext(); + + spawn_p = new sc_spawn_object_v<T>(r_p, object); + if ( !opt_p || !opt_p->is_method() ) + { + sc_process_handle thread_handle = context_p->create_thread_process( + name_p, true, + SC_MAKE_FUNC_PTR(sc_spawn_object_v<T>,semantics), + spawn_p, opt_p + ); + return thread_handle; + } + else + { + sc_process_handle method_handle = context_p->create_method_process( + name_p, true, + SC_MAKE_FUNC_PTR(sc_spawn_object_v<T>,semantics), + spawn_p, opt_p + ); + return method_handle; + } +} + +#else +// for HP aCC +template<typename T, typename R> +class sc_spawn_object_v : public sc_process_host { + public: + sc_spawn_object_v( R* r_p, T object) : + m_object(object), m_result_p(r_p) + { + } + + virtual void semantics() + { + *m_result_p = m_object(); + } + + protected: + T m_object; + R* m_result_p; +}; + +template <typename T, typename R> +inline sc_process_handle sc_spawn( + R* r_p, + T object, + const char* name_p = 0, + const sc_spawn_options* opt_p = 0) +{ + sc_simcontext* context_p; + sc_spawn_object_v<T,R>* spawn_p; + + context_p = sc_get_curr_simcontext(); + + spawn_p = new sc_spawn_object_v<T,R>(r_p, object); + if ( !opt_p || !opt_p->is_method() ) + { + sc_process_handle thread_handle = context_p->create_thread_process( + name_p, true, + static_cast<sc_core::SC_ENTRY_FUNC>( + &sc_spawn_object_v<T,R>::semantics), + spawn_p, opt_p + ); + return thread_handle; + } + else + { + sc_process_handle method_handle = context_p->create_method_process( + name_p, true, + static_cast<sc_core::SC_ENTRY_FUNC>( + &sc_spawn_object_v<T,R>::semantics), + spawn_p, opt_p + ); + return method_handle; + } +} + +#endif // HP + +} // namespace sc_core + +// $Log: sc_spawn.h,v $ +// Revision 1.7 2011/08/26 20:46:11 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.6 2011/02/18 20:27:14 acg +// Andy Goodrich: Updated Copyrights. +// +// Revision 1.5 2011/02/13 21:47:38 acg +// Andy Goodrich: update copyright notice. +// +// Revision 1.4 2011/02/01 21:14:02 acg +// Andy Goodrich: formatting. +// +// Revision 1.3 2009/07/28 01:10:53 acg +// Andy Goodrich: updates for 2.3 release candidate. +// +// 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.6 2006/05/26 20:33:16 acg +// Andy Goodrich: changes required by additional platform compilers (i.e., +// Microsoft VC++, Sun Forte, HP aCC). +// +// Revision 1.5 2006/05/08 18:01:44 acg +// Andy Goodrich: changed the HP-specific implementations of sc_spawn() to +// use a static_cast to create their entry functions rather than the +// SC_MAKE_FUNC_PTR macro. The HP preprocessor does not parse template +// arguments that contain a comma properly. +// +// Revision 1.4 2006/04/11 23:13:21 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.3 2006/01/13 18:44:30 acg +// Added $Log to record CVS changes into the source. + +#endif // !defined(sc_spawn_h_INCLUDED) diff --git a/ext/systemc/src/sysc/kernel/sc_spawn_options.cpp b/ext/systemc/src/sysc/kernel/sc_spawn_options.cpp new file mode 100644 index 000000000..c577f1d87 --- /dev/null +++ b/ext/systemc/src/sysc/kernel/sc_spawn_options.cpp @@ -0,0 +1,124 @@ +/***************************************************************************** + + 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_spawn_options.cpp -- Process spawning options implementation. + + Original Authors: Andy Goodrich, Forte Design Systems, 17 June 2003 + Stuart Swan, Cadence, + Bishnupriya Bhattacharya, Cadence Design Systems, + 25 August, 2003 + + CHANGE LOG AT THE END OF THE FILE + *****************************************************************************/ + +#include "sysc/kernel/sc_spawn_options.h" +#include "sysc/kernel/sc_reset.h" + +namespace sc_core { + +// +====================================================================== +// | CLASS sc_spawn_reset_base - Class to do a generic access to an +// | sc_spawn_rest object instance +// +====================================================================== +class sc_spawn_reset_base +{ + public: + sc_spawn_reset_base( bool async, bool level ) + : m_async( async ), m_level(level) + {} + virtual ~sc_spawn_reset_base() {} + virtual void specify_reset() = 0; + + protected: + bool m_async; // = true if async reset. + bool m_level; // level indicating reset. +}; + +// +====================================================================== +// | CLASS sc_spawn_reset<SOURCE> +// | - Reset specification for sc_spawn_options. +// +====================================================================== +template<typename SOURCE> +class sc_spawn_reset : public sc_spawn_reset_base +{ + public: + sc_spawn_reset( bool async, const SOURCE& source, bool level ) + : sc_spawn_reset_base(async, level), m_source(source) + {} + virtual ~sc_spawn_reset() {} + virtual void specify_reset() + { + sc_reset::reset_signal_is( m_async, m_source, m_level ); + } + + protected: + const SOURCE& m_source; // source of reset signal. +}; + +// +====================================================================== +// | CLASS sc_spawn_options (implementation) +// | +// +====================================================================== + +sc_spawn_options::~sc_spawn_options() +{ + std::vector<sc_spawn_reset_base*>::size_type resets_n = m_resets.size(); + for ( std::vector<sc_spawn_reset_base*>::size_type reset_i = 0; reset_i < resets_n; reset_i++ ) + delete m_resets[reset_i]; +} + +#define SC_DEFINE_RESET_SIGNALS( Port ) \ + /* asynchronous reset */ \ + void \ + sc_spawn_options:: \ + async_reset_signal_is ( const Port & port, bool level ) \ + { \ + m_resets.push_back( \ + new sc_spawn_reset< Port >(true, port, level) ); \ + } \ + /* sync reset */ \ + void \ + sc_spawn_options:: \ + reset_signal_is ( const Port & port, bool level ) \ + { \ + m_resets.push_back( \ + new sc_spawn_reset< Port >(false, port, level) ); \ + } + +SC_DEFINE_RESET_SIGNALS( sc_in<bool> ) +SC_DEFINE_RESET_SIGNALS( sc_inout<bool> ) +SC_DEFINE_RESET_SIGNALS( sc_out<bool> ) +SC_DEFINE_RESET_SIGNALS( sc_signal_in_if<bool> ) + +#undef SC_DEFINE_RESET_SIGNALS + +void +sc_spawn_options::specify_resets() const +{ + std::vector<sc_spawn_reset_base*>::size_type resets_n; // number of reset specifications to process. + resets_n = m_resets.size(); + for ( std::vector<sc_spawn_reset_base*>::size_type reset_i = 0; reset_i < resets_n; reset_i++ ) + m_resets[reset_i]->specify_reset(); +} + +} // namespace sc_core + +// Taf! diff --git a/ext/systemc/src/sysc/kernel/sc_spawn_options.h b/ext/systemc/src/sysc/kernel/sc_spawn_options.h new file mode 100644 index 000000000..4c3f64baa --- /dev/null +++ b/ext/systemc/src/sysc/kernel/sc_spawn_options.h @@ -0,0 +1,161 @@ +/***************************************************************************** + + 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_spawn_options.h -- Process spawning options specification. + + Original Authors: Andy Goodrich, Forte Design Systems, 17 June 2003 + Stuart Swan, Cadence, + Bishnupriya Bhattacharya, Cadence Design Systems, + 25 August, 2003 + + CHANGE LOG AT THE END OF THE FILE + *****************************************************************************/ + +#if !defined(sc_spawn_options_h_INCLUDED) +#define sc_spawn_options_h_INCLUDED + +#include <vector> +#include "sysc/communication/sc_export.h" +#include "sysc/communication/sc_signal_ports.h" + +namespace sc_core { + +class sc_event; +class sc_port_base; +class sc_interface; +class sc_event_finder; +class sc_process_b; +class sc_spawn_reset_base; + +//============================================================================= +// CLASS sc_spawn_options +// +//============================================================================= +class sc_spawn_options { + friend class sc_cthread_process; + friend class sc_method_process; + friend class sc_process_b; + friend class sc_thread_process; + public: + sc_spawn_options() : + m_dont_initialize(false), m_resets(), m_sensitive_events(), + m_sensitive_event_finders(), m_sensitive_interfaces(), + m_sensitive_port_bases(), m_spawn_method(false), m_stack_size(0) + { } + + ~sc_spawn_options(); + + void async_reset_signal_is( const sc_in<bool>&, bool level ); + void async_reset_signal_is( const sc_inout<bool>&, bool level ); + void async_reset_signal_is( const sc_out<bool>&, bool level ); + void async_reset_signal_is( const sc_signal_in_if<bool>&, bool level ); + + void reset_signal_is( const sc_in<bool>&, bool level ); + void reset_signal_is( const sc_inout<bool>&, bool level ); + void reset_signal_is( const sc_out<bool>&, bool level ); + void reset_signal_is( const sc_signal_in_if<bool>&, bool level ); + + void dont_initialize() { m_dont_initialize = true; } + + bool is_method() const { return m_spawn_method; } + + void set_stack_size(int stack_size) { m_stack_size = stack_size; } + + void set_sensitivity(const sc_event* event) + { m_sensitive_events.push_back(event); } + + void set_sensitivity(sc_port_base* port_base) + { m_sensitive_port_bases.push_back(port_base); } + + void set_sensitivity(sc_interface* interface_p) + { m_sensitive_interfaces.push_back(interface_p); } + + void set_sensitivity(sc_export_base* export_base) + { m_sensitive_interfaces.push_back(export_base->get_interface()); } + + void set_sensitivity(sc_event_finder* event_finder) + { m_sensitive_event_finders.push_back(event_finder); } + + void spawn_method() { m_spawn_method = true; } + + protected: + void specify_resets() const; + + private: + sc_spawn_options( const sc_spawn_options& ); + const sc_spawn_options& operator = ( const sc_spawn_options& ); + + protected: + bool m_dont_initialize; + std::vector<sc_spawn_reset_base*> m_resets; + std::vector<const sc_event*> m_sensitive_events; + std::vector<sc_event_finder*> m_sensitive_event_finders; + std::vector<sc_interface*> m_sensitive_interfaces; + std::vector<sc_port_base*> m_sensitive_port_bases; + bool m_spawn_method; // Method not thread. + int m_stack_size; // Thread stack size. +}; + +} // namespace sc_core + +// $Log: sc_spawn_options.h,v $ +// Revision 1.11 2011/08/26 20:46:11 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.10 2011/08/24 22:05:51 acg +// Torsten Maehne: initialization changes to remove warnings. +// +// 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/07 19:17:20 acg +// Andy Goodrich: changes for IEEE 1666 compatibility. +// +// Revision 1.6 2010/12/07 20:09:15 acg +// Andy Goodrich: replaced sc_signal signatures with sc_signal_in_if signatures for reset methods. +// +// Revision 1.5 2010/11/20 17:10:57 acg +// Andy Goodrich: reset processing changes for new IEEE 1666 standard. +// +// Revision 1.4 2009/05/22 16:06:29 acg +// Andy Goodrich: process control updates. +// +// 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 // !defined(sc_spawn_options_h_INCLUDED) diff --git a/ext/systemc/src/sysc/kernel/sc_status.h b/ext/systemc/src/sysc/kernel/sc_status.h new file mode 100644 index 000000000..1d3b016db --- /dev/null +++ b/ext/systemc/src/sysc/kernel/sc_status.h @@ -0,0 +1,83 @@ +/***************************************************************************** + + 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_status.h -- Definition of the simulation phases + + Original Author: Philipp A. Hartmann, OFFIS, 2013-02-15 + + CHANGE LOG AT THE END OF THE FILE + *****************************************************************************/ + +#ifndef SC_STATUS_H_INCLUDED_ +#define SC_STATUS_H_INCLUDED_ + +#include <iosfwd> + +namespace sc_core { + +// simulation status codes + +const int SC_SIM_OK = 0; +const int SC_SIM_ERROR = 1; +const int SC_SIM_USER_STOP = 2; + +enum sc_status +{ // sc_get_status values: + SC_UNITIALIZED=0x00, // initialize() not called yet + + SC_ELABORATION = 0x01, // during module hierarchy construction + SC_BEFORE_END_OF_ELABORATION = 0x02, // during before_end_of_elaboration() + SC_END_OF_ELABORATION = 0x04, // during end_of_elaboration() + SC_START_OF_SIMULATION = 0x08, // during start_of_simulation() + + SC_RUNNING = 0x10, // initialization, evaluation or update + SC_PAUSED = 0x20, // when scheduler stopped by sc_pause() + SC_STOPPED = 0x40, // when scheduler stopped by sc_stop() + SC_END_OF_SIMULATION = 0x80, // during end_of_simulation() + + // detailed simulation phases (for dynamic callbacks) + SC_END_OF_INITIALIZATION = 0x100, // after initialization +// SC_END_OF_EVALUATION = 0x200, // between eval and update + SC_END_OF_UPDATE = 0x400, // after update/notify phase + SC_BEFORE_TIMESTEP = 0x800, // before next time step + + SC_STATUS_LAST = SC_BEFORE_TIMESTEP, + SC_STATUS_ANY = 0xdff +}; + +// pretty-printing of sc_status values +std::ostream& operator << ( std::ostream&, sc_status ); + +} // namespace sc_core + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affiliation, date and + changes you are making here. + + Name, Affiliation, Date: + Description of Modification: + + *****************************************************************************/ + +#endif /* SC_STATUS_H_INCLUDED_ */ +// Taf! + diff --git a/ext/systemc/src/sysc/kernel/sc_thread_process.cpp b/ext/systemc/src/sysc/kernel/sc_thread_process.cpp new file mode 100644 index 000000000..140096c95 --- /dev/null +++ b/ext/systemc/src/sysc/kernel/sc_thread_process.cpp @@ -0,0 +1,1127 @@ +/***************************************************************************** + + 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_thread_process.cpp -- Thread process implementation + + Original Author: Andy Goodrich, Forte Design Systems, 4 August 2005 + + CHANGE LOG AT THE END OF THE FILE + *****************************************************************************/ + +#include "sysc/kernel/sc_cmnhdr.h" +#include "sysc/kernel/sc_constants.h" +#include "sysc/kernel/sc_thread_process.h" +#include "sysc/kernel/sc_process_handle.h" +#include "sysc/kernel/sc_simcontext_int.h" +#include "sysc/kernel/sc_module.h" +#include "sysc/utils/sc_machine.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 + + +//------------------------------------------------------------------------------ +// user-defined default stack-size +//------------------------------------------------------------------------------ +#if defined(SC_OVERRIDE_DEFAULT_STACK_SIZE) +# define SC_DEFAULT_STACK_SIZE_ SC_OVERRIDE_DEFAULT_STACK_SIZE + +//------------------------------------------------------------------------------ +// architecture-specific default stack sizes +//------------------------------------------------------------------------------ +#elif !defined(SC_USE_PTHREADS) && (defined(__CYGWIN32__) || defined(__CYGWIN32)) +# define SC_DEFAULT_STACK_SIZE_ 0x50000 + +#elif defined(SC_LONG_64) || defined(__x86_64__) || defined(__LP64__) || \ + defined(_M_X64) || defined(_M_AMD64) +# define SC_DEFAULT_STACK_SIZE_ 0x40000 + +#else +# define SC_DEFAULT_STACK_SIZE_ 0x20000 + +#endif // SC_DEFAULT_STACK_SIZE_ + + +//------------------------------------------------------------------------------ +// force 16-byte alignment on coroutine entry functions, needed for +// QuickThreads (32-bit, see also fixes in qt/md/{i386,iX86_64}.[hs]), +// and MinGW32 / Cygwin32 compilers on Windows platforms +#if defined(__GNUC__) && !defined(__ICC) && !defined(__x86_64__) && \ + (__GNUC__ > 4 || __GNUC__ == 4 && __GNUC_MINOR__ > 1 ) +# define SC_ALIGNED_STACK_ \ + __attribute__((force_align_arg_pointer)) +#else +# define SC_ALIGNED_STACK_ /* empty */ +#endif + + +namespace sc_core { + +const int SC_DEFAULT_STACK_SIZE = SC_DEFAULT_STACK_SIZE_; +#undef SC_DEFAULT_STACK_SIZE_ +#undef SC_OVERRIDE_DEFAULT_STACK_SIZE + +//------------------------------------------------------------------------------ +//"sc_thread_cor_fn" +// +// This function invokes the coroutine for the supplied object instance. +//------------------------------------------------------------------------------ +SC_ALIGNED_STACK_ +void sc_thread_cor_fn( void* arg ) +{ + sc_simcontext* simc_p = sc_get_curr_simcontext(); + sc_thread_handle thread_h = RCAST<sc_thread_handle>( arg ); + + // PROCESS THE THREAD AND PROCESS ANY EXCEPTIONS THAT ARE THROWN: + + while( true ) { + + try { + thread_h->semantics(); + } + catch( sc_user ) { + continue; + } + catch( sc_halt ) { + ::std::cout << "Terminating process " + << thread_h->name() << ::std::endl; + } + catch( const sc_unwind_exception& ex ) { + ex.clear(); + if ( ex.is_reset() ) continue; + } + catch( ... ) { + sc_report* err_p = sc_handle_exception(); + thread_h->simcontext()->set_error( err_p ); + } + break; + } + + sc_process_b* active_p = sc_get_current_process_b(); + + // REMOVE ALL TRACES OF OUR THREAD FROM THE SIMULATORS DATA STRUCTURES: + + thread_h->disconnect_process(); + + // IF WE AREN'T ACTIVE MAKE SURE WE WON'T EXECUTE: + + if ( thread_h->next_runnable() != 0 ) + { + simc_p->remove_runnable_thread(thread_h); + } + + // IF WE ARE THE ACTIVE PROCESS ABORT OUR EXECUTION: + + + if ( active_p == (sc_process_b*)thread_h ) + { + + sc_core::sc_cor* x = simc_p->next_cor(); + simc_p->cor_pkg()->abort( x ); + } + +} + + +//------------------------------------------------------------------------------ +//"sc_thread_process::disable_process" +// +// This virtual method suspends this process and its children if requested to. +// descendants = indicator of whether this process' children should also +// be suspended +//------------------------------------------------------------------------------ +void sc_thread_process::disable_process( + sc_descendant_inclusion_info descendants ) +{ + + // IF NEEDED PROPOGATE THE DISABLE REQUEST THROUGH OUR DESCENDANTS: + + if ( descendants == SC_INCLUDE_DESCENDANTS ) + { + const std::vector<sc_object*>& children = get_child_objects(); + int child_n = children.size(); + + for ( int child_i = 0; child_i < child_n; child_i++ ) + { + sc_process_b* child_p = DCAST<sc_process_b*>(children[child_i]); + if ( child_p ) child_p->disable_process(descendants); + } + } + + // DON'T ALLOW CORNER CASE BY DEFAULT: + + if ( !sc_allow_process_control_corners ) + { + switch( m_trigger_type ) + { + case AND_LIST_TIMEOUT: + case EVENT_TIMEOUT: + case OR_LIST_TIMEOUT: + case TIMEOUT: + report_error(SC_ID_PROCESS_CONTROL_CORNER_CASE_, + "attempt to disable a thread with timeout wait"); + break; + default: + break; + } + } + + // DISABLE OUR OBJECT INSTANCE: + + m_state = m_state | ps_bit_disabled; + + // IF THIS CALL IS BEFORE THE SIMULATION DON'T RUN THE THREAD: + + if ( !sc_is_running() ) + { + m_state = m_state | ps_bit_ready_to_run; + simcontext()->remove_runnable_thread(this); + } +} + +//------------------------------------------------------------------------------ +//"sc_thread_process::enable_process" +// +// This method resumes the execution of this process, and if requested, its +// descendants. If the process was suspended and has a resumption pending it +// will be dispatched in the next delta cycle. Otherwise the state will be +// adjusted to indicate it is no longer suspended, but no immediate execution +// will occur. +//------------------------------------------------------------------------------ +void sc_thread_process::enable_process( + sc_descendant_inclusion_info descendants ) +{ + + // IF NEEDED PROPOGATE THE ENABLE REQUEST THROUGH OUR DESCENDANTS: + + if ( descendants == SC_INCLUDE_DESCENDANTS ) + { + const std::vector<sc_object*>& children = get_child_objects(); + int child_n = children.size(); + + for ( int child_i = 0; child_i < child_n; child_i++ ) + { + sc_process_b* child_p = DCAST<sc_process_b*>(children[child_i]); + if ( child_p ) child_p->enable_process(descendants); + } + } + + // ENABLE THIS OBJECT INSTANCE: + // + // If it was disabled and ready to run then put it on the run queue. + + m_state = m_state & ~ps_bit_disabled; + if ( m_state == ps_bit_ready_to_run && sc_allow_process_control_corners ) + { + m_state = ps_normal; + if ( next_runnable() == 0 ) + simcontext()->push_runnable_thread(this); + } +} + + +//------------------------------------------------------------------------------ +//"sc_thread_process::kill_process" +// +// This method removes this object instance from use. It calls the +// sc_process_b::kill_process() method to perform low level clean up. Then +// it aborts this process if it is the active process. +//------------------------------------------------------------------------------ +void sc_thread_process::kill_process(sc_descendant_inclusion_info descendants ) +{ + + // IF THE SIMULATION HAS NOT BEEN INITIALIZED YET THAT IS AN ERROR: + + if ( !sc_is_running() ) + { + report_error( SC_ID_KILL_PROCESS_WHILE_UNITIALIZED_ ); + } + + // IF NEEDED PROPOGATE THE KILL REQUEST THROUGH OUR DESCENDANTS: + + if ( descendants == SC_INCLUDE_DESCENDANTS ) + { + const std::vector<sc_object*> children = get_child_objects(); + int child_n = children.size(); + + for ( int child_i = 0; child_i < child_n; child_i++ ) + { + sc_process_b* child_p = DCAST<sc_process_b*>(children[child_i]); + if ( child_p ) child_p->kill_process(descendants); + } + } + + // IF THE PROCESS IS CURRENTLY UNWINDING OR IS ALREADY A ZOMBIE + // IGNORE THE KILL: + + if ( m_unwinding ) + { + SC_REPORT_WARNING( SC_ID_PROCESS_ALREADY_UNWINDING_, name() ); + return; + } + + if ( m_state & ps_bit_zombie ) + return; + + // SET UP TO KILL THE PROCESS IF SIMULATION HAS STARTED: + // + // If the thread does not have a stack don't try the throw! + + if ( sc_is_running() && m_has_stack ) + { + m_throw_status = THROW_KILL; + m_wait_cycle_n = 0; + simcontext()->preempt_with(this); + } + + // IF THE SIMULATION HAS NOT STARTED REMOVE TRACES OF OUR PROCESS FROM + // EVENT QUEUES, ETC.: + + else + { + disconnect_process(); + } +} + +//------------------------------------------------------------------------------ +//"sc_thread_process::prepare_for_simulation" +// +// This method prepares this object instance for simulation. It calls the +// coroutine package to create the actual thread. +//------------------------------------------------------------------------------ +void sc_thread_process::prepare_for_simulation() +{ + m_cor_p = simcontext()->cor_pkg()->create( m_stack_size, + sc_thread_cor_fn, this ); + m_cor_p->stack_protect( true ); +} + + +//------------------------------------------------------------------------------ +//"sc_thread_process::resume_process" +// +// This method resumes the execution of this process, and if requested, its +// descendants. If the process was suspended and has a resumption pending it +// will be dispatched in the next delta cycle. Otherwise the state will be +// adjusted to indicate it is no longer suspended, but no immediate execution +// will occur. +//------------------------------------------------------------------------------ +void sc_thread_process::resume_process( + sc_descendant_inclusion_info descendants ) +{ + + // IF NEEDED PROPOGATE THE RESUME REQUEST THROUGH OUR DESCENDANTS: + + if ( descendants == SC_INCLUDE_DESCENDANTS ) + { + const std::vector<sc_object*>& children = get_child_objects(); + int child_n = children.size(); + + for ( int child_i = 0; child_i < child_n; child_i++ ) + { + sc_process_b* child_p = DCAST<sc_process_b*>(children[child_i]); + if ( child_p ) child_p->resume_process(descendants); + } + } + + // BY DEFAULT THE CORNER CASE IS AN ERROR: + + if ( !sc_allow_process_control_corners && (m_state & ps_bit_disabled) && + (m_state & ps_bit_suspended) ) + { + m_state = m_state & ~ps_bit_suspended; + report_error(SC_ID_PROCESS_CONTROL_CORNER_CASE_, + "call to resume() on a disabled suspended thread"); + } + + // CLEAR THE SUSPENDED BIT: + + m_state = m_state & ~ps_bit_suspended; + + // RESUME OBJECT INSTANCE IF IT IS READY TO RUN: + + if ( m_state & ps_bit_ready_to_run ) + { + m_state = m_state & ~ps_bit_ready_to_run; + if ( next_runnable() == 0 ) + simcontext()->push_runnable_thread(this); + remove_dynamic_events(); // order important. + } +} + +//------------------------------------------------------------------------------ +//"sc_thread_process::sc_thread_process" +// +// This is the object instance constructor for this class. +//------------------------------------------------------------------------------ +sc_thread_process::sc_thread_process( const char* name_p, bool free_host, + SC_ENTRY_FUNC method_p, sc_process_host* host_p, + const sc_spawn_options* opt_p +): + sc_process_b( + name_p ? name_p : sc_gen_unique_name("thread_p"), + true, free_host, method_p, host_p, opt_p), + m_cor_p(0), m_monitor_q(), m_stack_size(SC_DEFAULT_STACK_SIZE), + m_wait_cycle_n(0) +{ + + // CHECK IF THIS IS AN sc_module-BASED PROCESS AND SIMULATION HAS STARTED: + + if ( DCAST<sc_module*>(host_p) != 0 && sc_is_running() ) + { + report_error( SC_ID_MODULE_THREAD_AFTER_START_ ); + } + + // INITIALIZE VALUES: + // + // If there are spawn options use them. + + m_process_kind = SC_THREAD_PROC_; + + if (opt_p) { + m_dont_init = opt_p->m_dont_initialize; + if ( opt_p->m_stack_size ) m_stack_size = opt_p->m_stack_size; + + // traverse event sensitivity list + for (unsigned int i = 0; i < opt_p->m_sensitive_events.size(); i++) { + sc_sensitive::make_static_sensitivity( + this, *opt_p->m_sensitive_events[i]); + } + + // traverse port base sensitivity list + for ( unsigned int i = 0; i < opt_p->m_sensitive_port_bases.size(); i++) + { + sc_sensitive::make_static_sensitivity( + this, *opt_p->m_sensitive_port_bases[i]); + } + + // traverse interface sensitivity list + for ( unsigned int i = 0; i < opt_p->m_sensitive_interfaces.size(); i++) + { + sc_sensitive::make_static_sensitivity( + this, *opt_p->m_sensitive_interfaces[i]); + } + + // traverse event finder sensitivity list + for ( unsigned int i = 0; i < opt_p->m_sensitive_event_finders.size(); + i++) + { + sc_sensitive::make_static_sensitivity( + this, *opt_p->m_sensitive_event_finders[i]); + } + + // process any reset signal specification: + + opt_p->specify_resets(); + + } + + else + { + m_dont_init = false; + } + +} + +//------------------------------------------------------------------------------ +//"sc_thread_process::~sc_thread_process" +// +// This is the object instance constructor for this class. +//------------------------------------------------------------------------------ +sc_thread_process::~sc_thread_process() +{ + + // DESTROY THE COROUTINE FOR THIS THREAD: + + if( m_cor_p != 0 ) { + m_cor_p->stack_protect( false ); + delete m_cor_p; + m_cor_p = 0; + } +} + + +//------------------------------------------------------------------------------ +//"sc_thread_process::signal_monitors" +// +// This methods signals the list of monitors for this object instance. +//------------------------------------------------------------------------------ +void sc_thread_process::signal_monitors(int type) +{ + int mon_n; // # of monitors present. + + mon_n = m_monitor_q.size(); + for ( int mon_i = 0; mon_i < mon_n; mon_i++ ) + m_monitor_q[mon_i]->signal(this, type); +} + + +//------------------------------------------------------------------------------ +//"sc_thread_process::suspend_process" +// +// This virtual method suspends this process and its children if requested to. +// descendants = indicator of whether this process' children should also +// be suspended +//------------------------------------------------------------------------------ +void sc_thread_process::suspend_process( + sc_descendant_inclusion_info descendants ) +{ + + // IF NEEDED PROPOGATE THE SUSPEND REQUEST THROUGH OUR DESCENDANTS: + + if ( descendants == SC_INCLUDE_DESCENDANTS ) + { + const std::vector<sc_object*>& children = get_child_objects(); + int child_n = children.size(); + + for ( int child_i = 0; child_i < child_n; child_i++ ) + { + sc_process_b* child_p = DCAST<sc_process_b*>(children[child_i]); + if ( child_p ) child_p->suspend_process(descendants); + } + } + + // CORNER CASE CHECKS, THE FOLLOWING ARE ERRORS: + // (a) if this thread has a reset_signal_is specification + // (b) if this thread is in synchronous reset + + if ( !sc_allow_process_control_corners && m_has_reset_signal ) + { + report_error(SC_ID_PROCESS_CONTROL_CORNER_CASE_, + "attempt to suspend a thread that has a reset signal"); + } + else if ( !sc_allow_process_control_corners && m_sticky_reset ) + { + report_error(SC_ID_PROCESS_CONTROL_CORNER_CASE_, + "attempt to suspend a thread in synchronous reset"); + } + + // SUSPEND OUR OBJECT INSTANCE: + // + // (1) If we are on the runnable queue then set suspended and ready_to_run, + // and remove ourselves from the run queue. + // (2) If this is a self-suspension then a resume should cause immediate + // scheduling of the process, and we need to call suspend_me() here. + + m_state = m_state | ps_bit_suspended; + if ( next_runnable() != 0 ) + { + m_state = m_state | ps_bit_ready_to_run; + simcontext()->remove_runnable_thread( this ); + } + if ( sc_get_current_process_b() == DCAST<sc_process_b*>(this) ) + { + m_state = m_state | ps_bit_ready_to_run; + suspend_me(); + } +} + +//------------------------------------------------------------------------------ +//"sc_thread_process::throw_reset" +// +// This virtual method is invoked when an reset is to be thrown. The +// method will cancel any dynamic waits. If the reset is asynchronous it will +// queue this object instance to be executed. +//------------------------------------------------------------------------------ +void sc_thread_process::throw_reset( bool async ) +{ + // IF THE PROCESS IS CURRENTLY UNWINDING OR IS ALREADY A ZOMBIE + // IGNORE THE RESET: + + if ( m_unwinding ) + { + SC_REPORT_WARNING( SC_ID_PROCESS_ALREADY_UNWINDING_, name() ); + return; + } + + if ( m_state & ps_bit_zombie ) + return; + + + // Set the throw type and clear any pending dynamic events: + + m_throw_status = async ? THROW_ASYNC_RESET : THROW_SYNC_RESET; + m_wait_cycle_n = 0; + + // If this is an asynchronous reset: + // + // (a) Cancel any dynamic events + // (b) Set the thread up for execution: + // (i) If we are in the execution phase do it now. + // (ii) If we are not queue it to execute next when we hit + // the execution phase. + + if ( async ) + { + m_state = m_state & ~ps_bit_ready_to_run; + remove_dynamic_events(); + if ( simcontext()->evaluation_phase() ) + { + simcontext()->preempt_with( this ); + } + else + { + if ( is_runnable() ) + simcontext()->remove_runnable_thread(this); + simcontext()->execute_thread_next(this); + } + } +} + + +//------------------------------------------------------------------------------ +//"sc_thread_process::throw_user" +// +// This virtual method is invoked when a user exception is to be thrown. +// If requested it will also throw the exception to the children of this +// object instance. The order of dispatch for the processes that are +// thrown the exception is from youngest child to oldest child and then +// this process instance. This means that this instance will be pushed onto +// the front of the simulator's runnable queue and then the children will +// be processed recursively. +// helper_p = helper object to use to throw the exception. +// descendants = indicator of whether this process' children should also +// be suspended +//------------------------------------------------------------------------------ +void sc_thread_process::throw_user( const sc_throw_it_helper& helper, + sc_descendant_inclusion_info descendants ) +{ + + // IF THE SIMULATION IS NOT ACTAULLY RUNNING THIS IS AN ERROR: + + if ( sc_get_status() != SC_RUNNING ) + { + report_error( SC_ID_THROW_IT_WHILE_NOT_RUNNING_ ); + } + + // IF NEEDED PROPOGATE THE THROW REQUEST THROUGH OUR DESCENDANTS: + + if ( descendants == SC_INCLUDE_DESCENDANTS ) + { + const std::vector<sc_object*> children = get_child_objects(); + int child_n = children.size(); + + for ( int child_i = 0; child_i < child_n; child_i++ ) + { + sc_process_b* child_p = DCAST<sc_process_b*>(children[child_i]); + if ( child_p ) + { + DEBUG_MSG(DEBUG_NAME,child_p,"about to throw user on"); + child_p->throw_user(helper, descendants); + } + } + } + + // IF THE PROCESS IS CURRENTLY UNWINDING IGNORE THE THROW: + + if ( m_unwinding ) + { + SC_REPORT_WARNING( SC_ID_PROCESS_ALREADY_UNWINDING_, name() ); + return; + } + + // SET UP THE THROW REQUEST FOR THIS OBJECT INSTANCE AND QUEUE IT FOR + // EXECUTION: + + if( m_has_stack ) + { + remove_dynamic_events(); + DEBUG_MSG(DEBUG_NAME,this,"throwing user exception to"); + m_throw_status = THROW_USER; + if ( m_throw_helper_p != 0 ) delete m_throw_helper_p; + m_throw_helper_p = helper.clone(); + simcontext()->preempt_with( this ); + } + else + { + SC_REPORT_WARNING( SC_ID_THROW_IT_IGNORED_, name() ); + } +} + + +//------------------------------------------------------------------------------ +//"sc_thread_process::trigger_dynamic" +// +// This method sets up a dynamic trigger on an event. +// +// Notes: +// (1) This method is identical to sc_method_process::trigger_dynamic(), +// but they cannot be combined as sc_process_b::trigger_dynamic() +// because the signatures things like sc_event::remove_dynamic() +// have different overloads for sc_thread_process* and sc_method_process*. +// So if you change code here you'll also need to change it in +// sc_method_process.cpp. +// +// Result is true if this process should be removed from the event's list, +// false if not. +//------------------------------------------------------------------------------ +bool sc_thread_process::trigger_dynamic( sc_event* e ) +{ + // No time outs yet, and keep gcc happy. + + m_timed_out = false; + + // Escape cases: + // (a) If this thread issued the notify() don't schedule it for + // execution, but leave the sensitivity in place. + // (b) If this thread is already runnable can't trigger an event. + + // not possible for thread processes! +#if 0 // ! defined( SC_ENABLE_IMMEDIATE_SELF_NOTIFICATIONS ) + if ( sc_get_current_process_b() == (sc_process_b*)this ) + { + report_immediate_self_notification(); + return false; + } +#endif // SC_ENABLE_IMMEDIATE_SELF_NOTIFICATIONS + + if( is_runnable() ) + return true; + + // If a process is disabled then we ignore any events, leaving them enabled: + // + // But if this is a time out event we need to remove both it and the + // event that was being waited for. + + if ( m_state & ps_bit_disabled ) + { + if ( e == m_timeout_event_p ) + { + remove_dynamic_events( true ); + return true; + } + else + { + return false; + } + } + + + // Process based on the event type and current process state: + // + // Every case needs to set 'rc' and continue on to the end of + // this method to allow suspend processing to work correctly. + + switch( m_trigger_type ) + { + case EVENT: + m_event_p = 0; + m_trigger_type = STATIC; + break; + + case AND_LIST: + -- m_event_count; + if ( m_event_count == 0 ) + { + m_event_list_p->auto_delete(); + m_event_list_p = 0; + m_trigger_type = STATIC; + } + else + { + return true; + } + break; + + case OR_LIST: + m_event_list_p->remove_dynamic( this, e ); + m_event_list_p->auto_delete(); + m_event_list_p = 0; + m_trigger_type = STATIC; + break; + + case TIMEOUT: + m_trigger_type = STATIC; + break; + + case EVENT_TIMEOUT: + if ( e == m_timeout_event_p ) + { + m_timed_out = true; + m_event_p->remove_dynamic( this ); + m_event_p = 0; + m_trigger_type = STATIC; + } + else + { + m_timeout_event_p->cancel(); + m_timeout_event_p->reset(); + m_event_p = 0; + m_trigger_type = STATIC; + } + break; + + case OR_LIST_TIMEOUT: + if ( e == m_timeout_event_p ) + { + m_timed_out = true; + m_event_list_p->remove_dynamic( this, e ); + m_event_list_p->auto_delete(); + m_event_list_p = 0; + m_trigger_type = STATIC; + } + + else + { + m_timeout_event_p->cancel(); + m_timeout_event_p->reset(); + m_event_list_p->remove_dynamic( this, e ); + m_event_list_p->auto_delete(); + m_event_list_p = 0; + m_trigger_type = STATIC; + } + break; + + case AND_LIST_TIMEOUT: + if ( e == m_timeout_event_p ) + { + m_timed_out = true; + m_event_list_p->remove_dynamic( this, e ); + m_event_list_p->auto_delete(); + m_event_list_p = 0; + m_trigger_type = STATIC; + } + + else + { + -- m_event_count; + if ( m_event_count == 0 ) + { + m_timeout_event_p->cancel(); + m_timeout_event_p->reset(); + // no need to remove_dynamic + m_event_list_p->auto_delete(); + m_event_list_p = 0; + m_trigger_type = STATIC; + } + else + { + return true; + } + } + break; + + case STATIC: { + // we should never get here, but throw_it() can make it happen. + SC_REPORT_WARNING(SC_ID_NOT_EXPECTING_DYNAMIC_EVENT_NOTIFY_, name()); + return true; + } + } + + // If we get here then the thread is has satisfied its wait criteria, if + // its suspended mark its state as ready to run. If its not suspended then + // push it onto the runnable queue. + + if ( (m_state & ps_bit_suspended) ) + { + m_state = m_state | ps_bit_ready_to_run; + } + else + { + simcontext()->push_runnable_thread(this); + } + + return true; +} + + +//------------------------------------------------------------------------------ +//"sc_set_stack_size" +// +//------------------------------------------------------------------------------ +void +sc_set_stack_size( sc_thread_handle thread_h, std::size_t size ) +{ + thread_h->set_stack_size( size ); +} + +#undef DEBUG_MSG +#undef DEBUG_NAME + +} // namespace sc_core + + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affiliation, date and + changes you are making here. + + Name, Affiliation, Date: + Description of Modification: + + *****************************************************************************/ + +// $Log: sc_thread_process.cpp,v $ +// Revision 1.57 2011/08/24 22:05:51 acg +// Torsten Maehne: initialization changes to remove warnings. +// +// Revision 1.56 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.55 2011/08/04 17:16:22 acg +// Philipp A. Hartmann: fix handling of child objects in kill routine, need +// to use a copy rather than a reference. +// +// Revision 1.53 2011/07/29 22:45:38 acg +// Philipp A. Hartmann: changes to handle case where a process control +// invocation on a child process causes the list of child processes to change. +// +// Revision 1.52 2011/07/24 11:27:04 acg +// Andy Goodrich: moved the check for unwinding processes until after the +// descendants have been processed in throw_user and kill. +// +// Revision 1.51 2011/07/24 11:20:03 acg +// Philipp A. Hartmann: process control error message improvements: +// (1) Downgrade error to warning for re-kills of processes. +// (2) Add process name to process messages. +// (3) drop some superfluous colons in messages. +// +// Revision 1.50 2011/05/09 04:07:49 acg +// Philipp A. Hartmann: +// (1) Restore hierarchy in all phase callbacks. +// (2) Ensure calls to before_end_of_elaboration. +// +// Revision 1.49 2011/05/05 17:45:27 acg +// Philip A. Hartmann: changes in WIN64 support. +// Andy Goodrich: additional DEBUG_MSG instances to trace process handling. +// +// Revision 1.48 2011/04/19 15:04:27 acg +// Philipp A. Hartmann: clean up SC_ID messages. +// +// Revision 1.47 2011/04/19 02:39:09 acg +// Philipp A. Hartmann: added checks for additional throws during stack unwinds. +// +// Revision 1.46 2011/04/14 22:33:43 acg +// Andy Goodrich: added missing checks for a process being a zombie. +// +// Revision 1.45 2011/04/13 02:45:11 acg +// Andy Goodrich: eliminated warning message that occurred if the DEBUG_MSG +// macro was used. +// +// Revision 1.44 2011/04/11 22:04:33 acg +// Andy Goodrich: use the DEBUG_NAME macro for DEBUG_MSG messages. +// +// Revision 1.43 2011/04/10 22:12:32 acg +// Andy Goodrich: adding debugging macros. +// +// Revision 1.42 2011/04/08 22:40:26 acg +// Andy Goodrich: moved the reset event notification code out of throw_reset() +// and into suspend_me. +// +// Revision 1.41 2011/04/08 18:24:07 acg +// Andy Goodrich: fix asynchronous reset dispatch and when the reset_event() +// is fired. +// +// Revision 1.40 2011/04/05 20:50:57 acg +// Andy Goodrich: +// (1) changes to make sure that event(), posedge() and negedge() only +// return true if the clock has not moved. +// (2) fixes for method self-resumes. +// (3) added SC_PRERELEASE_VERSION +// (4) removed kernel events from the object hierarchy, added +// sc_hierarchy_name_exists(). +// +// Revision 1.39 2011/04/01 22:30:39 acg +// Andy Goodrich: change hard assertion to warning for trigger_dynamic() +// getting called when there is only STATIC sensitivity. This can result +// because of sc_process_handle::throw_it(). +// +// Revision 1.38 2011/03/23 16:17:52 acg +// Andy Goodrich: don't emit an error message for a resume on a disabled +// process that is not suspended. +// +// Revision 1.37 2011/03/20 13:43:23 acg +// Andy Goodrich: added async_signal_is() plus suspend() as a corner case. +// +// Revision 1.36 2011/03/08 20:49:31 acg +// Andy Goodrich: implement coarse checking for synchronous reset - suspend +// interaction. +// +// Revision 1.35 2011/03/08 20:32:28 acg +// Andy Goodrich: implemented "coarse" checking for undefined process +// control interactions. +// +// Revision 1.34 2011/03/07 18:25:19 acg +// Andy Goodrich: tightening of check for resume on a disabled process to +// only produce an error if it is ready to run. +// +// Revision 1.33 2011/03/07 17:38:44 acg +// Andy Goodrich: tightening up of checks for undefined interaction between +// synchronous reset and suspend. +// +// Revision 1.32 2011/03/06 23:30:13 acg +// Andy Goodrich: refining suspend - sync reset corner case checking so that +// the following are error situations: +// (1) Calling suspend on a process with a reset_signal_is() specification +// or sync_reset_on() is active. +// (2) Calling sync_reset_on() on a suspended process. +// +// Revision 1.31 2011/03/06 19:57:11 acg +// Andy Goodrich: refinements for the illegal suspend - synchronous reset +// interaction. +// +// Revision 1.30 2011/03/06 16:47:09 acg +// Andy Goodrich: changes for testing sync_reset - suspend corner cases. +// +// Revision 1.29 2011/03/06 15:59:23 acg +// Andy Goodrich: added process control corner case checks. +// +// Revision 1.28 2011/03/05 19:44:20 acg +// Andy Goodrich: changes for object and event naming and structures. +// +// Revision 1.27 2011/02/19 08:30:53 acg +// Andy Goodrich: Moved process queueing into trigger_static from +// sc_event::notify. +// +// Revision 1.26 2011/02/18 20:27:14 acg +// Andy Goodrich: Updated Copyrights. +// +// Revision 1.25 2011/02/17 19:54:33 acg +// Andy Goodrich: +// (1) Changed signature of trigger_dynamic() back to bool, and moved +// run queue processing into trigger_dynamic. +// (2) Simplified process control usage. +// +// Revision 1.24 2011/02/16 22:37:31 acg +// Andy Goodrich: clean up to remove need for ps_disable_pending. +// +// Revision 1.23 2011/02/14 17:51:40 acg +// Andy Goodrich: proper pushing an poppping of the module hierarchy for +// start_of_simulation() and end_of_simulation. +// +// Revision 1.22 2011/02/13 23:09:58 acg +// Andy Goodrich: only remove dynamic events for asynchronous resets. +// +// Revision 1.21 2011/02/13 21:47:38 acg +// Andy Goodrich: update copyright notice. +// +// Revision 1.20 2011/02/13 21:37:13 acg +// Andy Goodrich: removed temporary diagnostic. Also there is +// remove_dynamic_events() call in reset code. +// +// Revision 1.19 2011/02/13 21:35:09 acg +// Andy Goodrich: added error messages for throws before the simulator is +// initialized. +// +// Revision 1.18 2011/02/11 13:25:24 acg +// Andy Goodrich: Philipp A. Hartmann's changes: +// (1) Removal of SC_CTHREAD method overloads. +// (2) New exception processing code. +// +// Revision 1.17 2011/02/08 08:18:16 acg +// Andy Goodrich: removed obsolete code. +// +// Revision 1.16 2011/02/07 19:17:20 acg +// Andy Goodrich: changes for IEEE 1666 compatibility. +// +// Revision 1.15 2011/02/04 15:27:36 acg +// Andy Goodrich: changes for suspend-resume semantics. +// +// Revision 1.14 2011/02/01 23:01:53 acg +// Andy Goodrich: removed dead code. +// +// Revision 1.13 2011/02/01 21:16:36 acg +// Andy Goodrich: +// (1) New version of trigger_dynamic() to implement new return codes and +// proper processing of events with new dynamic process rules. +// (2) Recoding of kill_process(), throw_user() and reset support to +// consolidate preemptive thread execution in sc_simcontext::preempt_with(). +// +// Revision 1.12 2011/01/25 20:50:37 acg +// Andy Goodrich: changes for IEEE 1666 2011. +// +// Revision 1.11 2011/01/20 16:52:20 acg +// Andy Goodrich: changes for IEEE 1666 2011. +// +// Revision 1.10 2011/01/19 23:21:50 acg +// Andy Goodrich: changes for IEEE 1666 2011 +// +// Revision 1.9 2011/01/18 20:10:45 acg +// Andy Goodrich: changes for IEEE1666_2011 semantics. +// +// Revision 1.8 2011/01/06 18:02:16 acg +// Andy Goodrich: added check for disabled thread to trigger_dynamic(). +// +// Revision 1.7 2010/11/20 17:10:57 acg +// Andy Goodrich: reset processing changes for new IEEE 1666 standard. +// +// Revision 1.6 2010/07/22 20:02:33 acg +// Andy Goodrich: bug fixes. +// +// Revision 1.5 2009/07/28 01:10:53 acg +// Andy Goodrich: updates for 2.3 release candidate. +// +// Revision 1.4 2009/05/22 16:06:29 acg +// Andy Goodrich: process control updates. +// +// Revision 1.3 2008/05/22 17:06:06 acg +// Andy Goodrich: formatting and comments. +// +// Revision 1.2 2007/09/20 20:32:35 acg +// Andy Goodrich: changes to the semantics of throw_it() to match the +// specification. A call to throw_it() will immediately suspend the calling +// thread until all the throwees have executed. At that point the calling +// thread will be restarted before the execution of any other threads. +// +// Revision 1.1.1.1 2006/12/15 20:20:05 acg +// SystemC 2.3 +// +// Revision 1.8 2006/04/20 17:08:17 acg +// Andy Goodrich: 3.0 style process changes. +// +// Revision 1.7 2006/04/11 23:13:21 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/03/21 00:00:34 acg +// Andy Goodrich: changed name of sc_get_current_process_base() to be +// sc_get_current_process_b() since its returning an sc_process_b instance. +// +// Revision 1.5 2006/01/26 21:04:55 acg +// Andy Goodrich: deprecation message changes and additional messages. +// +// Revision 1.4 2006/01/24 20:49:05 acg +// Andy Goodrich: changes to remove the use of deprecated features within the +// simulator, and to issue warning messages when deprecated features are used. +// +// Revision 1.3 2006/01/13 18:44:30 acg +// Added $Log to record CVS changes into the source. +// diff --git a/ext/systemc/src/sysc/kernel/sc_thread_process.h b/ext/systemc/src/sysc/kernel/sc_thread_process.h new file mode 100644 index 000000000..5e834506a --- /dev/null +++ b/ext/systemc/src/sysc/kernel/sc_thread_process.h @@ -0,0 +1,635 @@ +/***************************************************************************** + + 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_thread_process.h -- Thread process declarations + + Original Author: Andy Goodrich, Forte Design Systems, 4 August 2005 + + + CHANGE LOG AT THE END OF THE FILE + *****************************************************************************/ + + +#if !defined(sc_thread_process_h_INCLUDED) +#define sc_thread_process_h_INCLUDED + +#include "sysc/kernel/sc_spawn_options.h" +#include "sysc/kernel/sc_process.h" +#include "sysc/kernel/sc_cor.h" +#include "sysc/kernel/sc_event.h" +#include "sysc/kernel/sc_except.h" +#include "sysc/kernel/sc_reset.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 { + +// forward references: +class sc_event_and_list; +class sc_event_or_list; +class sc_reset; +void sc_thread_cor_fn( void* ); +void sc_set_stack_size( sc_thread_handle, std::size_t ); +class sc_event; +class sc_join; +class sc_module; +class sc_process_handle; +class sc_process_table; +class sc_simcontext; +class sc_runnable; + +sc_cor* get_cor_pointer( sc_process_b* process_p ); +void sc_set_stack_size( sc_thread_handle thread_h, std::size_t size ); +void wait( sc_simcontext* ); +void wait( const sc_event&, sc_simcontext* ); +void wait( const sc_event_or_list&, sc_simcontext* ); +void wait( const sc_event_and_list&, sc_simcontext* ); +void wait( const sc_time&, sc_simcontext* ); +void wait( const sc_time&, const sc_event&, sc_simcontext* ); +void wait( const sc_time&, const sc_event_or_list&, sc_simcontext* ); +void wait( const sc_time&, const sc_event_and_list&, sc_simcontext* ); + +//============================================================================== +// sc_thread_process - +// +//============================================================================== +class sc_thread_process : public sc_process_b { + friend void sc_thread_cor_fn( void* ); + friend void sc_set_stack_size( sc_thread_handle, std::size_t ); + friend class sc_event; + friend class sc_join; + friend class sc_module; + friend class sc_process_b; + friend class sc_process_handle; + friend class sc_process_table; + friend class sc_simcontext; + friend class sc_runnable; + friend sc_cor* get_cor_pointer( sc_process_b* process_p ); + + friend void wait( sc_simcontext* ); + friend void wait( const sc_event&, sc_simcontext* ); + friend void wait( const sc_event_or_list&, sc_simcontext* ); + friend void wait( const sc_event_and_list&, sc_simcontext* ); + friend void wait( const sc_time&, sc_simcontext* ); + friend void wait( const sc_time&, const sc_event&, sc_simcontext* ); + friend void wait( const sc_time&, const sc_event_or_list&, sc_simcontext* ); + friend void wait( const sc_time&, const sc_event_and_list&, sc_simcontext*); + public: + sc_thread_process( const char* name_p, bool free_host, + SC_ENTRY_FUNC method_p, sc_process_host* host_p, + const sc_spawn_options* opt_p ); + + virtual const char* kind() const + { return "sc_thread_process"; } + + protected: + // may not be deleted manually (called from sc_process_b) + virtual ~sc_thread_process(); + + virtual void disable_process( + sc_descendant_inclusion_info descendants = SC_NO_DESCENDANTS ); + virtual void enable_process( + sc_descendant_inclusion_info descendants = SC_NO_DESCENDANTS ); + virtual void kill_process( + sc_descendant_inclusion_info descendants = SC_NO_DESCENDANTS ); + sc_thread_handle next_exist(); + sc_thread_handle next_runnable(); + virtual void prepare_for_simulation(); + virtual void resume_process( + sc_descendant_inclusion_info descendants = SC_NO_DESCENDANTS ); + void set_next_exist( sc_thread_handle next_p ); + void set_next_runnable( sc_thread_handle next_p ); + + void set_stack_size( std::size_t size ); + inline void suspend_me(); + virtual void suspend_process( + sc_descendant_inclusion_info descendants = SC_NO_DESCENDANTS ); + virtual void throw_reset( bool async ); + virtual void throw_user( const sc_throw_it_helper& helper, + sc_descendant_inclusion_info descendants = SC_NO_DESCENDANTS ); + + bool trigger_dynamic( sc_event* ); + inline void trigger_static(); + + void wait( const sc_event& ); + void wait( const sc_event_or_list& ); + void wait( const sc_event_and_list& ); + void wait( const sc_time& ); + void wait( const sc_time&, const sc_event& ); + void wait( const sc_time&, const sc_event_or_list& ); + void wait( const sc_time&, const sc_event_and_list& ); + void wait_cycles( int n=1 ); + + protected: + void add_monitor( sc_process_monitor* monitor_p ); + void remove_monitor( sc_process_monitor* monitor_p); + void signal_monitors( int type = 0 ); + + protected: + sc_cor* m_cor_p; // Thread's coroutine. + std::vector<sc_process_monitor*> m_monitor_q; // Thread monitors. + std::size_t m_stack_size; // Thread stack size. + int m_wait_cycle_n; // # of waits to be done. + + private: // disabled + sc_thread_process( const sc_thread_process& ); + const sc_thread_process& operator = ( const sc_thread_process& ); + +}; + +//------------------------------------------------------------------------------ +//"sc_thread_process::set_stack_size" +// +//------------------------------------------------------------------------------ +inline void sc_thread_process::set_stack_size( std::size_t size ) +{ + assert( size ); + m_stack_size = size; +} + +//------------------------------------------------------------------------------ +//"sc_thread_process::suspend_me" +// +// This method suspends this object instance in favor of the next runnable +// process. Upon awakening we check to see if an exception should be thrown. +// There are two types of exceptions that can be thrown, synchronous reset +// and asynchronous reset. At a future time there may be more asynchronous +// exceptions. If an asynchronous reset is seen and there is not static reset +// specified, or the static reset is not active then clear the throw +// type for the next time this method is called. +// +// Notes: +// (1) For an explanation of how the reset mechanism works see the top of +// the file sc_reset.cpp. +// (2) The m_sticky_reset field is used to handle synchronous resets that +// are enabled via the sc_process_handle::sync_reset_on() method. These +// resets are not generated by a signal, but rather are modal by +// method call: sync_reset_on() - sync_reset_off(). +//------------------------------------------------------------------------------ +inline void sc_thread_process::suspend_me() +{ + // remember, if we're currently unwinding + + bool unwinding_preempted = m_unwinding; + + sc_simcontext* simc_p = simcontext(); + sc_cor* cor_p = simc_p->next_cor(); + + // do not switch, if we're about to execute next (e.g. suicide) + + if( m_cor_p != cor_p ) + { + DEBUG_MSG( DEBUG_NAME , this, "suspending thread"); + simc_p->cor_pkg()->yield( cor_p ); + DEBUG_MSG( DEBUG_NAME , this, "resuming thread"); + } + + // IF THERE IS A THROW TO BE DONE FOR THIS PROCESS DO IT NOW: + // + // (1) Optimize THROW_NONE for speed as it is the normal case. + // (2) If this thread is already unwinding then suspend_me() was + // called from the catch clause to throw an exception on another + // process, so just go back to the catch clause. + + if ( m_throw_status == THROW_NONE ) return; + + if ( m_unwinding ) return; + + switch( m_throw_status ) + { + case THROW_ASYNC_RESET: + case THROW_SYNC_RESET: + DEBUG_MSG( DEBUG_NAME , this, "throwing reset for"); + if ( m_reset_event_p ) m_reset_event_p->notify(); + throw sc_unwind_exception( this, true ); + + case THROW_USER: + DEBUG_MSG( DEBUG_NAME, this, "invoking throw_it for"); + m_throw_status = m_active_areset_n ? THROW_ASYNC_RESET : + (m_active_reset_n ? THROW_SYNC_RESET : + THROW_NONE); + m_throw_helper_p->throw_it(); + break; + + case THROW_KILL: + DEBUG_MSG( DEBUG_NAME, this, "throwing kill for"); + throw sc_unwind_exception( this, false ); + + default: // THROWING_NOW + sc_assert( unwinding_preempted ); + DEBUG_MSG( DEBUG_NAME, this, "restarting thread"); + break; + } +} + + +//------------------------------------------------------------------------------ +//"sc_thread_process::wait" +// +//------------------------------------------------------------------------------ +inline +void +sc_thread_process::wait( const sc_event& e ) +{ + if( m_unwinding ) + SC_REPORT_ERROR( SC_ID_WAIT_DURING_UNWINDING_, name() ); + + m_event_p = &e; // for cleanup. + e.add_dynamic( this ); + m_trigger_type = EVENT; + suspend_me(); +} + +inline +void +sc_thread_process::wait( const sc_event_or_list& el ) +{ + if( m_unwinding ) + SC_REPORT_ERROR( SC_ID_WAIT_DURING_UNWINDING_, name() ); + + el.add_dynamic( this ); + m_event_list_p = ⪙ + m_trigger_type = OR_LIST; + suspend_me(); +} + +inline +void +sc_thread_process::wait( const sc_event_and_list& el ) +{ + if( m_unwinding ) + SC_REPORT_ERROR( SC_ID_WAIT_DURING_UNWINDING_, name() ); + + el.add_dynamic( this ); + m_event_list_p = ⪙ + m_event_count = el.size(); + m_trigger_type = AND_LIST; + suspend_me(); +} + +inline +void +sc_thread_process::wait( const sc_time& t ) +{ + if( m_unwinding ) + SC_REPORT_ERROR( SC_ID_WAIT_DURING_UNWINDING_, name() ); + + m_timeout_event_p->notify_internal( t ); + m_timeout_event_p->add_dynamic( this ); + m_trigger_type = TIMEOUT; + suspend_me(); +} + +inline +void +sc_thread_process::wait( const sc_time& t, const sc_event& e ) +{ + if( m_unwinding ) + SC_REPORT_ERROR( SC_ID_WAIT_DURING_UNWINDING_, name() ); + + m_timeout_event_p->notify_internal( t ); + m_timeout_event_p->add_dynamic( this ); + e.add_dynamic( this ); + m_event_p = &e; + m_trigger_type = EVENT_TIMEOUT; + suspend_me(); +} + +inline +void +sc_thread_process::wait( const sc_time& t, const sc_event_or_list& el ) +{ + if( m_unwinding ) + SC_REPORT_ERROR( SC_ID_WAIT_DURING_UNWINDING_, name() ); + + m_timeout_event_p->notify_internal( t ); + m_timeout_event_p->add_dynamic( this ); + el.add_dynamic( this ); + m_event_list_p = ⪙ + m_trigger_type = OR_LIST_TIMEOUT; + suspend_me(); +} + +inline +void +sc_thread_process::wait( const sc_time& t, const sc_event_and_list& el ) +{ + if( m_unwinding ) + SC_REPORT_ERROR( SC_ID_WAIT_DURING_UNWINDING_, name() ); + + m_timeout_event_p->notify_internal( t ); + m_timeout_event_p->add_dynamic( this ); + el.add_dynamic( this ); + m_event_list_p = ⪙ + m_event_count = el.size(); + m_trigger_type = AND_LIST_TIMEOUT; + suspend_me(); +} + +//------------------------------------------------------------------------------ +//"sc_thread_process::wait_cycles" +// +// This method suspends this object instance for the specified number of cycles. +// A cycle is defined as the event the thread is set up to staticly wait on. +// The field m_wait_cycle_n is set to one less than the number of cycles to +// be waited for, since the value is tested before being decremented in +// the simulation kernel. +//------------------------------------------------------------------------------ +inline +void +sc_thread_process::wait_cycles( int n ) +{ + if( m_unwinding ) + SC_REPORT_ERROR( SC_ID_WAIT_DURING_UNWINDING_, name() ); + + m_wait_cycle_n = n-1; + suspend_me(); +} + +//------------------------------------------------------------------------------ +//"sc_thread_process::miscellaneous support" +// +//------------------------------------------------------------------------------ +inline +void sc_thread_process::add_monitor(sc_process_monitor* monitor_p) +{ + m_monitor_q.push_back(monitor_p); +} + + +inline +void sc_thread_process::remove_monitor(sc_process_monitor* monitor_p) +{ + int mon_n = m_monitor_q.size(); + + for ( int mon_i = 0; mon_i < mon_n; mon_i++ ) + { + if ( m_monitor_q[mon_i] == monitor_p ) + { + m_monitor_q[mon_i] = m_monitor_q[mon_n-1]; + m_monitor_q.resize(mon_n-1); + } + } +} + +inline +void sc_thread_process::set_next_exist(sc_thread_handle next_p) +{ + m_exist_p = next_p; +} + +inline +sc_thread_handle sc_thread_process::next_exist() +{ + return (sc_thread_handle)m_exist_p; +} + +inline +void sc_thread_process::set_next_runnable(sc_thread_handle next_p) +{ + m_runnable_p = next_p; +} + +inline +sc_thread_handle sc_thread_process::next_runnable() +{ + return (sc_thread_handle)m_runnable_p; +} + +inline sc_cor* get_cor_pointer( sc_process_b* process_p ) +{ + sc_thread_handle thread_p = DCAST<sc_thread_handle>(process_p); + return thread_p->m_cor_p; +} + +//------------------------------------------------------------------------------ +//"sc_thread_process::trigger_static" +// +// This inline method adds the current thread to the queue of runnable +// processes, if required. This is the case if the following criteria +// are met: +// (1) The process is in a runnable state. +// (2) The process is not already on the run queue. +// (3) The process is expecting a static trigger, +// dynamic event waits take priority. +// (4) The process' static wait count is zero. +// +// If the triggering process is the same process, the trigger is +// ignored as well, unless SC_ENABLE_IMMEDIATE_SELF_NOTIFICATIONS +// is defined. +//------------------------------------------------------------------------------ +inline +void +sc_thread_process::trigger_static() +{ + // No need to try queueing this thread if one of the following is true: + // (a) its disabled + // (b) its already queued for execution + // (c) its waiting on a dynamic event + // (d) its wait count is not satisfied + + if ( (m_state & ps_bit_disabled) || is_runnable() || + m_trigger_type != STATIC ) + return; + +#if ! defined( SC_ENABLE_IMMEDIATE_SELF_NOTIFICATIONS ) + if( SC_UNLIKELY_( sc_get_current_process_b() == this ) ) + { + report_immediate_self_notification(); + return; + } +#endif // SC_ENABLE_IMMEDIATE_SELF_NOTIFICATIONS + + if ( m_wait_cycle_n > 0 ) + { + --m_wait_cycle_n; + return; + } + + // If we get here then the thread is has satisfied its wait criteria, if + // its suspended mark its state as ready to run. If its not suspended then + // push it onto the runnable queue. + + if ( m_state & ps_bit_suspended ) + { + m_state = m_state | ps_bit_ready_to_run; + } + else + { + simcontext()->push_runnable_thread(this); + } +} + +#undef DEBUG_MSG +#undef DEBUG_NAME + +} // namespace sc_core + +// $Log: sc_thread_process.h,v $ +// Revision 1.30 2011/08/26 20:46:11 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.29 2011/08/24 23:36:12 acg +// Andy Goodrich: removed break statements that can never be reached and +// which causes warnings in the Greenhills C++ compiler. +// +// Revision 1.28 2011/04/14 22:34:27 acg +// Andy Goodrich: removed dead code. +// +// Revision 1.27 2011/04/13 05:02:18 acg +// Andy Goodrich: added missing check to the wake up code in suspend_me() +// so that we just return if the call to suspend_me() was issued from a +// stack unwinding. +// +// Revision 1.26 2011/04/13 02:44:26 acg +// Andy Goodrich: added m_unwinding flag in place of THROW_NOW because the +// throw status will be set back to THROW_*_RESET if reset is active and +// the check for an unwind being complete was expecting THROW_NONE as the +// clearing of THROW_NOW. +// +// Revision 1.25 2011/04/11 22:05:14 acg +// Andy Goodrich: use the DEBUG_NAME macro in DEBUG_MSG invocations. +// +// Revision 1.24 2011/04/10 22:12:32 acg +// Andy Goodrich: adding debugging macros. +// +// Revision 1.23 2011/04/08 22:41:28 acg +// Andy Goodrich: added comment pointing to the description of the reset +// mechanism in sc_reset.cpp. +// +// Revision 1.22 2011/04/08 18:27:33 acg +// Andy Goodrich: added check to make sure we don't schedule a running process +// because of it issues a notify() it is sensitive to. +// +// Revision 1.21 2011/04/05 06:22:38 acg +// Andy Goodrich: expanded comment for trigger_static() initial vetting. +// +// Revision 1.20 2011/04/01 21:24:57 acg +// Andy Goodrich: removed unused code. +// +// Revision 1.19 2011/02/19 08:30:53 acg +// Andy Goodrich: Moved process queueing into trigger_static from +// sc_event::notify. +// +// Revision 1.18 2011/02/18 20:27:14 acg +// Andy Goodrich: Updated Copyrights. +// +// Revision 1.17 2011/02/17 19:55:58 acg +// Andy Goodrich: +// (1) Changed signature of trigger_dynamic() back to a bool. +// (2) Simplified process control usage. +// (3) Changed trigger_static() to recognize process controls and to +// do the down-count on wait(N), allowing the elimination of +// ready_to_run(). +// +// Revision 1.16 2011/02/16 22:37:31 acg +// Andy Goodrich: clean up to remove need for ps_disable_pending. +// +// Revision 1.15 2011/02/13 21:47:38 acg +// Andy Goodrich: update copyright notice. +// +// Revision 1.14 2011/02/13 21:35:54 acg +// Andy Goodrich: added error for performing a wait() during unwinding. +// +// Revision 1.13 2011/02/11 13:25:24 acg +// Andy Goodrich: Philipp A. Hartmann's changes: +// (1) Removal of SC_CTHREAD method overloads. +// (2) New exception processing code. +// +// Revision 1.12 2011/02/01 23:01:53 acg +// Andy Goodrich: removed dead code. +// +// Revision 1.11 2011/02/01 21:18:01 acg +// Andy Goodrich: +// (1) Changes in throw processing for new process control rules. +// (2) Support of new process_state enum values. +// +// Revision 1.10 2011/01/25 20:50:37 acg +// Andy Goodrich: changes for IEEE 1666 2011. +// +// Revision 1.9 2011/01/19 23:21:50 acg +// Andy Goodrich: changes for IEEE 1666 2011 +// +// Revision 1.8 2011/01/18 20:10:45 acg +// Andy Goodrich: changes for IEEE1666_2011 semantics. +// +// Revision 1.7 2011/01/06 17:59:58 acg +// Andy Goodrich: removed debugging output. +// +// Revision 1.6 2010/07/22 20:02:33 acg +// Andy Goodrich: bug fixes. +// +// Revision 1.5 2009/07/28 01:10:53 acg +// Andy Goodrich: updates for 2.3 release candidate. +// +// Revision 1.4 2009/05/22 16:06:29 acg +// Andy Goodrich: process control updates. +// +// Revision 1.3 2009/03/12 22:59:58 acg +// Andy Goodrich: updates for 2.4 stuff. +// +// Revision 1.2 2008/05/22 17:06:06 acg +// Andy Goodrich: formatting and comments. +// +// Revision 1.1.1.1 2006/12/15 20:20:05 acg +// SystemC 2.3 +// +// Revision 1.7 2006/05/08 17:57:13 acg +// Andy Goodrich: Added David Long's forward declarations for friend functions +// to keep the Microsoft C++ compiler happy. +// +// Revision 1.6 2006/04/20 17:08:17 acg +// Andy Goodrich: 3.0 style process changes. +// +// Revision 1.5 2006/04/11 23:13:21 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.4 2006/01/24 20:49:05 acg +// Andy Goodrich: changes to remove the use of deprecated features within the +// simulator, and to issue warning messages when deprecated features are used. +// +// Revision 1.3 2006/01/13 18:44:30 acg +// Added $Log to record CVS changes into the source. + +#endif // !defined(sc_thread_process_h_INCLUDED) diff --git a/ext/systemc/src/sysc/kernel/sc_time.cpp b/ext/systemc/src/sysc/kernel/sc_time.cpp new file mode 100644 index 000000000..e3fdd5865 --- /dev/null +++ b/ext/systemc/src/sysc/kernel/sc_time.cpp @@ -0,0 +1,465 @@ +/***************************************************************************** + + 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_time.cpp -- + + Original Author: Martin Janssen, Synopsys, Inc., 2001-05-21 + + CHANGE LOG AT THE END OF THE FILE + *****************************************************************************/ + + +#include <math.h> +#include <stdio.h> + +#include "sysc/kernel/sc_kernel_ids.h" +#include "sysc/kernel/sc_simcontext.h" +#include "sysc/kernel/sc_time.h" +#include "sysc/utils/sc_utils_ids.h" + +#if !defined(PRIu64) +# if defined(_MSC_VER) || defined(__MINGW32__) +# define PRIu64 "I64u" +# else +# define PRIu64 "llu" +# endif +#endif // PRIu64 + +#ifdef SC_ENABLE_EARLY_MAXTIME_CREATION +# define SC_MAXTIME_ALLOWED_ 1 +#else +# define SC_MAXTIME_ALLOWED_ 0 +#endif + +namespace sc_core { + +static +double time_values[] = { + 1, // fs + 1e3, // ps + 1e6, // ns + 1e9, // us + 1e12, // ms + 1e15 // s +}; + +static +const char* time_units[] = { + "fs", + "ps", + "ns", + "us", + "ms", + "s" +}; + + +// ---------------------------------------------------------------------------- +// CLASS : sc_time +// +// The time class. +// ---------------------------------------------------------------------------- + +// constructors + +sc_time::sc_time( double v, sc_time_unit tu ) +: m_value( 0 ) +{ + if( v != 0 ) { + sc_time_params* time_params = sc_get_curr_simcontext()->m_time_params; + double scale_fac = time_values[tu] / time_params->time_resolution; + // linux bug workaround; don't change next two lines + volatile double tmp = v * scale_fac + 0.5; + m_value = SCAST<sc_dt::int64>( tmp ); + time_params->time_resolution_fixed = true; + } +} + +sc_time::sc_time( double v, sc_time_unit tu, sc_simcontext* simc ) +: m_value( 0 ) +{ + if( v != 0 ) { + sc_time_params* time_params = simc->m_time_params; + double scale_fac = time_values[tu] / time_params->time_resolution; + // linux bug workaround; don't change next two lines + volatile double tmp = v * scale_fac + 0.5; + m_value = SCAST<sc_dt::int64>( tmp ); + time_params->time_resolution_fixed = true; + } +} + +sc_time::sc_time( double v, bool scale ) +: m_value( 0 ) +{ + static bool warn_constructor=true; + if ( warn_constructor ) { + warn_constructor=false; + SC_REPORT_INFO(SC_ID_IEEE_1666_DEPRECATION_, + "deprecated constructor: sc_time(double,bool)"); + } + + if( v != 0 ) { + sc_time_params* time_params = sc_get_curr_simcontext()->m_time_params; + if( scale ) { + double scale_fac = sc_dt::uint64_to_double( + time_params->default_time_unit ); + // linux bug workaround; don't change next two lines + volatile double tmp = v * scale_fac + 0.5; + m_value = SCAST<sc_dt::int64>( tmp ); + } else { + // linux bug workaround; don't change next two lines + volatile double tmp = v + 0.5; + m_value = SCAST<sc_dt::int64>( tmp ); + } + time_params->time_resolution_fixed = true; + } +} + +sc_time::sc_time( value_type v, bool scale ) +: m_value( 0 ) +{ + static bool warn_constructor=true; + if ( warn_constructor ) { + warn_constructor=false; + SC_REPORT_INFO(SC_ID_IEEE_1666_DEPRECATION_, + "deprecated constructor: sc_time(uint64,bool)"); + } + + if( v != 0 ) { + sc_time_params* time_params = sc_get_curr_simcontext()->m_time_params; + if( scale ) { + double scale_fac = sc_dt::uint64_to_double( + time_params->default_time_unit ); + // linux bug workaround; don't change next two lines + volatile double tmp = sc_dt::uint64_to_double( v ) * + scale_fac + 0.5; + m_value = SCAST<sc_dt::int64>( tmp ); + } else { + m_value = v; + } + time_params->time_resolution_fixed = true; + } +} + +sc_time +sc_time::from_value( value_type v ) +{ + sc_time t; + if( v != 0 && !(SC_MAXTIME_ALLOWED_ && v == ~sc_dt::UINT64_ZERO) ) { + sc_time_params* time_params = sc_get_curr_simcontext()->m_time_params; + time_params->time_resolution_fixed = true; + } + t.m_value = v; + return t; +} + + +// conversion functions + +double +sc_time::to_default_time_units() const +{ + sc_time_params* time_params = sc_get_curr_simcontext()->m_time_params; +# if SC_MAXTIME_ALLOWED_ + if( m_value == 0 ) + return 0.0; + time_params->time_resolution_fixed = true; +# endif // SC_MAXTIME_ALLOWED_ + return ( sc_dt::uint64_to_double( m_value ) / + sc_dt::uint64_to_double( time_params->default_time_unit ) ); +} + +double +sc_time::to_seconds() const +{ + sc_time_params* time_params = sc_get_curr_simcontext()->m_time_params; +# if SC_MAXTIME_ALLOWED_ + if( m_value == 0 ) + return 0.0; + time_params->time_resolution_fixed = true; +# endif // SC_MAXTIME_ALLOWED_ + return ( sc_dt::uint64_to_double( m_value ) * + time_params->time_resolution * 1e-15 ); +} + +const std::string +sc_time::to_string() const +{ + value_type val = m_value; + if( val == 0 ) { + return std::string( "0 s" ); + } + sc_time_params* time_params = sc_get_curr_simcontext()->m_time_params; +# if SC_MAXTIME_ALLOWED_ + time_params->time_resolution_fixed = true; +# endif // SC_MAXTIME_ALLOWED_ + value_type tr = SCAST<sc_dt::int64>( time_params->time_resolution ); + int n = 0; + while( ( tr % 10 ) == 0 ) { + tr /= 10; + n ++; + } + assert( tr == 1 ); + while( ( val % 10 ) == 0 ) { + val /= 10; + n ++; + } + char buf[BUFSIZ]; + std::sprintf( buf, "%" PRIu64, val ); + std::string result( buf ); + if( n >= 15 ) { + for( int i = n - 15; i > 0; -- i ) { + result += "0"; + } + result += " s"; + } else { + for( int i = n % 3; i > 0; -- i ) { + result += "0"; + } + result += " "; + result += time_units[n / 3]; + } + return result; +} + + +// print function + +void +sc_time::print( ::std::ostream& os ) const +{ + os << to_string(); +} + + +// ---------------------------------------------------------------------------- +// STRUCT : sc_time_params +// +// Struct that holds the time resolution and default time unit. +// ---------------------------------------------------------------------------- + +sc_time_params::sc_time_params() +: time_resolution( 1000 ), // default 1 ps + time_resolution_specified( false ), + time_resolution_fixed( false ), + default_time_unit( 1000 ), // default 1 ns + default_time_unit_specified( false ) +{} + +sc_time_params::~sc_time_params() +{} + + +// ---------------------------------------------------------------------------- + +// functions for accessing the time resolution and default time unit + +void +sc_set_time_resolution( double v, sc_time_unit tu ) +{ + // first perform the necessary checks + + // must be positive + if( v < 0.0 ) { + SC_REPORT_ERROR( SC_ID_SET_TIME_RESOLUTION_, "value not positive" ); + } + + // must be a power of ten + double dummy; +#if defined( __HP_aCC ) || defined(__ppc__) + // aCC seems to have a bug in modf() + if( modf( log10( v < 1.0 ? 1.0/v : v ), &dummy ) != 0.0 ) { +#else + if( modf( log10( v ), &dummy ) != 0.0 ) { +#endif + SC_REPORT_ERROR( SC_ID_SET_TIME_RESOLUTION_, + "value not a power of ten" ); + } + + sc_simcontext* simc = sc_get_curr_simcontext(); + + // can only be specified during elaboration + if( sc_is_running() ) { + SC_REPORT_ERROR( SC_ID_SET_TIME_RESOLUTION_, "simulation running" ); + } + + sc_time_params* time_params = simc->m_time_params; + + // can be specified only once + if( time_params->time_resolution_specified ) { + SC_REPORT_ERROR( SC_ID_SET_TIME_RESOLUTION_, "already specified" ); + } + + // can only be specified before any sc_time is constructed + if( time_params->time_resolution_fixed ) { + SC_REPORT_ERROR( SC_ID_SET_TIME_RESOLUTION_, + "sc_time object(s) constructed" ); + } + + // must be larger than or equal to 1 fs + volatile double resolution = v * time_values[tu]; + if( resolution < 1.0 ) { + SC_REPORT_ERROR( SC_ID_SET_TIME_RESOLUTION_, + "value smaller than 1 fs" ); + } + + // recalculate the default time unit + volatile double time_unit = sc_dt::uint64_to_double( + time_params->default_time_unit ) * + ( time_params->time_resolution / resolution ); + if( time_unit < 1.0 ) { + SC_REPORT_WARNING( SC_ID_DEFAULT_TIME_UNIT_CHANGED_, 0 ); + time_params->default_time_unit = 1; + } else { + time_params->default_time_unit = SCAST<sc_dt::int64>( time_unit ); + } + + time_params->time_resolution = resolution; + time_params->time_resolution_specified = true; +} + +sc_time +sc_get_time_resolution() +{ + return sc_time::from_value( sc_dt::UINT64_ONE ); +} + + +void +sc_set_default_time_unit( double v, sc_time_unit tu ) +{ + static bool warn_default_time_unit=true; + if ( warn_default_time_unit ) + { + warn_default_time_unit=false; + SC_REPORT_INFO(SC_ID_IEEE_1666_DEPRECATION_, + "deprecated function: sc_set_default_time_unit"); + } + + // first perform the necessary checks + + // must be positive + if( v < 0.0 ) { + SC_REPORT_ERROR( SC_ID_SET_DEFAULT_TIME_UNIT_, "value not positive" ); + } + + // must be a power of ten + double dummy; + if( modf( log10( v ), &dummy ) != 0.0 ) { + SC_REPORT_ERROR( SC_ID_SET_DEFAULT_TIME_UNIT_, + "value not a power of ten" ); + } + + sc_simcontext* simc = sc_get_curr_simcontext(); + + // can only be specified during elaboration + if( sc_is_running() ) { + SC_REPORT_ERROR( SC_ID_SET_DEFAULT_TIME_UNIT_, "simulation running" ); + } + + sc_time_params* time_params = simc->m_time_params; + + // can only be specified before any sc_time is constructed + if( time_params->time_resolution_fixed ) { + SC_REPORT_ERROR( SC_ID_SET_DEFAULT_TIME_UNIT_, + "sc_time object(s) constructed" ); + } + + // can be specified only once + if( time_params->default_time_unit_specified ) { + SC_REPORT_ERROR( SC_ID_SET_DEFAULT_TIME_UNIT_, "already specified" ); + } + + // must be larger than or equal to the time resolution + volatile double time_unit = ( v * time_values[tu] ) / + time_params->time_resolution; + if( time_unit < 1.0 ) { + SC_REPORT_ERROR( SC_ID_SET_DEFAULT_TIME_UNIT_, + "value smaller than time resolution" ); + } + + time_params->default_time_unit = SCAST<sc_dt::int64>( time_unit ); + time_params->default_time_unit_specified = true; +} + +sc_time +sc_get_default_time_unit() +{ + static bool warn_get_default_time_unit = true; + if ( warn_get_default_time_unit ) + { + warn_get_default_time_unit=false; + SC_REPORT_INFO(SC_ID_IEEE_1666_DEPRECATION_, + "deprecated function: sc_get_default_time_unit"); + } + return sc_time::from_value( + sc_get_curr_simcontext()->m_time_params->default_time_unit + ); +} + + +// ---------------------------------------------------------------------------- + +const sc_time SC_ZERO_TIME; + +#undef SC_MAXTIME_ALLOWED_ + +} // namespace sc_core + +// $Log: sc_time.cpp,v $ +// Revision 1.7 2011/08/26 20:46:11 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.6 2011/07/24 16:08:36 acg +// Philipp A. Hartmann: fix C99 format specifiers for Solaris. +// +// Revision 1.5 2011/02/18 20:27:14 acg +// Andy Goodrich: Updated Copyrights. +// +// Revision 1.4 2011/02/13 21:47:38 acg +// Andy Goodrich: update copyright notice. +// +// Revision 1.3 2011/01/19 23:21:50 acg +// Andy Goodrich: changes for IEEE 1666 2011 +// +// Revision 1.2 2008/05/22 17:06:27 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.6 2006/01/26 21:04:55 acg +// Andy Goodrich: deprecation message changes and additional messages. +// +// Revision 1.5 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.4 2006/01/24 20:49:05 acg +// Andy Goodrich: changes to remove the use of deprecated features within the +// simulator, and to issue warning messages when deprecated features are used. +// +// Revision 1.3 2006/01/13 18:44:30 acg +// Added $Log to record CVS changes into the source. +// + +// Taf! diff --git a/ext/systemc/src/sysc/kernel/sc_time.h b/ext/systemc/src/sysc/kernel/sc_time.h new file mode 100644 index 000000000..af222dd0f --- /dev/null +++ b/ext/systemc/src/sysc/kernel/sc_time.h @@ -0,0 +1,414 @@ +/***************************************************************************** + + 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_time.h -- The time class. + + Original Author: Martin Janssen, Synopsys, Inc., 2001-05-21 + + CHANGE LOG AT THE END OF THE FILE + *****************************************************************************/ + + +#ifndef SC_TIME_H +#define SC_TIME_H + + +#include "sysc/datatypes/int/sc_nbdefs.h" +#include "sysc/datatypes/fx/scfx_ieee.h" +#include "sysc/utils/sc_iostream.h" + +namespace sc_core { + +class sc_simcontext; + +// friend operator declarations + + const sc_time operator + ( const sc_time&, const sc_time& ); + const sc_time operator - ( const sc_time&, const sc_time& ); + const sc_time operator * ( const sc_time&, double ); + const sc_time operator * ( double, const sc_time& ); + const sc_time operator / ( const sc_time&, double ); + double operator / ( const sc_time&, const sc_time& ); + + +// ---------------------------------------------------------------------------- +// ENUM : sc_time_unit +// +// Enumeration of time units. +// ---------------------------------------------------------------------------- + +enum sc_time_unit +{ + SC_FS = 0, + SC_PS, + SC_NS, + SC_US, + SC_MS, + SC_SEC +}; + + +// ---------------------------------------------------------------------------- +// CLASS : sc_time +// +// The time class. +// ---------------------------------------------------------------------------- + +class sc_time +{ +public: + + typedef sc_dt::uint64 value_type; + + // constructors + + sc_time(); + sc_time( double, sc_time_unit ); + sc_time( double, sc_time_unit, sc_simcontext* ); + sc_time( const sc_time& ); + + static sc_time from_value( value_type ); + + // deprecated, use from_value(v) + sc_time( double, bool scale ); + sc_time( value_type, bool scale ); + + // assignment operator + + sc_time& operator = ( const sc_time& ); + + + // conversion functions + + value_type value() const; // relative to the time resolution + double to_double() const; // relative to the time resolution + double to_default_time_units() const; + double to_seconds() const; + const std::string to_string() const; + + + // relational operators + + bool operator == ( const sc_time& ) const; + bool operator != ( const sc_time& ) const; + bool operator < ( const sc_time& ) const; + bool operator <= ( const sc_time& ) const; + bool operator > ( const sc_time& ) const; + bool operator >= ( const sc_time& ) const; + + + // arithmetic operators + + sc_time& operator += ( const sc_time& ); + sc_time& operator -= ( const sc_time& ); + + friend const sc_time operator + ( const sc_time&, const sc_time& ); + friend const sc_time operator - ( const sc_time&, const sc_time& ); + + sc_time& operator *= ( double ); + sc_time& operator /= ( double ); + sc_time& operator %= ( const sc_time& ); + + friend const sc_time operator * ( const sc_time&, double ); + friend const sc_time operator * ( double, const sc_time& ); + friend const sc_time operator / ( const sc_time&, double ); + friend double operator / ( const sc_time&, const sc_time& ); + friend const sc_time operator % ( const sc_time&, const sc_time& ); + + + // print function + + void print( ::std::ostream& os = std::cout ) const; + +private: + + value_type m_value; +}; + + +// print operator + +inline ::std::ostream& operator << ( ::std::ostream&, const sc_time& ); + + +// IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII + +// constructors + +inline +sc_time::sc_time() +: m_value( 0 ) +{} + +inline +sc_time::sc_time( const sc_time& t ) +: m_value( t.m_value ) +{} + + +// assignment operator + +inline +sc_time& +sc_time::operator = ( const sc_time& t ) +{ + m_value = t.m_value; + return *this; +} + + +// conversion functions + +inline +sc_time::value_type +sc_time::value() const // relative to the time resolution +{ + return m_value; +} + + +inline +double +sc_time::to_double() const // relative to the time resolution +{ + return sc_dt::uint64_to_double( m_value ); +} + + +// relational operators + +inline +bool +sc_time::operator == ( const sc_time& t ) const +{ + return ( m_value == t.m_value ); +} + +inline +bool +sc_time::operator != ( const sc_time& t ) const +{ + return ( m_value != t.m_value ); +} + +inline +bool +sc_time::operator < ( const sc_time& t ) const +{ + return ( m_value < t.m_value ); +} + +inline +bool +sc_time::operator <= ( const sc_time& t ) const +{ + return ( m_value <= t.m_value ); +} + +inline +bool +sc_time::operator > ( const sc_time& t ) const +{ + return ( m_value > t.m_value ); +} + +inline +bool +sc_time::operator >= ( const sc_time& t ) const +{ + return ( m_value >= t.m_value ); +} + + +// arithmetic operators + +inline +sc_time& +sc_time::operator += ( const sc_time& t ) +{ + m_value += t.m_value; + return *this; +} + +inline +sc_time& +sc_time::operator -= ( const sc_time& t ) +{ + m_value -= t.m_value; + return *this; +} + + +inline +const sc_time +operator + ( const sc_time& t1, const sc_time& t2 ) +{ + return sc_time( t1 ) += t2; +} + +inline +const sc_time +operator - ( const sc_time& t1, const sc_time& t2 ) +{ + return sc_time( t1 ) -= t2; +} + + +inline +sc_time& +sc_time::operator *= ( double d ) +{ + // linux bug workaround; don't change next two lines + volatile double tmp = sc_dt::uint64_to_double( m_value ) * d + 0.5; + m_value = SCAST<sc_dt::int64>( tmp ); + return *this; +} + +inline +sc_time& +sc_time::operator /= ( double d ) +{ + // linux bug workaround; don't change next two lines + volatile double tmp = sc_dt::uint64_to_double( m_value ) / d + 0.5; + m_value = SCAST<sc_dt::int64>( tmp ); + return *this; +} + +inline +sc_time& +sc_time::operator %= ( const sc_time& t ) +{ + m_value %= t.m_value; + return *this; +} + +inline +const sc_time +operator * ( const sc_time& t, double d ) +{ + sc_time tmp( t ); + return tmp *= d; +} + +inline +const sc_time +operator * ( double d, const sc_time& t ) +{ + sc_time tmp( t ); + return tmp *= d; +} + +inline +const sc_time +operator / ( const sc_time& t, double d ) +{ + sc_time tmp( t ); + return tmp /= d; +} + +inline +double +operator / ( const sc_time& t1, const sc_time& t2 ) +{ + return ( t1.to_double() / t2.to_double() ); +} + +inline +const sc_time +operator % ( const sc_time& t1, const sc_time& t2 ) +{ + sc_time tmp(t1); + return tmp %= t2; +} + +// print operator + +inline +::std::ostream& +operator << ( ::std::ostream& os, const sc_time& t ) +{ + t.print( os ); + return os; +} + + +// ---------------------------------------------------------------------------- +// STRUCT : sc_time_params +// +// Struct that holds the time resolution and default time unit. +// ---------------------------------------------------------------------------- + +struct sc_time_params +{ + double time_resolution; // in femto seconds + bool time_resolution_specified; + bool time_resolution_fixed; + + sc_time::value_type default_time_unit; // in time resolution + bool default_time_unit_specified; + + sc_time_params(); + ~sc_time_params(); +}; + + +// ---------------------------------------------------------------------------- + +extern const sc_time SC_ZERO_TIME; + + +// functions for accessing the time resolution and default time unit + +extern void sc_set_time_resolution( double, sc_time_unit ); +extern sc_time sc_get_time_resolution(); + +extern void sc_set_default_time_unit( double, sc_time_unit ); +extern sc_time sc_get_default_time_unit(); + +} // namespace sc_core + +#endif + +// $Log: sc_time.h,v $ +// Revision 1.5 2011/08/26 20:46:11 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.4 2011/02/18 20:27:14 acg +// Andy Goodrich: Updated Copyrights. +// +// Revision 1.3 2011/02/13 21:47:38 acg +// Andy Goodrich: update copyright notice. +// +// Revision 1.2 2008/05/22 17:06:27 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/05/08 18:02:06 acg +// Andy Goodrich: added David Long's forward declarations for friend +// functions, methods, and operators to keep the Microsoft compiler happy. +// +// Revision 1.3 2006/01/13 18:44:30 acg +// Added $Log to record CVS changes into the source. + +// Taf! diff --git a/ext/systemc/src/sysc/kernel/sc_ver.cpp b/ext/systemc/src/sysc/kernel/sc_ver.cpp new file mode 100644 index 000000000..9883cd3bc --- /dev/null +++ b/ext/systemc/src/sysc/kernel/sc_ver.cpp @@ -0,0 +1,228 @@ +/***************************************************************************** + + 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_ver.cpp -- copyright information. + + Original Author: Stan Y. Liao, Synopsys, Inc. + + CHANGE LOG AT THE END OF THE FILE + *****************************************************************************/ + +#include <cstddef> +#include <cstdlib> + +#define SC_DISABLE_API_VERSION_CHECK // for in-library sc_ver.h inclusion + +#include "sysc/kernel/sc_ver.h" +#include "sysc/kernel/sc_kernel_ids.h" +#include "sysc/utils/sc_iostream.h" +#include "sysc/utils/sc_report.h" + +using std::getenv; +using std::strcmp; +using std::cerr; +using std::endl; + +namespace sc_core { + + +static +const char systemc_version[] = + "SystemC " SC_VERSION " --- " __DATE__ " " __TIME__; + +const unsigned int sc_version_major = SC_VERSION_MAJOR; +const unsigned int sc_version_minor = SC_VERSION_MINOR; +const unsigned int sc_version_patch = SC_VERSION_PATCH; +const bool sc_is_prerelease = SC_IS_PRERELEASE; + +const std::string sc_version_originator = SC_VERSION_ORIGINATOR; +const std::string sc_version_release_date = SC_VERSION_RELEASE_DATE; +const std::string sc_version_prerelease = SC_VERSION_PRERELEASE; +const std::string sc_version_string = SC_VERSION; +const std::string sc_copyright_string = SC_COPYRIGHT; + +const char* +sc_copyright() +{ + return SC_COPYRIGHT; +} + + +const char* +sc_release() +{ + return SC_VERSION; +} + + +const char* +sc_version() +{ + return systemc_version; +} + + +#if !defined(SC_DISABLE_COPYRIGHT_MESSAGE) +# define SC_DISABLE_COPYRIGHT_MESSAGE 0 +#endif + +// ---------------------------------------------------------------------------- + +void +pln() +{ + static bool lnp = SC_DISABLE_COPYRIGHT_MESSAGE; + if ( lnp || getenv("SYSTEMC_DISABLE_COPYRIGHT_MESSAGE") != 0 ) + lnp = true; + if ( const char * lnp_env = getenv("SC_COPYRIGHT_MESSAGE") ) { + lnp = !strcmp( lnp_env, "DISABLE" ); + } + if( ! lnp ) { + + static const char indent[] = " "; + std::string line; + std::stringstream copyright; + + // temporary stream to print copyright line-wise with indentation + copyright << sc_copyright(); + + cerr << endl; + cerr << indent << sc_version() << endl; + while( getline( copyright, line ) ) + cerr << indent << line << endl; + + // regressions check point + + if( getenv( "SYSTEMC_REGRESSION" ) != 0 ) { + cerr << "SystemC Simulation" << endl; + } + + lnp = true; + } +} + +#define SC_API_PERFORM_CHECK_( Type, Name, Symbol ) \ + do { \ + static bool SC_CONCAT_UNDERSCORE_( Name, config_seen ) = false; \ + static Type SC_CONCAT_UNDERSCORE_( Name, config ); \ + if( ! SC_CONCAT_UNDERSCORE_( Name, config_seen ) ) { \ + SC_CONCAT_UNDERSCORE_( Name, config_seen ) = true; \ + SC_CONCAT_UNDERSCORE_( Name, config ) = Name; \ + } else if( SC_CONCAT_UNDERSCORE_( Name, config ) != Name ) { \ + SC_REPORT_FATAL( SC_ID_INCONSISTENT_API_CONFIG_, Symbol ); \ + } \ + } while( false ) + +// THIS CONSTRUCTOR ROOTS OUT OLD OBJECTS AT LINK TIME +// +// Each source file which includes sc_ver.h for this SystemC version +// will have a static instance of the class sc_api_version_XXX defined +// in it. That object instanciation will cause the constructor below +// to be invoked. If the version of the SystemC being linked against +// does not contain the constructor below a linkage error will occur. +// +// Some preprocessor switches need to be consistent between the application +// and the library (e.g. if sizes of classes are affected or other parts of +// the ABI are affected). (Some of) these are checked here at link-time as +// well, by setting template parameters to sc_api_version_XXX, while only +// one variant is defined here. +// +// Some preprocessor switches need to be consistent between different +// translation units of an application. Those can't be easily checked +// during link-time. Instead, perform a check during run-time by +// passing the value to the constructor of the api_version_check object. + +// const int DEBUG_SYSTEMC_CHECK_ = 1; +const int SC_DISABLE_VIRTUAL_BIND_CHECK_ = 1; + +template<> +SC_API_VERSION_STRING +< +// & DEBUG_SYSTEMC_CHECK_, + & SC_DISABLE_VIRTUAL_BIND_CHECK_ +> +::SC_API_VERSION_STRING +( + sc_writer_policy default_writer_policy +) +{ + SC_API_PERFORM_CHECK_( sc_writer_policy + , default_writer_policy + , "SC_DEFAULT_WRITER_POLICY" ); +} + +} // namespace sc_core + +// $Log: sc_ver.cpp,v $ +// Revision 1.14 2011/08/26 21:56:55 acg +// Torsten Maehne: use usings rather than absolute namespace addressing. +// +// Revision 1.13 2011/08/26 20:46:11 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.12 2011/07/25 10:20:34 acg +// Andy Goodrich: check in aftermath of call to automake. +// +// Revision 1.11 2011/07/02 12:55:19 acg +// Andy Goodrich: automake refresh. +// +// Revision 1.10 2011/07/01 18:49:07 acg +// Andy Goodrich: moved pln() from sc_simcontext.cpp to sc_ver.cpp. +// +// Revision 1.9 2011/07/01 18:33:08 acg +// Andy Goodrich: changes for IEEE 1666, removal of macros and use of them. +// +// Revision 1.8 2011/04/08 18:27:53 acg +// Andy Goodrich: respin of the PoC. +// +// Revision 1.7 2011/04/05 20:50:57 acg +// Andy Goodrich: +// (1) changes to make sure that event(), posedge() and negedge() only +// return true if the clock has not moved. +// (2) fixes for method self-resumes. +// (3) added SC_PRERELEASE_VERSION +// (4) removed kernel events from the object hierarchy, added +// sc_hierarchy_name_exists(). +// +// Revision 1.6 2011/02/18 20:27:14 acg +// Andy Goodrich: Updated Copyrights. +// +// Revision 1.5 2011/02/13 21:47:38 acg +// Andy Goodrich: update copyright notice. +// +// Revision 1.4 2011/01/18 20:10:45 acg +// Andy Goodrich: changes for IEEE1666_2011 semantics. +// +// Revision 1.3 2010/11/20 17:10:57 acg +// Andy Goodrich: reset processing changes for new IEEE 1666 standard. +// +// Revision 1.2 2008/05/22 17:06:27 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.3 2006/01/13 18:44:30 acg +// Added $Log to record CVS changes into the source. +// + +// Taf! diff --git a/ext/systemc/src/sysc/kernel/sc_ver.h b/ext/systemc/src/sysc/kernel/sc_ver.h new file mode 100644 index 000000000..34112f9f8 --- /dev/null +++ b/ext/systemc/src/sysc/kernel/sc_ver.h @@ -0,0 +1,186 @@ +/***************************************************************************** + + 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_ver.h -- Version and copyright information. + + Original Author: Stan Y. Liao, Synopsys, Inc. + + NO AUTOMATIC CHANGE LOG IS GENERATED, EXPLICIT CHANGE LOG AT END OF FILE + *****************************************************************************/ + + +#ifndef SC_VER_H +#define SC_VER_H + +#include "sysc/kernel/sc_macros.h" // SC_CONCAT_UNDERSCORE_ + // SC_STRINGIFY_HELPER_ +#include "sysc/communication/sc_writer_policy.h" // SC_DEFAULT_WRITER_POLICY + +#include <string> + +namespace sc_core { + +extern const char* sc_copyright(); +extern const char* sc_release(); +extern const char* sc_version(); + +extern const unsigned int sc_version_major; +extern const unsigned int sc_version_minor; +extern const unsigned int sc_version_patch; + +extern const std::string sc_version_originator; +extern const std::string sc_version_release_date; +extern const std::string sc_version_prerelease; +extern const bool sc_is_prerelease; +extern const std::string sc_version_string; +extern const std::string sc_copyright_string; + +#define SYSTEMC_2_3_1 + +#define SYSTEMC_VERSION 20140417 +#define SC_VERSION_ORIGINATOR "Accellera" +#define SC_VERSION_MAJOR 2 +#define SC_VERSION_MINOR 3 +#define SC_VERSION_PATCH 1 +#define SC_IS_PRERELEASE 0 + +/// compliancy with IEEE 1666-2011 (see 8.6.5) +#define IEEE_1666_SYSTEMC 201101L + +#define SC_COPYRIGHT \ + "Copyright (c) 1996-2014 by all Contributors,\n" \ + "ALL RIGHTS RESERVED\n" + + +#define SC_VERSION_RELEASE_DATE \ + SC_STRINGIFY_HELPER_( SYSTEMC_VERSION ) + +#if ( SC_IS_PRERELEASE == 1 ) +# define SC_VERSION_PRERELEASE "pub_rev" +# define SC_VERSION \ + SC_STRINGIFY_HELPER_( SC_VERSION_MAJOR.SC_VERSION_MINOR.SC_VERSION_PATCH ) \ + "_" SC_VERSION_PRERELEASE "_" SC_VERSION_RELEASE_DATE \ + "-" SC_VERSION_ORIGINATOR +#else +# define SC_VERSION_PRERELEASE "" // nothing +# define SC_VERSION \ + SC_STRINGIFY_HELPER_( SC_VERSION_MAJOR.SC_VERSION_MINOR.SC_VERSION_PATCH ) \ + "-" SC_VERSION_ORIGINATOR +#endif + +// THIS CLASS AND STATIC INSTANCE BELOW DETECTS BAD REV OBJECTS AT LINK TIME +// +// Each source file which includes this file for the current SystemC version +// will have a static instance of the class sc_api_version_XXX defined +// in it. That object instance will cause the constructor below +// to be invoked. If the version of the SystemC being linked against +// does not contain the constructor below a linkage error will occur. + +#define SC_API_VERSION_STRING \ + SC_CONCAT_UNDERSCORE_( sc_api_version, \ + SC_CONCAT_UNDERSCORE_( SC_VERSION_MAJOR, \ + SC_CONCAT_UNDERSCORE_( SC_VERSION_MINOR, \ + SC_VERSION_PATCH ) ) ) + +// explicitly avoid macro expansion +#define SC_API_DEFINED_( Symbol ) \ + Symbol ## _DEFINED_ +#define SC_API_UNDEFINED_( Symbol ) \ + Symbol ## _UNDEFINED_ + +// Some preprocessor switches need to be consistent between the application +// and the library (e.g. if sizes of classes are affected or other parts of +// the ABI are affected). (Some of) these are checked here at link-time as +// well, by setting template parameters to sc_api_version_XXX, while only +// one variant is defined in sc_ver.cpp. + +#if 0 // don't enforce check of DEBUG_SYSTEMC for now +// DEBUG_SYSTEMC +#if defined( DEBUG_SYSTEMC ) +# define DEBUG_SYSTEMC_CHECK_ \ + SC_CONFIG_DEFINED_(DEBUG_SYSTEMC) +#else +# define DEBUG_SYSTEMC_CHECK_ \ + SC_CONFIG_UNDEFINED_(DEBUG_SYSTEMC) +#endif +extern const int DEBUG_SYSTEMC_CHECK_; +#endif + +// SC_DISABLE_VIRTUAL_BIND +#if defined( SC_DISABLE_VIRTUAL_BIND ) +# define SC_DISABLE_VIRTUAL_BIND_CHECK_ \ + SC_API_DEFINED_(SC_DISABLE_VIRTUAL_BIND) +#else +# define SC_DISABLE_VIRTUAL_BIND_CHECK_ \ + SC_API_UNDEFINED_(SC_DISABLE_VIRTUAL_BIND) +#endif +extern const int SC_DISABLE_VIRTUAL_BIND_CHECK_; + +// Some preprocessor switches need to be consistent between different +// translation units of an application. Those can't be easily checked +// during link-time. Instead, perform a check during run-time by +// passing the value to the constructor of the api_version_check object. + +// Note: Template and constructor parameters are not passed as default +// values to avoid ODR violations in the check itself. + +template // use pointers for more verbose error messages +< +// const int * DebugSystemC, + const int * DisableVirtualBind +> +struct SC_API_VERSION_STRING +{ + SC_API_VERSION_STRING + ( + // SC_DEFAULT_WRITER_POLICY + sc_writer_policy default_writer_policy + ); +}; + +#if !defined( SC_DISABLE_API_VERSION_CHECK ) // disabled in sc_ver.cpp +static +SC_API_VERSION_STRING +< +// & DEBUG_SYSTEMC_CHECK_, + & SC_DISABLE_VIRTUAL_BIND_CHECK_ +> +api_version_check +( + SC_DEFAULT_WRITER_POLICY +); +#endif // SC_DISABLE_API_VERSION_CHECK + +//#undef SC_API_DEFINED_ +//#undef SC_API_UNDEFINED_ + +} // namespace sc_core + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affiliation, date and + changes you are making here. + + Name, Affiliation, Date: + Description of Modification: + + *****************************************************************************/ +#endif diff --git a/ext/systemc/src/sysc/kernel/sc_wait.cpp b/ext/systemc/src/sysc/kernel/sc_wait.cpp new file mode 100644 index 000000000..9c9f2bdfb --- /dev/null +++ b/ext/systemc/src/sysc/kernel/sc_wait.cpp @@ -0,0 +1,446 @@ +/***************************************************************************** + + 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_wait.cpp -- Wait() and related functions. + + Original Author: Stan Y. Liao, Synopsys, Inc. + Martin Janssen, Synopsys, Inc. + + CHANGE LOG AT THE END OF THE FILE + *****************************************************************************/ + + +#include "sysc/kernel/sc_except.h" +#include "sysc/kernel/sc_kernel_ids.h" +#include "sysc/kernel/sc_cthread_process.h" +#include "sysc/kernel/sc_thread_process.h" +#include "sysc/kernel/sc_simcontext_int.h" +#include "sysc/kernel/sc_wait.h" +#include "sysc/utils/sc_utils_ids.h" + +namespace sc_core { + +// static sensitivity for SC_THREADs and SC_CTHREADs + +void warn_cthread_wait() +{ + static bool warn_wait = true; + if ( warn_wait ) + { + warn_wait = false; + SC_REPORT_INFO(SC_ID_IEEE_1666_DEPRECATION_, + "all waits except wait() and wait(N)\n" \ + " are deprecated for SC_CTHREAD, " \ + "use an SC_THREAD instead"); + } +} + +void +wait( sc_simcontext* simc ) +{ + sc_curr_proc_handle cpi = simc->get_curr_proc_info(); + switch( cpi->kind ) { + case SC_THREAD_PROC_: + case SC_CTHREAD_PROC_: { + RCAST<sc_cthread_handle>( cpi->process_handle )->wait_cycles(); + break; + } + default: + SC_REPORT_ERROR( SC_ID_WAIT_NOT_ALLOWED_, "\n " + "in SC_METHODs use next_trigger() instead" ); + break; + } +} + +// dynamic sensitivity for SC_THREADs and SC_CTHREADs + +void +wait( const sc_event& e, sc_simcontext* simc ) +{ + sc_curr_proc_handle cpi = simc->get_curr_proc_info(); + switch( cpi->kind ) { + case SC_THREAD_PROC_: { + RCAST<sc_thread_handle>( cpi->process_handle )->wait( e ); + break; + } + case SC_CTHREAD_PROC_: { + warn_cthread_wait(); + sc_cthread_handle cthread_h = + RCAST<sc_cthread_handle>( cpi->process_handle ); + cthread_h->wait( e ); + cthread_h->wait_cycles(); + break; + } + default: + SC_REPORT_ERROR( SC_ID_WAIT_NOT_ALLOWED_, "\n " + "in SC_METHODs use next_trigger() instead" ); + break; + } +} + +void +wait( const sc_event_or_list& el, sc_simcontext* simc ) +{ + sc_curr_proc_handle cpi = simc->get_curr_proc_info(); + switch( cpi->kind ) { + case SC_THREAD_PROC_: { + RCAST<sc_thread_handle>( cpi->process_handle )->wait( el ); + break; + } + case SC_CTHREAD_PROC_: { + warn_cthread_wait(); + SC_REPORT_INFO(SC_ID_IEEE_1666_DEPRECATION_, + "wait(event_list) is deprecated for SC_CTHREAD, use SC_THREAD"); + sc_cthread_handle cthread_h = + RCAST<sc_cthread_handle>( cpi->process_handle ); + cthread_h->wait( el ); + cthread_h->wait_cycles(); + break; + } + default: + SC_REPORT_ERROR( SC_ID_WAIT_NOT_ALLOWED_, "\n " + "in SC_METHODs use next_trigger() instead" ); + break; + } +} + +void +wait( const sc_event_and_list& el, sc_simcontext* simc ) +{ + sc_curr_proc_handle cpi = simc->get_curr_proc_info(); + switch( cpi->kind ) { + case SC_THREAD_PROC_: { + RCAST<sc_thread_handle>( cpi->process_handle )->wait( el ); + break; + } + case SC_CTHREAD_PROC_: { + warn_cthread_wait(); + sc_cthread_handle cthread_h = + RCAST<sc_cthread_handle>( cpi->process_handle ); + cthread_h->wait( el ); + cthread_h->wait_cycles(); + break; + } + default: + SC_REPORT_ERROR( SC_ID_WAIT_NOT_ALLOWED_, "\n " + "in SC_METHODs use next_trigger() instead" ); + break; + } +} + +void +wait( const sc_time& t, sc_simcontext* simc ) +{ + sc_curr_proc_handle cpi = simc->get_curr_proc_info(); + switch( cpi->kind ) { + case SC_THREAD_PROC_: { + RCAST<sc_thread_handle>( cpi->process_handle )->wait( t ); + break; + } + case SC_CTHREAD_PROC_: { + warn_cthread_wait(); + sc_cthread_handle cthread_h = + RCAST<sc_cthread_handle>( cpi->process_handle ); + cthread_h->wait( t ); + cthread_h->wait_cycles(); + break; + } + default: + SC_REPORT_ERROR( SC_ID_WAIT_NOT_ALLOWED_, "\n " + "in SC_METHODs use next_trigger() instead" ); + break; + } +} + +void +wait( const sc_time& t, const sc_event& e, sc_simcontext* simc ) +{ + sc_curr_proc_handle cpi = simc->get_curr_proc_info(); + switch( cpi->kind ) { + case SC_THREAD_PROC_: { + RCAST<sc_thread_handle>( cpi->process_handle )->wait( t, e ); + break; + } + case SC_CTHREAD_PROC_: { + warn_cthread_wait(); + sc_cthread_handle cthread_h = + RCAST<sc_cthread_handle>( cpi->process_handle ); + cthread_h->wait( t, e ); + cthread_h->wait_cycles(); + break; + } + default: + SC_REPORT_ERROR( SC_ID_WAIT_NOT_ALLOWED_, "\n " + "in SC_METHODs use next_trigger() instead" ); + break; + } +} + +void +wait( const sc_time& t, const sc_event_or_list& el, sc_simcontext* simc ) +{ + sc_curr_proc_handle cpi = simc->get_curr_proc_info(); + switch( cpi->kind ) { + case SC_THREAD_PROC_: { + RCAST<sc_thread_handle>( cpi->process_handle )->wait( t, el ); + break; + } + case SC_CTHREAD_PROC_: { + warn_cthread_wait(); + sc_cthread_handle cthread_h = + RCAST<sc_cthread_handle>( cpi->process_handle ); + cthread_h->wait( t, el ); + cthread_h->wait_cycles(); + break; + } + default: + SC_REPORT_ERROR( SC_ID_WAIT_NOT_ALLOWED_, "\n " + "in SC_METHODs use next_trigger() instead" ); + break; + } +} + +void +wait( const sc_time& t, const sc_event_and_list& el, sc_simcontext* simc ) +{ + sc_curr_proc_handle cpi = simc->get_curr_proc_info(); + switch( cpi->kind ) { + case SC_THREAD_PROC_: { + RCAST<sc_thread_handle>( cpi->process_handle )->wait( t, el ); + break; + } + case SC_CTHREAD_PROC_: { + warn_cthread_wait(); + sc_cthread_handle cthread_h = + RCAST<sc_cthread_handle>( cpi->process_handle ); + cthread_h->wait( t, el ); + cthread_h->wait_cycles(); + break; + } + default: + SC_REPORT_ERROR( SC_ID_WAIT_NOT_ALLOWED_, "\n " + "in SC_METHODs use next_trigger() instead" ); + break; + } +} + + +// static sensitivity for SC_METHODs + +void +next_trigger( sc_simcontext* simc ) +{ + sc_curr_proc_handle cpi = simc->get_curr_proc_info(); + if( cpi->kind == SC_METHOD_PROC_ ) { + RCAST<sc_method_handle>( cpi->process_handle )->clear_trigger(); + } else { + SC_REPORT_ERROR( SC_ID_NEXT_TRIGGER_NOT_ALLOWED_, "\n " + "in SC_THREADs and SC_CTHREADs use wait() instead" ); + } +} + + +// dynamic sensitivity for SC_METHODs + +void +next_trigger( const sc_event& e, sc_simcontext* simc ) +{ + sc_curr_proc_handle cpi = simc->get_curr_proc_info(); + if( cpi->kind == SC_METHOD_PROC_ ) { + RCAST<sc_method_handle>( cpi->process_handle )->next_trigger( e ); + } else { + SC_REPORT_ERROR( SC_ID_NEXT_TRIGGER_NOT_ALLOWED_, "\n " + "in SC_THREADs and SC_CTHREADs use wait() instead" ); + } +} + +void +next_trigger( const sc_event_or_list& el, sc_simcontext* simc ) +{ + sc_curr_proc_handle cpi = simc->get_curr_proc_info(); + if( cpi->kind == SC_METHOD_PROC_ ) { + RCAST<sc_method_handle>( cpi->process_handle )->next_trigger( el ); + } else { + SC_REPORT_ERROR( SC_ID_NEXT_TRIGGER_NOT_ALLOWED_, "\n " + "in SC_THREADs and SC_CTHREADs use wait() instead" ); + } +} + +void +next_trigger( const sc_event_and_list& el, sc_simcontext* simc ) +{ + sc_curr_proc_handle cpi = simc->get_curr_proc_info(); + if( cpi->kind == SC_METHOD_PROC_ ) { + RCAST<sc_method_handle>( cpi->process_handle )->next_trigger( el ); + } else { + SC_REPORT_ERROR( SC_ID_NEXT_TRIGGER_NOT_ALLOWED_, "\n " + "in SC_THREADs and SC_CTHREADs use wait() instead" ); + } +} + +void +next_trigger( const sc_time& t, sc_simcontext* simc ) +{ + sc_curr_proc_handle cpi = simc->get_curr_proc_info(); + if( cpi->kind == SC_METHOD_PROC_ ) { + RCAST<sc_method_handle>( cpi->process_handle )->next_trigger( t ); + } else { + SC_REPORT_ERROR( SC_ID_NEXT_TRIGGER_NOT_ALLOWED_, "\n " + "in SC_THREADs and SC_CTHREADs use wait() instead" ); + } +} + +void +next_trigger( const sc_time& t, const sc_event& e, sc_simcontext* simc ) +{ + sc_curr_proc_handle cpi = simc->get_curr_proc_info(); + if( cpi->kind == SC_METHOD_PROC_ ) { + RCAST<sc_method_handle>( cpi->process_handle )->next_trigger( t, e ); + } else { + SC_REPORT_ERROR( SC_ID_NEXT_TRIGGER_NOT_ALLOWED_, "\n " + "in SC_THREADs and SC_CTHREADs use wait() instead" ); + } +} + +void +next_trigger( const sc_time& t, const sc_event_or_list& el, sc_simcontext* simc) +{ + sc_curr_proc_handle cpi = simc->get_curr_proc_info(); + if( cpi->kind == SC_METHOD_PROC_ ) { + RCAST<sc_method_handle>( cpi->process_handle )->next_trigger( t, el ); + } else { + SC_REPORT_ERROR( SC_ID_NEXT_TRIGGER_NOT_ALLOWED_, "\n " + "in SC_THREADs and SC_CTHREADs use wait() instead" ); + } +} + +void +next_trigger(const sc_time& t, const sc_event_and_list& el, sc_simcontext* simc) +{ + sc_curr_proc_handle cpi = simc->get_curr_proc_info(); + if( cpi->kind == SC_METHOD_PROC_ ) { + RCAST<sc_method_handle>( cpi->process_handle )->next_trigger( t, el ); + } else { + SC_REPORT_ERROR( SC_ID_NEXT_TRIGGER_NOT_ALLOWED_, "\n " + "in SC_THREADs and SC_CTHREADs use wait() instead" ); + } +} + + +// for SC_METHODs and SC_THREADs and SC_CTHREADs + +bool +timed_out( sc_simcontext* simc ) +{ + static bool warn_timed_out=true; + if ( warn_timed_out ) + { + warn_timed_out = false; + SC_REPORT_INFO(SC_ID_IEEE_1666_DEPRECATION_, + "timed_out() function is deprecated" ); + } + + sc_curr_proc_handle cpi = simc->get_curr_proc_info(); + return cpi->process_handle->timed_out(); +} + + + +// misc. + +void +sc_set_location( const char* file, int lineno, sc_simcontext* simc ) +{ + sc_curr_proc_handle cpi = simc->get_curr_proc_info(); + sc_process_b* handle = cpi->process_handle; + handle->file = file; + handle->lineno = lineno; +} + +} // namespace sc_core + +/* +$Log: sc_wait.cpp,v $ +Revision 1.6 2011/08/26 20:46:11 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.5 2011/02/18 20:27:14 acg + Andy Goodrich: Updated Copyrights. + +Revision 1.4 2011/02/13 21:47:38 acg + Andy Goodrich: update copyright notice. + +Revision 1.3 2011/01/18 20:10:45 acg + Andy Goodrich: changes for IEEE1666_2011 semantics. + +Revision 1.2 2008/05/22 17:06:27 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.7 2006/02/02 20:20:39 acg + Andy Goodrich: warnings for SC_THREAD waits. + +Revision 1.6 2006/02/01 01:36:54 acg + Andy Goodrich: addition of deprecation comments for SC_CTHREAD waits other + than wait() and wait(N). + +Revision 1.5 2006/01/31 22:17:40 acg + Andy Goodrich: added deprecation warnings for SC_CTHREAD waits other than + wait() and wait(N). + +Revision 1.4 2006/01/25 00:31:20 acg + Andy Goodrich: Changed over to use a standard message id of + SC_ID_IEEE_1666_DEPRECATION for all deprecation messages. + +Revision 1.3 2006/01/24 20:49:05 acg +Andy Goodrich: changes to remove the use of deprecated features within the +simulator, and to issue warning messages when deprecated features are used. + +Revision 1.2 2006/01/03 23:18:45 acg +Changed copyright to include 2006. + +Revision 1.1.1.1 2005/12/19 23:16:44 acg +First check in of SystemC 2.1 into its own archive. + +Revision 1.10 2005/09/02 19:03:30 acg +Changes for dynamic processes. Removal of lambda support. + +Revision 1.9 2005/07/30 03:45:05 acg +Changes from 2.1, including changes for sc_process_handle. + +Revision 1.8 2005/04/04 00:16:07 acg +Changes for directory name change to sys from systemc. +Changes for sc_string going to std::string. +Changes for sc_pvector going to std::vector. +Changes for reference pools for bit and part selections. +Changes for const sc_concatref support. + +Revision 1.5 2004/09/27 20:49:10 acg +Andy Goodrich, Forte Design Systems, Inc. + - Added a $Log comment so that CVS checkin comments appear in the + checkout source. + +*/ + +// Taf! diff --git a/ext/systemc/src/sysc/kernel/sc_wait.h b/ext/systemc/src/sysc/kernel/sc_wait.h new file mode 100644 index 000000000..f598cf4bb --- /dev/null +++ b/ext/systemc/src/sysc/kernel/sc_wait.h @@ -0,0 +1,277 @@ +/***************************************************************************** + + 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_wait.h -- Wait() and related functions. + + Original Author: Stan Y. Liao, Synopsys, Inc. + Martin Janssen, Synopsys, Inc. + + CHANGE LOG AT THE END OF THE FILE + *****************************************************************************/ + +#ifndef SC_WAIT_H +#define SC_WAIT_H + + +#include "sysc/kernel/sc_simcontext.h" + +namespace sc_core { + +class sc_event; +class sc_event_and_list; +class sc_event_or_list; +class sc_simcontext; + +extern sc_simcontext* sc_get_curr_simcontext(); + +// static sensitivity for SC_THREADs and SC_CTHREADs + +extern +void +wait( sc_simcontext* = sc_get_curr_simcontext() ); + + +// dynamic sensitivity for SC_THREADs and SC_CTHREADs + +extern +void +wait( const sc_event&, + sc_simcontext* = sc_get_curr_simcontext() ); + +extern +void +wait( const sc_event_or_list&, + sc_simcontext* = sc_get_curr_simcontext() ); + +extern +void +wait( const sc_event_and_list&, + sc_simcontext* = sc_get_curr_simcontext() ); + +extern +void +wait( const sc_time&, + sc_simcontext* = sc_get_curr_simcontext() ); + +inline +void +wait( double v, sc_time_unit tu, + sc_simcontext* simc = sc_get_curr_simcontext() ) +{ + wait( sc_time( v, tu, simc ), simc ); +} + +extern +void +wait( const sc_time&, + const sc_event&, + sc_simcontext* = sc_get_curr_simcontext() ); + +inline +void +wait( double v, sc_time_unit tu, + const sc_event& e, + sc_simcontext* simc = sc_get_curr_simcontext() ) +{ + wait( sc_time( v, tu, simc ), e, simc ); +} + +extern +void +wait( const sc_time&, + const sc_event_or_list&, + sc_simcontext* = sc_get_curr_simcontext() ); + +inline +void +wait( double v, sc_time_unit tu, + const sc_event_or_list& el, + sc_simcontext* simc = sc_get_curr_simcontext() ) +{ + wait( sc_time( v, tu, simc ), el, simc ); +} + +extern +void +wait( const sc_time&, + const sc_event_and_list&, + sc_simcontext* = sc_get_curr_simcontext() ); + +inline +void +wait( double v, sc_time_unit tu, + const sc_event_and_list& el, + sc_simcontext* simc = sc_get_curr_simcontext() ) +{ + wait( sc_time( v, tu, simc ), el, simc ); +} + + +// static sensitivity for SC_METHODs + +extern +void +next_trigger( sc_simcontext* = sc_get_curr_simcontext() ); + + +// dynamic sensitivity for SC_METHODs + +extern +void +next_trigger( const sc_event&, + sc_simcontext* = sc_get_curr_simcontext() ); + +extern +void +next_trigger( const sc_event_or_list&, + sc_simcontext* = sc_get_curr_simcontext() ); + +extern +void +next_trigger( const sc_event_and_list&, + sc_simcontext* = sc_get_curr_simcontext() ); + +extern +void +next_trigger( const sc_time&, + sc_simcontext* = sc_get_curr_simcontext() ); + +inline +void +next_trigger( double v, sc_time_unit tu, + sc_simcontext* simc = sc_get_curr_simcontext() ) +{ + next_trigger( sc_time( v, tu, simc ), simc ); +} + +extern +void +next_trigger( const sc_time&, + const sc_event&, + sc_simcontext* = sc_get_curr_simcontext() ); + +inline +void +next_trigger( double v, sc_time_unit tu, + const sc_event& e, + sc_simcontext* simc = sc_get_curr_simcontext() ) +{ + next_trigger( sc_time( v, tu, simc ), e, simc ); +} + +extern +void +next_trigger( const sc_time&, + const sc_event_or_list&, + sc_simcontext* = sc_get_curr_simcontext() ); + +inline +void +next_trigger( double v, sc_time_unit tu, + const sc_event_or_list& el, + sc_simcontext* simc = sc_get_curr_simcontext() ) +{ + next_trigger( sc_time( v, tu, simc ), el, simc ); +} + +extern +void +next_trigger( const sc_time&, + const sc_event_and_list&, + sc_simcontext* = sc_get_curr_simcontext() ); + +inline +void +next_trigger( double v, sc_time_unit tu, + const sc_event_and_list& el, + sc_simcontext* simc = sc_get_curr_simcontext() ) +{ + next_trigger( sc_time( v, tu, simc ), el, simc ); +} + + +// for SC_METHODs and SC_THREADs and SC_CTHREADs + +extern +bool +timed_out( sc_simcontext* = sc_get_curr_simcontext() ); + +// misc. + +extern +void +sc_set_location( const char*, + int, + sc_simcontext* = sc_get_curr_simcontext() ); + +} // namespace sc_core + +/* +$Log: sc_wait.h,v $ +Revision 1.6 2011/08/26 20:46:11 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.5 2011/02/18 20:27:14 acg + Andy Goodrich: Updated Copyrights. + +Revision 1.4 2011/02/13 21:47:38 acg + Andy Goodrich: update copyright notice. + +Revision 1.3 2011/01/18 20:10:45 acg + Andy Goodrich: changes for IEEE1666_2011 semantics. + +Revision 1.2 2008/05/22 17:06:27 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.2 2006/01/03 23:18:45 acg +Changed copyright to include 2006. + +Revision 1.1.1.1 2005/12/19 23:16:44 acg +First check in of SystemC 2.1 into its own archive. + +Revision 1.10 2005/07/30 03:45:05 acg +Changes from 2.1, including changes for sc_process_handle. + +Revision 1.9 2005/04/04 00:16:08 acg +Changes for directory name change to sys from systemc. +Changes for sc_string going to std::string. +Changes for sc_pvector going to std::vector. +Changes for reference pools for bit and part selections. +Changes for const sc_concatref support. + +Revision 1.6 2004/10/13 18:13:22 acg +sc_ver.h - updated version number. sc_wait.h remove inclusion of +sysc/kernel/sc_event.h because it is not necessary. + +Revision 1.5 2004/09/27 20:49:10 acg +Andy Goodrich, Forte Design Systems, Inc. + - Added a $Log comment so that CVS checkin comments appear in the + checkout source. + +*/ + +#endif + +// Taf! diff --git a/ext/systemc/src/sysc/kernel/sc_wait_cthread.cpp b/ext/systemc/src/sysc/kernel/sc_wait_cthread.cpp new file mode 100644 index 000000000..4dee96ed7 --- /dev/null +++ b/ext/systemc/src/sysc/kernel/sc_wait_cthread.cpp @@ -0,0 +1,169 @@ +/***************************************************************************** + + 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_wait_cthread.cpp -- Wait() and related functions for SC_CTHREADs. + + Original Author: Stan Y. Liao, Synopsys, Inc. + Martin Janssen, Synopsys, Inc. + + CHANGE LOG AT THE END OF THE FILE + *****************************************************************************/ + + + +#include "sysc/kernel/sc_kernel_ids.h" +#include "sysc/kernel/sc_cthread_process.h" +#include "sysc/kernel/sc_simcontext_int.h" +#include "sysc/kernel/sc_wait_cthread.h" +#include "sysc/communication/sc_port.h" +#include "sysc/kernel/sc_wait.h" +namespace sc_core +{ + +// for SC_CTHREADs + +void +halt( sc_simcontext* simc ) +{ + sc_curr_proc_handle cpi = simc->get_curr_proc_info(); + switch( cpi->kind ) { + case SC_CTHREAD_PROC_: { + RCAST<sc_cthread_handle>( cpi->process_handle )->wait_halt(); + break; + } + default: + SC_REPORT_ERROR( SC_ID_HALT_NOT_ALLOWED_, 0 ); + break; + } +} + + +void +wait( int n, sc_simcontext* simc ) +{ + sc_curr_proc_handle cpi = simc->get_curr_proc_info(); + if( n <= 0 ) { + char msg[BUFSIZ]; + std::sprintf( msg, "n = %d", n ); + SC_REPORT_ERROR( SC_ID_WAIT_N_INVALID_, msg ); + } + switch( cpi->kind ) { + case SC_THREAD_PROC_: + case SC_CTHREAD_PROC_: + RCAST<sc_cthread_handle>( cpi->process_handle )->wait_cycles( n ); + break; + default: + SC_REPORT_ERROR( SC_ID_WAIT_NOT_ALLOWED_, "\n " + "in SC_METHODs use next_trigger() instead" ); + break; + } +} + + +void +at_posedge( const sc_signal_in_if<bool>& s, sc_simcontext* simc ) +{ + if( s.read() == true ) + do { wait(simc); } while ( s.read() == true ); + do { wait(simc); } while ( s.read() == false ); +} + +void +at_posedge( const sc_signal_in_if<sc_dt::sc_logic>& s, sc_simcontext* simc ) +{ + if( s.read() == '1' ) + do { wait(simc); } while ( s.read() == '1' ); + do { wait(simc); } while ( s.read() == '0' ); +} + +void +at_negedge( const sc_signal_in_if<bool>& s, sc_simcontext* simc ) +{ + if( s.read() == false ) + do { wait(simc); } while ( s.read() == false ); + do { wait(simc); } while ( s.read() == true ); +} + +void +at_negedge( const sc_signal_in_if<sc_dt::sc_logic>& s, sc_simcontext* simc ) +{ + if( s.read() == '0' ) + do { wait(simc); } while ( s.read() == '0' ); + do { wait(simc); } while ( s.read() == '1' ); +} + + +} // namespace sc_core + +/* +$Log: sc_wait_cthread.cpp,v $ +Revision 1.6 2011/08/26 20:46:11 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.5 2011/02/18 20:27:14 acg + Andy Goodrich: Updated Copyrights. + +Revision 1.4 2011/02/13 21:47:38 acg + Andy Goodrich: update copyright notice. + +Revision 1.3 2009/10/14 19:07:42 acg + Andy Goodrich: added an error message for wait(n) being called from an + SC_METHOD. + +Revision 1.2 2008/05/22 17:06:27 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.3 2006/03/13 20:26:51 acg + Andy Goodrich: Addition of forward class declarations, e.g., + sc_reset, to keep gcc 4.x happy. + +Revision 1.2 2006/01/03 23:18:45 acg +Changed copyright to include 2006. + +Revision 1.1.1.1 2005/12/19 23:16:44 acg +First check in of SystemC 2.1 into its own archive. + +Revision 1.10 2005/09/15 23:02:18 acg +Added std:: prefix to appropriate methods and types to get around +issues with the Edison Front End. + +Revision 1.9 2005/09/02 19:03:30 acg +Changes for dynamic processes. Removal of lambda support. + +Revision 1.8 2005/04/04 00:16:08 acg +Changes for directory name change to sys from systemc. +Changes for sc_string going to std::string. +Changes for sc_pvector going to std::vector. +Changes for reference pools for bit and part selections. +Changes for const sc_concatref support. + +Revision 1.5 2004/09/27 20:49:10 acg +Andy Goodrich, Forte Design Systems, Inc. + - Added a $Log comment so that CVS checkin comments appear in the + checkout source. + +*/ + +// Taf! diff --git a/ext/systemc/src/sysc/kernel/sc_wait_cthread.h b/ext/systemc/src/sysc/kernel/sc_wait_cthread.h new file mode 100644 index 000000000..a04bfecc1 --- /dev/null +++ b/ext/systemc/src/sysc/kernel/sc_wait_cthread.h @@ -0,0 +1,126 @@ +/***************************************************************************** + + 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_wait_cthread.h -- Wait() and related functions for SC_CTHREADs. + + Original Author: Stan Y. Liao, Synopsys, Inc. + Martin Janssen, Synopsys, Inc. + + CHANGE LOG AT THE END OF THE FILE + *****************************************************************************/ + + +#ifndef SC_WAIT_CTHREAD_H +#define SC_WAIT_CTHREAD_H + + +#include "sysc/kernel/sc_simcontext.h" +#include "sysc/datatypes/bit/sc_logic.h" +#include "sysc/communication/sc_signal_ifs.h" + + +namespace sc_core +{ + +// for SC_CTHREADs + +extern +void +halt( sc_simcontext* = sc_get_curr_simcontext() ); + + +extern +void +wait( int, + sc_simcontext* = sc_get_curr_simcontext() ); + + +extern +void +at_posedge( const sc_signal_in_if<bool>&, + sc_simcontext* = sc_get_curr_simcontext() ); + +extern +void +at_posedge( const sc_signal_in_if<sc_dt::sc_logic>&, + sc_simcontext* = sc_get_curr_simcontext() ); + +extern +void +at_negedge( const sc_signal_in_if<bool>&, + sc_simcontext* = sc_get_curr_simcontext() ); + +extern +void +at_negedge( const sc_signal_in_if<sc_dt::sc_logic>&, + sc_simcontext* = sc_get_curr_simcontext() ); + + +} // namespace sc_core + +/* +$Log: sc_wait_cthread.h,v $ +Revision 1.6 2011/08/26 20:46:11 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.5 2011/08/24 22:05:51 acg + Torsten Maehne: initialization changes to remove warnings. + +Revision 1.4 2011/02/18 20:27:14 acg + Andy Goodrich: Updated Copyrights. + +Revision 1.3 2011/02/13 21:47:38 acg + Andy Goodrich: update copyright notice. + +Revision 1.2 2008/05/22 17:06:27 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.2 2006/01/03 23:18:45 acg +Changed copyright to include 2006. + +Revision 1.1.1.1 2005/12/19 23:16:44 acg +First check in of SystemC 2.1 into its own archive. + +Revision 1.10 2005/09/02 19:03:30 acg +Changes for dynamic processes. Removal of lambda support. + +Revision 1.9 2005/04/04 00:16:08 acg +Changes for directory name change to sys from systemc. +Changes for sc_string going to std::string. +Changes for sc_pvector going to std::vector. +Changes for reference pools for bit and part selections. +Changes for const sc_concatref support. + +Revision 1.6 2005/01/10 17:52:20 acg +Addition of namespace specifications. + +Revision 1.5 2004/09/27 20:49:10 acg +Andy Goodrich, Forte Design Systems, Inc. + - Added a $Log comment so that CVS checkin comments appear in the + checkout source. + +*/ + +#endif |