diff options
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.cpp | 301 |
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! |