sc_process_handle.h revision 12027
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_process_handle.h -- Process access support. 23 24 Original Author: Andy Goodrich, Forte Design Systems, 17 June 2003 25 26 27 CHANGE LOG AT THE END OF THE FILE 28 *****************************************************************************/ 29 30// $Log: sc_process_handle.h,v $ 31// Revision 1.21 2011/08/26 21:54:04 acg 32// Torsten Maehne: Simplify use of dynamic_cast<> for initializing m_target. 33// 34// Revision 1.20 2011/08/26 20:46:10 acg 35// Andy Goodrich: moved the modification log to the end of the file to 36// eliminate source line number skew when check-ins are done. 37// 38 39#if !defined(sc_process_handle_h_INCLUDED) 40#define sc_process_handle_h_INCLUDED 41 42#include "sysc/kernel/sc_module.h" 43 44namespace sc_core { 45 46// forward operator declarations: 47 48class sc_process_handle; 49bool 50operator == ( const sc_process_handle& left, const sc_process_handle& right ); 51bool 52operator != ( const sc_process_handle& left, const sc_process_handle& right ); 53bool 54operator < ( const sc_process_handle& left, const sc_process_handle& right ); 55 56 57 58//============================================================================= 59// CLASS sc_process_handle 60// 61// This class provides access to an sc_process_b object instance in a 62// manner which allows some persistence after the deletion of the actual 63// process. 64//============================================================================= 65class sc_simcontext; 66class sc_process_handle { 67 typedef sc_process_handle this_type; 68 69 friend bool operator == ( const this_type& left, const this_type& right ); 70 friend bool operator != ( const this_type& left, const this_type& right ); 71 friend bool operator < ( const this_type& left, const this_type& right ); 72 friend class sc_object; 73 friend class sc_join; 74 friend class sc_module; 75 friend class sc_reset; 76 friend class sc_sensitive; 77 friend class sc_sensitive_pos; 78 friend class sc_sensitive_neg; 79 friend class sc_thread_process; 80 81 public: 82 inline sc_process_handle(); 83 inline explicit sc_process_handle( sc_object* object_p ); 84 inline explicit sc_process_handle( sc_process_b* process_p ); 85 inline sc_process_handle( const sc_process_handle& orig ); 86 inline ~sc_process_handle(); 87 inline sc_process_handle& operator = ( sc_process_handle src ); 88 inline void swap( sc_process_handle& other ); 89 90 public: 91 inline void disable( 92 sc_descendant_inclusion_info descendants=SC_NO_DESCENDANTS ); 93 inline bool dynamic() const; 94 inline void enable( 95 sc_descendant_inclusion_info descendants=SC_NO_DESCENDANTS ); 96 inline const std::vector<sc_event*>& get_child_events() const; 97 inline const std::vector<sc_object*>& get_child_objects() const; 98 inline sc_object* get_parent_object() const; 99 inline sc_object* get_process_object() const; 100 inline bool is_unwinding() const; 101 inline void kill( 102 sc_descendant_inclusion_info descendants=SC_NO_DESCENDANTS ); 103 inline const char* name() const; 104 inline sc_curr_proc_kind proc_kind() const; 105 inline void reset( 106 sc_descendant_inclusion_info descendants=SC_NO_DESCENDANTS ); 107 inline sc_event& reset_event() const; 108 inline void resume( 109 sc_descendant_inclusion_info descendants=SC_NO_DESCENDANTS ); 110 inline void suspend( 111 sc_descendant_inclusion_info descendants=SC_NO_DESCENDANTS ); 112 inline void sync_reset_off( 113 sc_descendant_inclusion_info descendants=SC_NO_DESCENDANTS ); 114 inline void sync_reset_on( 115 sc_descendant_inclusion_info descendants=SC_NO_DESCENDANTS ); 116 inline sc_event& terminated_event(); 117 inline bool terminated() const; 118 template<typename EXCEPT> 119 inline void throw_it( const EXCEPT& exception, 120 sc_descendant_inclusion_info descendants=SC_NO_DESCENDANTS ); 121 inline bool valid() const; 122 123 public: // implementation specific methods: 124 inline std::string dump_state() const; 125 126 protected: 127 inline bool dont_initialize() const 128 { return m_target_p ? m_target_p->dont_initialize() : false; } 129 inline void dont_initialize( bool dont ); 130 131 public: 132 operator sc_process_b* () 133 { return m_target_p; } 134 operator sc_cthread_handle (); 135 operator sc_method_handle (); 136 operator sc_thread_handle (); 137 138 protected: 139 sc_process_b* m_target_p; // Target for this object instance. 140 141 protected: 142 static std::vector<sc_event*> empty_event_vector; // If m_target_p == 0. 143 static std::vector<sc_object*> empty_object_vector; // If m_target_p == 0. 144 static sc_event non_event; // If m_target_p == 0. 145}; 146 147inline bool operator == ( 148 const sc_process_handle& left, const sc_process_handle& right ) 149{ 150 return (left.m_target_p != 0) && (right.m_target_p != 0) && 151 (left.m_target_p == right.m_target_p); 152} 153 154inline bool operator != ( 155 const sc_process_handle& left, const sc_process_handle& right ) 156{ 157 return (left.m_target_p == 0) || (right.m_target_p == 0) || 158 (left.m_target_p != right.m_target_p); 159} 160 161inline bool operator < ( 162 const sc_process_handle& left, const sc_process_handle& right ) 163{ 164 return left.m_target_p < right.m_target_p; 165} 166 167//------------------------------------------------------------------------------ 168//"sc_process_handle::sc_process_handle - non-pointer constructor" 169// 170// This version of the object instance constructor for this class creates 171// an object instance whose target needs to be supplied via an assignment. 172//------------------------------------------------------------------------------ 173inline sc_process_handle::sc_process_handle() : m_target_p(0) 174{ 175} 176 177//------------------------------------------------------------------------------ 178//"sc_process_handle::sc_process_handle - pointer constructor" 179// 180// This version of the object instance constructor for this class creates 181// an object instance whose target is the supplied sc_object instance. 182// The supplied sc_object must in fact be an sc_process_b instance. 183// object_p -> sc_object instance this is handle for. 184//------------------------------------------------------------------------------ 185inline sc_process_handle::sc_process_handle( sc_object* object_p ) : 186 m_target_p(DCAST<sc_process_b*>(object_p)) 187{ 188 if ( m_target_p ) m_target_p->reference_increment(); 189} 190 191//------------------------------------------------------------------------------ 192//"sc_process_handle::sc_process_handle - pointer constructor" 193// 194// This version of the object instance constructor for this class creates 195// an object instance whose target is the supplied sc_process_b instance. 196// This saves a dynamic cast compared to the sc_object* case. 197// process_p -> process instance this is handle for. 198//------------------------------------------------------------------------------ 199inline sc_process_handle::sc_process_handle( sc_process_b* process_p ) : 200 m_target_p(process_p) 201{ 202 if ( m_target_p ) m_target_p->reference_increment(); 203} 204 205//------------------------------------------------------------------------------ 206//"sc_process_handle::sc_process_handle - copy constructor" 207// 208// This version of the object instance constructor for this class provides 209// the copy constructor for the class. It clones the supplied original 210// handle and increments the references to its target. 211// orig = sc_process_handle object instance to be copied from. 212//------------------------------------------------------------------------------ 213inline sc_process_handle::sc_process_handle( const sc_process_handle& orig ) : 214 m_target_p(orig.m_target_p) 215{ 216 if ( m_target_p ) m_target_p->reference_increment(); 217} 218 219 220//------------------------------------------------------------------------------ 221//"sc_process_handle::operator =" 222// 223// This assignment operator signature is call by value rather than reference. 224// This means that an sc_process_handle instance will be created and the 225// target for that instance will be incremented before the assignment is done. 226// The assignment is done using the swap() method, which simply swaps the 227// targets of 'orig' and this object instance. We don't need to increment 228// the reference count for our new target since that was done when 'orig' 229// was created. Our old target's reference count will be decremented when 230// 'orig' is deleted. 231// orig = sc_process_handle object instance to be copied from. 232// Result is a reference for this object instance. 233//------------------------------------------------------------------------------ 234inline sc_process_handle& 235sc_process_handle::operator = ( sc_process_handle orig ) 236{ 237 swap( orig ); 238 return *this; 239} 240 241 242//------------------------------------------------------------------------------ 243//"sc_process_handle::~sc_process_handle" 244// 245// This is the object instance destructor for this class. It decrements 246// the reference count for its target. 247//------------------------------------------------------------------------------ 248inline sc_process_handle::~sc_process_handle() 249{ 250 if ( m_target_p ) m_target_p->reference_decrement(); 251} 252 253//------------------------------------------------------------------------------ 254//"sc_process_handle::inline methods" 255// 256// These are short inline methods. 257//------------------------------------------------------------------------------ 258 259// disable this object instance's target. 260 261inline void sc_process_handle::disable(sc_descendant_inclusion_info descendants) 262{ 263 if ( m_target_p ) 264 m_target_p->disable_process(descendants); 265 else 266 SC_REPORT_WARNING( SC_ID_EMPTY_PROCESS_HANDLE_, "disable()"); 267} 268 269// call dont_initialize() on this object instance's target. 270 271inline void sc_process_handle::dont_initialize( bool dont ) 272{ 273 if ( m_target_p ) 274 m_target_p->dont_initialize( dont ); 275 else 276 SC_REPORT_WARNING( SC_ID_EMPTY_PROCESS_HANDLE_, "dont_initialize()"); 277} 278 279// dump the status of this object instance's target: 280 281inline std::string sc_process_handle::dump_state() const 282{ 283 return m_target_p ? m_target_p->dump_state() : std::string("NO TARGET"); 284} 285 286// return whether this object instance's target is dynamic or not. 287 288inline bool sc_process_handle::dynamic() const 289{ 290 return m_target_p ? m_target_p->dynamic() : false; 291} 292 293// enable this object instance's target. 294 295inline void sc_process_handle::enable(sc_descendant_inclusion_info descendants) 296{ 297 if ( m_target_p ) 298 m_target_p->enable_process(descendants); 299 else 300 SC_REPORT_WARNING( SC_ID_EMPTY_PROCESS_HANDLE_, "enable()"); 301} 302 303// return the child objects for this object instance's target. 304 305inline 306const std::vector<sc_event*>& sc_process_handle::get_child_events() const 307{ 308 return m_target_p ? m_target_p->get_child_events() : empty_event_vector; 309} 310 311// return the child objects for this object instance's target. 312 313inline 314const std::vector<sc_object*>& sc_process_handle::get_child_objects() const 315{ 316 return m_target_p ? m_target_p->get_child_objects() : empty_object_vector; 317} 318 319// return the parent object for this object instance's target. 320 321inline sc_object* sc_process_handle::get_parent_object() const 322{ 323 return m_target_p ? m_target_p->get_parent_object() : NULL; 324} 325 326// return this object instance's target. 327 328inline sc_object* sc_process_handle::get_process_object() const 329{ 330 return m_target_p; 331} 332 333// return whether this object instance is unwinding or not. 334 335inline bool sc_process_handle::is_unwinding() const 336{ 337 if ( m_target_p ) 338 return m_target_p->is_unwinding(); 339 else { 340 SC_REPORT_WARNING( SC_ID_EMPTY_PROCESS_HANDLE_, "is_unwinding()"); 341 return false; 342 } 343} 344 345// kill this object instance's target. 346 347inline void sc_process_handle::kill( sc_descendant_inclusion_info descendants ) 348{ 349 if ( m_target_p ) 350 m_target_p->kill_process( descendants ); 351 else 352 SC_REPORT_WARNING( SC_ID_EMPTY_PROCESS_HANDLE_, "kill()"); 353} 354 355// return the name of this object instance's target. 356 357inline const char* sc_process_handle::name() const 358{ 359 return m_target_p ? m_target_p->name() : ""; 360} 361 362// return the process kind for this object instance's target. 363 364inline sc_curr_proc_kind sc_process_handle::proc_kind() const 365{ 366 return m_target_p ? m_target_p->proc_kind() : SC_NO_PROC_; 367} 368 369// reset this object instance's target. 370 371inline void sc_process_handle::reset( sc_descendant_inclusion_info descendants ) 372{ 373 if ( m_target_p ) 374 m_target_p->reset_process( sc_process_b::reset_asynchronous, 375 descendants ); 376 else 377 SC_REPORT_WARNING( SC_ID_EMPTY_PROCESS_HANDLE_, "reset()"); 378} 379 380// return the reset event for this object instance's target. 381 382inline sc_event& sc_process_handle::reset_event() const 383{ 384 if ( m_target_p ) 385 return m_target_p->reset_event(); 386 else 387 { 388 SC_REPORT_WARNING( SC_ID_EMPTY_PROCESS_HANDLE_, "reset()"); 389 return sc_process_handle::non_event; 390 } 391} 392 393// resume this object instance's target. 394 395inline void sc_process_handle::resume(sc_descendant_inclusion_info descendants) 396{ 397 if ( m_target_p ) 398 m_target_p->resume_process(descendants); 399 else 400 SC_REPORT_WARNING( SC_ID_EMPTY_PROCESS_HANDLE_, "resume()"); 401} 402 403// suspend this object instance's target. 404 405inline void sc_process_handle::suspend(sc_descendant_inclusion_info descendants) 406{ 407 if ( m_target_p ) 408 m_target_p->suspend_process(descendants); 409 else 410 SC_REPORT_WARNING( SC_ID_EMPTY_PROCESS_HANDLE_, "suspend()"); 411} 412 413// swap targets of this process handle with the supplied one. 414 415inline void sc_process_handle::swap( sc_process_handle& other ) 416{ 417 sc_process_b* tmp = m_target_p; 418 m_target_p = other.m_target_p; 419 other.m_target_p = tmp; 420} 421 422// turn sync_reset off for this object instance's target. 423 424inline void sc_process_handle::sync_reset_off( 425 sc_descendant_inclusion_info descendants) 426{ 427 if ( m_target_p ) 428 m_target_p->reset_process( sc_process_b::reset_synchronous_off, 429 descendants); 430 else 431 SC_REPORT_WARNING( SC_ID_EMPTY_PROCESS_HANDLE_, "sync_reset_off()"); 432} 433 434// turn sync_reset on for this object instance's target. 435 436inline void sc_process_handle::sync_reset_on( 437 sc_descendant_inclusion_info descendants) 438{ 439 if ( m_target_p ) 440 { 441 m_target_p->reset_process(sc_process_b::reset_synchronous_on, 442 descendants); 443 } 444 else 445 { 446 SC_REPORT_WARNING( SC_ID_EMPTY_PROCESS_HANDLE_, "sync_reset_on()"); 447 } 448} 449 450// terminate this object instance's target. 451 452inline bool sc_process_handle::terminated() const 453{ 454 return m_target_p ? m_target_p->terminated() : false; 455} 456 457// return the termination event for this object instance's target. 458 459inline sc_event& sc_process_handle::terminated_event() 460{ 461 if ( m_target_p ) 462 return m_target_p->terminated_event(); 463 else 464 { 465 SC_REPORT_WARNING( SC_ID_EMPTY_PROCESS_HANDLE_, "terminated_event()"); 466 return sc_process_handle::non_event; 467 } 468} 469 470// return true if this object instance has a target, false it not. 471 472inline bool sc_process_handle::valid() const 473{ 474 return m_target_p ? true : false; 475} 476 477//------------------------------------------------------------------------------ 478//"sc_process_handle::sc_throw_it" 479// 480// This method throws the supplied exception to the process whose handle this 481// object instance is, and optionally to the process' descendants. Once the 482// exception is thrown the currently executed process will suspend to allow 483// the exception to be propagated. Once the propagation has occurred the 484// current process will be resumed. 485// 486// Notes: 487// (1) We allocate the helper function on the stack, see the description of 488// sc_throw_it<EXCEPT>, in sc_process.h, for why. 489// 490// Arguments: 491// exception = exception to be thrown 492// descendants = indication of whether descendant processes should also 493// receive the throw. 494//------------------------------------------------------------------------------ 495template<typename EXCEPT> 496inline void sc_process_handle::throw_it( const EXCEPT& exception, 497 sc_descendant_inclusion_info descendants) 498{ 499 sc_throw_it<EXCEPT> helper(exception); // helper to throw the exception. 500 501 if ( !m_target_p ) 502 { 503 SC_REPORT_WARNING( SC_ID_EMPTY_PROCESS_HANDLE_, "throw_it()"); 504 return; 505 } 506 m_target_p->throw_user(helper, descendants); 507} 508 509 510//------------------------------------------------------------------------------ 511//"sc_process_b::last_created_process_handle" 512// 513// This method returns the kind of this process. 514//------------------------------------------------------------------------------ 515inline sc_process_handle sc_process_b::last_created_process_handle() 516{ 517 return sc_process_handle(m_last_created_process_p); 518} 519 520inline sc_process_handle sc_get_last_created_process_handle() 521{ 522 return sc_process_b::last_created_process_handle(); 523} 524 525} // namespace sc_core 526 527// Revision 1.19 2011/08/24 22:05:51 acg 528// Torsten Maehne: initialization changes to remove warnings. 529// 530// Revision 1.18 2011/04/01 22:08:26 acg 531// Andy Goodrich: remove unused variable. 532// 533// Revision 1.17 2011/03/12 21:07:51 acg 534// Andy Goodrich: changes to kernel generated event support. 535// 536// Revision 1.16 2011/02/18 20:27:14 acg 537// Andy Goodrich: Updated Copyrights. 538// 539// Revision 1.15 2011/02/17 19:53:03 acg 540// Andy Goodrich: changed dump_status() to dump_state() with new signature. 541// 542// Revision 1.14 2011/02/13 21:47:37 acg 543// Andy Goodrich: update copyright notice. 544// 545// Revision 1.13 2011/02/13 21:33:30 acg 546// Andy Goodrich: added dump_status() to allow the dumping of the status 547// of a process handle's target. 548// 549// Revision 1.12 2011/02/01 23:01:53 acg 550// Andy Goodrich: removed dead code. 551// 552// Revision 1.11 2011/02/01 21:07:36 acg 553// Andy Goodrich: defering of run queue manipulations to the 554// sc_thread_process::throw_it() method. 555// 556// Revision 1.10 2011/01/25 20:50:37 acg 557// Andy Goodrich: changes for IEEE 1666 2011. 558// 559// Revision 1.9 2011/01/20 16:52:20 acg 560// Andy Goodrich: changes for IEEE 1666 2011. 561// 562// Revision 1.8 2011/01/19 23:21:50 acg 563// Andy Goodrich: changes for IEEE 1666 2011 564// 565// Revision 1.7 2011/01/18 20:10:45 acg 566// Andy Goodrich: changes for IEEE1666_2011 semantics. 567// 568// Revision 1.6 2010/07/30 05:21:22 acg 569// Andy Goodrich: release 2.3 fixes. 570// 571// Revision 1.5 2010/07/22 20:02:33 acg 572// Andy Goodrich: bug fixes. 573// 574// Revision 1.4 2009/05/22 16:06:29 acg 575// Andy Goodrich: process control updates. 576// 577// Revision 1.3 2008/05/22 17:06:26 acg 578// Andy Goodrich: updated copyright notice to include 2008. 579// 580// Revision 1.2 2007/09/20 20:32:35 acg 581// Andy Goodrich: changes to the semantics of throw_it() to match the 582// specification. A call to throw_it() will immediately suspend the calling 583// thread until all the throwees have executed. At that point the calling 584// thread will be restarted before the execution of any other threads. 585// 586// Revision 1.1.1.1 2006/12/15 20:20:05 acg 587// SystemC 2.3 588// 589// Revision 1.7 2006/05/08 17:58:24 acg 590// Andy Goodrich: added David Long's forward declarations for friend 591// functions, methods, and operators to keep the Microsoft compiler happy. 592// 593// Revision 1.6 2006/04/20 17:08:17 acg 594// Andy Goodrich: 3.0 style process changes. 595// 596// Revision 1.5 2006/04/11 23:13:21 acg 597// Andy Goodrich: Changes for reduced reset support that only includes 598// sc_cthread, but has preliminary hooks for expanding to method and thread 599// processes also. 600// 601// Revision 1.4 2006/01/24 20:49:05 acg 602// Andy Goodrich: changes to remove the use of deprecated features within the 603// simulator, and to issue warning messages when deprecated features are used. 604// 605// Revision 1.3 2006/01/13 18:44:30 acg 606// Added $Log to record CVS changes into the source. 607 608#endif // !defined(sc_spawn_h_INCLUDED) 609