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