sc_reset.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_reset.cpp -- Support for reset.
00021 
00022   Original Author: Andy Goodrich, Forte Design Systems
00023 
00024  *****************************************************************************/
00025 
00026 // $Log: sc_reset.cpp,v $
00027 // Revision 1.1.1.1  2006/12/15 20:31:37  acg
00028 // SystemC 2.2
00029 //
00030 // Revision 1.5  2006/04/11 23:13:21  acg
00031 //   Andy Goodrich: Changes for reduced reset support that only includes
00032 //   sc_cthread, but has preliminary hooks for expanding to method and thread
00033 //   processes also.
00034 //
00035 // Revision 1.4  2006/01/24 20:49:05  acg
00036 // Andy Goodrich: changes to remove the use of deprecated features within the
00037 // simulator, and to issue warning messages when deprecated features are used.
00038 //
00039 // Revision 1.3  2006/01/13 18:44:30  acg
00040 // Added $Log to record CVS changes into the source.
00041 //
00042 
00043 #include "sysc/kernel/sc_simcontext.h"
00044 #include "sysc/kernel/sc_reset.h"
00045 #include "sysc/kernel/sc_process_handle.h"
00046 #include "sysc/communication/sc_signal.h"
00047 #include "sysc/communication/sc_signal_ports.h"
00048 
00049 
00050 namespace sc_core {
00051 
00052 class sc_reset_finder;
00053 static sc_reset_finder* reset_finder_q=0;  // Q of reset finders to reconcile.
00054 
00055 //==============================================================================
00056 // sc_reset_finder -
00057 //
00058 //==============================================================================
00059 class sc_reset_finder {
00060     friend class sc_reset;
00061   public:
00062     sc_reset_finder(
00063         const sc_in<bool>* port_p, bool level, sc_process_b* target_p);
00064 
00065   protected:
00066     bool                 m_level;     // Level for reset.
00067     sc_reset_finder*     m_next_p;    // Next reset finder in list.
00068     const sc_in<bool>*   m_port_p;    // Port for which reset is needed.
00069     sc_process_b*        m_target_p;  // Process to reset.
00070 
00071   private: // disabled
00072     sc_reset_finder( const sc_reset_finder& );
00073     const sc_reset_finder& operator = ( const sc_reset_finder& );
00074 };
00075 
00076 inline sc_reset_finder::sc_reset_finder(
00077     const sc_in<bool>* port_p, bool level, sc_process_b* target_p
00078 ) : 
00079     m_level(level), m_port_p(port_p), m_target_p(target_p)
00080 {   
00081     m_next_p = reset_finder_q;
00082     reset_finder_q = this;
00083 }
00084 
00085 
00086 //------------------------------------------------------------------------------
00087 //"sc_reset::notify_processes"
00088 //
00089 // Notify processes that there is a change in the reset signal value.
00090 //------------------------------------------------------------------------------
00091 void sc_reset::notify_processes()
00092 {
00093     int process_i; // Index of process resetting.
00094     int process_n; // # of processes to reset.
00095     process_n = m_processes.size();
00096     for ( process_i = 0; process_i < process_n; process_i++ )
00097     {
00098         m_processes[process_i]->reset_changed();
00099     }
00100 }
00101 
00102 
00103 //------------------------------------------------------------------------------
00104 //"sc_reset::read"
00105 //
00106 // This method returns the value of the signal associated with this object 
00107 // instance.
00108 //------------------------------------------------------------------------------
00109 bool sc_reset::read()
00110 {
00111     return m_iface_p->read(); 
00112 }
00113 
00114 
00115 //------------------------------------------------------------------------------
00116 //"sc_reset::reconcile_resets"
00117 //
00118 // This static method processes the sc_reset_finders to establish the actual
00119 // reset connections.
00120 //
00121 // Notes:
00122 //   (1) For sc_cthread_process instances we do not record the process in
00123 //       the m_processes list. This is because we want the reset to act as
00124 //       a synchronous reset rather than an asynchronous one.
00125 //------------------------------------------------------------------------------
00126 void sc_reset::reconcile_resets()
00127 {
00128     const sc_signal_in_if<bool>*  iface_p; // Interface to reset signal.
00129     sc_reset_finder*              next_p;  // Next finder to process.
00130     sc_reset_finder*              now_p;   // Finder currently processing.
00131     sc_reset*                     reset_p; // Reset object to use.
00132 
00133     for ( now_p = reset_finder_q; now_p; now_p = next_p )
00134     {
00135         next_p = now_p->m_next_p;
00136         if ( now_p->m_target_p->m_reset_p )
00137             SC_REPORT_ERROR(SC_ID_MULTIPLE_RESETS_,now_p->m_target_p->name());
00138         iface_p = DCAST<const sc_signal_in_if<bool>*>(
00139             now_p->m_port_p->get_interface());
00140         assert( iface_p != 0 );
00141         reset_p = iface_p->is_reset();
00142         now_p->m_target_p->m_reset_p = reset_p;
00143         now_p->m_target_p->m_reset_level = now_p->m_level;
00144         reset_p->m_processes.push_back(now_p->m_target_p);
00145         delete now_p;
00146     }
00147 }
00148 
00149 
00150 //------------------------------------------------------------------------------
00151 //"sc_reset::remove_process"
00152 //
00153 //------------------------------------------------------------------------------
00154 void sc_reset::remove_process( sc_process_b* process_p )
00155 {
00156     int process_i; // Index of process resetting.
00157     int process_n; // # of processes to reset.
00158 
00159     process_n = m_processes.size();
00160     for ( process_i = 0; process_i < process_n; process_i++ )
00161     {
00162         if ( m_processes[process_i] == process_p )
00163         {
00164             m_processes[process_i] = m_processes[process_n-1];
00165             m_processes.resize(process_n-1);
00166             return;
00167         }
00168     }
00169 }
00170 
00171 //------------------------------------------------------------------------------
00172 //"sc_reset_signal_is"
00173 //
00174 //------------------------------------------------------------------------------
00175 void sc_reset::reset_signal_is( const sc_in<bool>& port, bool level )
00176 {
00177     const sc_signal_in_if<bool>* iface_p;
00178     sc_process_b*                process_p;
00179     
00180     process_p = (sc_process_b*)sc_get_current_process_handle();
00181     assert( process_p );
00182     switch ( process_p->proc_kind() )
00183     {
00184       case SC_THREAD_PROC_:
00185       case SC_METHOD_PROC_:
00186         SC_REPORT_ERROR(SC_ID_RESET_SIGNAL_IS_NOT_ALLOWED_,"");
00187         break;
00188       case SC_CTHREAD_PROC_:
00189         process_p->m_reset_level = level;
00190         iface_p = DCAST<const sc_signal_in_if<bool>*>(port.get_interface());
00191         if ( iface_p )
00192             reset_signal_is( *iface_p, level );
00193         else
00194         {
00195             new sc_reset_finder( &port, level, process_p );
00196         }
00197         break;
00198       default:
00199         SC_REPORT_ERROR(SC_ID_UNKNOWN_PROCESS_TYPE_, process_p->name());
00200         break;
00201     }
00202 }
00203 
00204 //------------------------------------------------------------------------------
00205 //"sc_reset::reset_signal_is"
00206 //
00207 // Notes:
00208 //   (1) For sc_cthread_process instances we do not record the process in
00209 //       the m_processes list. This is because we want the reset to act as
00210 //       a synchronous reset rather than an asynchronous one.
00211 //------------------------------------------------------------------------------
00212 void sc_reset::reset_signal_is( const sc_signal_in_if<bool>& iface, bool level )
00213 {
00214     sc_process_b* process_p; // Process adding reset for.
00215     sc_reset*        reset_p;   // Reset object.
00216 
00217     process_p = sc_process_b::last_created_process_base();
00218     assert( process_p );
00219     if ( process_p->m_reset_p )
00220         SC_REPORT_ERROR(SC_ID_MULTIPLE_RESETS_,process_p->name());
00221     switch ( process_p->proc_kind() )
00222     {
00223       case SC_CTHREAD_PROC_:
00224         process_p->m_reset_level = level;
00225         reset_p = iface.is_reset();
00226         process_p->m_reset_p = reset_p;
00227         reset_p->m_processes.push_back(process_p);
00228         break;
00229       case SC_THREAD_PROC_:
00230       case SC_METHOD_PROC_:
00231         SC_REPORT_ERROR(SC_ID_RESET_SIGNAL_IS_NOT_ALLOWED_,"");
00232         break;
00233       default:
00234         SC_REPORT_ERROR(SC_ID_UNKNOWN_PROCESS_TYPE_, process_p->name());
00235         break;
00236     }
00237 }
00238 
00239 
00240 } // namespace sc_core

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