SystemC  Recoding Infrastructure for SystemC v0.6.2 derived from Accellera SystemC 2.3.1
Accellera SystemC proof-of-concept library
sc_port.h
Go to the documentation of this file.
1 /*****************************************************************************
2 
3  The following code is derived, directly or indirectly, from the SystemC
4  source code Copyright (c) 1996-2014 by all Contributors.
5  All Rights reserved.
6 
7  The contents of this file are subject to the restrictions and limitations
8  set forth in the SystemC Open Source License (the "License");
9  You may not use this file except in compliance with such restrictions and
10  limitations. You may obtain instructions on how to receive a copy of the
11  License at http://www.accellera.org/. Software distributed by Contributors
12  under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF
13  ANY KIND, either express or implied. See the License for the specific
14  language governing rights and limitations under the License.
15 
16  *****************************************************************************/
17 
18 /*****************************************************************************
19 
20  sc_port.h -- Base classes of all port classes.
21 
22  Original Author: Martin Janssen, Synopsys, Inc., 2001-05-21
23 
24  CHANGE LOG IS AT THE END OF THE FILE
25  *****************************************************************************/
26 
27 #ifndef SC_PORT_H
28 #define SC_PORT_H
29 
30 
33 #include "sysc/kernel/sc_event.h"
34 #include "sysc/kernel/sc_object.h"
35 #include "sysc/kernel/sc_process.h"
36 #include <typeinfo>
37 
38 #if ! defined( SC_DISABLE_VIRTUAL_BIND )
39 # define SC_VIRTUAL_ virtual
40 #else
41 # define SC_VIRTUAL_ /* non-virtual */
42 #endif
43 
44 namespace sc_core {
45 
46 class sc_event_finder;
47 
48 struct sc_bind_info;
49 
51 {
52  SC_ONE_OR_MORE_BOUND, // Default
55 };
56 
57 
58 // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
59 // BEWARE: Ports can only be created and bound during elaboration.
60 // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
61 
62 
63 /**************************************************************************/
70 : public sc_object
71 {
72  friend class sc_module;
73  friend class sc_port_registry;
74  friend class sc_sensitive;
75  friend class sc_sensitive_pos;
76  friend class sc_sensitive_neg;
77 
78 public:
79 
80  // typedefs
81 
83 
84 public:
85 
86  int bind_count();
87 
88  // get the first interface without checking for nil
89  virtual sc_interface* get_interface() = 0;
90  virtual const sc_interface* get_interface() const = 0;
91 
92  virtual const char* kind() const
93  { return "sc_port_base"; }
94 
95 protected:
96 
97  // constructors
98  explicit sc_port_base( int max_size_,
100  sc_port_base( const char* name_, int max_size_,
102 
103  // destructor
104  virtual ~sc_port_base();
105 
106  // bind interface to this port
107  void bind( sc_interface& interface_ );
108 
109  // bind parent port to this port
110  void bind( this_type& parent_ );
111 
112  // called by pbind (for internal use only)
113  virtual int vbind( sc_interface& ) = 0;
114  virtual int vbind( sc_port_base& ) = 0;
115 
116  // called by complete_binding (for internal use only)
117  virtual void add_interface( sc_interface* ) = 0;
118  virtual int interface_count() = 0;
119  virtual const char* if_typename() const = 0;
120 
121  // called by construction_done (does nothing by default)
122  virtual void before_end_of_elaboration();
123 
124  // called by elaboration_done (does nothing)
125  virtual void end_of_elaboration();
126 
127  // called by start_simulation (does nothing by default)
128  virtual void start_of_simulation();
129 
130  // called by simulation_done (does nothing by default)
131  virtual void end_of_simulation();
132 
133  // error reporting
134  void report_error( const char* id, const char* add_msg = 0) const;
135 
136 protected:
137  // called by the sc_sensitive* classes
138  virtual void make_sensitive( sc_thread_handle, sc_event_finder* = 0 ) const;
139  virtual void make_sensitive( sc_method_handle, sc_event_finder* = 0 ) const;
140  void add_static_event(
141  sc_method_handle process_p, const sc_event& event) const;
142  void add_static_event(
143  sc_thread_handle process_p, const sc_event& event) const;
144 
145 private:
146 
147  // called by class sc_module for positional binding
148  int pbind( sc_interface& );
149  int pbind( sc_port_base& );
150 
151 
152  // support methods
153  int first_parent();
154  void insert_parent( int );
155 
156  // called when construction is done
157  void construction_done();
158 
159  // called when elaboration is done
160  void complete_binding();
161  void elaboration_done();
162 
163  // called before simulation starts
164  void start_simulation();
165 
166  // called after simulation ends
167  void simulation_done();
168 
169 protected:
170 
171  sc_bind_info* m_bind_info;
172 
173 private:
174 
175  // disabled
176  sc_port_base();
177  sc_port_base( const this_type& );
178  this_type& operator = ( const this_type& );
179 };
180 
181 
182 /**************************************************************************/
191 {
192  friend class sc_simcontext;
193 
194 public:
195 
196  void insert( sc_port_base* );
197  void remove( sc_port_base* );
198 
199  int size() const
200  { return m_port_vec.size(); }
201 
202 private:
203 
204  // constructor
205  explicit sc_port_registry( sc_simcontext& simc_ );
206 
207  // destructor
208  ~sc_port_registry();
209 
210  // called when by construction_done and elaboration done
211  void complete_binding();
212 
213  // called when construction is done
214  bool construction_done();
215 
216  // called when elaboration is done
217  void elaboration_done();
218 
219  // called before simulation starts
220  void start_simulation();
221 
222  // called after simulation ends
223  void simulation_done();
224 
225  static void replace_port( sc_port_registry* );
226 
227 private:
228 
229  int m_construction_done;
230  std::vector<sc_port_base*> m_port_vec;
231  sc_simcontext* m_simc;
232 
233 private:
234 
235  // disabled
238  sc_port_registry& operator = ( const sc_port_registry& );
239 };
240 
241 
242 /**************************************************************************/
248 template <class IF>
250 : public sc_port_base
251 {
252 public:
253 
254  friend class sc_sensitive;
255  friend class sc_sensitive_neg;
256  friend class sc_sensitive_pos;
257 
258  // typedefs
259 
263 
264 public:
265 
266  // bind an interface of type IF to this port
267 
268  SC_VIRTUAL_ void bind( IF& interface_ )
269  { base_type::bind( interface_ ); }
270 
271  void operator () ( IF& interface_ )
272  { this->bind( interface_ ); }
273 
274 
275  // bind a parent port with type IF to this port
276 
277  SC_VIRTUAL_ void bind( port_type& parent_ )
278  { base_type::bind( parent_ ); }
279 
280  void operator () ( port_type& parent_ )
281  { this->bind( parent_ ); }
282 
283 
284  // number of connected interfaces
285 
286  int size() const
287  { return m_interface_vec.size(); }
288 
289 
290  // allow to call methods provided by the first interface
291  IF* operator -> ();
292  const IF* operator -> () const;
293 
294 
295  // allow to call methods provided by interface at index
296  inline const IF* get_interface( int iface_i ) const;
297  inline IF* get_interface( int iface_i );
298  IF* operator [] ( int index_ )
299  { return get_interface( index_ ); }
300  const IF* operator [] ( int index_ ) const
301  { return get_interface( index_ ); }
302 
303 
304  // get the first interface without checking for nil
305 
307  { return m_interface; }
308 
309  virtual const sc_interface* get_interface() const
310  { return m_interface; }
311 
312 protected:
313 
314  // constructors
315 
316  explicit sc_port_b( int max_size_,
318  base_type( max_size_, policy ), m_interface( 0 ), m_interface_vec()
319  {}
320 
321  sc_port_b( const char* name_, int max_size_,
323  base_type( name_, max_size_, policy ), m_interface( 0 ),
324  m_interface_vec()
325  {}
326 
327 
328  // destructor (does nothing)
329 
330  virtual ~sc_port_b()
331  {}
332 
333 
334  // called by pbind (for internal use only)
335  virtual int vbind( sc_interface& );
336  virtual int vbind( sc_port_base& );
337 
338 protected:
339 
340  // called by the sc_sensitive* classes
341  virtual void make_sensitive( sc_thread_handle, sc_event_finder* = 0 ) const;
342  virtual void make_sensitive( sc_method_handle, sc_event_finder* = 0 ) const;
343 
344 private:
345 
346  // called by complete_binding (for internal use only)
347  virtual void add_interface( sc_interface* );
348  virtual const char* if_typename() const;
349  virtual int interface_count();
350 
351  // disabled
352  sc_port_b();
353  sc_port_b( const this_type& );
354  this_type& operator = ( const this_type& );
355 
356 private:
357 
358  IF* m_interface; // first interface in interface vec
359  std::vector<IF*> m_interface_vec;
360 };
361 
362 
363 /**************************************************************************/
372 extern void sc_warn_port_constructor();
373 
374 template <class IF, int N = 1, sc_port_policy P=SC_ONE_OR_MORE_BOUND>
375 class 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 
383 public:
384 
385  // constructors
386 
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 
428 private:
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 
446 template <class IF>
447 inline
448 IF*
450 {
451  if( m_interface == 0 ) {
452  report_error( SC_ID_GET_IF_, "port is not bound" );
453  }
454  return m_interface;
455 }
456 
457 template <class IF>
458 inline
459 const IF*
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 
475 template <class IF>
476 inline
477 IF*
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 
489 template <class IF>
490 inline
491 const IF*
492 sc_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 
506 template <class IF>
507 inline
508 int
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 
520 template <class IF>
521 inline
522 int
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 
537 template <class IF>
538 inline
539 void
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 
563 template <class IF>
564 inline
565 const char*
566 sc_port_b<IF>::if_typename() const
567 {
568  return typeid( IF ).name();
569 }
570 
571 template <class IF>
572 inline
573 int
574 sc_port_b<IF>::interface_count()
575 {
576  return m_interface_vec.size();
577 }
578 
579 template <class IF>
580 void
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 
600 template <class IF>
601 void
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 $
652 Revision 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 
656 Revision 1.9 2011/08/24 22:05:36 acg
657  Torsten Maehne: initialization changes to remove warnings.
658 
659 Revision 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 
663 Revision 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 
667 Revision 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 
672 Revision 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 
676 Revision 1.4 2011/02/18 20:23:45 acg
677  Andy Goodrich: Copyright update.
678 
679 Revision 1.3 2011/01/20 16:52:15 acg
680  Andy Goodrich: changes for IEEE 1666 2011.
681 
682 Revision 1.2 2010/08/03 18:01:11 acg
683  Andy Goodrich: formatting.
684 
685 Revision 1.1.1.1 2006/12/15 20:20:04 acg
686 SystemC 2.3
687 
688 Revision 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 
692 Revision 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 
700 Revision 1.3 2006/01/24 20:46:31 acg
701 Andy Goodrich: changes to eliminate use of deprecated features. For instance,
702 using notify(SC_ZERO_TIME) in place of notify_delayed().
703 
704 Revision 1.2 2006/01/03 23:18:26 acg
705 Changed copyright to include 2006.
706 
707 Revision 1.1.1.1 2005/12/19 23:16:43 acg
708 First check in of SystemC 2.1 into its own archive.
709 
710 Revision 1.10 2005/09/15 23:01:51 acg
711 Added std:: prefix to appropriate methods and types to get around
712 issues with the Edison Front End.
713 
714 Revision 1.9 2005/08/10 01:35:59 acg
715 Changes for 64-bit support.
716 
717 Revision 1.8 2005/04/03 22:52:51 acg
718 Namespace changes.
719 
720 Revision 1.7 2005/03/21 22:31:32 acg
721 Changes to sc_core namespace.
722 
723 Revision 1.6 2004/09/27 21:02:54 acg
724 Andy 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!
virtual void add_interface(sc_interface *)=0
int size() const
Definition: sc_port.h:286
virtual void start_of_simulation()
sc_port(const char *name_, IF &interface_)
Definition: sc_port.h:399
virtual void end_of_simulation()
virtual const char * kind() const
Definition: sc_port.h:425
virtual void make_sensitive(sc_thread_handle, sc_event_finder *=0) const
Abstract base class for class sc_port.
Definition: sc_port.h:249
sc_port(base_type &parent_)
Definition: sc_port.h:403
virtual void end_of_elaboration()
sc_port(IF &interface_)
Definition: sc_port.h:395
void report_error(const char *id, const char *add_msg=0) const
sc_port_base base_type
Definition: sc_port.h:260
virtual sc_interface * get_interface()=0
virtual ~sc_port()
Definition: sc_port.h:422
SC_VIRTUAL_ void bind(port_type &parent_)
Definition: sc_port.h:277
virtual ~sc_port_b()
Definition: sc_port.h:330
Generic port class and base class for other port classes.
Definition: sc_port.h:375
this_type port_type
Definition: sc_port.h:262
virtual void make_sensitive(sc_thread_handle, sc_event_finder *=0) const
Definition: sc_port.h:581
virtual int interface_count()=0
Registry for all ports.
Definition: sc_port.h:190
class sc_method_process * sc_method_handle
Definition: sc_process.h:120
sc_port_b< IF > this_type
Definition: sc_port.h:261
virtual void before_end_of_elaboration()
virtual const char * kind() const
Definition: sc_port.h:92
sc_port(this_type &parent_)
Definition: sc_port.h:411
void sc_warn_port_constructor()
IF * operator->()
Definition: sc_port.h:449
SC_VIRTUAL_ void bind(IF &interface_)
Definition: sc_port.h:268
sc_port(const char *name_, this_type &parent_)
Definition: sc_port.h:415
class sc_thread_process * sc_thread_handle
Definition: sc_process.h:121
virtual const char * if_typename() const =0
sc_port(const char *name_, base_type &parent_)
Definition: sc_port.h:407
void add_static_event(sc_method_handle process_p, const sc_event &event) const
sc_port_b(const char *name_, int max_size_, sc_port_policy policy=SC_ONE_OR_MORE_BOUND)
Definition: sc_port.h:321
sc_port_b(int max_size_, sc_port_policy policy=SC_ONE_OR_MORE_BOUND)
Definition: sc_port.h:316
virtual int vbind(sc_interface &)
Definition: sc_port.h:509
The event class.
Definition: sc_event.h:260
void operator()(IF &interface_)
Definition: sc_port.h:271
The simulation context.
Abstract base class of all interface classes.
Definition: sc_interface.h:44
Event finder base class.
virtual sc_interface * get_interface()
Definition: sc_port.h:306
Base class for all structural entities.
Definition: sc_module.h:83
virtual int vbind(sc_interface &)=0
Abstract base class for class sc_port_b.
Definition: sc_port.h:69
sc_port_policy
Definition: sc_port.h:50
void bind(sc_interface &interface_)
sc_port_base this_type
Definition: sc_port.h:82
void insert(sc_port_base *)
sc_port(const char *name_)
Definition: sc_port.h:391
#define SC_VIRTUAL_
Definition: sc_port.h:39
virtual const sc_interface * get_interface() const
Definition: sc_port.h:309
Abstract base class of all SystemC `simulation&#39; objects.
Definition: sc_object.h:51
sc_bind_info * m_bind_info
Definition: sc_port.h:171
IF * operator[](int index_)
Definition: sc_port.h:298