diff options
Diffstat (limited to 'ext/systemc/src/sysc/communication/sc_clock.cpp')
-rw-r--r-- | ext/systemc/src/sysc/communication/sc_clock.cpp | 409 |
1 files changed, 409 insertions, 0 deletions
diff --git a/ext/systemc/src/sysc/communication/sc_clock.cpp b/ext/systemc/src/sysc/communication/sc_clock.cpp new file mode 100644 index 000000000..158d54b7a --- /dev/null +++ b/ext/systemc/src/sysc/communication/sc_clock.cpp @@ -0,0 +1,409 @@ +/***************************************************************************** + + 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_clock.cpp -- The clock channel. + + Original Author: Martin Janssen, Synopsys, Inc., 2001-05-21 + + CHANGE LOG IS AT THE END OF THE FILE + *****************************************************************************/ + +// using notify_delayed(). +// +// Revision 1.4 2006/01/18 21:42:26 acg +// Andy Goodrich: Changes for check writer support, and tightening up sc_clock +// port usage. +// +// Revision 1.3 2006/01/13 18:47:41 acg +// Added $Log command so that CVS comments are reproduced in the source. +// + +#include "sysc/communication/sc_clock.h" +#include "sysc/communication/sc_communication_ids.h" +#include "sysc/kernel/sc_simcontext.h" +#include "sysc/kernel/sc_process.h" +#include "sysc/kernel/sc_spawn.h" +#include "sysc/utils/sc_utils_ids.h" + +namespace sc_core { + +// ---------------------------------------------------------------------------- +// CLASS : sc_clock +// +// The clock channel. +// ---------------------------------------------------------------------------- + +// constructors + +sc_clock::sc_clock() : + base_type( sc_gen_unique_name( "clock" ) ), + m_period(), m_duty_cycle(), m_start_time(), m_posedge_first(), + m_posedge_time(), m_negedge_time(), + m_next_posedge_event( (std::string(SC_KERNEL_EVENT_PREFIX) + + "_next_posedge_event").c_str()), + m_next_negedge_event( (std::string(SC_KERNEL_EVENT_PREFIX) + + "_next_negedge_event").c_str()) + +{ + init( sc_time::from_value(simcontext()->m_time_params->default_time_unit), + 0.5, + SC_ZERO_TIME, + true ); + + m_next_posedge_event.notify_internal( m_start_time ); +} + +sc_clock::sc_clock( const char* name_ ) : + base_type( name_ ), + m_period(), m_duty_cycle(), m_start_time(), m_posedge_first(), + m_posedge_time(), m_negedge_time(), + m_next_posedge_event( (std::string(SC_KERNEL_EVENT_PREFIX) + + std::string(name_) + "_next_posedge_event").c_str()), + m_next_negedge_event( (std::string(SC_KERNEL_EVENT_PREFIX) + + std::string(name_) + "_next_negedge_event").c_str()) +{ + init( sc_time::from_value(simcontext()->m_time_params->default_time_unit), + 0.5, + SC_ZERO_TIME, + true ); + + m_next_posedge_event.notify_internal( m_start_time ); +} + +sc_clock::sc_clock( const char* name_, + const sc_time& period_, + double duty_cycle_, + const sc_time& start_time_, + bool posedge_first_ ) : + base_type( name_ ), + m_period(), m_duty_cycle(), m_start_time(), m_posedge_first(), + m_posedge_time(), m_negedge_time(), + m_next_posedge_event( (std::string(SC_KERNEL_EVENT_PREFIX) + + std::string(name_) + "_next_posedge_event").c_str()), + m_next_negedge_event( (std::string(SC_KERNEL_EVENT_PREFIX) + + std::string(name_) + "_next_negedge_event").c_str()) +{ + init( period_, + duty_cycle_, + start_time_, + posedge_first_ ); + + if( posedge_first_ ) { + // posedge first + m_next_posedge_event.notify_internal( m_start_time ); + } else { + // negedge first + m_next_negedge_event.notify_internal( m_start_time ); + } +} + +sc_clock::sc_clock( const char* name_, + double period_v_, + sc_time_unit period_tu_, + double duty_cycle_ ) : + base_type( name_ ), + m_period(), m_duty_cycle(), m_start_time(), m_posedge_first(), + m_posedge_time(), m_negedge_time(), + m_next_posedge_event( (std::string(SC_KERNEL_EVENT_PREFIX) + + std::string(name_) + "_next_posedge_event").c_str()), + m_next_negedge_event( (std::string(SC_KERNEL_EVENT_PREFIX) + + std::string(name_) + "_next_negedge_event").c_str()) +{ + init( sc_time( period_v_, period_tu_, simcontext() ), + duty_cycle_, + SC_ZERO_TIME, + true ); + + // posedge first + m_next_posedge_event.notify_internal( m_start_time ); +} + +sc_clock::sc_clock( const char* name_, + double period_v_, + sc_time_unit period_tu_, + double duty_cycle_, + double start_time_v_, + sc_time_unit start_time_tu_, + bool posedge_first_ ) : + base_type( name_ ), + m_period(), m_duty_cycle(), m_start_time(), m_posedge_first(), + m_posedge_time(), m_negedge_time(), + m_next_posedge_event( (std::string(SC_KERNEL_EVENT_PREFIX) + + std::string(name_) + "_next_posedge_event").c_str()), + m_next_negedge_event( (std::string(SC_KERNEL_EVENT_PREFIX) + + std::string(name_) + "_next_negedge_event").c_str()) +{ + init( sc_time( period_v_, period_tu_, simcontext() ), + duty_cycle_, + sc_time( start_time_v_, start_time_tu_, simcontext() ), + posedge_first_ ); + + if( posedge_first_ ) { + // posedge first + m_next_posedge_event.notify_internal( m_start_time ); + } else { + // negedge first + m_next_negedge_event.notify_internal( m_start_time ); + } +} + +// for backward compatibility with 1.0 +sc_clock::sc_clock( const char* name_, + double period_, // in default time units + double duty_cycle_, + double start_time_, // in default time units + bool posedge_first_ ) : + base_type( name_ ), + m_period(), m_duty_cycle(), m_start_time(), m_posedge_first(), + m_posedge_time(), m_negedge_time(), + m_next_posedge_event( (std::string(SC_KERNEL_EVENT_PREFIX) + + std::string(name_) + "_next_posedge_event").c_str()), + m_next_negedge_event( (std::string(SC_KERNEL_EVENT_PREFIX) + + std::string(name_) + "_next_negedge_event").c_str()) +{ + static bool warn_sc_clock=true; + if ( warn_sc_clock ) + { + warn_sc_clock = false; + SC_REPORT_INFO(SC_ID_IEEE_1666_DEPRECATION_, + "\n sc_clock(const char*, double, double, double, bool)\n" + " is deprecated use a form that includes sc_time or\n" + " sc_time_unit"); + } + + sc_time default_time = + sc_time::from_value( simcontext()->m_time_params->default_time_unit ); + + init( ( period_ * default_time ), + duty_cycle_, + ( start_time_ * default_time ), + posedge_first_ ); + + if( posedge_first_ ) { + // posedge first + m_next_posedge_event.notify_internal( m_start_time ); + } else { + // negedge first + m_next_negedge_event.notify_internal( m_start_time ); + } +} + + +//------------------------------------------------------------------------------ +//"sc_clock::before_end_of_elaboration" +// +// This callback is used to spawn the edge processes for this object instance. +// The processes are created here rather than the constructor for the object +// so that the processes are registered with the global simcontext rather +// than the scope of the clock's parent. +//------------------------------------------------------------------------------ +#if ( defined(_MSC_VER) && _MSC_VER < 1300 ) //VC++6.0 doesn't support sc_spawn with functor. +# define sc_clock_posedge_callback(ptr) sc_clock_posedge_callback + +# define sc_clock_negedge_callback(ptr) sc_clock_negedge_callback + +# define sc_spawn(a,b,c) { \ + sc_process_handle result(new sc_spawn_object<a>(a(this),b,c)); \ + } +#endif // ( defined(_MSC_VER) && _MSC_VER < 1300 ) + +void sc_clock::before_end_of_elaboration() +{ + std::string gen_base; + sc_spawn_options posedge_options; // Options for posedge process. + sc_spawn_options negedge_options; // Options for negedge process. + + posedge_options.spawn_method(); + posedge_options.dont_initialize(); + posedge_options.set_sensitivity(&m_next_posedge_event); + gen_base = basename(); + gen_base += "_posedge_action"; + sc_spawn(sc_clock_posedge_callback(this), + sc_gen_unique_name( gen_base.c_str() ), &posedge_options); + + negedge_options.spawn_method(); + negedge_options.dont_initialize(); + negedge_options.set_sensitivity(&m_next_negedge_event); + gen_base = basename(); + gen_base += "_negedge_action"; + sc_spawn( sc_clock_negedge_callback(this), + sc_gen_unique_name( gen_base.c_str() ), &negedge_options ); +} + +//clear VC++6.0 macros +#undef sc_clock_posedge_callback +#undef sc_clock_negedge_callback +#undef sc_spawn + +// destructor (does nothing) + +sc_clock::~sc_clock() +{} + +void sc_clock::register_port( sc_port_base& /*port*/, const char* if_typename_ ) +{ + std::string nm( if_typename_ ); + if( nm == typeid( sc_signal_inout_if<bool> ).name() ) { + SC_REPORT_ERROR(SC_ID_ATTEMPT_TO_BIND_CLOCK_TO_OUTPUT_, ""); + } +} + +void +sc_clock::write( const bool& /* value */ ) +{ + SC_REPORT_ERROR(SC_ID_ATTEMPT_TO_WRITE_TO_CLOCK_, ""); +} + +// interface methods + +// get the current time + +const sc_time& +sc_clock::time_stamp() +{ + return sc_time_stamp(); +} + + +// error reporting + +void +sc_clock::report_error( const char* id, const char* add_msg ) const +{ + char msg[BUFSIZ]; + if( add_msg != 0 ) { + std::sprintf( msg, "%s: clock '%s'", add_msg, name() ); + } else { + std::sprintf( msg, "clock '%s'", name() ); + } + SC_REPORT_ERROR( id, msg ); +} + + +void +sc_clock::init( const sc_time& period_, + double duty_cycle_, + const sc_time& start_time_, + bool posedge_first_ ) +{ + if( period_ == SC_ZERO_TIME ) { + report_error( SC_ID_CLOCK_PERIOD_ZERO_, + "increase the period" ); + } + m_period = period_; + m_posedge_first = posedge_first_; + + if( duty_cycle_ <= 0.0 || duty_cycle_ >= 1.0 ) { + m_duty_cycle = 0.5; + } else { + m_duty_cycle = duty_cycle_; + } + + m_negedge_time = m_period * m_duty_cycle; + m_posedge_time = m_period - m_negedge_time; + + if( m_negedge_time == SC_ZERO_TIME ) { + report_error( SC_ID_CLOCK_HIGH_TIME_ZERO_, + "increase the period or increase the duty cycle" ); + } + if( m_posedge_time == SC_ZERO_TIME ) { + report_error( SC_ID_CLOCK_LOW_TIME_ZERO_, + "increase the period or decrease the duty cycle" ); + } + + if( posedge_first_ ) { + this->m_cur_val = false; + this->m_new_val = false; + } else { + this->m_cur_val = true; + this->m_new_val = true; + } + + m_start_time = start_time_; + +} + +} // 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, + Andy Goodrich, Forte Design Systems, + 3 October, 2003 + Description of Modification: sc_clock inherits from sc_signal<bool> only + instead of sc_signal_in_if<bool> and sc_module. + The 2 methods posedge_action() and + negedge_action() are created using sc_spawn(). + boost::bind() is not required, instead a local + bind function can be used since the signatures + of the spawned functions are statically known. + + Name, Affiliation, Date: + Description of Modification: + + *****************************************************************************/ + +// $Log: sc_clock.cpp,v $ +// Revision 1.7 2011/08/26 20:45:39 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:35 acg +// Torsten Maehne: initialization changes to remove warnings. +// +// Revision 1.5 2011/08/15 16:43:24 acg +// Torsten Maehne: changes to remove unused argument warnings. +// +// Revision 1.4 2011/03/12 21:07:42 acg +// Andy Goodrich: changes to kernel generated event support. +// +// Revision 1.3 2011/03/06 15:55:08 acg +// Andy Goodrich: Changes for named events. +// +// Revision 1.2 2011/02/18 20:23:45 acg +// Andy Goodrich: Copyright update. +// +// Revision 1.1.1.1 2006/12/15 20:20:04 acg +// SystemC 2.3 +// +// Revision 1.8 2006/04/18 23:36:50 acg +// Andy Goodrich: made add_trace_internal public until I can figure out +// how to do a friend specification for sc_trace in an environment where +// there are partial template and full template specifications for its +// arguments. +// +// Revision 1.7 2006/04/17 16:38:42 acg +// Andy Goodrich: added more context to the deprecation message for the +// sc_clock constructor. +// +// Revision 1.6 2006/01/25 00:31:11 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:43:24 acg +// Andy Goodrich: convert notify_delayed() calls into notify_internal() calls. +// notify_internal() is an implementation dependent version of notify_delayed() +// that is simpler, and does not trigger the deprecation warning one would get + +// Taf! |