src/sysc/communication/sc_signal.h

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

Generated on Wed Apr 25 13:53:25 2007 for SystemC by  doxygen 1.5.1