summaryrefslogtreecommitdiff
path: root/ext/systemc/src/sysc/kernel/sc_phase_callback_registry.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'ext/systemc/src/sysc/kernel/sc_phase_callback_registry.cpp')
-rw-r--r--ext/systemc/src/sysc/kernel/sc_phase_callback_registry.cpp301
1 files changed, 301 insertions, 0 deletions
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!