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