1/*****************************************************************************
2
3  Licensed to Accellera Systems Initiative Inc. (Accellera) under one or
4  more contributor license agreements.  See the NOTICE file distributed
5  with this work for additional information regarding copyright ownership.
6  Accellera licenses this file to you under the Apache License, Version 2.0
7  (the "License"); you may not use this file except in compliance with the
8  License.  You may obtain a copy of the License at
9
10    http://www.apache.org/licenses/LICENSE-2.0
11
12  Unless required by applicable law or agreed to in writing, software
13  distributed under the License is distributed on an "AS IS" BASIS,
14  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
15  implied.  See the License for the specific language governing
16  permissions and limitations under the License.
17
18 *****************************************************************************/
19
20/*****************************************************************************
21
22  sc_event.h --
23
24  Original Author: Martin Janssen, Synopsys, Inc., 2001-05-21
25
26  CHANGE LOG AT THE END OF THE FILE
27 *****************************************************************************/
28
29
30#ifndef SC_EVENT_H
31#define SC_EVENT_H
32
33#include "sysc/kernel/sc_cmnhdr.h"
34#include "sysc/kernel/sc_kernel_ids.h"
35#include "sysc/kernel/sc_simcontext.h"
36#include "sysc/communication/sc_writer_policy.h"
37
38namespace sc_core {
39
40// forward declarations
41class sc_event;
42class sc_event_timed;
43class sc_event_list;
44class sc_event_or_list;
45class sc_event_and_list;
46class sc_object;
47
48// friend function declarations
49    int sc_notify_time_compare( const void*, const void* );
50
51// ----------------------------------------------------------------------------
52//  CLASS : sc_event_expr
53//
54//  The event expression class.
55// ----------------------------------------------------------------------------
56
57template< typename T >
58class sc_event_expr
59{
60    friend class sc_event;
61    friend class sc_event_and_list;
62    friend class sc_event_or_list;
63
64    typedef T type;
65
66    inline sc_event_expr()
67       : m_expr( new T(true) )
68    {}
69
70public:
71
72    inline sc_event_expr( sc_event_expr const & e) // move semantics
73      : m_expr(e.m_expr)
74    {
75        e.m_expr = 0;
76    }
77
78    T const & release() const
79    {
80        sc_assert( m_expr );
81        T* expr = m_expr;
82        m_expr=0;
83        return *expr;
84    }
85
86    void push_back( sc_event const & e) const
87    {
88        sc_assert( m_expr );
89        m_expr->push_back(e);
90    }
91
92    void push_back( type const & el) const
93    {
94        sc_assert( m_expr );
95        m_expr->push_back(el);
96    }
97    operator T const &() const
98    {
99        return release();
100    }
101
102    ~sc_event_expr()
103    {
104        delete m_expr;
105    }
106
107private:
108    mutable type * m_expr;
109
110    // disabled
111    void operator=( sc_event_expr const & );
112};
113
114// ----------------------------------------------------------------------------
115//  CLASS : sc_event_list
116//
117//  Base class for lists of events.
118// ----------------------------------------------------------------------------
119
120class sc_event_list
121{
122    friend class sc_process_b;
123    friend class sc_method_process;
124    friend class sc_thread_process;
125    friend void sc_thread_cor_fn( void* arg );
126
127public:
128    sc_event_list( const sc_event_list& );
129    sc_event_list& operator = ( const sc_event_list& );
130
131    int size() const;
132
133protected:
134
135    void push_back( const sc_event& );
136    void push_back( const sc_event_list& );
137
138    explicit
139    sc_event_list( bool and_list_, bool auto_delete_ = false );
140
141    sc_event_list( const sc_event&,
142                   bool and_list_,
143                   bool auto_delete_ = false );
144
145    ~sc_event_list();
146
147    void swap( sc_event_list& );
148    void move_from( const sc_event_list& );
149
150    bool and_list() const;
151
152    void add_dynamic( sc_method_handle ) const;
153    void add_dynamic( sc_thread_handle ) const;
154    void remove_dynamic( sc_method_handle, const sc_event* ) const;
155    void remove_dynamic( sc_thread_handle, const sc_event* ) const;
156
157    bool busy()        const;
158    bool temporary()   const;
159    void auto_delete() const;
160
161    void report_premature_destruction() const;
162    void report_invalid_modification()  const;
163
164private:
165
166    std::vector<const sc_event*> m_events;
167    bool                         m_and_list;
168    bool                         m_auto_delete;
169    mutable unsigned             m_busy;
170};
171
172
173// ----------------------------------------------------------------------------
174//  CLASS : sc_event_and_list
175//
176//  AND list of events.
177// ----------------------------------------------------------------------------
178
179class sc_event_and_list
180: public sc_event_list
181{
182    friend class sc_event;
183    friend class sc_event_expr<sc_event_and_list>;
184    friend class sc_process_b;
185    friend class sc_method_process;
186    friend class sc_thread_process;
187
188protected:
189
190    explicit
191    sc_event_and_list( bool auto_delete_ );
192
193public:
194
195    sc_event_and_list();
196    sc_event_and_list( const sc_event& );
197
198    void swap( sc_event_and_list& );
199    sc_event_and_list& operator &= ( const sc_event& );
200    sc_event_and_list& operator &= ( const sc_event_and_list & );
201
202    sc_event_expr<sc_event_and_list>  operator & ( const sc_event& );
203    sc_event_expr<sc_event_and_list>  operator & ( const sc_event_and_list& );
204};
205
206typedef sc_event_expr<sc_event_and_list> sc_event_and_expr;
207
208// ----------------------------------------------------------------------------
209//  CLASS : sc_event_or_list
210//
211//  OR list of events.
212// ----------------------------------------------------------------------------
213
214class sc_event_or_list
215: public sc_event_list
216{
217    friend class sc_event;
218    friend class sc_event_expr<sc_event_or_list>;
219    friend class sc_process_b;
220    friend class sc_method_process;
221    friend class sc_thread_process;
222
223protected:
224
225    explicit
226    sc_event_or_list( bool auto_delete_ );
227
228public:
229    sc_event_or_list();
230    sc_event_or_list( const sc_event& );
231    void swap( sc_event_or_list& );
232    sc_event_or_list& operator |= ( const sc_event& );
233    sc_event_or_list& operator |= ( const sc_event_or_list & );
234    sc_event_expr<sc_event_or_list>  operator | ( const sc_event& ) const;
235    sc_event_expr<sc_event_or_list>  operator | ( const sc_event_or_list& ) const;
236};
237
238typedef sc_event_expr<sc_event_or_list> sc_event_or_expr;
239
240// ----------------------------------------------------------------------------
241//  CLASS : sc_event
242//
243//  The event class.
244// ----------------------------------------------------------------------------
245
246class sc_event
247{
248    friend class sc_clock;
249    friend class sc_event_list;
250    friend class sc_event_timed;
251    friend class sc_simcontext;
252    friend class sc_object;
253    friend class sc_process_b;
254    friend class sc_method_process;
255    friend class sc_thread_process;
256    template<typename IF, sc_writer_policy POL> friend class sc_signal;
257    friend void sc_thread_cor_fn( void* arg );
258
259public:
260
261    sc_event();
262    sc_event( const char* name );
263    ~sc_event();
264
265    void cancel();
266
267    const char* name() const             { return m_name.c_str(); }
268    const char* basename() const;
269    sc_object* get_parent_object() const { return m_parent_p; }
270    bool in_hierarchy() const            { return m_name.length() != 0; }
271
272    void notify();
273    void notify( const sc_time& );
274    void notify( double, sc_time_unit );
275
276    void notify_delayed();
277    void notify_delayed( const sc_time& );
278    void notify_delayed( double, sc_time_unit );
279
280    sc_event_or_expr  operator | ( const sc_event& ) const;
281    sc_event_or_expr  operator | ( const sc_event_or_list& ) const;
282    sc_event_and_expr operator & ( const sc_event& ) const;
283    sc_event_and_expr operator & ( const sc_event_and_list& ) const;
284
285
286private:
287
288    void add_static( sc_method_handle ) const;
289    void add_static( sc_thread_handle ) const;
290    void add_dynamic( sc_method_handle ) const;
291    void add_dynamic( sc_thread_handle ) const;
292
293    void notify_internal( const sc_time& );
294    void notify_next_delta();
295
296    bool remove_static( sc_method_handle ) const;
297    bool remove_static( sc_thread_handle ) const;
298    bool remove_dynamic( sc_method_handle ) const;
299    bool remove_dynamic( sc_thread_handle ) const;
300
301    void register_event( const char* name );
302    void reset();
303
304    void trigger();
305
306private:
307
308    enum notify_t { NONE, DELTA, TIMED };
309
310    std::string     m_name;     // name of object.
311    sc_object*      m_parent_p; // parent sc_object for this event.
312    sc_simcontext*  m_simc;
313    notify_t        m_notify_type;
314    int             m_delta_event_index;
315    sc_event_timed* m_timed;
316
317    mutable std::vector<sc_method_handle> m_methods_static;
318    mutable std::vector<sc_method_handle> m_methods_dynamic;
319    mutable std::vector<sc_thread_handle> m_threads_static;
320    mutable std::vector<sc_thread_handle> m_threads_dynamic;
321
322private:
323
324    // disabled
325    sc_event( const sc_event& );
326    sc_event& operator = ( const sc_event& );
327};
328
329#define SC_KERNEL_EVENT_PREFIX "$$$$kernel_event$$$$_"
330
331extern sc_event sc_non_event; // Event that never happens.
332
333// ----------------------------------------------------------------------------
334//  CLASS : sc_event_timed
335//
336//  Class for storing the time to notify a timed event.
337// ----------------------------------------------------------------------------
338
339class sc_event_timed
340{
341    friend class sc_event;
342    friend class sc_simcontext;
343
344    friend int sc_notify_time_compare( const void*, const void* );
345
346private:
347
348    sc_event_timed( sc_event* e, const sc_time& t )
349        : m_event( e ), m_notify_time( t )
350        {}
351
352    ~sc_event_timed()
353        { if( m_event != 0 ) { m_event->m_timed = 0; } }
354
355    sc_event* event() const
356        { return m_event; }
357
358    const sc_time& notify_time() const
359        { return m_notify_time; }
360
361    static void* operator new( std::size_t )
362        { return allocate(); }
363
364    static void operator delete( void* p, std::size_t )
365        { deallocate( p ); }
366
367private:
368
369    // dedicated memory management
370    static void* allocate();
371    static void  deallocate( void* );
372
373private:
374
375    sc_event* m_event;
376    sc_time   m_notify_time;
377
378private:
379
380    // disabled
381    sc_event_timed();
382    sc_event_timed( const sc_event_timed& );
383    sc_event_timed& operator = ( const sc_event_timed& );
384};
385
386
387// IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII
388
389inline
390void
391sc_event::notify( double v, sc_time_unit tu )
392{
393    notify( sc_time( v, tu, m_simc ) );
394}
395
396
397inline
398void
399sc_event::notify_internal( const sc_time& t )
400{
401    if( t == SC_ZERO_TIME ) {
402        // add this event to the delta events set
403        m_delta_event_index = m_simc->add_delta_event( this );
404        m_notify_type = DELTA;
405    } else {
406        sc_event_timed* et =
407		new sc_event_timed( this, m_simc->time_stamp() + t );
408        m_simc->add_timed_event( et );
409        m_timed = et;
410        m_notify_type = TIMED;
411    }
412}
413
414inline
415void
416sc_event::notify_next_delta()
417{
418    if( m_notify_type != NONE ) {
419        SC_REPORT_ERROR( SC_ID_NOTIFY_DELAYED_, 0 );
420    }
421    // add this event to the delta events set
422    m_delta_event_index = m_simc->add_delta_event( this );
423    m_notify_type = DELTA;
424}
425
426inline
427void
428sc_event::notify_delayed( double v, sc_time_unit tu )
429{
430    notify_delayed( sc_time( v, tu, m_simc ) );
431}
432
433
434inline
435void
436sc_event::add_static( sc_method_handle method_h ) const
437{
438    m_methods_static.push_back( method_h );
439}
440
441inline
442void
443sc_event::add_static( sc_thread_handle thread_h ) const
444{
445    m_threads_static.push_back( thread_h );
446}
447
448inline
449void
450sc_event::add_dynamic( sc_method_handle method_h ) const
451{
452    m_methods_dynamic.push_back( method_h );
453}
454
455inline
456void
457sc_event::add_dynamic( sc_thread_handle thread_h ) const
458{
459    m_threads_dynamic.push_back( thread_h );
460}
461
462
463// ----------------------------------------------------------------------------
464//  Deprecated functional notation for notifying events.
465// ----------------------------------------------------------------------------
466
467extern void notify( sc_event& e );
468extern void notify( const sc_time& t, sc_event& e );
469extern void notify( double v, sc_time_unit tu, sc_event& e );
470
471
472// IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII
473
474inline
475sc_event_list::sc_event_list( bool and_list_, bool auto_delete_ )
476  : m_events()
477  , m_and_list( and_list_ )
478  , m_auto_delete( auto_delete_ )
479  , m_busy( 0 )
480{
481}
482
483inline
484sc_event_list::sc_event_list( const sc_event& e,
485                              bool and_list_,
486                              bool auto_delete_ )
487  : m_events()
488  , m_and_list( and_list_ )
489  , m_auto_delete( auto_delete_ )
490  , m_busy(0)
491{
492    m_events.push_back( &e );
493}
494
495inline
496sc_event_list::sc_event_list( sc_event_list const & that )
497  : m_events()
498  , m_and_list( that.m_and_list )
499  , m_auto_delete( false )
500  , m_busy( 0 )
501{
502    move_from( that );
503    that.auto_delete(); // free automatic lists
504}
505
506inline
507sc_event_list&
508sc_event_list::operator=( sc_event_list const & that )
509{
510    if( m_busy )
511        report_invalid_modification();
512
513    move_from( that );
514    that.auto_delete(); // free automatic lists
515
516    return *this;
517}
518
519inline
520sc_event_list::~sc_event_list()
521{
522    if( m_busy )
523        report_premature_destruction();
524}
525
526inline
527void
528sc_event_list::swap( sc_event_list& that )
529{
530    if( busy() || that.busy() )
531        report_invalid_modification();
532    m_events.swap( that.m_events );
533}
534
535inline
536void
537sc_event_list::move_from( sc_event_list const&  that )
538{
539    if( that.temporary() ) {
540        swap( const_cast<sc_event_list&>(that) ); // move from source
541    } else {
542        m_events = that.m_events;                 // copy from source
543    }
544}
545
546inline
547int
548sc_event_list::size() const
549{
550    return m_events.size();
551}
552
553inline
554bool
555sc_event_list::and_list() const
556{
557    return m_and_list;
558}
559
560
561inline
562bool
563sc_event_list::busy() const
564{
565    return m_busy != 0;
566}
567
568
569inline
570bool
571sc_event_list::temporary() const
572{
573    return m_auto_delete && ! m_busy;
574}
575
576inline
577void
578sc_event_list::auto_delete() const
579{
580    if( m_busy ) {
581        --m_busy;
582    }
583    if( ! m_busy && m_auto_delete ) {
584        delete this;
585    }
586}
587
588
589
590// IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII
591
592inline
593sc_event_or_list::sc_event_or_list()
594  : sc_event_list( false )
595{}
596
597inline
598sc_event_or_list::sc_event_or_list( const sc_event& e )
599: sc_event_list( false )
600{
601  push_back( e );
602}
603
604inline
605sc_event_or_list::sc_event_or_list( bool auto_delete_ )
606: sc_event_list( false, auto_delete_ )
607{}
608
609inline
610sc_event_or_list&
611sc_event_or_list::operator |= ( const sc_event& e )
612{
613    if( busy() )
614        report_invalid_modification();
615
616    push_back( e );
617    return *this;
618}
619
620inline
621sc_event_or_list&
622sc_event_or_list::operator |= ( const sc_event_or_list& el )
623{
624    if( busy() )
625        report_invalid_modification();
626
627    push_back( el );
628    return *this;
629}
630
631inline
632sc_event_or_expr
633sc_event_or_list::operator | ( const sc_event& e2 ) const
634{
635    sc_event_or_expr expr;
636    expr.push_back( *this );
637    expr.push_back( e2 );
638    return expr;
639}
640
641inline
642sc_event_or_expr
643sc_event_or_list::operator | ( const sc_event_or_list& e2 ) const
644{
645    sc_event_or_expr expr;
646    expr.push_back( *this );
647    expr.push_back( e2 );
648    return expr;
649}
650
651
652// sc_event
653
654inline
655sc_event_or_expr
656sc_event::operator | ( const sc_event& e2 ) const
657{
658    sc_event_or_expr expr;
659    expr.push_back( *this );
660    expr.push_back( e2 );
661    return expr;
662}
663
664inline
665sc_event_or_expr
666sc_event::operator | ( const sc_event_or_list& e2 ) const
667{
668    sc_event_or_expr expr;
669    expr.push_back( *this );
670    expr.push_back( e2 );
671    return expr;
672}
673
674// sc_event_expr
675
676inline
677sc_event_or_expr
678operator | ( sc_event_or_expr expr, sc_event const & e )
679{
680    expr.push_back( e );
681    return expr;
682}
683
684inline
685sc_event_or_expr
686operator | ( sc_event_or_expr expr, sc_event_or_list const & el )
687{
688    expr.push_back( el );
689    return expr;
690}
691
692inline
693void
694sc_event_or_list::swap( sc_event_or_list & that )
695{
696  sc_event_list::swap( that );
697}
698
699
700
701// IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII
702
703inline
704sc_event_and_list::sc_event_and_list()
705  : sc_event_list( true )
706{}
707
708inline
709sc_event_and_list::sc_event_and_list( const sc_event& e )
710: sc_event_list( true )
711{
712  push_back( e );
713}
714
715inline
716sc_event_and_list::sc_event_and_list( bool auto_delete_ )
717: sc_event_list( true, auto_delete_ )
718{}
719
720inline
721void
722sc_event_and_list::swap( sc_event_and_list & that )
723{
724  sc_event_list::swap( that );
725}
726
727
728inline
729sc_event_and_list&
730sc_event_and_list::operator &= ( const sc_event& e )
731{
732    if( busy() )
733        report_invalid_modification();
734
735    push_back( e );
736    return *this;
737}
738
739inline
740sc_event_and_list&
741sc_event_and_list::operator &= ( const sc_event_and_list& el )
742{
743    if( busy() )
744        report_invalid_modification();
745
746    push_back( el );
747    return *this;
748}
749
750inline
751sc_event_and_expr
752sc_event_and_list::operator & ( const sc_event& e )
753{
754    sc_event_and_expr expr;
755    expr.push_back( *this );
756    expr.push_back( e );
757    return expr;
758}
759
760inline
761sc_event_and_expr
762sc_event_and_list::operator & ( const sc_event_and_list& el )
763{
764    sc_event_and_expr expr;
765    expr.push_back( *this );
766    expr.push_back( el );
767    return expr;
768}
769
770// sc_event
771
772inline
773sc_event_and_expr
774sc_event::operator & ( const sc_event& e2 ) const
775{
776    sc_event_and_expr expr;
777    expr.push_back( *this );
778    expr.push_back( e2 );
779    return expr;
780}
781
782inline
783sc_event_and_expr
784sc_event::operator & ( const sc_event_and_list& e2 ) const
785{
786    sc_event_and_expr expr;
787    expr.push_back( *this );
788    expr.push_back( e2 );
789    return expr;
790}
791
792// sc_event_expr
793
794inline
795sc_event_and_expr
796operator & ( sc_event_and_expr expr, sc_event const & e )
797{
798    expr.push_back( e );
799    return expr;
800}
801
802inline
803sc_event_and_expr
804operator & ( sc_event_and_expr expr, sc_event_and_list const & el )
805{
806    expr.push_back( el );
807    return expr;
808}
809
810} // namespace sc_core
811
812// $Log: sc_event.h,v $
813// Revision 1.14  2011/08/29 18:04:32  acg
814//  Philipp A. Hartmann: miscellaneous clean ups.
815//
816// Revision 1.13  2011/08/26 20:46:09  acg
817//  Andy Goodrich: moved the modification log to the end of the file to
818//  eliminate source line number skew when check-ins are done.
819//
820// Revision 1.12  2011/08/24 22:05:50  acg
821//  Torsten Maehne: initialization changes to remove warnings.
822//
823// Revision 1.11  2011/03/12 21:07:51  acg
824//  Andy Goodrich: changes to kernel generated event support.
825//
826// Revision 1.10  2011/03/06 15:55:11  acg
827//  Andy Goodrich: Changes for named events.
828//
829// Revision 1.9  2011/03/05 01:39:21  acg
830//  Andy Goodrich: changes for named events.
831//
832// Revision 1.8  2011/02/18 20:27:14  acg
833//  Andy Goodrich: Updated Copyrights.
834//
835// Revision 1.7  2011/02/13 21:47:37  acg
836//  Andy Goodrich: update copyright notice.
837//
838// Revision 1.6  2011/02/01 21:03:23  acg
839//  Andy Goodrich: new return codes for trigger_dynamic calls.
840//
841// Revision 1.5  2011/01/18 20:10:44  acg
842//  Andy Goodrich: changes for IEEE1666_2011 semantics.
843//
844// Revision 1.4  2010/12/07 20:09:11  acg
845// Andy Goodrich: writer policy fix.
846//
847// Revision 1.3  2009/05/22 16:06:29  acg
848//  Andy Goodrich: process control updates.
849//
850// Revision 1.2  2008/05/22 17:06:25  acg
851//  Andy Goodrich: updated copyright notice to include 2008.
852//
853// Revision 1.1.1.1  2006/12/15 20:20:05  acg
854// SystemC 2.3
855//
856// Revision 1.8  2006/05/26 20:33:16  acg
857//   Andy Goodrich: changes required by additional platform compilers (i.e.,
858//   Microsoft VC++, Sun Forte, HP aCC).
859//
860// Revision 1.7  2006/05/08 17:57:51  acg
861// Andy Goodrich: added David Long's forward declarations for friend
862//   functions, methods, and operators to keep the Microsoft compiler happy.
863//
864// Revision 1.6  2006/04/11 23:13:20  acg
865//   Andy Goodrich: Changes for reduced reset support that only includes
866//   sc_cthread, but has preliminary hooks for expanding to method and thread
867//   processes also.
868//
869// Revision 1.5  2006/01/24 20:56:00  acg
870//  Andy Goodrich: fixed up CVS comment.
871//
872// Revision 1.4  2006/01/24 20:48:14  acg
873// Andy Goodrich: added deprecation warnings for notify_delayed(). Added two
874// new implementation-dependent methods, notify_next_delta() & notify_internal()
875// to replace calls to notify_delayed() from within the simulator. These two
876// new methods are simpler than notify_delayed() and should speed up simulations
877//
878// Revision 1.3  2006/01/13 18:44:29  acg
879// Added $Log to record CVS changes into the source.
880//
881
882#endif
883
884// Taf!
885