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_signal_ports.h -- The sc_signal<T> port classes. 23 24 Original Author: Martin Janssen, Synopsys, Inc., 2001-05-21 25 26 CHANGE LOG APPEARS AT THE END OF THE FILE 27 *****************************************************************************/ 28 29#ifndef SC_SIGNAL_PORTS_H 30#define SC_SIGNAL_PORTS_H 31 32 33#include "sysc/communication/sc_event_finder.h" 34#include "sysc/communication/sc_port.h" 35#include "sysc/communication/sc_signal_ifs.h" 36#include "sysc/datatypes/bit/sc_logic.h" 37#include "sysc/tracing/sc_trace.h" 38 39#if ! defined( SC_DISABLE_VIRTUAL_BIND ) 40# define SC_VIRTUAL_ virtual 41#else 42# define SC_VIRTUAL_ /* non-virtual */ 43#endif 44 45namespace sc_core { 46 47// ---------------------------------------------------------------------------- 48// STRUCT : sc_trace_params 49// 50// Struct for storing the trace file and object name of an sc_trace call. 51// FOR INTERNAL USE ONLY! 52// ---------------------------------------------------------------------------- 53 54extern void sc_deprecated_add_trace(); 55 56struct sc_trace_params 57{ 58 sc_trace_file* tf; 59 std::string name; 60 61 sc_trace_params( sc_trace_file* tf_, const std::string& name_ ) 62 : tf( tf_ ), name( name_ ) 63 {} 64}; 65 66 67typedef std::vector<sc_trace_params*> sc_trace_params_vec; 68 69 70// ---------------------------------------------------------------------------- 71// CLASS : sc_in<T> 72// 73// The sc_signal<T> input port class. 74// ---------------------------------------------------------------------------- 75 76template <class T> 77class sc_in 78: public sc_port<sc_signal_in_if<T>,1,SC_ONE_OR_MORE_BOUND> 79{ 80public: 81 82 // typedefs 83 84 typedef T data_type; 85 86 typedef sc_signal_in_if<data_type> if_type; 87 typedef sc_port<if_type,1,SC_ONE_OR_MORE_BOUND> base_type; 88 typedef sc_in<data_type> this_type; 89 typedef typename base_type::port_type base_port_type; 90 91 typedef if_type in_if_type; 92 typedef base_type in_port_type; 93 typedef sc_signal_inout_if<data_type> inout_if_type; 94 typedef sc_port<inout_if_type,1,SC_ONE_OR_MORE_BOUND> inout_port_type; 95 96public: 97 98 // constructors 99 100 sc_in() 101 : base_type(), m_traces( 0 ), 102 m_change_finder_p(0) 103 {} 104 105 explicit sc_in( const char* name_ ) 106 : base_type( name_ ), m_traces( 0 ), 107 m_change_finder_p(0) 108 {} 109 110 explicit sc_in( const in_if_type& interface_ ) 111 : base_type( CCAST<in_if_type&>( interface_ ) ), m_traces( 0 ), 112 m_change_finder_p(0) 113 {} 114 115 sc_in( const char* name_, const in_if_type& interface_ ) 116 : base_type( name_, CCAST<in_if_type&>( interface_ ) ), m_traces( 0 ), 117 m_change_finder_p(0) 118 {} 119 120 explicit sc_in( in_port_type& parent_ ) 121 : base_type( parent_ ), m_traces( 0 ), 122 m_change_finder_p(0) 123 {} 124 125 sc_in( const char* name_, in_port_type& parent_ ) 126 : base_type( name_, parent_ ), m_traces( 0 ), 127 m_change_finder_p(0) 128 {} 129 130 explicit sc_in( inout_port_type& parent_ ) 131 : base_type(), m_traces( 0 ), 132 m_change_finder_p(0) 133 { sc_port_base::bind( parent_ ); } 134 135 sc_in( const char* name_, inout_port_type& parent_ ) 136 : base_type( name_ ), m_traces( 0 ), 137 m_change_finder_p(0) 138 { sc_port_base::bind( parent_ ); } 139 140 sc_in( this_type& parent_ ) 141 : base_type( parent_ ), m_traces( 0 ), 142 m_change_finder_p(0) 143 {} 144 145 sc_in( const char* name_, this_type& parent_ ) 146 : base_type( name_, parent_ ), m_traces( 0 ), 147 m_change_finder_p(0) 148 {} 149 150 151 // destructor 152 153 virtual ~sc_in() 154 { 155 remove_traces(); 156 delete m_change_finder_p; 157 } 158 159 160 // bind to in interface 161 162 SC_VIRTUAL_ void bind( const in_if_type& interface_ ) 163 { sc_port_base::bind( CCAST<in_if_type&>( interface_ ) ); } 164 165 SC_VIRTUAL_ void bind( in_if_type& interface_ ) 166 { this->bind( CCAST<const in_if_type&>( interface_ ) ); } 167 168 void operator () ( const in_if_type& interface_ ) 169 { this->bind( interface_ ); } 170 171 172 // bind to parent in port 173 174 SC_VIRTUAL_ void bind( in_port_type& parent_ ) 175 { sc_port_base::bind( parent_ ); } 176 177 void operator () ( in_port_type& parent_ ) 178 { this->bind( parent_ ); } 179 180 181 // bind to parent inout port 182 183 SC_VIRTUAL_ void bind( inout_port_type& parent_ ) 184 { sc_port_base::bind( parent_ ); } 185 186 void operator () ( inout_port_type& parent_ ) 187 { this->bind( parent_ ); } 188 189 190 // interface access shortcut methods 191 192 // get the default event 193 194 const sc_event& default_event() const 195 { return (*this)->default_event(); } 196 197 198 // get the value changed event 199 200 const sc_event& value_changed_event() const 201 { return (*this)->value_changed_event(); } 202 203 204 // read the current value 205 206 const data_type& read() const 207 { return (*this)->read(); } 208 209 operator const data_type& () const 210 { return (*this)->read(); } 211 212 213 // was there a value changed event? 214 215 bool event() const 216 { return (*this)->event(); } 217 218 219 // (other) event finder method(s) 220 221 sc_event_finder& value_changed() const 222 { 223 if ( !m_change_finder_p ) 224 { 225 m_change_finder_p = new sc_event_finder_t<in_if_type>( 226 *this, &in_if_type::value_changed_event ); 227 } 228 return *m_change_finder_p; 229 } 230 231 232 // called when elaboration is done 233 /* WHEN DEFINING THIS METHOD IN A DERIVED CLASS, */ 234 /* MAKE SURE THAT THIS METHOD IS CALLED AS WELL. */ 235 236 virtual void end_of_elaboration(); 237 238 virtual const char* kind() const 239 { return "sc_in"; } 240 241 242 void add_trace( sc_trace_file*, const std::string& ) const; 243 244 // called by sc_trace 245 void add_trace_internal( sc_trace_file*, const std::string& ) const; 246 247protected: 248 249 void remove_traces() const; 250 251 mutable sc_trace_params_vec* m_traces; 252 253protected: 254 255 // called by pbind (for internal use only) 256 virtual int vbind( sc_interface& ); 257 virtual int vbind( sc_port_base& ); 258 259 // implement virtual base_type port-binding function 260 // - avoids warnings on some compilers 261 // - should only be called, when using sc_port_b explicitly 262 // - errors are detected during elaboration 263 264 SC_VIRTUAL_ void bind( base_port_type& parent_ ) 265 { sc_port_base::bind( parent_ ); } 266 267 268private: 269 mutable sc_event_finder* m_change_finder_p; 270 271private: 272 273 // disabled 274 sc_in( const this_type& ); 275 this_type& operator = ( const this_type& ); 276 277#ifdef __GNUC__ 278 // Needed to circumvent a problem in the g++-2.95.2 compiler: 279 // This unused variable forces the compiler to instantiate 280 // an object of T template so an implicit conversion from 281 // read() to a C++ intrinsic data type will work. 282 static data_type dummy; 283#endif 284}; 285 286template<typename T> 287::std::ostream& operator << ( ::std::ostream& os, const sc_in<T>& a ) 288{ 289 return os << a->read(); 290} 291 292// IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII 293 294 295// called when elaboration is done 296 297template <class T> 298inline 299void 300sc_in<T>::end_of_elaboration() 301{ 302 if( m_traces != 0 ) { 303 for( int i = 0; i < (int)m_traces->size(); ++ i ) { 304 sc_trace_params* p = (*m_traces)[i]; 305 in_if_type* iface = DCAST<in_if_type*>( this->get_interface() ); 306 sc_trace( p->tf, iface->read(), p->name ); 307 } 308 remove_traces(); 309 } 310} 311 312 313// called by sc_trace 314 315template <class T> 316inline 317void 318sc_in<T>::add_trace_internal( sc_trace_file* tf_, const std::string& name_ ) 319const 320{ 321 if( tf_ != 0 ) { 322 if( m_traces == 0 ) { 323 m_traces = new sc_trace_params_vec; 324 } 325 m_traces->push_back( new sc_trace_params( tf_, name_ ) ); 326 } 327} 328 329template <class T> 330inline 331void 332sc_in<T>::add_trace( sc_trace_file* tf_, const std::string& name_ ) 333const 334{ 335 sc_deprecated_add_trace(); 336 add_trace_internal(tf_, name_); 337} 338 339template <class T> 340inline 341void 342sc_in<T>::remove_traces() const 343{ 344 if( m_traces != 0 ) { 345 for( int i = (int)m_traces->size() - 1; i >= 0; -- i ) { 346 delete (*m_traces)[i]; 347 } 348 delete m_traces; 349 m_traces = 0; 350 } 351} 352 353 354// called by pbind (for internal use only) 355 356template <class T> 357inline 358int 359sc_in<T>::vbind( sc_interface& interface_ ) 360{ 361 return sc_port_b<if_type>::vbind( interface_ ); 362} 363 364template <class T> 365inline 366int 367sc_in<T>::vbind( sc_port_base& parent_ ) 368{ 369 in_port_type* in_parent = DCAST<in_port_type*>( &parent_ ); 370 if( in_parent != 0 ) { 371 sc_port_base::bind( *in_parent ); 372 return 0; 373 } 374 inout_port_type* inout_parent = DCAST<inout_port_type*>( &parent_ ); 375 if( inout_parent != 0 ) { 376 sc_port_base::bind( *inout_parent ); 377 return 0; 378 } 379 // type mismatch 380 return 2; 381} 382 383 384// ---------------------------------------------------------------------------- 385// CLASS : sc_in<bool> 386// 387// Specialization of sc_in<T> for type bool. 388// ---------------------------------------------------------------------------- 389 390template <> 391class sc_in<bool> : 392 public sc_port<sc_signal_in_if<bool>,1,SC_ONE_OR_MORE_BOUND> 393{ 394public: 395 396 // typedefs 397 398 typedef bool data_type; 399 400 typedef sc_signal_in_if<data_type> if_type; 401 typedef sc_port<if_type,1,SC_ONE_OR_MORE_BOUND> base_type; 402 typedef sc_in<data_type> this_type; 403 typedef /* typename */ base_type::port_type base_port_type; 404 405 typedef if_type in_if_type; 406 typedef base_type in_port_type; 407 typedef sc_signal_inout_if<data_type> inout_if_type; 408 typedef sc_port<inout_if_type,1,SC_ONE_OR_MORE_BOUND> inout_port_type; 409 410public: 411 412 // constructors 413 414 sc_in() 415 : base_type(), m_traces( 0 ), m_change_finder_p(0), 416 m_neg_finder_p(0), m_pos_finder_p(0) 417 {} 418 419 explicit sc_in( const char* name_ ) 420 : base_type( name_ ), m_traces( 0 ), m_change_finder_p(0), 421 m_neg_finder_p(0), m_pos_finder_p(0) 422 {} 423 424 explicit sc_in( const in_if_type& interface_ ) 425 : base_type( CCAST<in_if_type&>( interface_ ) ), m_traces( 0 ), 426 m_change_finder_p(0), m_neg_finder_p(0), m_pos_finder_p(0) 427 {} 428 429 sc_in( const char* name_, const in_if_type& interface_ ) 430 : base_type( name_, CCAST<in_if_type&>( interface_ ) ), m_traces( 0 ), 431 m_change_finder_p(0), m_neg_finder_p(0), m_pos_finder_p(0) 432 {} 433 434 explicit sc_in( in_port_type& parent_ ) 435 : base_type( parent_ ), m_traces( 0 ), 436 m_change_finder_p(0), m_neg_finder_p(0), m_pos_finder_p(0) 437 {} 438 439 sc_in( const char* name_, in_port_type& parent_ ) 440 : base_type( name_, parent_ ), m_traces( 0 ), 441 m_change_finder_p(0), m_neg_finder_p(0), m_pos_finder_p(0) 442 {} 443 444 explicit sc_in( inout_port_type& parent_ ) 445 : base_type(), m_traces( 0 ), 446 m_change_finder_p(0), m_neg_finder_p(0), m_pos_finder_p(0) 447 { sc_port_base::bind( parent_ ); } 448 449 sc_in( const char* name_, inout_port_type& parent_ ) 450 : base_type( name_ ), m_traces( 0 ), 451 m_change_finder_p(0), m_neg_finder_p(0), m_pos_finder_p(0) 452 { sc_port_base::bind( parent_ ); } 453 454 sc_in( this_type& parent_ ) 455 : base_type( parent_ ), m_traces( 0 ), 456 m_change_finder_p(0), m_neg_finder_p(0), m_pos_finder_p(0) 457 {} 458 459#if defined(TESTING) 460 sc_in( const this_type& parent_ ) 461 : base_type( *(in_if_type*)parent_.get_interface() ) , m_traces( 0 ), 462 m_change_finder_p(0), m_neg_finder_p(0), m_pos_finder_p(0) 463 {} 464#endif 465 466 sc_in( const char* name_, this_type& parent_ ) 467 : base_type( name_, parent_ ), m_traces( 0 ), 468 m_change_finder_p(0), m_neg_finder_p(0), m_pos_finder_p(0) 469 {} 470 471 472 // destructor 473 474 virtual ~sc_in() 475 { 476 remove_traces(); 477 delete m_change_finder_p; 478 delete m_neg_finder_p; 479 delete m_pos_finder_p; 480 } 481 482 483 // bind to in interface 484 485 SC_VIRTUAL_ void bind( const in_if_type& interface_ ) 486 { sc_port_base::bind( CCAST<in_if_type&>( interface_ ) ); } 487 488 SC_VIRTUAL_ void bind( in_if_type& interface_ ) 489 { this->bind( CCAST<const in_if_type&>( interface_ ) ); } 490 491 void operator () ( const in_if_type& interface_ ) 492 { this->bind( interface_ ); } 493 494 495 // bind to parent in port 496 497 SC_VIRTUAL_ void bind( in_port_type& parent_ ) 498 { sc_port_base::bind( parent_ ); } 499 500 void operator () ( in_port_type& parent_ ) 501 { this->bind( parent_ ); } 502 503 504 // bind to parent inout port 505 506 SC_VIRTUAL_ void bind( inout_port_type& parent_ ) 507 { sc_port_base::bind( parent_ ); } 508 509 void operator () ( inout_port_type& parent_ ) 510 { this->bind( parent_ ); } 511 512 513 // interface access shortcut methods 514 515 // get the default event 516 517 const sc_event& default_event() const 518 { return (*this)->default_event(); } 519 520 521 // get the value changed event 522 523 const sc_event& value_changed_event() const 524 { return (*this)->value_changed_event(); } 525 526 // get the positive edge event 527 528 const sc_event& posedge_event() const 529 { return (*this)->posedge_event(); } 530 531 // get the negative edge event 532 533 const sc_event& negedge_event() const 534 { return (*this)->negedge_event(); } 535 536 537 // read the current value 538 539 const data_type& read() const 540 { return (*this)->read(); } 541 542 operator const data_type& () const 543 { return (*this)->read(); } 544 545 546 // use for positive edge sensitivity 547 548 sc_event_finder& pos() const 549 { 550 if ( !m_pos_finder_p ) 551 { 552 m_pos_finder_p = new sc_event_finder_t<in_if_type>( 553 *this, &in_if_type::posedge_event ); 554 } 555 return *m_pos_finder_p; 556 } 557 558 // use for negative edge sensitivity 559 560 sc_event_finder& neg() const 561 { 562 if ( !m_neg_finder_p ) 563 { 564 m_neg_finder_p = new sc_event_finder_t<in_if_type>( 565 *this, &in_if_type::negedge_event ); 566 } 567 return *m_neg_finder_p; 568 } 569 570 571 // was there a value changed event? 572 573 bool event() const 574 { return (*this)->event(); } 575 576 // was there a positive edge event? 577 578 bool posedge() const 579 { return (*this)->posedge(); } 580 581 // was there a negative edge event? 582 583 bool negedge() const 584 { return (*this)->negedge(); } 585 586 // (other) event finder method(s) 587 588 sc_event_finder& value_changed() const 589 { 590 if ( !m_change_finder_p ) 591 { 592 m_change_finder_p = new sc_event_finder_t<in_if_type>( 593 *this, &in_if_type::value_changed_event ); 594 } 595 return *m_change_finder_p; 596 } 597 598 599 // called when elaboration is done 600 /* WHEN DEFINING THIS METHOD IN A DERIVED CLASS, */ 601 /* MAKE SURE THAT THIS METHOD IS CALLED AS WELL. */ 602 603 virtual void end_of_elaboration(); 604 605 virtual const char* kind() const 606 { return "sc_in"; } 607 608 609 void add_trace( sc_trace_file*, const std::string& ) const; 610 611 // called by sc_trace 612 void add_trace_internal( sc_trace_file*, const std::string& ) const; 613 614protected: 615 616 void remove_traces() const; 617 618 mutable sc_trace_params_vec* m_traces; 619 620protected: 621 622 // called by pbind (for internal use only) 623 virtual int vbind( sc_interface& ); 624 virtual int vbind( sc_port_base& ); 625 626 // implement virtual base_type port-binding function 627 // - avoids warnings on some compilers 628 // - should only be called, when using sc_port_b explicitly 629 // - errors are detected during elaboration 630 631 SC_VIRTUAL_ void bind( base_port_type& parent_ ) 632 { sc_port_base::bind( parent_ ); } 633 634private: 635 mutable sc_event_finder* m_change_finder_p; 636 mutable sc_event_finder* m_neg_finder_p; 637 mutable sc_event_finder* m_pos_finder_p; 638 639private: 640 641 // disabled 642#if defined(TESTING) 643#else 644 sc_in( const this_type& ); 645#endif 646 this_type& operator = ( const this_type& ); 647 648#ifdef __GNUC__ 649 // Needed to circumvent a problem in the g++-2.95.2 compiler: 650 // This unused variable forces the compiler to instantiate 651 // an object of T template so an implicit conversion from 652 // read() to a C++ intrinsic data type will work. 653 static data_type dummy; 654#endif 655}; 656 657 658// ---------------------------------------------------------------------------- 659// CLASS : sc_in<sc_dt::sc_logic> 660// 661// Specialization of sc_in<T> for type sc_dt::sc_logic. 662// ---------------------------------------------------------------------------- 663 664template <> 665class sc_in<sc_dt::sc_logic> 666: public sc_port<sc_signal_in_if<sc_dt::sc_logic>,1,SC_ONE_OR_MORE_BOUND> 667{ 668public: 669 670 // typedefs 671 672 typedef sc_dt::sc_logic data_type; 673 674 typedef sc_signal_in_if<data_type> if_type; 675 typedef sc_port<if_type,1,SC_ONE_OR_MORE_BOUND> base_type; 676 typedef sc_in<data_type> this_type; 677 typedef /* typename */ base_type::port_type base_port_type; 678 679 typedef if_type in_if_type; 680 typedef base_type in_port_type; 681 typedef sc_signal_inout_if<data_type> inout_if_type; 682 typedef sc_port<inout_if_type,1,SC_ONE_OR_MORE_BOUND> inout_port_type; 683 684public: 685 686 // constructors 687 688 sc_in() 689 : base_type(), m_traces( 0 ), 690 m_change_finder_p(0), m_neg_finder_p(0), m_pos_finder_p(0) 691 {} 692 693 explicit sc_in( const char* name_ ) 694 : base_type( name_ ), m_traces( 0 ), 695 m_change_finder_p(0), m_neg_finder_p(0), m_pos_finder_p(0) 696 {} 697 698 explicit sc_in( const in_if_type& interface_ ) 699 : base_type( CCAST<in_if_type&>( interface_ ) ), m_traces( 0 ), 700 m_change_finder_p(0), m_neg_finder_p(0), m_pos_finder_p(0) 701 {} 702 703 sc_in( const char* name_, const in_if_type& interface_ ) 704 : base_type( name_, CCAST<in_if_type&>( interface_ ) ), m_traces( 0 ), 705 m_change_finder_p(0), m_neg_finder_p(0), m_pos_finder_p(0) 706 {} 707 708 explicit sc_in( in_port_type& parent_ ) 709 : base_type( parent_ ), m_traces( 0 ), 710 m_change_finder_p(0), m_neg_finder_p(0), m_pos_finder_p(0) 711 {} 712 713 sc_in( const char* name_, in_port_type& parent_ ) 714 : base_type( name_, parent_ ), m_traces( 0 ), 715 m_change_finder_p(0), m_neg_finder_p(0), m_pos_finder_p(0) 716 {} 717 718 explicit sc_in( inout_port_type& parent_ ) 719 : base_type(), m_traces( 0 ), 720 m_change_finder_p(0), m_neg_finder_p(0), m_pos_finder_p(0) 721 { sc_port_base::bind( parent_ ); } 722 723 sc_in( const char* name_, inout_port_type& parent_ ) 724 : base_type( name_ ), m_traces( 0 ), 725 m_change_finder_p(0), m_neg_finder_p(0), m_pos_finder_p(0) 726 { sc_port_base::bind( parent_ ); } 727 728 sc_in( this_type& parent_ ) 729 : base_type( parent_ ), m_traces( 0 ), 730 m_change_finder_p(0), m_neg_finder_p(0), m_pos_finder_p(0) 731 {} 732 733 sc_in( const char* name_, this_type& parent_ ) 734 : base_type( name_, parent_ ), m_traces( 0 ), 735 m_change_finder_p(0), m_neg_finder_p(0), m_pos_finder_p(0) 736 {} 737 738 739 // destructor 740 741 virtual ~sc_in() 742 { 743 remove_traces(); 744 delete m_change_finder_p; 745 delete m_neg_finder_p; 746 delete m_pos_finder_p; 747 } 748 749 750 // bind to in interface 751 752 SC_VIRTUAL_ void bind( const in_if_type& interface_ ) 753 { sc_port_base::bind( CCAST<in_if_type&>( interface_ ) ); } 754 755 SC_VIRTUAL_ void bind( in_if_type& interface_ ) 756 { this->bind( CCAST<const in_if_type&>( interface_ ) ); } 757 758 void operator () ( const in_if_type& interface_ ) 759 { this->bind( interface_ ); } 760 761 762 // bind to parent in port 763 764 SC_VIRTUAL_ void bind( in_port_type& parent_ ) 765 { sc_port_base::bind( parent_ ); } 766 767 void operator () ( in_port_type& parent_ ) 768 { this->bind( parent_ ); } 769 770 771 // bind to parent inout port 772 773 SC_VIRTUAL_ void bind( inout_port_type& parent_ ) 774 { sc_port_base::bind( parent_ ); } 775 776 void operator () ( inout_port_type& parent_ ) 777 { this->bind( parent_ ); } 778 779 780 // interface access shortcut methods 781 782 // get the default event 783 784 const sc_event& default_event() const 785 { return (*this)->default_event(); } 786 787 788 // get the value changed event 789 790 const sc_event& value_changed_event() const 791 { return (*this)->value_changed_event(); } 792 793 // get the positive edge event 794 795 const sc_event& posedge_event() const 796 { return (*this)->posedge_event(); } 797 798 // get the negative edge event 799 800 const sc_event& negedge_event() const 801 { return (*this)->negedge_event(); } 802 803 804 // read the current value 805 806 const data_type& read() const 807 { return (*this)->read(); } 808 809 operator const data_type& () const 810 { return (*this)->read(); } 811 812 813 // use for positive edge sensitivity 814 815 sc_event_finder& pos() const 816 { 817 if ( !m_pos_finder_p ) 818 { 819 m_pos_finder_p = new sc_event_finder_t<in_if_type>( 820 *this, &in_if_type::posedge_event ); 821 } 822 return *m_pos_finder_p; 823 } 824 825 // use for negative edge sensitivity 826 827 sc_event_finder& neg() const 828 { 829 if ( !m_neg_finder_p ) 830 { 831 m_neg_finder_p = new sc_event_finder_t<in_if_type>( 832 *this, &in_if_type::negedge_event ); 833 } 834 return *m_neg_finder_p; 835 } 836 837 838 // was there a value changed event? 839 840 bool event() const 841 { return (*this)->event(); } 842 843 // was there a positive edge event? 844 845 bool posedge() const 846 { return (*this)->posedge(); } 847 848 // was there a negative edge event? 849 850 bool negedge() const 851 { return (*this)->negedge(); } 852 853 // (other) event finder method(s) 854 855 sc_event_finder& value_changed() const 856 { 857 if ( !m_change_finder_p ) 858 { 859 m_change_finder_p = new sc_event_finder_t<in_if_type>( 860 *this, &in_if_type::value_changed_event ); 861 } 862 return *m_change_finder_p; 863 } 864 865 866 // called when elaboration is done 867 /* WHEN DEFINING THIS METHOD IN A DERIVED CLASS, */ 868 /* MAKE SURE THAT THIS METHOD IS CALLED AS WELL. */ 869 870 virtual void end_of_elaboration(); 871 872 virtual const char* kind() const 873 { return "sc_in"; } 874 875 876 void add_trace( sc_trace_file*, const std::string& ) const; 877 878 // called by sc_trace 879 void add_trace_internal( sc_trace_file*, const std::string& ) const; 880 881protected: 882 883 void remove_traces() const; 884 885 mutable sc_trace_params_vec* m_traces; 886 887protected: 888 889 // called by pbind (for internal use only) 890 virtual int vbind( sc_interface& ); 891 virtual int vbind( sc_port_base& ); 892 893 // implement virtual base_type port-binding function 894 // - avoids warnings on some compilers 895 // - should only be called, when using sc_port_b explicitly 896 // - errors are detected during elaboration 897 898 SC_VIRTUAL_ void bind( base_port_type& parent_ ) 899 { sc_port_base::bind( parent_ ); } 900 901private: 902 mutable sc_event_finder* m_change_finder_p; 903 mutable sc_event_finder* m_neg_finder_p; 904 mutable sc_event_finder* m_pos_finder_p; 905 906private: 907 908 // disabled 909 sc_in( const this_type& ); 910 this_type& operator = ( const this_type& ); 911 912#ifdef __GNUC__ 913 // Needed to circumvent a problem in the g++-2.95.2 compiler: 914 // This unused variable forces the compiler to instantiate 915 // an object of T template so an implicit conversion from 916 // read() to a C++ intrinsic data type will work. 917 static data_type dummy; 918#endif 919}; 920 921 922// ---------------------------------------------------------------------------- 923// CLASS : sc_inout<T> 924// 925// The sc_signal<T> input/output port class. 926// ---------------------------------------------------------------------------- 927 928template <class T> 929class sc_inout 930: public sc_port<sc_signal_inout_if<T>,1,SC_ONE_OR_MORE_BOUND> 931{ 932public: 933 934 // typedefs 935 936 typedef T data_type; 937 938 typedef sc_signal_inout_if<data_type> if_type; 939 typedef sc_port<if_type,1,SC_ONE_OR_MORE_BOUND> base_type; 940 typedef sc_inout<data_type> this_type; 941 942 typedef sc_signal_in_if<data_type> in_if_type; 943 typedef sc_port<in_if_type,1,SC_ONE_OR_MORE_BOUND> in_port_type; 944 typedef if_type inout_if_type; 945 typedef base_type inout_port_type; 946 947public: 948 949 // constructors 950 951 sc_inout() 952 : base_type(), m_init_val( 0 ), m_traces( 0 ), 953 m_change_finder_p(0) 954 {} 955 956 explicit sc_inout( const char* name_ ) 957 : base_type( name_ ), m_init_val( 0 ), m_traces( 0 ), 958 m_change_finder_p(0) 959 {} 960 961 explicit sc_inout( inout_if_type& interface_ ) 962 : base_type( interface_ ), m_init_val( 0 ), m_traces( 0 ), 963 m_change_finder_p(0) 964 {} 965 966 sc_inout( const char* name_, inout_if_type& interface_ ) 967 : base_type( name_, interface_ ), m_init_val( 0 ), m_traces( 0 ), 968 m_change_finder_p(0) 969 {} 970 971 explicit sc_inout( inout_port_type& parent_ ) 972 : base_type( parent_ ), m_init_val( 0 ), m_traces( 0 ), 973 m_change_finder_p(0) 974 {} 975 976 sc_inout( const char* name_, inout_port_type& parent_ ) 977 : base_type( name_, parent_ ), m_init_val( 0 ), m_traces( 0 ), 978 m_change_finder_p(0) 979 {} 980 981 sc_inout( this_type& parent_ ) 982 : base_type( parent_ ), m_init_val( 0 ), m_traces( 0 ), 983 m_change_finder_p(0) 984 {} 985 986 sc_inout( const char* name_, this_type& parent_ ) 987 : base_type( name_, parent_ ), m_init_val( 0 ), m_traces( 0 ), 988 m_change_finder_p(0) 989 {} 990 991 992 // destructor 993 994 virtual ~sc_inout(); 995 996 997 // interface access shortcut methods 998 999 // get the default event 1000 1001 const sc_event& default_event() const 1002 { return (*this)->default_event(); } 1003 1004 1005 // get the value changed event 1006 1007 const sc_event& value_changed_event() const 1008 { return (*this)->value_changed_event(); } 1009 1010 1011 // read the current value 1012 1013 const data_type& read() const 1014 { return (*this)->read(); } 1015 1016 operator const data_type& () const 1017 { return (*this)->read(); } 1018 1019 1020 // was there a value changed event? 1021 1022 bool event() const 1023 { return (*this)->event(); } 1024 1025 1026 // write the new value 1027 1028 void write( const data_type& value_ ) 1029 { (*this)->write( value_ ); } 1030 1031 this_type& operator = ( const data_type& value_ ) 1032 { (*this)->write( value_ ); return *this; } 1033 1034 this_type& operator = ( const in_if_type& interface_ ) 1035 { (*this)->write( interface_.read() ); return *this; } 1036 1037 this_type& operator = ( const in_port_type& port_ ) 1038 { (*this)->write( port_->read() ); return *this; } 1039 1040 this_type& operator = ( const inout_port_type& port_ ) 1041 { (*this)->write( port_->read() ); return *this; } 1042 1043 this_type& operator = ( const this_type& port_ ) 1044 { (*this)->write( port_->read() ); return *this; } 1045 1046 1047 // set initial value (can also be called when port is not bound yet) 1048 1049 void initialize( const data_type& value_ ); 1050 1051 void initialize( const in_if_type& interface_ ) 1052 { initialize( interface_.read() ); } 1053 1054 1055 // called when elaboration is done 1056 /* WHEN DEFINING THIS METHOD IN A DERIVED CLASS, */ 1057 /* MAKE SURE THAT THIS METHOD IS CALLED AS WELL. */ 1058 1059 virtual void end_of_elaboration(); 1060 1061 1062 // (other) event finder method(s) 1063 1064 sc_event_finder& value_changed() const 1065 { 1066 if ( !m_change_finder_p ) 1067 { 1068 m_change_finder_p = new sc_event_finder_t<in_if_type>( 1069 *this, &in_if_type::value_changed_event ); 1070 } 1071 return *m_change_finder_p; 1072 } 1073 1074 virtual const char* kind() const 1075 { return "sc_inout"; } 1076 1077protected: 1078 1079 data_type* m_init_val; 1080 1081public: 1082 1083 // called by sc_trace 1084 void add_trace_internal( sc_trace_file*, const std::string& ) const; 1085 1086 void add_trace( sc_trace_file*, const std::string& ) const; 1087 1088protected: 1089 1090 void remove_traces() const; 1091 1092 mutable sc_trace_params_vec* m_traces; 1093 1094private: 1095 mutable sc_event_finder* m_change_finder_p; 1096 1097private: 1098 1099 // disabled 1100 sc_inout( const this_type& ); 1101 1102#ifdef __GNUC__ 1103 // Needed to circumvent a problem in the g++-2.95.2 compiler: 1104 // This unused variable forces the compiler to instantiate 1105 // an object of T template so an implicit conversion from 1106 // read() to a C++ intrinsic data type will work. 1107 static data_type dummy; 1108#endif 1109}; 1110 1111template<typename T> 1112::std::ostream& operator << ( ::std::ostream& os, const sc_inout<T>& a ) 1113{ 1114 return os << a->read(); 1115} 1116 1117// IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII 1118 1119 1120// destructor 1121 1122template <class T> 1123inline 1124sc_inout<T>::~sc_inout() 1125{ 1126 delete m_change_finder_p; 1127 delete m_init_val; 1128 remove_traces(); 1129} 1130 1131 1132// set initial value (can also be called when port is not bound yet) 1133 1134template <class T> 1135inline 1136void 1137sc_inout<T>::initialize( const data_type& value_ ) 1138{ 1139 inout_if_type* iface = DCAST<inout_if_type*>( this->get_interface() ); 1140 if( iface != 0 ) { 1141 iface->write( value_ ); 1142 } else { 1143 if( m_init_val == 0 ) { 1144 m_init_val = new data_type; 1145 } 1146 *m_init_val = value_; 1147 } 1148} 1149 1150 1151// called when elaboration is done 1152 1153template <class T> 1154inline 1155void 1156sc_inout<T>::end_of_elaboration() 1157{ 1158 if( m_init_val != 0 ) { 1159 write( *m_init_val ); 1160 delete m_init_val; 1161 m_init_val = 0; 1162 } 1163 if( m_traces != 0 ) { 1164 for( int i = 0; i < (int)m_traces->size(); ++ i ) { 1165 sc_trace_params* p = (*m_traces)[i]; 1166 in_if_type* iface = DCAST<in_if_type*>( this->get_interface() ); 1167 sc_trace( p->tf, iface->read(), p->name ); 1168 } 1169 remove_traces(); 1170 } 1171} 1172 1173 1174// called by sc_trace 1175 1176template <class T> 1177inline 1178void 1179sc_inout<T>::add_trace_internal( sc_trace_file* tf_, const std::string& name_) 1180const 1181{ 1182 if( tf_ != 0 ) { 1183 if( m_traces == 0 ) { 1184 m_traces = new sc_trace_params_vec; 1185 } 1186 m_traces->push_back( new sc_trace_params( tf_, name_ ) ); 1187 } 1188} 1189 1190template <class T> 1191inline 1192void 1193sc_inout<T>::add_trace( sc_trace_file* tf_, const std::string& name_) const 1194{ 1195 sc_deprecated_add_trace(); 1196 add_trace_internal(tf_, name_); 1197} 1198 1199template <class T> 1200inline 1201void 1202sc_inout<T>::remove_traces() const 1203{ 1204 if( m_traces != 0 ) { 1205 for( int i = m_traces->size() - 1; i >= 0; -- i ) { 1206 delete (*m_traces)[i]; 1207 } 1208 delete m_traces; 1209 m_traces = 0; 1210 } 1211} 1212 1213 1214// ---------------------------------------------------------------------------- 1215// CLASS : sc_inout<bool> 1216// 1217// Specialization of sc_inout<T> for type bool. 1218// ---------------------------------------------------------------------------- 1219 1220template <> 1221class sc_inout<bool> : 1222 public sc_port<sc_signal_inout_if<bool>,1,SC_ONE_OR_MORE_BOUND> 1223{ 1224public: 1225 1226 // typedefs 1227 1228 typedef bool data_type; 1229 1230 typedef sc_signal_inout_if<data_type> if_type; 1231 typedef sc_port<if_type,1,SC_ONE_OR_MORE_BOUND> base_type; 1232 typedef sc_inout<data_type> this_type; 1233 1234 typedef sc_signal_in_if<data_type> in_if_type; 1235 typedef sc_port<in_if_type,1,SC_ONE_OR_MORE_BOUND> in_port_type; 1236 typedef if_type inout_if_type; 1237 typedef base_type inout_port_type; 1238 1239public: 1240 1241 // constructors 1242 1243 sc_inout() 1244 : base_type(), m_init_val( 0 ), m_traces( 0 ), 1245 m_change_finder_p(0), m_neg_finder_p(0), m_pos_finder_p(0) 1246 {} 1247 1248 explicit sc_inout( const char* name_ ) 1249 : base_type( name_ ), m_init_val( 0 ), m_traces( 0 ), 1250 m_change_finder_p(0), m_neg_finder_p(0), m_pos_finder_p(0) 1251 {} 1252 1253 explicit sc_inout( inout_if_type& interface_ ) 1254 : base_type( interface_ ), m_init_val( 0 ), m_traces( 0 ), 1255 m_change_finder_p(0), m_neg_finder_p(0), m_pos_finder_p(0) 1256 {} 1257 1258 sc_inout( const char* name_, inout_if_type& interface_ ) 1259 : base_type( name_, interface_ ), m_init_val( 0 ), m_traces( 0 ), 1260 m_change_finder_p(0), m_neg_finder_p(0), m_pos_finder_p(0) 1261 {} 1262 1263 explicit sc_inout( inout_port_type& parent_ ) 1264 : base_type( parent_ ), m_init_val( 0 ), m_traces( 0 ), 1265 m_change_finder_p(0), m_neg_finder_p(0), m_pos_finder_p(0) 1266 {} 1267 1268 sc_inout( const char* name_, inout_port_type& parent_ ) 1269 : base_type( name_, parent_ ), m_init_val( 0 ), m_traces( 0 ), 1270 m_change_finder_p(0), m_neg_finder_p(0), m_pos_finder_p(0) 1271 {} 1272 1273 sc_inout( this_type& parent_ ) 1274 : base_type( parent_ ), m_init_val( 0 ), m_traces( 0 ), 1275 m_change_finder_p(0), m_neg_finder_p(0), m_pos_finder_p(0) 1276 {} 1277 1278 sc_inout( const char* name_, this_type& parent_ ) 1279 : base_type( name_, parent_ ), m_init_val( 0 ), m_traces( 0 ), 1280 m_change_finder_p(0), m_neg_finder_p(0), m_pos_finder_p(0) 1281 {} 1282 1283 1284 // destructor 1285 1286 virtual ~sc_inout(); 1287 1288 1289 // interface access shortcut methods 1290 1291 // get the default event 1292 1293 const sc_event& default_event() const 1294 { return (*this)->default_event(); } 1295 1296 1297 // get the value changed event 1298 1299 const sc_event& value_changed_event() const 1300 { return (*this)->value_changed_event(); } 1301 1302 // get the positive edge event 1303 1304 const sc_event& posedge_event() const 1305 { return (*this)->posedge_event(); } 1306 1307 // get the negative edge event 1308 1309 const sc_event& negedge_event() const 1310 { return (*this)->negedge_event(); } 1311 1312 1313 // read the current value 1314 1315 const data_type& read() const 1316 { return (*this)->read(); } 1317 1318 operator const data_type& () const 1319 { return (*this)->read(); } 1320 1321 1322 // use for positive edge sensitivity 1323 1324 sc_event_finder& pos() const 1325 { 1326 if ( !m_pos_finder_p ) 1327 { 1328 m_pos_finder_p = new sc_event_finder_t<in_if_type>( 1329 *this, &in_if_type::posedge_event ); 1330 } 1331 return *m_pos_finder_p; 1332 } 1333 1334 // use for negative edge sensitivity 1335 1336 sc_event_finder& neg() const 1337 { 1338 if ( !m_neg_finder_p ) 1339 { 1340 m_neg_finder_p = new sc_event_finder_t<in_if_type>( 1341 *this, &in_if_type::negedge_event ); 1342 } 1343 return *m_neg_finder_p; 1344 } 1345 1346 1347 // was there a value changed event? 1348 1349 bool event() const 1350 { return (*this)->event(); } 1351 1352 // was there a positive edge event? 1353 1354 bool posedge() const 1355 { return (*this)->posedge(); } 1356 1357 // was there a negative edge event? 1358 1359 bool negedge() const 1360 { return (*this)->negedge(); } 1361 1362 // write the new value 1363 1364 void write( const data_type& value_ ) 1365 { (*this)->write( value_ ); } 1366 1367 this_type& operator = ( const data_type& value_ ) 1368 { (*this)->write( value_ ); return *this; } 1369 1370 this_type& operator = ( const in_if_type& interface_ ) 1371 { (*this)->write( interface_.read() ); return *this; } 1372 1373 this_type& operator = ( const in_port_type& port_ ) 1374 { (*this)->write( port_->read() ); return *this; } 1375 1376 this_type& operator = ( const inout_port_type& port_ ) 1377 { (*this)->write( port_->read() ); return *this; } 1378 1379 this_type& operator = ( const this_type& port_ ) 1380 { (*this)->write( port_->read() ); return *this; } 1381 1382 1383 // set initial value (can also be called when port is not bound yet) 1384 1385 void initialize( const data_type& value_ ); 1386 1387 void initialize( const in_if_type& interface_ ) 1388 { initialize( interface_.read() ); } 1389 1390 1391 // called when elaboration is done 1392 /* WHEN DEFINING THIS METHOD IN A DERIVED CLASS, */ 1393 /* MAKE SURE THAT THIS METHOD IS CALLED AS WELL. */ 1394 1395 virtual void end_of_elaboration(); 1396 1397 1398 // (other) event finder method(s) 1399 1400 sc_event_finder& value_changed() const 1401 { 1402 if ( !m_change_finder_p ) 1403 { 1404 m_change_finder_p = new sc_event_finder_t<in_if_type>( 1405 *this, &in_if_type::value_changed_event ); 1406 } 1407 return *m_change_finder_p; 1408 } 1409 1410 virtual const char* kind() const 1411 { return "sc_inout"; } 1412 1413protected: 1414 1415 data_type* m_init_val; 1416 1417public: 1418 1419 // called by sc_trace 1420 void add_trace_internal( sc_trace_file*, const std::string& ) const; 1421 1422 void add_trace( sc_trace_file*, const std::string& ) const; 1423 1424protected: 1425 1426 void remove_traces() const; 1427 1428 mutable sc_trace_params_vec* m_traces; 1429 1430private: 1431 mutable sc_event_finder* m_change_finder_p; 1432 mutable sc_event_finder* m_neg_finder_p; 1433 mutable sc_event_finder* m_pos_finder_p; 1434 1435private: 1436 1437 // disabled 1438 sc_inout( const this_type& ); 1439 1440#ifdef __GNUC__ 1441 // Needed to circumvent a problem in the g++-2.95.2 compiler: 1442 // This unused variable forces the compiler to instantiate 1443 // an object of T template so an implicit conversion from 1444 // read() to a C++ intrinsic data type will work. 1445 static data_type dummy; 1446#endif 1447}; 1448 1449 1450// ---------------------------------------------------------------------------- 1451// CLASS : sc_inout<sc_dt::sc_logic> 1452// 1453// Specialization of sc_inout<T> for type sc_dt::sc_logic. 1454// ---------------------------------------------------------------------------- 1455 1456template <> 1457class sc_inout<sc_dt::sc_logic> 1458: public sc_port<sc_signal_inout_if<sc_dt::sc_logic>,1,SC_ONE_OR_MORE_BOUND> 1459{ 1460public: 1461 1462 // typedefs 1463 1464 typedef sc_dt::sc_logic data_type; 1465 1466 typedef sc_signal_inout_if<data_type> if_type; 1467 typedef sc_port<if_type,1,SC_ONE_OR_MORE_BOUND> base_type; 1468 typedef sc_inout<data_type> this_type; 1469 1470 typedef sc_signal_in_if<data_type> in_if_type; 1471 typedef sc_port<in_if_type,1,SC_ONE_OR_MORE_BOUND> in_port_type; 1472 typedef if_type inout_if_type; 1473 typedef base_type inout_port_type; 1474 1475public: 1476 1477 // constructors 1478 1479 sc_inout() 1480 : base_type(), m_init_val( 0 ), m_traces( 0 ), 1481 m_change_finder_p(0), m_neg_finder_p(0), m_pos_finder_p(0) 1482 {} 1483 1484 explicit sc_inout( const char* name_ ) 1485 : base_type( name_ ), m_init_val( 0 ), m_traces( 0 ), 1486 m_change_finder_p(0), m_neg_finder_p(0), m_pos_finder_p(0) 1487 {} 1488 1489 explicit sc_inout( inout_if_type& interface_ ) 1490 : base_type( interface_ ), m_init_val( 0 ), m_traces( 0 ), 1491 m_change_finder_p(0), m_neg_finder_p(0), m_pos_finder_p(0) 1492 {} 1493 1494 sc_inout( const char* name_, inout_if_type& interface_ ) 1495 : base_type( name_, interface_ ), m_init_val( 0 ), m_traces( 0 ), 1496 m_change_finder_p(0), m_neg_finder_p(0), m_pos_finder_p(0) 1497 {} 1498 1499 explicit sc_inout( inout_port_type& parent_ ) 1500 : base_type( parent_ ), m_init_val( 0 ), m_traces( 0 ), 1501 m_change_finder_p(0), m_neg_finder_p(0), m_pos_finder_p(0) 1502 {} 1503 1504 sc_inout( const char* name_, inout_port_type& parent_ ) 1505 : base_type( name_, parent_ ), m_init_val( 0 ), m_traces( 0 ), 1506 m_change_finder_p(0), m_neg_finder_p(0), m_pos_finder_p(0) 1507 {} 1508 1509 sc_inout( this_type& parent_ ) 1510 : base_type( parent_ ), m_init_val( 0 ), m_traces( 0 ), 1511 m_change_finder_p(0), m_neg_finder_p(0), m_pos_finder_p(0) 1512 {} 1513 1514 sc_inout( const char* name_, this_type& parent_ ) 1515 : base_type( name_, parent_ ), m_init_val( 0 ), m_traces( 0 ), 1516 m_change_finder_p(0), m_neg_finder_p(0), m_pos_finder_p(0) 1517 {} 1518 1519 1520 // destructor 1521 1522 virtual ~sc_inout(); 1523 1524 1525 // interface access shortcut methods 1526 1527 // get the default event 1528 1529 const sc_event& default_event() const 1530 { return (*this)->default_event(); } 1531 1532 1533 // get the value changed event 1534 1535 const sc_event& value_changed_event() const 1536 { return (*this)->value_changed_event(); } 1537 1538 // get the positive edge event 1539 1540 const sc_event& posedge_event() const 1541 { return (*this)->posedge_event(); } 1542 1543 // get the negative edge event 1544 1545 const sc_event& negedge_event() const 1546 { return (*this)->negedge_event(); } 1547 1548 1549 // read the current value 1550 1551 const data_type& read() const 1552 { return (*this)->read(); } 1553 1554 operator const data_type& () const 1555 { return (*this)->read(); } 1556 1557 1558 // use for positive edge sensitivity 1559 1560 sc_event_finder& pos() const 1561 { 1562 if ( !m_pos_finder_p ) 1563 { 1564 m_pos_finder_p = new sc_event_finder_t<in_if_type>( 1565 *this, &in_if_type::posedge_event ); 1566 } 1567 return *m_pos_finder_p; 1568 } 1569 1570 // use for negative edge sensitivity 1571 1572 sc_event_finder& neg() const 1573 { 1574 if ( !m_neg_finder_p ) 1575 { 1576 m_neg_finder_p = new sc_event_finder_t<in_if_type>( 1577 *this, &in_if_type::negedge_event ); 1578 } 1579 return *m_neg_finder_p; 1580 } 1581 1582 1583 // was there a value changed event? 1584 1585 bool event() const 1586 { return (*this)->event(); } 1587 1588 // was there a positive edge event? 1589 1590 bool posedge() const 1591 { return (*this)->posedge(); } 1592 1593 // was there a negative edge event? 1594 1595 bool negedge() const 1596 { return (*this)->negedge(); } 1597 1598 // write the new value 1599 1600 void write( const data_type& value_ ) 1601 { (*this)->write( value_ ); } 1602 1603 this_type& operator = ( const data_type& value_ ) 1604 { (*this)->write( value_ ); return *this; } 1605 1606 this_type& operator = ( const in_if_type& interface_ ) 1607 { (*this)->write( interface_.read() ); return *this; } 1608 1609 this_type& operator = ( const in_port_type& port_ ) 1610 { (*this)->write( port_->read() ); return *this; } 1611 1612 this_type& operator = ( const inout_port_type& port_ ) 1613 { (*this)->write( port_->read() ); return *this; } 1614 1615 this_type& operator = ( const this_type& port_ ) 1616 { (*this)->write( port_->read() ); return *this; } 1617 1618 1619 // set initial value (can also be called when port is not bound yet) 1620 1621 void initialize( const data_type& value_ ); 1622 1623 void initialize( const in_if_type& interface_ ) 1624 { initialize( interface_.read() ); } 1625 1626 1627 // called when elaboration is done 1628 /* WHEN DEFINING THIS METHOD IN A DERIVED CLASS, */ 1629 /* MAKE SURE THAT THIS METHOD IS CALLED AS WELL. */ 1630 1631 virtual void end_of_elaboration(); 1632 1633 1634 // (other) event finder method(s) 1635 1636 sc_event_finder& value_changed() const 1637 { 1638 if ( !m_change_finder_p ) 1639 { 1640 m_change_finder_p = new sc_event_finder_t<in_if_type>( 1641 *this, &in_if_type::value_changed_event ); 1642 } 1643 return *m_change_finder_p; 1644 } 1645 1646 virtual const char* kind() const 1647 { return "sc_inout"; } 1648 1649protected: 1650 1651 data_type* m_init_val; 1652 1653public: 1654 1655 // called by sc_trace 1656 void add_trace_internal( sc_trace_file*, const std::string& ) const; 1657 1658 void add_trace( sc_trace_file*, const std::string& ) const; 1659 1660protected: 1661 1662 void remove_traces() const; 1663 1664 mutable sc_trace_params_vec* m_traces; 1665 1666private: 1667 mutable sc_event_finder* m_change_finder_p; 1668 mutable sc_event_finder* m_neg_finder_p; 1669 mutable sc_event_finder* m_pos_finder_p; 1670 1671private: 1672 1673 // disabled 1674 sc_inout( const this_type& ); 1675 1676#ifdef __GNUC__ 1677 // Needed to circumvent a problem in the g++-2.95.2 compiler: 1678 // This unused variable forces the compiler to instantiate 1679 // an object of T template so an implicit conversion from 1680 // read() to a C++ intrinsic data type will work. 1681 static data_type dummy; 1682#endif 1683}; 1684 1685 1686// ---------------------------------------------------------------------------- 1687// CLASS : sc_out<T> 1688// 1689// The sc_signal<T> output port class. 1690// ---------------------------------------------------------------------------- 1691 1692// sc_out can also read from its port, hence no difference with sc_inout. 1693// For debugging reasons, a class is provided instead of a define. 1694 1695template <class T> 1696class sc_out 1697: public sc_inout<T> 1698{ 1699public: 1700 1701 // typedefs 1702 1703 typedef T data_type; 1704 1705 typedef sc_out<data_type> this_type; 1706 typedef sc_inout<data_type> base_type; 1707 1708 typedef typename base_type::in_if_type in_if_type; 1709 typedef typename base_type::in_port_type in_port_type; 1710 typedef typename base_type::inout_if_type inout_if_type; 1711 typedef typename base_type::inout_port_type inout_port_type; 1712 1713public: 1714 1715 // constructors 1716 1717 sc_out() 1718 : base_type() 1719 {} 1720 1721 explicit sc_out( const char* name_ ) 1722 : base_type( name_ ) 1723 {} 1724 1725 explicit sc_out( inout_if_type& interface_ ) 1726 : base_type( interface_ ) 1727 {} 1728 1729 sc_out( const char* name_, inout_if_type& interface_ ) 1730 : base_type( name_, interface_ ) 1731 {} 1732 1733 explicit sc_out( inout_port_type& parent_ ) 1734 : base_type( parent_ ) 1735 {} 1736 1737 sc_out( const char* name_, inout_port_type& parent_ ) 1738 : base_type( name_, parent_ ) 1739 {} 1740 1741 sc_out( this_type& parent_ ) 1742 : base_type( parent_ ) 1743 {} 1744 1745 sc_out( const char* name_, this_type& parent_ ) 1746 : base_type( name_, parent_ ) 1747 {} 1748 1749 1750 // destructor (does nothing) 1751 1752 virtual ~sc_out() 1753 {} 1754 1755 1756 // write the new value 1757 1758 this_type& operator = ( const data_type& value_ ) 1759 { (*this)->write( value_ ); return *this; } 1760 1761 this_type& operator = ( const in_if_type& interface_ ) 1762 { (*this)->write( interface_.read() ); return *this; } 1763 1764 this_type& operator = ( const in_port_type& port_ ) 1765 { (*this)->write( port_->read() ); return *this; } 1766 1767 this_type& operator = ( const inout_port_type& port_ ) 1768 { (*this)->write( port_->read() ); return *this; } 1769 1770 this_type& operator = ( const this_type& port_ ) 1771 { (*this)->write( port_->read() ); return *this; } 1772 1773 virtual const char* kind() const 1774 { return "sc_out"; } 1775 1776private: 1777 1778 // disabled 1779 sc_out( const this_type& ); 1780}; 1781 1782 1783// IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII 1784 1785 1786// ---------------------------------------------------------------------------- 1787// FUNCTION : sc_trace 1788// ---------------------------------------------------------------------------- 1789 1790template <class T> 1791inline 1792void 1793sc_trace(sc_trace_file* tf, const sc_in<T>& port, const std::string& name) 1794{ 1795 const sc_signal_in_if<T>* iface = 0; 1796 if (sc_get_curr_simcontext()->elaboration_done() ) 1797 { 1798 iface = DCAST<const sc_signal_in_if<T>*>( port.get_interface() ); 1799 } 1800 1801 if ( iface ) 1802 sc_trace( tf, iface->read(), name ); 1803 else 1804 port.add_trace_internal( tf, name ); 1805} 1806 1807template <class T> 1808inline 1809void 1810sc_trace( sc_trace_file* tf, const sc_inout<T>& port, 1811 const std::string& name ) 1812{ 1813 const sc_signal_in_if<T>* iface = 0; 1814 if (sc_get_curr_simcontext()->elaboration_done() ) 1815 { 1816 iface =DCAST<const sc_signal_in_if<T>*>( port.get_interface() ); 1817 } 1818 1819 if ( iface ) 1820 sc_trace( tf, iface->read(), name ); 1821 else 1822 port.add_trace_internal( tf, name ); 1823} 1824 1825} // namespace sc_core 1826 1827#undef SC_VIRTUAL_ 1828 1829/***************************************************************************** 1830 1831 MODIFICATION LOG - modifiers, enter your name, affiliation, date and 1832 changes you are making here. 1833 1834 Name, Affiliation, Date: Jason Elbaum, Motorola, Inc., 2001-11-12 1835 Description of Modification: Added a static, private, otherwise 1836 unused data member to the sc_in 1837 and sc_inout classes to address 1838 a bug in the GNU compiler *only*. 1839 This works around a bug in g++ 2.95.2 1840 regarding implicit casting from a 1841 templated class to a C++ intrinsic type. 1842 1843 *****************************************************************************/ 1844//$Log: sc_signal_ports.h,v $ 1845//Revision 1.10 2011/08/29 18:04:32 acg 1846// Philipp A. Hartmann: miscellaneous clean ups. 1847// 1848//Revision 1.9 2011/08/26 20:45:43 acg 1849// Andy Goodrich: moved the modification log to the end of the file to 1850// eliminate source line number skew when check-ins are done. 1851// 1852//Revision 1.8 2011/08/07 19:08:01 acg 1853// Andy Goodrich: moved logs to end of file so line number synching works 1854// better between versions. 1855// 1856//Revision 1.7 2011/08/07 18:53:09 acg 1857// Philipp A. Hartmann: add virtual instances of the bind function for 1858// base classes to eliminate warning messages for clang platforms. 1859// 1860//Revision 1.6 2011/04/02 00:03:23 acg 1861// Andy Goodrich: catch the other bind()'s that I missed in Philipp's update. 1862// 1863//Revision 1.5 2011/04/01 22:33:31 acg 1864// Philipp A. Harmann: Use const interface signature to implement non-const 1865// interface signature for virtual bind(...). 1866// 1867//Revision 1.4 2011/03/30 16:46:10 acg 1868// Andy Goodrich: added a signature and removed a virtual specification 1869// to eliminate warnings with certain compilers. 1870// 1871//Revision 1.3 2011/02/18 20:23:45 acg 1872// Andy Goodrich: Copyright update. 1873// 1874//Revision 1.2 2011/01/20 16:52:15 acg 1875// Andy Goodrich: changes for IEEE 1666 2011. 1876// 1877//Revision 1.1.1.1 2006/12/15 20:20:04 acg 1878//SystemC 2.3 1879// 1880//Revision 1.11 2006/04/18 23:36:50 acg 1881// Andy Goodrich: made add_trace_internal public until I can figure out 1882// how to do a friend specification for sc_trace in an environment where 1883// there are partial template and full template specifications for its 1884// arguments. 1885// 1886//Revision 1.10 2006/04/18 18:01:26 acg 1887// Andy Goodrich: added an add_trace_internal() method to the various port 1888// classes so that sc_trace has something to call that won't emit an 1889// IEEE 1666 deprecation message. 1890// 1891//Revision 1.9 2006/03/13 20:19:44 acg 1892// Andy Goodrich: changed sc_event instances into pointers to sc_event instances 1893// that are allocated as needed. This saves considerable storage for large 1894// numbers of signals, etc. 1895// 1896//Revision 1.8 2006/02/02 23:42:37 acg 1897// Andy Goodrich: implemented a much better fix to the sc_event_finder 1898// proliferation problem. This new version allocates only a single event 1899// finder for each port for each type of event, e.g., pos(), neg(), and 1900// value_change(). The event finder persists as long as the port does, 1901// which is what the LRM dictates. Because only a single instance is 1902// allocated for each event type per port there is not a potential 1903// explosion of storage as was true in the 2.0.1/2.1 versions. 1904// 1905//Revision 1.7 2006/02/02 21:38:12 acg 1906// Andy Goodrich: fix to the comment log. 1907// 1908//Revision 1.4 2006/01/24 20:46:32 acg 1909//Andy Goodrich: changes to eliminate use of deprecated features. For instance, 1910//using notify(SC_ZERO_TIME) in place of notify_delayed(). 1911// 1912//Revision 1.3 2006/01/13 18:47:42 acg 1913//Added $Log command so that CVS comments are reproduced in the source. 1914// 1915//Revision 1.2 2006/01/03 23:18:26 acg 1916//Changed copyright to include 2006. 1917// 1918//Revision 1.1.1.1 2005/12/19 23:16:43 acg 1919//First check in of SystemC 2.1 into its own archive. 1920// 1921//Revision 1.18 2005/09/15 23:01:52 acg 1922//Added std:: prefix to appropriate methods and types to get around 1923//issues with the Edison Front End. 1924// 1925//Revision 1.17 2005/06/10 22:43:55 acg 1926//Added CVS change log annotation. 1927// 1928 1929#endif 1930 1931// Taf! 1932