sc_signal.h

Go to the documentation of this file.
00001 
00008 /*****************************************************************************
00009 
00010   The following code is derived, directly or indirectly, from the SystemC
00011   source code Copyright (c) 1996-2005 by all Contributors.
00012   All Rights reserved.
00013 
00014   The contents of this file are subject to the restrictions and limitations
00015   set forth in the SystemC Open Source License Version 2.4 (the "License");
00016   You may not use this file except in compliance with such restrictions and
00017   limitations. You may obtain instructions on how to receive a copy of the
00018   License at http://www.systemc.org/. Software distributed by Contributors
00019   under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF
00020   ANY KIND, either express or implied. See the License for the specific
00021   language governing rights and limitations under the License.
00022 
00023  *****************************************************************************/
00024 
00025 /*****************************************************************************
00026 
00027   sc_signal.h -- The sc_signal<T> primitive channel class.
00028 
00029   Original Author: Martin Janssen, Synopsys, Inc., 2001-05-21
00030 
00031  *****************************************************************************/
00032 
00033 /*****************************************************************************
00034 
00035   MODIFICATION LOG - modifiers, enter your name, affiliation, date and
00036   changes you are making here.
00037 
00038       Name, Affiliation, Date:
00039   Description of Modification:
00040     
00041  *****************************************************************************/
00042 
00043 #ifndef SC_SIGNAL_H
00044 #define SC_SIGNAL_H
00045 
00046 
00047 #include "sysc/communication/sc_port.h"
00048 #include "sysc/communication/sc_prim_channel.h"
00049 #include "sysc/communication/sc_signal_ifs.h"
00050 #include "sysc/kernel/sc_event.h"
00051 #include "sysc/kernel/sc_process_b.h"
00052 #include "sysc/kernel/sc_simcontext.h"
00053 #include "sysc/datatypes/bit/sc_logic.h"
00054 #include "sysc/tracing/sc_trace.h"
00055 #include "sysc/utils/sc_string.h"
00056 #include <typeinfo>
00057 
00058 namespace sc_core {
00059 
00060 // to avoid code bloat in sc_signal<T>
00061 
00062 extern
00063 void
00064 sc_signal_invalid_writer( const char* name,
00065                           const char* kind,
00066                           const char* first_writer,
00067                           const char* second_writer );
00068 
00069 
00070 // ----------------------------------------------------------------------------
00071 //  CLASS : sc_signal<T>
00072 //
00073 //  The sc_signal<T> primitive channel class.
00074 // ----------------------------------------------------------------------------
00075 
00076 template <class T>
00077 class sc_signal
00078 : public sc_signal_inout_if<T>,
00079   public sc_prim_channel
00080 {
00081     //  ##PINAPA Integration: BEGIN
00082     T * m_pinapa_initial_value;
00083     //  ##PINAPA Integration: END
00084 
00085 public:
00086 
00087     // constructors
00088 
00089     sc_signal()
00090         : sc_prim_channel( sc_gen_unique_name( "signal" ) ),
00091           //  ##PINAPA Integration: BEGIN
00092           m_pinapa_initial_value(NULL),
00093           //  ##PINAPA Integration: END
00094           m_output( 0 ), m_cur_val( T() ), m_new_val( T() ),
00095           m_delta( ~sc_dt::UINT64_ONE ), m_writer( 0 )
00096         {}
00097 
00098     explicit sc_signal( const char* name_ )
00099         : sc_prim_channel( name_ ),
00100           m_output( 0 ), m_cur_val( T() ), m_new_val( T() ),
00101           m_delta( ~sc_dt::UINT64_ONE ), m_writer( 0 )
00102         {}
00103 
00104 
00105     // destructor (does nothing)
00106 
00107     virtual ~sc_signal()
00108         {}
00109 
00110 
00111     // interface methods
00112 
00113     virtual void register_port( sc_port_base&, const char* );
00114 
00115 
00116     // get the default event
00117     virtual const sc_event& default_event() const
00118         { return m_value_changed_event; }
00119 
00120 
00121     // get the value changed event
00122     virtual const sc_event& value_changed_event() const
00123         { return m_value_changed_event; }
00124 
00125 
00126     // read the current value
00127     virtual const T& read() const
00128         { return m_cur_val; }
00129 
00130     // get a reference to the current value (for tracing)
00131     virtual const T& get_data_ref() const
00132         { return m_cur_val; }
00133 
00134 
00135     // was there an event?
00136     virtual bool event() const
00137         { return ( simcontext()->delta_count() == m_delta + 1 ); }
00138 
00139     // write the new value
00140     virtual void write( const T& );
00141 
00142     //  ##PINAPA Integration: BEGIN
00143     virtual void initialize(T i) {
00144       m_pinapa_initial_value = new T(i);}
00145     virtual T * get_initial_value() {return m_pinapa_initial_value;}    
00146     //  ##PINAPA Integration: END
00147 
00148     // other methods
00149 
00150     operator const T& () const
00151         { return read(); }
00152 
00153 
00154     sc_signal<T>& operator = ( const T& a )
00155         { write( a ); return *this; }
00156 
00157     sc_signal<T>& operator = ( const sc_signal<T>& a )
00158         { write( a.read() ); return *this; }
00159 
00160 
00161     const T& get_new_value() const
00162         { return m_new_val; }
00163 
00164 
00165     void trace( sc_trace_file* tf ) const
00166 #ifdef DEBUG_SYSTEMC
00167         { sc_trace( tf, get_data_ref(), name() ); }
00168 #else
00169         {}
00170 #endif
00171 
00172 
00173     virtual void print( ::std::ostream& = ::std::cout ) const;
00174     virtual void dump( ::std::ostream& = ::std::cout ) const;
00175 
00176     virtual const char* kind() const
00177         { return "sc_signal"; }
00178 
00179 protected:
00180 
00181     virtual void update();
00182 
00183     void check_writer();
00184 
00185 protected:
00186 
00187     sc_port_base* m_output; // used for static design rule checking
00188 
00189     T             m_cur_val;
00190     T             m_new_val;
00191 
00192     sc_event      m_value_changed_event;
00193 
00194     sc_dt::uint64 m_delta; // delta of last event
00195 
00196     sc_process_b* m_writer; // used for dynamic design rule checking
00197 
00198 private:
00199 
00200     // disabled
00201     sc_signal( const sc_signal<T>& );
00202 };
00203 
00204 
00205 // IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII
00206 
00207 
00208 template <class T>
00209 inline
00210 void
00211 sc_signal<T>::register_port( sc_port_base& port_, const char* if_typename_ )
00212 {
00213 #ifdef DEBUG_SYSTEMC
00214     std::string nm( if_typename_ );
00215     if( nm == typeid( sc_signal_inout_if<T> ).name() ) {
00216         // an out or inout port; only one can be connected
00217         if( m_output != 0 ) {
00218             sc_signal_invalid_writer( name(), kind(),
00219                                       m_output->name(), port_.name() );
00220         }
00221         m_output = &port_;
00222     }
00223 #endif
00224 }
00225 
00226 
00227 // write the new value
00228 
00229 template <class T>
00230 inline
00231 void
00232 sc_signal<T>::write( const T& value_ )
00233 {
00234 #ifdef DEBUG_SYSTEMC
00235     check_writer();
00236 #endif
00237     m_new_val = value_;
00238     if( !( m_new_val == m_cur_val ) ) {
00239         request_update();
00240     }
00241 }
00242 
00243 
00244 template <class T>
00245 inline
00246 void
00247 sc_signal<T>::print( ::std::ostream& os ) const
00248 {
00249     os << m_cur_val;
00250 }
00251 
00252 template <class T>
00253 inline
00254 void
00255 sc_signal<T>::dump( ::std::ostream& os ) const
00256 {
00257     os << "     name = " << name() << ::std::endl;
00258     os << "    value = " << m_cur_val << ::std::endl;
00259     os << "new value = " << m_new_val << ::std::endl;
00260 }
00261 
00262 
00263 template <class T>
00264 inline
00265 void
00266 sc_signal<T>::update()
00267 {
00268     if( !( m_new_val == m_cur_val ) ) {
00269         m_cur_val = m_new_val;
00270         m_value_changed_event.notify_delayed();
00271         m_delta = simcontext()->delta_count();
00272     }
00273 }
00274 
00275 
00276 template <class T>
00277 inline
00278 void
00279 sc_signal<T>::check_writer()
00280 {
00281     sc_process_b* writer = sc_get_curr_process_handle();
00282     if( m_writer == 0 ) {
00283         m_writer = writer;
00284     } else if( m_writer != writer ) {
00285         sc_signal_invalid_writer( name(), kind(),
00286                                   m_writer->name(), writer->name() );
00287     }
00288 }
00289 
00290 
00291 // ----------------------------------------------------------------------------
00292 //  CLASS : sc_signal<bool>
00293 //
00294 //  Specialization of sc_signal<T> for type bool.
00295 // ----------------------------------------------------------------------------
00296 
00297 template <>
00298 class sc_signal<bool>
00299 : public sc_signal_inout_if<bool>,
00300   public sc_prim_channel 
00301 {
00302     //  ##PINAPA Integration: BEGIN
00303     bool * m_pinapa_initial_value;
00304     //  ##PINAPA Integration: END
00305 
00306 public:
00307 
00308     // constructors
00309 
00310     sc_signal()
00311         : sc_prim_channel( sc_gen_unique_name( "signal" ) ),
00312           m_output( 0 ),
00313           m_cur_val( false ),
00314           m_new_val( false ),
00315           m_delta( ~sc_dt::UINT64_ONE ),
00316           m_writer( 0 )
00317         {}
00318 
00319     explicit sc_signal( const char* name_ )
00320         : sc_prim_channel( name_ ),
00321           m_output( 0 ),
00322           m_cur_val( false ),
00323           m_new_val( false ),
00324           m_delta( ~sc_dt::UINT64_ONE ),
00325           m_writer( 0 )
00326         {}
00327 
00328 
00329     // destructor (does nothing)
00330 
00331     virtual ~sc_signal()
00332         {}
00333 
00334 
00335     // interface methods
00336 
00337     virtual void register_port( sc_port_base&, const char* );
00338 
00339 
00340     // get the default event
00341     virtual const sc_event& default_event() const
00342         { return m_value_changed_event; }
00343 
00344 
00345     // get the value changed event
00346     virtual const sc_event& value_changed_event() const
00347         { return m_value_changed_event; }
00348 
00349     // get the positive edge event
00350     virtual const sc_event& posedge_event() const
00351         { return m_posedge_event; }
00352 
00353     // get the negative edge event
00354     virtual const sc_event& negedge_event() const
00355         { return m_negedge_event; }
00356 
00357 
00358     // read the current value
00359     virtual const bool& read() const
00360         { return m_cur_val; }
00361 
00362     // get a reference to the current value (for tracing)
00363     virtual const bool& get_data_ref() const
00364         { return m_cur_val; }
00365 
00366 
00367     // was there a value changed event?
00368     virtual bool event() const
00369         { return ( simcontext()->delta_count() == m_delta + 1 ); }
00370 
00371     // was there a positive edge event?
00372     virtual bool posedge() const
00373         { return ( event() && m_cur_val ); }
00374 
00375     // was there a negative edge event?
00376     virtual bool negedge() const
00377         { return ( event() && ! m_cur_val ); }
00378 
00379 
00380     // write the new value
00381     virtual void write( const bool& );
00382 
00383     //  ##PINAPA Integration: BEGIN
00384     virtual void initialize(bool i) {
00385       m_pinapa_initial_value = new bool(i);}
00386     virtual bool * get_initial_value() {return m_pinapa_initial_value;}    
00387     //  ##PINAPA Integration: END
00388 
00389     // delayed evaluation
00390     virtual const sc_signal_bool_deval& delayed() const;
00391 
00392     // other methods
00393 
00394     operator const bool& () const
00395         { return read(); }
00396 
00397 
00398     sc_signal<bool>& operator = ( const bool& a )
00399         { write( a ); return *this; }
00400 
00401     sc_signal<bool>& operator = ( const sc_signal<bool>& a )
00402         { write( a.read() ); return *this; }
00403 
00404 
00405     const bool& get_new_value() const
00406         { return m_new_val; }
00407 
00408 
00409     void trace( sc_trace_file* tf ) const
00410 #ifdef DEBUG_SYSTEMC
00411         { sc_trace( tf, get_data_ref(), name() ); }
00412 #else
00413         {}
00414 #endif
00415 
00416 
00417     virtual void print( ::std::ostream& = ::std::cout ) const;
00418     virtual void dump( ::std::ostream& = ::std::cout ) const;
00419 
00420     virtual const char* kind() const
00421         { return "sc_signal"; }
00422 
00423 protected:
00424 
00425     virtual void update();
00426 
00427     void check_writer();
00428 
00429     virtual bool is_clock() const { return false; }
00430 
00431 protected:
00432 
00433     sc_port_base* m_output; // used for static design rule checking
00434 
00435     bool          m_cur_val;
00436     bool          m_new_val;
00437 
00438     sc_event      m_value_changed_event;
00439     sc_event      m_posedge_event;
00440     sc_event      m_negedge_event;
00441 
00442     sc_dt::uint64 m_delta; // delta of last event
00443 
00444     sc_process_b* m_writer; // used for dynamic design rule checking
00445 
00446 private:
00447 
00448     // disabled
00449     sc_signal( const sc_signal<bool>& );
00450 };
00451 
00452 
00453 // IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII
00454 
00455 inline
00456 void
00457 sc_signal<bool>::register_port( sc_port_base& port_, const char* if_typename_ )
00458 {
00459 #ifdef DEBUG_SYSTEMC
00460     std::string nm( if_typename_ );
00461     if( nm == typeid( sc_signal_inout_if<bool> ).name() ) {
00462         // an out or inout port; only one can be connected
00463         if( m_output != 0 ) {
00464             sc_signal_invalid_writer( name(), kind(),
00465                                       m_output->name(), port_.name() );
00466         }
00467         m_output = &port_;
00468     }
00469 #endif
00470 }
00471 
00472 
00473 // write the new value
00474 
00475 inline
00476 void
00477 sc_signal<bool>::write( const bool& value_ )
00478 {
00479 #ifdef DEBUG_SYSTEMC
00480     check_writer();
00481 #endif
00482     m_new_val = value_;
00483     if( !( m_new_val == m_cur_val ) ) {
00484         request_update();
00485     }
00486 }
00487 
00488 
00489 // delayed evaluation
00490 
00491 inline
00492 const sc_signal_bool_deval&
00493 sc_signal<bool>::delayed() const
00494 {
00495     const sc_signal_in_if<bool>* iface = this;
00496     return RCAST<const sc_signal_bool_deval&>( *iface );
00497 }
00498 
00499 
00500 inline
00501 void
00502 sc_signal<bool>::print( ::std::ostream& os ) const
00503 {
00504     os << m_cur_val;
00505 }
00506 
00507 inline
00508 void
00509 sc_signal<bool>::dump( ::std::ostream& os ) const
00510 {
00511     os << "     name = " << name() << ::std::endl;
00512     os << "    value = " << m_cur_val << ::std::endl;
00513     os << "new value = " << m_new_val << ::std::endl;
00514 }
00515 
00516 
00517 inline
00518 void
00519 sc_signal<bool>::update()
00520 {
00521     if( !( m_new_val == m_cur_val ) ) {
00522         m_cur_val = m_new_val;
00523         m_value_changed_event.notify_delayed();
00524         if( m_cur_val ) {
00525             m_posedge_event.notify_delayed();
00526         } else {
00527             m_negedge_event.notify_delayed();
00528         }
00529         m_delta = simcontext()->delta_count();
00530     }
00531 }
00532 
00533 
00534 inline
00535 void
00536 sc_signal<bool>::check_writer()
00537 {
00538     if (is_clock()) return;
00539     sc_process_b* writer = sc_get_curr_process_handle();
00540     if( m_writer == 0 ) {
00541         m_writer = writer;
00542     } else if( m_writer != writer ) {
00543         sc_signal_invalid_writer( name(), kind(),
00544                                   m_writer->name(), writer->name() );
00545     }
00546 }
00547 
00548 
00549 // ----------------------------------------------------------------------------
00550 //  CLASS : sc_signal<sc_dt::sc_logic>
00551 //
00552 //  Specialization of sc_signal<T> for type sc_dt::sc_logic.
00553 // ----------------------------------------------------------------------------
00554 
00555 template <>
00556 class sc_signal<sc_dt::sc_logic>
00557 : public sc_signal_inout_if<sc_dt::sc_logic>,
00558   public sc_prim_channel
00559 {
00560 public:
00561 
00562     // constructors
00563 
00564     sc_signal()
00565         : sc_prim_channel( sc_gen_unique_name( "signal" ) ),
00566           m_output( 0 ),
00567           m_cur_val(),
00568           m_new_val(),
00569           m_delta( ~sc_dt::UINT64_ONE ),
00570           m_writer( 0 )
00571         {}
00572 
00573     explicit sc_signal( const char* name_ )
00574         : sc_prim_channel( name_ ),
00575           m_output( 0 ),
00576           m_cur_val(),
00577           m_new_val(),
00578           m_delta( ~sc_dt::UINT64_ONE ),
00579           m_writer( 0 )
00580         {}
00581 
00582 
00583     // destructor (does nothing)
00584 
00585     virtual ~sc_signal()
00586         {}
00587 
00588 
00589     // interface methods
00590 
00591     virtual void register_port( sc_port_base&, const char* );
00592 
00593 
00594     // get the default event
00595     virtual const sc_event& default_event() const
00596         { return m_value_changed_event; }
00597 
00598 
00599     // get the value changed event
00600     virtual const sc_event& value_changed_event() const
00601         { return m_value_changed_event; }
00602 
00603     // get the positive edge event
00604     virtual const sc_event& posedge_event() const
00605         { return m_posedge_event; }
00606 
00607     // get the negative edge event
00608     virtual const sc_event& negedge_event() const
00609         { return m_negedge_event; }
00610 
00611 
00612     // read the current value
00613     virtual const sc_dt::sc_logic& read() const
00614         { return m_cur_val; }
00615 
00616     // get a reference to the current value (for tracing)
00617     virtual const sc_dt::sc_logic& get_data_ref() const
00618         { return m_cur_val; }
00619 
00620 
00621     // was there an event?
00622     virtual bool event() const
00623         { return ( simcontext()->delta_count() == m_delta + 1 ); }
00624 
00625     // was there a positive edge event?
00626     virtual bool posedge() const
00627         { return ( event() && m_cur_val == sc_dt::SC_LOGIC_1 ); }
00628 
00629     // was there a negative edge event?
00630     virtual bool negedge() const
00631         { return ( event() && m_cur_val == sc_dt::SC_LOGIC_0 ); }
00632 
00633 
00634     // write the new value
00635     virtual void write( const sc_dt::sc_logic& );
00636 
00637 
00638     // delayed evaluation
00639     virtual const sc_signal_logic_deval& delayed() const;
00640 
00641 
00642     // other methods
00643 
00644     operator const sc_dt::sc_logic& () const
00645         { return read(); }
00646 
00647 
00648     sc_signal<sc_dt::sc_logic>& operator = ( const sc_dt::sc_logic& a )
00649         { write( a ); return *this; }
00650 
00651     sc_signal<sc_dt::sc_logic>& operator = (const sc_signal<sc_dt::sc_logic>& a)
00652         { write( a.read() ); return *this; }
00653 
00654 
00655     const sc_dt::sc_logic& get_new_value() const
00656         { return m_new_val; }
00657 
00658 
00659     void trace( sc_trace_file* tf ) const
00660 #ifdef DEBUG_SYSTEMC
00661         { sc_trace( tf, get_data_ref(), name() ); }
00662 #else
00663         {}
00664 #endif
00665 
00666 
00667     virtual void print( ::std::ostream& = ::std::cout ) const;
00668     virtual void dump( ::std::ostream& = ::std::cout ) const;
00669 
00670     virtual const char* kind() const
00671         { return "sc_signal"; }
00672 
00673 protected:
00674 
00675     virtual void update();
00676 
00677     void check_writer();
00678 
00679 protected:
00680 
00681     sc_port_base* m_output; // used for static design rule checking
00682 
00683     sc_dt::sc_logic      m_cur_val;
00684     sc_dt::sc_logic      m_new_val;
00685 
00686     sc_event             m_value_changed_event;
00687     sc_event             m_posedge_event;
00688     sc_event             m_negedge_event;
00689 
00690     sc_dt::uint64 m_delta; // delta of last event
00691 
00692     sc_process_b* m_writer; // used for dynamic design rule checking
00693 
00694 private:
00695 
00696     // disabled
00697     sc_signal( const sc_signal<sc_dt::sc_logic>& );
00698 };
00699 
00700 
00701 // IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII
00702 
00703 inline
00704 void
00705 sc_signal<sc_dt::sc_logic>::register_port( sc_port_base& port_,
00706                                     const char* if_typename_ )
00707 {
00708 #ifdef DEBUG_SYSTEMC
00709     std::string nm( if_typename_ );
00710     if( nm == typeid( sc_signal_inout_if<sc_dt::sc_logic> ).name() ) {
00711         // an out or inout port; only one can be connected
00712         if( m_output != 0 ) {
00713             sc_signal_invalid_writer( name(), kind(),
00714                                       m_output->name(), port_.name() );
00715         }
00716         m_output = &port_;
00717     }
00718 #endif
00719 }
00720 
00721 
00722 // write the new value
00723 
00724 inline
00725 void
00726 sc_signal<sc_dt::sc_logic>::write( const sc_dt::sc_logic& value_ )
00727 {
00728 #ifdef DEBUG_SYSTEMC
00729     check_writer();
00730 #endif
00731     m_new_val = value_;
00732     if( !( m_new_val == m_cur_val ) ) {
00733         request_update();
00734     }
00735 }
00736 
00737 
00738 // delayed evaluation
00739 
00740 inline
00741 const sc_signal_logic_deval&
00742 sc_signal<sc_dt::sc_logic>::delayed() const
00743 {
00744     const sc_signal_in_if<sc_dt::sc_logic>* iface = this;
00745     return RCAST<const sc_signal_logic_deval&>( *iface );
00746 }
00747 
00748 
00749 inline
00750 void
00751 sc_signal<sc_dt::sc_logic>::print( ::std::ostream& os ) const
00752 {
00753     os << m_cur_val;
00754 }
00755 
00756 inline
00757 void
00758 sc_signal<sc_dt::sc_logic>::dump( ::std::ostream& os ) const
00759 {
00760     os << "     name = " << name() << ::std::endl;
00761     os << "    value = " << m_cur_val << ::std::endl;
00762     os << "new value = " << m_new_val << ::std::endl;
00763 }
00764 
00765 
00766 inline
00767 void
00768 sc_signal<sc_dt::sc_logic>::update()
00769 {
00770     if( !( m_new_val == m_cur_val ) ) {
00771         m_cur_val = m_new_val;
00772         m_value_changed_event.notify_delayed();
00773         if( m_cur_val == sc_dt::SC_LOGIC_1 ) {
00774             m_posedge_event.notify_delayed();
00775         } else if( m_cur_val == sc_dt::SC_LOGIC_0 ) {
00776             m_negedge_event.notify_delayed();
00777         }
00778         m_delta = simcontext()->delta_count();
00779     }
00780 }
00781 
00782 
00783 
00784 inline
00785 void
00786 sc_signal<sc_dt::sc_logic>::check_writer()
00787 {
00788     sc_process_b* writer = sc_get_curr_process_handle();
00789     if( m_writer == 0 ) {
00790         m_writer = writer;
00791     } else if( m_writer != writer ) {
00792         sc_signal_invalid_writer( name(), kind(),
00793                                   m_writer->name(), writer->name() );
00794     }
00795 }
00796 
00797 
00798 // ----------------------------------------------------------------------------
00799 
00800 template <class T>
00801 inline
00802 ::std::ostream&
00803 operator << ( ::std::ostream& os, const sc_signal<T>& a )
00804 {
00805     return ( os << a.read() );
00806 }
00807 
00808 } // namespace sc_core
00809 
00810 #endif
00811 
00812 // Taf!
Generated by
Matthieu Moy <Matthieu.Moy@st.com>
Back to Pinapa Home Page