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_port.h -- Base classes of all port classes.
23
24  Original Author: Martin Janssen, Synopsys, Inc., 2001-05-21
25
26  CHANGE LOG IS AT THE END OF THE FILE
27 *****************************************************************************/
28
29#ifndef SC_PORT_H
30#define SC_PORT_H
31
32
33#include "sysc/communication/sc_communication_ids.h"
34#include "sysc/communication/sc_interface.h"
35#include "sysc/kernel/sc_event.h"
36#include "sysc/kernel/sc_object.h"
37#include "sysc/kernel/sc_process.h"
38#include <typeinfo>
39
40#if ! defined( SC_DISABLE_VIRTUAL_BIND )
41#  define SC_VIRTUAL_ virtual
42#else
43#  define SC_VIRTUAL_ /* non-virtual */
44#endif
45
46namespace sc_core {
47
48class sc_event_finder;
49
50struct sc_bind_info;
51
52enum sc_port_policy
53{
54    SC_ONE_OR_MORE_BOUND,   // Default
55    SC_ZERO_OR_MORE_BOUND,
56    SC_ALL_BOUND
57};
58
59
60// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
61//  BEWARE: Ports can only be created and bound during elaboration.
62// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
63
64
65// ----------------------------------------------------------------------------
66//  CLASS : sc_port_base
67//
68//  Abstract base class for class sc_port_b.
69// ----------------------------------------------------------------------------
70
71class sc_port_base
72: public sc_object
73{
74    friend class sc_module;
75    friend class sc_port_registry;
76    friend class sc_sensitive;
77    friend class sc_sensitive_pos;
78    friend class sc_sensitive_neg;
79
80public:
81
82    // typedefs
83
84    typedef sc_port_base this_type;
85
86public:
87
88    int bind_count();
89
90    // get the first interface without checking for nil
91    virtual       sc_interface* get_interface()       = 0;
92    virtual const sc_interface* get_interface() const = 0;
93
94    virtual const char* kind() const
95        { return "sc_port_base"; }
96
97protected:
98
99    // constructors
100    explicit sc_port_base( int max_size_,
101	    sc_port_policy policy=SC_ONE_OR_MORE_BOUND );
102    sc_port_base( const char* name_, int max_size_,
103		  sc_port_policy policy=SC_ONE_OR_MORE_BOUND );
104
105    // destructor
106    virtual ~sc_port_base();
107
108    // bind interface to this port
109    void bind( sc_interface& interface_ );
110
111    // bind parent port to this port
112    void bind( this_type& parent_ );
113
114    // called by pbind (for internal use only)
115    virtual int vbind( sc_interface& ) = 0;
116    virtual int vbind( sc_port_base& ) = 0;
117
118    // called by complete_binding (for internal use only)
119    virtual void add_interface( sc_interface* ) = 0;
120	virtual int interface_count() = 0;
121    virtual const char* if_typename() const = 0;
122
123    // called by construction_done (does nothing by default)
124    virtual void before_end_of_elaboration();
125
126    // called by elaboration_done (does nothing)
127    virtual void end_of_elaboration();
128
129    // called by start_simulation (does nothing by default)
130    virtual void start_of_simulation();
131
132    // called by simulation_done (does nothing by default)
133    virtual void end_of_simulation();
134
135    // error reporting
136    void report_error( const char* id, const char* add_msg = 0) const;
137
138protected:
139    // called by the sc_sensitive* classes
140    virtual void make_sensitive( sc_thread_handle, sc_event_finder* = 0 ) const;
141    virtual void make_sensitive( sc_method_handle, sc_event_finder* = 0 ) const;
142    void add_static_event(
143		sc_method_handle process_p, const sc_event& event) const;
144    void add_static_event(
145		sc_thread_handle process_p, const sc_event& event) const;
146
147private:
148
149    // called by class sc_module for positional binding
150    int pbind( sc_interface& );
151    int pbind( sc_port_base& );
152
153
154    // support methods
155    int first_parent();
156    void insert_parent( int );
157
158    // called when construction is done
159    void construction_done();
160
161    // called when elaboration is done
162    void complete_binding();
163    void elaboration_done();
164
165    // called before simulation starts
166    void start_simulation();
167
168    // called after simulation ends
169    void simulation_done();
170
171protected:
172
173    sc_bind_info* m_bind_info;
174
175private:
176
177    // disabled
178    sc_port_base();
179    sc_port_base( const this_type& );
180    this_type& operator = ( const this_type& );
181};
182
183
184// ----------------------------------------------------------------------------
185//  CLASS : sc_port_registry
186//
187//  Registry for all ports.
188//  FOR INTERNAL USE ONLY!
189// ----------------------------------------------------------------------------
190
191class sc_port_registry
192{
193    friend class sc_simcontext;
194
195public:
196
197    void insert( sc_port_base* );
198    void remove( sc_port_base* );
199
200    int size() const
201        { return m_port_vec.size(); }
202
203private:
204
205    // constructor
206    explicit sc_port_registry( sc_simcontext& simc_ );
207
208    // destructor
209    ~sc_port_registry();
210
211    // called when by construction_done and elaboration done
212    void complete_binding();
213
214    // called when construction is done
215    bool construction_done();
216
217    // called when elaboration is done
218    void elaboration_done();
219
220    // called before simulation starts
221    void start_simulation();
222
223    // called after simulation ends
224    void simulation_done();
225
226    static void replace_port( sc_port_registry* );
227
228private:
229
230    int                         m_construction_done;
231    std::vector<sc_port_base*>  m_port_vec;
232    sc_simcontext*              m_simc;
233
234private:
235
236    // disabled
237    sc_port_registry();
238    sc_port_registry( const sc_port_registry& );
239    sc_port_registry& operator = ( const sc_port_registry& );
240};
241
242
243// ----------------------------------------------------------------------------
244//  CLASS : sc_port_b
245//
246//  Abstract base class for class sc_port.
247// ----------------------------------------------------------------------------
248
249template <class IF>
250class sc_port_b
251: public sc_port_base
252{
253public:
254
255    friend class sc_sensitive;
256    friend class sc_sensitive_neg;
257    friend class sc_sensitive_pos;
258
259    // typedefs
260
261    typedef sc_port_base  base_type;
262    typedef sc_port_b<IF> this_type;
263    typedef this_type     port_type;
264
265public:
266
267    // bind an interface of type IF to this port
268
269    SC_VIRTUAL_ void bind( IF& interface_ )
270	{ base_type::bind( interface_ ); }
271
272    void operator () ( IF& interface_ )
273	{ this->bind( interface_ ); }
274
275
276    // bind a parent port with type IF to this port
277
278    SC_VIRTUAL_ void bind( port_type& parent_ )
279	{ base_type::bind( parent_ ); }
280
281    void operator () ( port_type& parent_ )
282	{ this->bind( parent_ ); }
283
284
285    // number of connected interfaces
286
287    int size() const
288	{ return m_interface_vec.size(); }
289
290
291    // allow to call methods provided by the first interface
292    IF* operator -> ();
293    const IF* operator -> () const;
294
295
296    // allow to call methods provided by interface at index
297    inline const IF* get_interface( int iface_i ) const;
298    inline IF* get_interface( int iface_i );
299    IF* operator [] ( int index_ )
300        { return get_interface( index_ ); }
301    const IF* operator [] ( int index_ ) const
302        { return get_interface( index_ ); }
303
304
305    // get the first interface without checking for nil
306
307    virtual sc_interface* get_interface()
308        { return m_interface; }
309
310    virtual const sc_interface* get_interface() const
311        { return m_interface; }
312
313protected:
314
315    // constructors
316
317    explicit sc_port_b( int max_size_,
318	                sc_port_policy policy=SC_ONE_OR_MORE_BOUND ) :
319	base_type( max_size_, policy ), m_interface( 0 ), m_interface_vec()
320	{}
321
322    sc_port_b( const char* name_, int max_size_,
323               sc_port_policy policy=SC_ONE_OR_MORE_BOUND ) :
324	base_type( name_, max_size_, policy ), m_interface( 0 ),
325	m_interface_vec()
326	{}
327
328
329    // destructor (does nothing)
330
331    virtual ~sc_port_b()
332	{}
333
334
335    // called by pbind (for internal use only)
336    virtual int vbind( sc_interface& );
337    virtual int vbind( sc_port_base& );
338
339protected:
340
341    // called by the sc_sensitive* classes
342    virtual void make_sensitive( sc_thread_handle, sc_event_finder* = 0 ) const;
343    virtual void make_sensitive( sc_method_handle, sc_event_finder* = 0 ) const;
344
345private:
346
347    // called by complete_binding (for internal use only)
348    virtual void add_interface( sc_interface* );
349    virtual const char* if_typename() const;
350	virtual int interface_count();
351
352    // disabled
353    sc_port_b();
354    sc_port_b( const this_type& );
355    this_type& operator = ( const this_type& );
356
357private:
358
359    IF*              m_interface;	// first interface in interface vec
360    std::vector<IF*> m_interface_vec;
361};
362
363
364// ----------------------------------------------------------------------------
365//  CLASS : sc_port
366//
367//  Generic port class and base class for other port classes.
368//  N is the maximum number of channels (with interface IF) that can be bound
369//  to this port. N <= 0 means no maximum.
370// ----------------------------------------------------------------------------
371
372extern void sc_warn_port_constructor();
373
374template <class IF, int N = 1, sc_port_policy P=SC_ONE_OR_MORE_BOUND>
375class sc_port
376: public sc_port_b<IF>
377{
378    // typdefs
379
380    typedef sc_port_b<IF> base_type;
381    typedef sc_port<IF,N,P> this_type;
382
383public:
384
385    // constructors
386
387    sc_port()
388	: base_type( N, P )
389	{}
390
391    explicit sc_port( const char* name_ )
392	: base_type( name_, N, P )
393	{}
394
395    explicit sc_port( IF& interface_ )
396	: base_type( N, P )
397	{ sc_warn_port_constructor(); base_type::bind( interface_ ); }
398
399    sc_port( const char* name_, IF& interface_ )
400	: base_type( name_, N, P )
401	{ sc_warn_port_constructor(); base_type::bind( interface_ ); }
402
403    explicit sc_port( base_type& parent_ )
404	: base_type( N, P )
405	{ sc_warn_port_constructor(); base_type::bind( parent_ ); }
406
407    sc_port( const char* name_, base_type& parent_ )
408	: base_type( name_, N, P )
409	{ sc_warn_port_constructor(); base_type::bind( parent_ ); }
410
411    sc_port( this_type& parent_ )
412	: base_type( N, P )
413	{ sc_warn_port_constructor(); base_type::bind( parent_ ); }
414
415    sc_port( const char* name_, this_type& parent_ )
416	: base_type( name_, N, P )
417	{ sc_warn_port_constructor(); base_type::bind( parent_ ); }
418
419
420    // destructor (does nothing)
421
422    virtual ~sc_port()
423	{}
424
425    virtual const char* kind() const
426        { return "sc_port"; }
427
428private:
429
430    // disabled
431    sc_port( const this_type& );
432    this_type& operator = ( const this_type& );
433};
434
435
436// IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII
437
438// ----------------------------------------------------------------------------
439//  CLASS : sc_port_b
440//
441//  Abstract base class for class sc_port.
442// ----------------------------------------------------------------------------
443
444// allow to call methods provided by the first interface
445
446template <class IF>
447inline
448IF*
449sc_port_b<IF>::operator -> ()
450{
451    if( m_interface == 0 ) {
452	report_error( SC_ID_GET_IF_, "port is not bound" );
453    }
454    return m_interface;
455}
456
457template <class IF>
458inline
459const IF*
460sc_port_b<IF>::operator -> () const
461{
462    if( m_interface == 0 ) {
463	report_error( SC_ID_GET_IF_, "port is not bound" );
464    }
465    return m_interface;
466}
467
468
469// allow to call methods provided by interface at index
470//
471// note that we special-case index of zero, since the method may be
472// called before binding has occurred, and we need to return a zero
473// in that case not an error.
474
475template <class IF>
476inline
477IF*
478sc_port_b<IF>::get_interface( int index_ )
479{
480    if ( index_ == 0 ) {
481    	return m_interface;
482    }
483    else if( index_ < 0 || index_ >= size() ) {
484	report_error( SC_ID_GET_IF_, "index out of range" );
485    }
486    return m_interface_vec[index_];
487}
488
489template <class IF>
490inline
491const IF*
492sc_port_b<IF>::get_interface( int index_ ) const
493{
494    if ( index_ == 0 ) {
495    	return m_interface;
496    }
497    else if( index_ < 0 || index_ >= size() ) {
498	report_error( SC_ID_GET_IF_, "index out of range" );
499    }
500    return m_interface_vec[index_];
501}
502
503
504// called by pbind (for internal use only)
505
506template <class IF>
507inline
508int
509sc_port_b<IF>::vbind( sc_interface& interface_ )
510{
511    IF* iface = DCAST<IF*>( &interface_ );
512    if( iface == 0 ) {
513	// type mismatch
514	return 2;
515    }
516    base_type::bind( *iface );
517    return 0;
518}
519
520template <class IF>
521inline
522int
523sc_port_b<IF>::vbind( sc_port_base& parent_ )
524{
525    this_type* parent = DCAST<this_type*>( &parent_ );
526    if( parent == 0 ) {
527	// type mismatch
528	return 2;
529    }
530    base_type::bind( *parent );
531    return 0;
532}
533
534
535// called by complete_binding (for internal use only)
536
537template <class IF>
538inline
539void
540sc_port_b<IF>::add_interface( sc_interface* interface_ )
541{
542    IF* iface = DCAST<IF*>( interface_ );
543    assert( iface != 0 );
544
545    // make sure that the interface is not already bound:
546
547    int size = m_interface_vec.size();
548    for ( int i = 0; i < size; i++ )
549    {
550    	if ( iface == m_interface_vec[i] )
551	{
552	    report_error( SC_ID_BIND_IF_TO_PORT_,
553	    	"interface already bound to port" );
554	}
555    }
556
557    // "bind" the interface and make sure our short cut for 0 is set up.
558
559    m_interface_vec.push_back( iface );
560    m_interface = m_interface_vec[0];
561}
562
563template <class IF>
564inline
565const char*
566sc_port_b<IF>::if_typename() const
567{
568    return typeid( IF ).name();
569}
570
571template <class IF>
572inline
573int
574sc_port_b<IF>::interface_count()
575{
576	return m_interface_vec.size();
577}
578
579template <class IF>
580void
581sc_port_b<IF>::make_sensitive( sc_thread_handle handle_p,
582                  sc_event_finder* event_finder_ ) const
583{
584    if ( m_bind_info == 0 )
585    {
586        int if_n = m_interface_vec.size();
587        for ( int if_i = 0; if_i < if_n; if_i++ )
588	{
589	    IF* iface_p = m_interface_vec[if_i];
590	    assert( iface_p != 0 );
591	    add_static_event( handle_p, iface_p->default_event() );
592	}
593    }
594    else
595    {
596        sc_port_base::make_sensitive( handle_p, event_finder_ );
597    }
598}
599
600template <class IF>
601void
602sc_port_b<IF>::make_sensitive( sc_method_handle handle_p,
603                  sc_event_finder* event_finder_ ) const
604{
605    if ( m_bind_info == 0 )
606    {
607        int if_n = m_interface_vec.size();
608        for ( int if_i = 0; if_i < if_n; if_i++ )
609	{
610	    IF* iface_p = m_interface_vec[if_i];
611	    assert( iface_p != 0 );
612	    add_static_event( handle_p, iface_p->default_event() );
613	}
614    }
615    else
616    {
617        sc_port_base::make_sensitive( handle_p, event_finder_ );
618    }
619}
620
621// ----------------------------------------------------------------------------
622//  CLASS : sc_port
623//
624//  Generic port class and base class for other port classes.
625//  N is the maximum number of channels (with interface IF) that can be bound
626//  to this port. N <= 0 means no maximum.
627// ----------------------------------------------------------------------------
628
629} // namespace sc_core
630
631#undef SC_VIRTUAL_
632
633/*****************************************************************************
634
635  MODIFICATION LOG - modifiers, enter your name, affiliation, date and
636  changes you are making here.
637
638      Name, Affiliation, Date: Andy Goodrich, Forte,
639                               Bishnupriya Bhattacharya, Cadence Design Systems,
640                               25 August, 2003
641  Description of Modification: phase callbacks
642
643      Name, Affiliation, Date: Andy Goodrich, Forte Design Systems
644                               12 December, 2005
645  Description of Modification: multiport binding policy changes
646
647
648 *****************************************************************************/
649
650/*
651$Log: sc_port.h,v $
652Revision 1.10  2011/08/26 20:45:41  acg
653 Andy Goodrich: moved the modification log to the end of the file to
654 eliminate source line number skew when check-ins are done.
655
656Revision 1.9  2011/08/24 22:05:36  acg
657 Torsten Maehne: initialization changes to remove warnings.
658
659Revision 1.8  2011/08/07 19:08:01  acg
660 Andy Goodrich: moved logs to end of file so line number synching works
661 better between versions.
662
663Revision 1.7  2011/08/07 18:53:09  acg
664 Philipp A. Hartmann: add virtual instances of the bind function for
665 base classes to eliminate warning messages for clang platforms.
666
667Revision 1.6  2011/05/09 04:07:37  acg
668 Philipp A. Hartmann:
669   (1) Restore hierarchy in all phase callbacks.
670   (2) Ensure calls to before_end_of_elaboration.
671
672Revision 1.5  2011/03/30 16:46:10  acg
673 Andy Goodrich: added a signature and removed a virtual specification
674 to eliminate warnings with certain compilers.
675
676Revision 1.4  2011/02/18 20:23:45  acg
677 Andy Goodrich: Copyright update.
678
679Revision 1.3  2011/01/20 16:52:15  acg
680 Andy Goodrich: changes for IEEE 1666 2011.
681
682Revision 1.2  2010/08/03 18:01:11  acg
683 Andy Goodrich: formatting.
684
685Revision 1.1.1.1  2006/12/15 20:20:04  acg
686SystemC 2.3
687
688Revision 1.5  2006/08/29 23:35:00  acg
689 Andy Goodrich: added bind_count() method to allow users to determine which
690 ports are connected in before_end_of_elaboration().
691
692Revision 1.4  2006/05/08 17:52:47  acg
693 Andy Goodrich:
694   (1) added David Long's forward declarations for friend functions,
695       methods, and operators to keep the Microsoft compiler happy.
696   (2) Added delta_count() method to sc_prim_channel for use by
697       sc_signal so that the friend declaration in sc_simcontext.h
698	   can be for a non-templated class (i.e., sc_prim_channel.)
699
700Revision 1.3  2006/01/24 20:46:31  acg
701Andy Goodrich: changes to eliminate use of deprecated features. For instance,
702using notify(SC_ZERO_TIME) in place of notify_delayed().
703
704Revision 1.2  2006/01/03 23:18:26  acg
705Changed copyright to include 2006.
706
707Revision 1.1.1.1  2005/12/19 23:16:43  acg
708First check in of SystemC 2.1 into its own archive.
709
710Revision 1.10  2005/09/15 23:01:51  acg
711Added std:: prefix to appropriate methods and types to get around
712issues with the Edison Front End.
713
714Revision 1.9  2005/08/10 01:35:59  acg
715Changes for 64-bit support.
716
717Revision 1.8  2005/04/03 22:52:51  acg
718Namespace changes.
719
720Revision 1.7  2005/03/21 22:31:32  acg
721Changes to sc_core namespace.
722
723Revision 1.6  2004/09/27 21:02:54  acg
724Andy Goodrich - Forte Design Systems, Inc.
725   - Added a $Log comment so that CVS checkin comments will appear in
726     checked out source.
727
728*/
729
730#endif
731
732// Taf!
733