src/sysc/kernel/sc_process_int.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_process_int.h -- Process internals.
00021                       DO NOT EXPORT THIS INCLUDE FILE.
00022 
00023   Original Author: Stan Y. Liao, Synopsys, Inc.
00024                    Martin Janssen, Synopsys, Inc.
00025 
00026  *****************************************************************************/
00027 
00028 /*****************************************************************************
00029 
00030   MODIFICATION LOG - modifiers, enter your name, affiliation, date and
00031   changes you are making here.
00032 
00033       Name, Affiliation, Date: Andy Goodrich, Forte Design Systems 20 May 2003
00034                                Bishnupriya Bhattacharya, Cadence Design Systems,
00035                                25 August, 2003
00036   Description of Modification: Changes for dynamic processes.
00037 
00038       Name, Affiliation, Date:
00039   Description of Modification:
00040 
00041  *****************************************************************************/
00042 
00043 #ifndef SC_PROCESS_INT_H
00044 #define SC_PROCESS_INT_H
00045 
00046 #include "sysc/kernel/sc_cor.h"
00047 #include "sysc/kernel/sc_except.h"
00048 #include "sysc/kernel/sc_lambda.h"
00049 #include "sysc/kernel/sc_module.h"
00050 #include "sysc/kernel/sc_process_b.h"
00051 #include "sysc/utils/sc_list.h"
00052 
00053 namespace sc_core {
00054 
00055 // ----------------------------------------------------------------------------
00056 //  CLASS : sc_process_b
00057 //
00058 //  Process base class.
00059 // ----------------------------------------------------------------------------
00060 
00061 // Declaration in sc_process_b.h
00062 
00063 
00064 // IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII
00065 
00066 inline
00067 bool
00068 sc_process_b::do_initialize() const
00069 {
00070     return m_do_initialize;
00071 }
00072 
00073 inline
00074 void
00075 sc_process_b::do_initialize( bool do_initialize_ )
00076 {
00077     m_do_initialize = do_initialize_;
00078 }
00079 
00080 
00081 inline
00082 bool
00083 sc_process_b::is_runnable()
00084 {
00085     return m_runnable_p != 0;
00086 }
00087 
00088 
00089 inline
00090 void
00091 sc_process_b::execute()
00092 {
00093 #ifndef SC_USE_MEMBER_FUNC_PTR
00094     entry_fn->invoke( host );
00095 #else
00096     (host->*entry_fn)(); 
00097 #endif
00098 }
00099 
00100 
00101 inline
00102 bool
00103 sc_process_b::trigger_static()
00104 {
00105     return ( !is_runnable() && m_trigger_type == STATIC );
00106 }
00107 
00108 
00109 inline
00110 bool
00111 sc_process_b::timed_out() const
00112 {
00113     return m_timed_out;
00114 }
00115 
00116 
00117 // ----------------------------------------------------------------------------
00118 //  CLASS : sc_method_process
00119 //
00120 //  Process class for SC_METHODs.
00121 // ----------------------------------------------------------------------------
00122 
00123 class sc_method_process
00124 : public sc_process_b
00125 {
00126     friend class sc_event;
00127     friend class sc_module;
00128     friend class sc_process_host;
00129     friend class sc_process_table;
00130     friend class sc_simcontext;
00131     friend class sc_runnable;
00132 
00133     friend void next_trigger( sc_simcontext* );
00134     friend void next_trigger( const sc_event&,
00135                               sc_simcontext* );
00136     friend void next_trigger( sc_event_or_list&,
00137                               sc_simcontext* );
00138     friend void next_trigger( sc_event_and_list&,
00139                               sc_simcontext* );
00140     friend void next_trigger( const sc_time&,
00141                               sc_simcontext* );
00142     friend void next_trigger( const sc_time&, const sc_event&,
00143                               sc_simcontext* );
00144     friend void next_trigger( const sc_time&, sc_event_or_list&,
00145                               sc_simcontext* );
00146     friend void next_trigger( const sc_time&, sc_event_and_list&,
00147                               sc_simcontext* );
00148 
00149 public:
00150 
00151     virtual const char* kind() const
00152         { return "sc_method_process"; }
00153 
00154 protected:
00155 
00156     sc_method_process( const char*   nm,
00157                        SC_ENTRY_FUNC fn,
00158                        sc_process_host*    host );
00159     virtual ~sc_method_process();
00160 
00161     void clear_trigger();
00162 
00163     void next_trigger( const sc_event& );
00164     void next_trigger( sc_event_or_list& );
00165     void next_trigger( sc_event_and_list& );
00166     void next_trigger( const sc_time& );
00167     void next_trigger( const sc_time&, const sc_event& );
00168     void next_trigger( const sc_time&, sc_event_or_list& );
00169     void next_trigger( const sc_time&, sc_event_and_list& );
00170 
00171     bool trigger_dynamic( sc_event* );
00172 
00173     void set_next_exist( sc_method_handle next_p );
00174     sc_method_handle next_exist();
00175     void set_next_runnable( sc_method_handle next_p );
00176     sc_method_handle next_runnable();
00177 
00178 };
00179 
00180 
00181 // IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII
00182 
00183 inline
00184 void
00185 sc_method_process::next_trigger( const sc_event& e )
00186 {
00187     clear_trigger();
00188     e.add_dynamic( this );
00189     m_event = &e;
00190     m_trigger_type = EVENT;
00191 }
00192 
00193 inline
00194 void
00195 sc_method_process::next_trigger( sc_event_or_list& el )
00196 {
00197     clear_trigger();
00198     el.add_dynamic( this );
00199     m_event_list = ⪙
00200     m_trigger_type = OR_LIST;
00201 }
00202 
00203 inline
00204 void
00205 sc_method_process::next_trigger( sc_event_and_list& el )
00206 {
00207     clear_trigger();
00208     el.add_dynamic( this );
00209     m_event_list = ⪙
00210     m_event_count = el.size();
00211     m_trigger_type = AND_LIST;
00212 }
00213 
00214 inline
00215 void
00216 sc_method_process::next_trigger( const sc_time& t )
00217 {
00218     clear_trigger();
00219     m_timeout_event.notify_delayed( t );
00220     m_timeout_event.add_dynamic( this );
00221     m_trigger_type = TIMEOUT;
00222 }
00223 
00224 inline
00225 void
00226 sc_method_process::next_trigger( const sc_time& t, const sc_event& e )
00227 {
00228     clear_trigger();
00229     m_timeout_event.notify_delayed( t );
00230     m_timeout_event.add_dynamic( this );
00231     e.add_dynamic( this );
00232     m_event = &e;
00233     m_trigger_type = EVENT_TIMEOUT;
00234 }
00235 
00236 inline
00237 void
00238 sc_method_process::next_trigger( const sc_time& t, sc_event_or_list& el )
00239 {
00240     clear_trigger();
00241     m_timeout_event.notify_delayed( t );
00242     m_timeout_event.add_dynamic( this );
00243     el.add_dynamic( this );
00244     m_event_list = ⪙
00245     m_trigger_type = OR_LIST_TIMEOUT;
00246 }
00247 
00248 inline
00249 void
00250 sc_method_process::next_trigger( const sc_time& t, sc_event_and_list& el )
00251 {
00252     clear_trigger();
00253     m_timeout_event.notify_delayed( t );
00254     m_timeout_event.add_dynamic( this );
00255     el.add_dynamic( this );
00256     m_event_list = ⪙
00257     m_event_count = el.size();
00258     m_trigger_type = AND_LIST_TIMEOUT;
00259 }
00260 
00261 inline
00262 void sc_method_process::set_next_exist(sc_method_handle next_p)
00263 {
00264     m_exist_p = next_p;
00265 }
00266 
00267 inline
00268 sc_method_handle sc_method_process::next_exist()
00269 {
00270     return (sc_method_handle)m_exist_p;
00271 }
00272 
00273 
00274 inline
00275 void sc_method_process::set_next_runnable(sc_method_handle next_p)
00276 {
00277     m_runnable_p = next_p;
00278 }
00279 
00280 inline
00281 sc_method_handle sc_method_process::next_runnable()
00282 {
00283     return (sc_method_handle)m_runnable_p;
00284 }
00285 
00286 
00287 // ----------------------------------------------------------------------------
00288 //  CLASS : sc_thread_process
00289 //
00290 //  Process class for SC_THREADs.
00291 // ----------------------------------------------------------------------------
00292 
00293 class sc_thread_process
00294 : public sc_process_b
00295 {
00296     friend class sc_event;
00297     friend class sc_module;
00298     friend class sc_process_table;
00299     friend class sc_simcontext;
00300     friend class sc_runnable;
00301 
00302     friend void wait( const sc_event&,
00303                       sc_simcontext* );
00304     friend void wait( sc_event_or_list&,
00305                       sc_simcontext* );
00306     friend void wait( sc_event_and_list&,
00307                       sc_simcontext* );
00308     friend void wait( const sc_time&,
00309                       sc_simcontext* );
00310     friend void wait( const sc_time&, const sc_event&,
00311                       sc_simcontext* );
00312     friend void wait( const sc_time&, sc_event_or_list&,
00313                       sc_simcontext* );
00314     friend void wait( const sc_time&, sc_event_and_list&,
00315                       sc_simcontext* );
00316 
00317 public:
00318 
00319     virtual const char* kind() const
00320         { return "sc_thread_process"; }
00321 
00322 public:
00323 
00324     void add_monitor( sc_process_monitor* monitor_p );
00325     void remove_monitor( sc_process_monitor* monitor_p);
00326     void signal_monitors( int type = 0 );
00327 
00328 protected:
00329 
00330     friend void sc_thread_cor_fn( void* );
00331     friend void sc_cthread_cor_fn( void* );
00332 
00333     sc_thread_process( const char*   nm,
00334                        SC_ENTRY_FUNC fn,
00335                        sc_process_host*    host);
00336 
00337     virtual ~sc_thread_process();
00338 
00339     void set_stack_size( size_t size );
00340 
00341     virtual void prepare_for_simulation();
00342 
00343     virtual bool ready_to_run();
00344 
00345     void wait( const sc_event& );
00346     void wait( sc_event_or_list& );
00347     void wait( sc_event_and_list& );
00348     void wait( const sc_time& );
00349     void wait( const sc_time&, const sc_event& );
00350     void wait( const sc_time&, sc_event_or_list& );
00351     void wait( const sc_time&, sc_event_and_list& );
00352 
00353     bool trigger_dynamic( sc_event* );
00354 
00355     friend void sc_set_stack_size( sc_thread_handle, size_t );
00356 
00357     void set_next_exist( sc_thread_handle next_p );
00358     sc_thread_handle next_exist();
00359     void set_next_runnable( sc_thread_handle next_p );
00360     sc_thread_handle next_runnable();
00361 
00362 protected:
00363 
00364     size_t  m_stack_size;
00365     sc_cor* m_cor;         // the thread's coroutine
00366     sc_pvector<sc_process_monitor*> m_monitor_q; // thread monitors.
00367 };
00368 
00369 
00370 // IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII
00371 
00372 inline
00373 void
00374 sc_switch_thread( sc_simcontext* simc )
00375 {
00376     simc->cor_pkg()->yield( simc->next_cor() );
00377 }
00378 
00379 
00380 // ----------------------------------------------------------------------------
00381 
00382 
00383 inline
00384 bool
00385 sc_thread_process::ready_to_run()
00386 {
00387     return true;
00388 }
00389 
00390 
00391 inline
00392 void
00393 sc_thread_process::wait( const sc_event& e )
00394 {
00395     e.add_dynamic( this );
00396     m_trigger_type = EVENT;
00397     sc_switch_thread( simcontext() );
00398 }
00399 
00400 inline
00401 void
00402 sc_thread_process::wait( sc_event_or_list& el )
00403 {
00404     el.add_dynamic( this );
00405     m_event_list = &el;
00406     m_trigger_type = OR_LIST;
00407     sc_switch_thread( simcontext() );
00408 }
00409 
00410 inline
00411 void
00412 sc_thread_process::wait( sc_event_and_list& el )
00413 {
00414     el.add_dynamic( this );
00415     m_event_list = &el;
00416     m_event_count = el.size();
00417     m_trigger_type = AND_LIST;
00418     sc_switch_thread( simcontext() );
00419 }
00420 
00421 inline
00422 void
00423 sc_thread_process::wait( const sc_time& t )
00424 {
00425     m_timeout_event.notify_delayed( t );
00426     m_timeout_event.add_dynamic( this );
00427     m_trigger_type = TIMEOUT;
00428     sc_switch_thread( simcontext() );
00429 }
00430 
00431 inline
00432 void
00433 sc_thread_process::wait( const sc_time& t, const sc_event& e )
00434 {
00435     m_timeout_event.notify_delayed( t );
00436     m_timeout_event.add_dynamic( this );
00437     e.add_dynamic( this );
00438     m_event = &e;
00439     m_trigger_type = EVENT_TIMEOUT;
00440     sc_switch_thread( simcontext() );
00441 }
00442 
00443 inline
00444 void
00445 sc_thread_process::wait( const sc_time& t, sc_event_or_list& el )
00446 {
00447     m_timeout_event.notify_delayed( t );
00448     m_timeout_event.add_dynamic( this );
00449     el.add_dynamic( this );
00450     m_event_list = &el;
00451     m_trigger_type = OR_LIST_TIMEOUT;
00452     sc_switch_thread( simcontext() );
00453 }
00454 
00455 inline
00456 void
00457 sc_thread_process::wait( const sc_time& t, sc_event_and_list& el )
00458 {
00459     m_timeout_event.notify_delayed( t );
00460     m_timeout_event.add_dynamic( this );
00461     el.add_dynamic( this );
00462     m_event_list = &el;
00463     m_event_count = el.size();
00464     m_trigger_type = AND_LIST_TIMEOUT;
00465     sc_switch_thread( simcontext() );
00466 }
00467 
00468 inline
00469 void sc_thread_process::add_monitor(sc_process_monitor* monitor_p)
00470 {
00471     m_monitor_q.push_back(monitor_p);
00472 }
00473 
00474 
00475 inline
00476 void sc_thread_process::remove_monitor(sc_process_monitor* monitor_p)
00477 {
00478     int mon_n = m_monitor_q.size();
00479 
00480     for ( int mon_i = 0; mon_i < mon_n; mon_i++ )
00481     {
00482         if  ( m_monitor_q[mon_i] == monitor_p )
00483         {
00484             m_monitor_q[mon_i] = m_monitor_q[mon_n-1];
00485             m_monitor_q.decr_count();
00486         }
00487     }
00488 }
00489 
00490 inline
00491 void sc_thread_process::set_next_exist(sc_thread_handle next_p)
00492 {
00493     m_exist_p = next_p;
00494 }
00495 
00496 inline
00497 sc_thread_handle sc_thread_process::next_exist()
00498 {
00499     return (sc_thread_handle)m_exist_p;
00500 }
00501 
00502 inline
00503 void sc_thread_process::set_next_runnable(sc_thread_handle next_p)
00504 {
00505     m_runnable_p = next_p;
00506 }
00507 
00508 inline
00509 sc_thread_handle sc_thread_process::next_runnable()
00510 {
00511     return (sc_thread_handle)m_runnable_p;
00512 }
00513 
00514 
00515 
00516 // ----------------------------------------------------------------------------
00517 //  CLASS : sc_cthread_process
00518 //
00519 //  Process class for SC_CTHREADs.
00520 // ----------------------------------------------------------------------------
00521 
00522 class sc_cthread_process
00523 : public sc_thread_process
00524 {
00525     friend class sc_module;
00526     friend class sc_process_table;
00527     friend class sc_simcontext;
00528     friend class sc_thread_process;
00529 
00530     friend void wait( sc_simcontext* );
00531     friend void wait( const sc_event&,
00532                       sc_simcontext* );
00533     friend void wait( sc_event_or_list&,
00534                       sc_simcontext* );
00535     friend void wait( sc_event_and_list&,
00536                       sc_simcontext* );
00537     friend void wait( const sc_time&,
00538                       sc_simcontext* );
00539     friend void wait( const sc_time&, const sc_event&,
00540                       sc_simcontext* );
00541     friend void wait( const sc_time&, sc_event_or_list&,
00542                       sc_simcontext* );
00543     friend void wait( const sc_time&, sc_event_and_list&,
00544                       sc_simcontext* );
00545 
00546     friend void halt( sc_simcontext* );
00547     friend void wait( int,
00548                       sc_simcontext* );
00549     friend void wait_until( const sc_lambda_ptr&,
00550                             sc_simcontext* );
00551     friend void watching_before_simulation( const sc_lambda_ptr&,
00552                                             sc_simcontext* );
00553     friend void watching_during_simulation( const sc_lambda_ptr&,
00554                                             sc_simcontext* );
00555 
00556     friend void __reset_watching( sc_cthread_handle );
00557     friend void __open_watching( sc_cthread_handle );
00558     friend void __close_watching( sc_cthread_handle );
00559     friend int  __watch_level( sc_cthread_handle );
00560     friend void __watching_first( sc_cthread_handle );
00561     friend void __sanitycheck_watchlists( sc_cthread_handle );
00562 
00563     void set_next_exist( sc_cthread_handle next_p );
00564     sc_cthread_handle next_exist();
00565 
00566 public:
00567 
00568     virtual const char* kind() const
00569         { return "sc_cthread_process"; }
00570 
00571 protected:
00572     friend void sc_cthread_cor_fn( void* );
00573     virtual ~sc_cthread_process();
00574 
00575 private:
00576 
00577     sc_cthread_process( const char*   nm,
00578                         SC_ENTRY_FUNC fn,
00579                         sc_process_host*    host );
00580      
00581     virtual bool is_cthread() const;
00582 
00583     virtual void prepare_for_simulation();
00584 
00585     virtual bool ready_to_run();
00586 
00587 
00588     bool eval_watchlist();
00589     bool eval_watchlist_curr_level();
00590 
00591     void wait_halt();
00592     void wait_clock( int = 1 );
00593     void wait_lambda( const sc_lambda_ptr& );
00594     void add_lambda( const sc_lambda_ptr& );
00595 
00596     void __reset_watching();
00597     void __open_watching();
00598     void __close_watching();
00599     int  __watch_level() const;
00600 
00601 private:
00602 
00603     typedef sc_pvector<sc_plist<sc_lambda_ptr*>* > watchlists_t;
00604 
00605     enum { UNKNOWN, CLOCK, LAMBDA } m_wait_state;
00606     int                             m_wait_cycles;
00607     sc_lambda_ptr                   m_wait_lambda;
00608     int                             m_exception_level;
00609 
00610     int                             m_watch_level;
00611 
00612     watchlists_t                    m_watchlists;
00613 };
00614 
00615 
00616 // IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII
00617 inline
00618 void sc_cthread_process::set_next_exist(sc_cthread_handle next_p)
00619 {
00620     m_exist_p = next_p;
00621 }
00622 
00623 inline
00624 sc_cthread_handle sc_cthread_process::next_exist()
00625 {
00626     return (sc_cthread_handle)m_exist_p;
00627 }
00628 
00629 
00630 inline
00631 void
00632 sc_cthread_process::wait_halt()
00633 {
00634     m_wait_cycles = 1;
00635     m_wait_state = CLOCK;
00636     sc_switch_thread( simcontext() );
00637     throw sc_halt();
00638 }
00639 
00640 inline
00641 void
00642 sc_cthread_process::wait_clock( int n  )
00643 {
00644     m_wait_cycles = n;
00645     m_wait_state = CLOCK;
00646     sc_switch_thread( simcontext() );
00647     m_wait_state = UNKNOWN;
00648     if( m_exception_level == 0 ) {
00649 
00650         throw sc_user();
00651 
00652     } else if( m_exception_level > 0 ) {
00653         throw m_exception_level;
00654     }
00655 }
00656 
00657 inline
00658 void
00659 sc_cthread_process::wait_lambda( const sc_lambda_ptr& lambda )
00660 {
00661     m_wait_lambda = lambda;
00662     m_wait_state = LAMBDA;
00663     sc_switch_thread( simcontext() );
00664     m_wait_state = UNKNOWN;
00665     if( m_exception_level == 0 ) {
00666 
00667         throw sc_user();
00668 
00669     } else if( m_exception_level > 0 ) {
00670         throw m_exception_level;
00671     }
00672 }
00673 
00674 inline
00675 void
00676 sc_cthread_process::add_lambda( const sc_lambda_ptr& lambda )
00677 {
00678     assert( m_watch_level < SC_MAX_WATCH_LEVEL );
00679     m_watchlists[m_watch_level]->push_back( new sc_lambda_ptr( lambda ) );
00680 }
00681 
00682 
00683 inline
00684 void
00685 sc_cthread_process::__reset_watching()
00686 {
00687     m_watch_level = 0;
00688 }
00689 
00690 inline
00691 void
00692 sc_cthread_process::__open_watching()
00693 {
00694     m_watch_level ++;
00695 }
00696 
00697 inline
00698 void
00699 sc_cthread_process::__close_watching()
00700 {
00701     m_watch_level --;
00702     assert( m_watch_level >= 0 );
00703 }
00704 
00705 inline
00706 int
00707 sc_cthread_process::__watch_level() const
00708 {
00709     return m_watch_level;
00710 }
00711 
00712 } // namespace sc_core
00713 
00714 #endif
00715 
00716 // Taf!

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