sc_clock.cpp

Go to the documentation of this file.
00001 /*****************************************************************************
00002 
00003   The following code is derived, directly or indirectly, from the SystemC
00004   source code Copyright (c) 1996-2006 by all Contributors.
00005   All Rights reserved.
00006 
00007   The contents of this file are subject to the restrictions and limitations
00008   set forth in the SystemC Open Source License Version 2.4 (the "License");
00009   You may not use this file except in compliance with such restrictions and
00010   limitations. You may obtain instructions on how to receive a copy of the
00011   License at http://www.systemc.org/. Software distributed by Contributors
00012   under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF
00013   ANY KIND, either express or implied. See the License for the specific
00014   language governing rights and limitations under the License.
00015 
00016  *****************************************************************************/
00017 
00018 /*****************************************************************************
00019 
00020   sc_clock.cpp -- The clock channel.
00021 
00022   Original Author: Martin Janssen, Synopsys, Inc., 2001-05-21
00023 
00024  *****************************************************************************/
00025 
00026 /*****************************************************************************
00027 
00028   MODIFICATION LOG - modifiers, enter your name, affiliation, date and
00029   changes you are making here.
00030 
00031       Name, Affiliation, Date: Bishnupriya Bhattacharya, Cadence Design Systems,
00032                                Andy Goodrich, Forte Design Systems,
00033                                3 October, 2003
00034   Description of Modification: sc_clock inherits from sc_signal<bool> only
00035                                instead of sc_signal_in_if<bool> and sc_module.
00036                                The 2 methods posedge_action() and
00037                                negedge_action() are created using sc_spawn().
00038                                boost::bind() is not required, instead a local
00039                                bind function can be used since the signatures
00040                                of the spawned functions are statically known.
00041 
00042       Name, Affiliation, Date:
00043   Description of Modification:
00044 
00045  *****************************************************************************/
00046 
00047 
00048 // $Log: sc_clock.cpp,v $
00049 // Revision 1.1.1.1  2006/12/15 20:31:35  acg
00050 // SystemC 2.2
00051 //
00052 // Revision 1.8  2006/04/18 23:36:50  acg
00053 //  Andy Goodrich: made add_trace_internal public until I can figure out
00054 //  how to do a friend specification for sc_trace in an environment where
00055 //  there are partial template and full template specifications for its
00056 //  arguments.
00057 //
00058 // Revision 1.7  2006/04/17 16:38:42  acg
00059 //  Andy Goodrich: added more context to the deprecation message for the
00060 //  sc_clock constructor.
00061 //
00062 // Revision 1.6  2006/01/25 00:31:11  acg
00063 //  Andy Goodrich: Changed over to use a standard message id of
00064 //  SC_ID_IEEE_1666_DEPRECATION for all deprecation messages.
00065 //
00066 // Revision 1.5  2006/01/24 20:43:24  acg
00067 // Andy Goodrich: convert notify_delayed() calls into notify_internal() calls.
00068 // notify_internal() is an implementation dependent version of notify_delayed()
00069 // that is simpler, and does not trigger the deprecation warning one would get
00070 // using notify_delayed().
00071 //
00072 // Revision 1.4  2006/01/18 21:42:26  acg
00073 // Andy Goodrich: Changes for check writer support, and tightening up sc_clock
00074 // port usage.
00075 //
00076 // Revision 1.3  2006/01/13 18:47:41  acg
00077 // Added $Log command so that CVS comments are reproduced in the source.
00078 //
00079 
00080 #include "sysc/communication/sc_clock.h"
00081 #include "sysc/communication/sc_communication_ids.h"
00082 #include "sysc/kernel/sc_simcontext.h"
00083 #include "sysc/kernel/sc_process.h"
00084 #include "sysc/kernel/sc_spawn.h"
00085 #include "sysc/utils/sc_utils_ids.h"
00086 
00087 namespace sc_core {
00088 
00089 // ----------------------------------------------------------------------------
00090 //  CLASS : sc_clock
00091 //
00092 //  The clock channel.
00093 // ----------------------------------------------------------------------------
00094 
00095 // constructors
00096 
00097 sc_clock::sc_clock()
00098 : sc_signal<bool>( sc_gen_unique_name( "clock" ) )
00099 {
00100     init( sc_time( 1.0, true ),
00101       0.5,
00102       SC_ZERO_TIME,
00103       true );
00104 
00105     m_next_posedge_event.notify_internal( m_start_time );
00106 }
00107 
00108 sc_clock::sc_clock( const char* name_ )
00109 : sc_signal<bool>( name_ )
00110 {
00111     init( sc_time( 1.0, true ),
00112       0.5,
00113       SC_ZERO_TIME,
00114       true );
00115 
00116     m_next_posedge_event.notify_internal( m_start_time );
00117 }
00118 
00119 sc_clock::sc_clock( const char* name_,
00120             const sc_time& period_,
00121             double         duty_cycle_,
00122             const sc_time& start_time_,
00123             bool           posedge_first_ )
00124 : sc_signal<bool>( name_ )
00125 {
00126     init( period_,
00127       duty_cycle_,
00128       start_time_,
00129       posedge_first_ );
00130 
00131     if( posedge_first_ ) {
00132     // posedge first
00133     m_next_posedge_event.notify_internal( m_start_time );
00134     } else {
00135     // negedge first
00136     m_next_negedge_event.notify_internal( m_start_time );
00137     }
00138 }
00139 
00140 sc_clock::sc_clock( const char* name_,
00141             double         period_v_,
00142             sc_time_unit   period_tu_,
00143             double         duty_cycle_ )
00144 : sc_signal<bool>( name_ )
00145 {
00146     init( sc_time( period_v_, period_tu_, simcontext() ),
00147       duty_cycle_,
00148       SC_ZERO_TIME,
00149       true );
00150 
00151     // posedge first
00152     m_next_posedge_event.notify_internal( m_start_time );
00153 }
00154 
00155 sc_clock::sc_clock( const char* name_,
00156             double         period_v_,
00157             sc_time_unit   period_tu_,
00158             double         duty_cycle_,
00159             double         start_time_v_,
00160             sc_time_unit   start_time_tu_,
00161             bool           posedge_first_ )
00162 : sc_signal<bool>( name_ )
00163 {
00164     init( sc_time( period_v_, period_tu_, simcontext() ),
00165       duty_cycle_,
00166       sc_time( start_time_v_, start_time_tu_, simcontext() ),
00167       posedge_first_ );
00168 
00169     if( posedge_first_ ) {
00170     // posedge first
00171     m_next_posedge_event.notify_internal( m_start_time );
00172     } else {
00173     // negedge first
00174     m_next_negedge_event.notify_internal( m_start_time );
00175     }
00176 }
00177 
00178 // for backward compatibility with 1.0
00179 sc_clock::sc_clock( const char* name_,
00180             double         period_,      // in default time units
00181             double         duty_cycle_,
00182             double         start_time_,  // in default time units
00183             bool           posedge_first_ )
00184 : sc_signal<bool>( name_ )
00185 {
00186     static bool warn_sc_clock=true;
00187     if ( warn_sc_clock )
00188     {
00189         warn_sc_clock = false;
00190     SC_REPORT_INFO(SC_ID_IEEE_1666_DEPRECATION_, 
00191        "\n    sc_clock(const char*, double, double, double, bool)\n"
00192        "    is deprecated use a form that includes sc_time or\n"
00193        "    sc_time_unit");
00194     }
00195 
00196     init( sc_time( period_, true ),
00197       duty_cycle_,
00198       sc_time( start_time_, true ),
00199       posedge_first_ );
00200 
00201     if( posedge_first_ ) {
00202     // posedge first
00203     m_next_posedge_event.notify_internal( m_start_time );
00204     } else {
00205     // negedge first
00206     m_next_negedge_event.notify_internal( m_start_time );
00207     }
00208 }
00209 
00210 
00211 //------------------------------------------------------------------------------
00212 //"sc_clock::before_end_of_elaboration"
00213 //
00214 // This callback is used to spawn the edge processes for this object instance.
00215 // The processes are created here rather than the constructor for the object
00216 // so that the processes are registered with the global simcontext rather
00217 // than the scope of the clock's parent.
00218 //------------------------------------------------------------------------------
00219 #if ( defined(_MSC_VER) && _MSC_VER < 1300 ) //VC++6.0 doesn't support sc_spawn with functor
00220 #   define sc_clock_posedge_callback(ptr) sc_clock_posedge_callback
00221 
00222 #   define sc_clock_negedge_callback(ptr) sc_clock_negedge_callback
00223 
00224 #   define sc_spawn(a,b,c) { \
00225         sc_process_handle result(new sc_spawn_object<a>(a(this),b,c)); \
00226     }
00227 #endif // ( defined(_MSC_VER) && _MSC_VER < 1300 )
00228 
00229 void sc_clock::before_end_of_elaboration()
00230 {
00231     std::string gen_base;
00232     sc_spawn_options posedge_options;   // Options for posedge process.
00233     sc_spawn_options negedge_options;   // Options for negedge process.
00234 
00235     posedge_options.spawn_method();
00236     posedge_options.dont_initialize();
00237     posedge_options.set_sensitivity(&m_next_posedge_event);
00238     gen_base = basename();
00239     gen_base += "_posedge_action";
00240     sc_spawn(sc_clock_posedge_callback(this),
00241     sc_gen_unique_name( gen_base.c_str() ), &posedge_options);
00242 
00243     negedge_options.spawn_method();
00244     negedge_options.dont_initialize();
00245     negedge_options.set_sensitivity(&m_next_negedge_event);
00246     gen_base = basename();
00247     gen_base += "_negedge_action";
00248     sc_spawn( sc_clock_negedge_callback(this),
00249         sc_gen_unique_name( gen_base.c_str() ), &negedge_options );
00250 }
00251 
00252 //clear VC++6.0 macros
00253 #undef sc_clock_posedge_callback
00254 #undef sc_clock_negedge_callback
00255 #undef sc_spawn
00256 
00257 // destructor (does nothing)
00258 
00259 sc_clock::~sc_clock()
00260 {}
00261 
00262 void sc_clock::register_port( sc_port_base& port, const char* if_typename_ )
00263 {
00264     std::string nm( if_typename_ );
00265     if( nm == typeid( sc_signal_inout_if<bool> ).name() ) {
00266         SC_REPORT_ERROR(SC_ID_ATTEMPT_TO_BIND_CLOCK_TO_OUTPUT_, "");
00267     }
00268 }
00269 
00270 void
00271 sc_clock::write( const bool& value)
00272 {
00273     SC_REPORT_ERROR(SC_ID_ATTEMPT_TO_WRITE_TO_CLOCK_, "");
00274 }
00275 
00276 // interface methods
00277 
00278 // get the current time
00279 
00280 const sc_time&
00281 sc_clock::time_stamp()
00282 {
00283     return sc_time_stamp();
00284 }
00285 
00286 
00287 // error reporting
00288 
00289 void
00290 sc_clock::report_error( const char* id, const char* add_msg ) const
00291 {
00292     char msg[BUFSIZ];
00293     if( add_msg != 0 ) {
00294     std::sprintf( msg, "%s: clock '%s'", add_msg, name() );
00295     } else {
00296     std::sprintf( msg, "clock '%s'", name() );
00297     }
00298     SC_REPORT_ERROR( id, msg );
00299 }
00300 
00301 
00302 void
00303 sc_clock::init( const sc_time& period_,
00304         double         duty_cycle_,
00305         const sc_time& start_time_,
00306         bool           posedge_first_ )
00307 {
00308     if( period_ == SC_ZERO_TIME ) {
00309     report_error( SC_ID_CLOCK_PERIOD_ZERO_,
00310               "increase the period" );
00311     }
00312     m_period = period_;
00313     m_posedge_first = posedge_first_;
00314 
00315     if( duty_cycle_ <= 0.0 || duty_cycle_ >= 1.0 ) {
00316     m_duty_cycle = 0.5;
00317     } else {
00318     m_duty_cycle = duty_cycle_;
00319     }
00320 
00321     m_negedge_time = m_period * m_duty_cycle;
00322     m_posedge_time = m_period - m_negedge_time;
00323 
00324     if( m_negedge_time == SC_ZERO_TIME ) {
00325     report_error( SC_ID_CLOCK_HIGH_TIME_ZERO_,
00326               "increase the period or increase the duty cycle" );
00327     }
00328     if( m_posedge_time == SC_ZERO_TIME ) {
00329     report_error( SC_ID_CLOCK_LOW_TIME_ZERO_,
00330               "increase the period or decrease the duty cycle" );
00331     }
00332 
00333     if( posedge_first_ ) {
00334     this->m_cur_val = false;
00335     this->m_new_val = false;
00336     } else {
00337     this->m_cur_val = true;
00338     this->m_new_val = true;
00339     }
00340 
00341     m_start_time = start_time_;
00342 
00343 }
00344 
00345 } // namespace sc_core
00346 
00347 
00348 // Taf!

Generated on Wed Jan 21 15:32:06 2009 for SystemC by  doxygen 1.5.5