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_object.cpp -- Abstract base class of all SystemC objects. 23 24 Original Author: Stan Y. Liao, Synopsys, Inc. 25 26 CHANGE LOG AT THE END OF THE FILE 27 *****************************************************************************/ 28 29 30#include <cstdlib> 31#include <cassert> 32#include <stddef.h> 33#include <cstdio> 34#include <string.h> 35#include <ctype.h> 36 37#include "sysc/kernel/sc_externs.h" 38#include "sysc/kernel/sc_kernel_ids.h" 39#include "sysc/kernel/sc_module.h" 40#include "sysc/kernel/sc_object.h" 41#include "sysc/kernel/sc_object_manager.h" 42#include "sysc/kernel/sc_phase_callback_registry.h" 43#include "sysc/kernel/sc_process_handle.h" 44#include "sysc/kernel/sc_simcontext.h" 45#include "sysc/kernel/sc_event.h" 46#include "sysc/utils/sc_hash.h" 47#include "sysc/utils/sc_iostream.h" 48#include "sysc/utils/sc_list.h" 49#include "sysc/utils/sc_utils_ids.h" 50#include "sysc/utils/sc_mempool.h" 51 52namespace sc_core { 53 54typedef int (*STRCMP)(const void*, const void*); 55 56const char SC_HIERARCHY_CHAR = '.'; 57 58/* This will be gotten rid after multiple-processes 59 are implemented. This is to fix some regression 60 problems. */ 61bool sc_enable_name_checking = true; 62 63 64// ---------------------------------------------------------------------------- 65// CLASS : sc_object 66// 67// Abstract base class of all SystemC `simulation' objects. 68// ---------------------------------------------------------------------------- 69 70void 71sc_object::add_child_event( sc_event* event_p ) 72{ 73 // no check if event_p is already in the set 74 m_child_events.push_back( event_p ); 75} 76 77void 78sc_object::add_child_object( sc_object* object_ ) 79{ 80 // no check if object_ is already in the set 81 m_child_objects.push_back( object_ ); 82} 83 84const char* 85sc_object::basename() const 86{ 87 size_t pos; // position of last SC_HIERARCHY_CHAR. 88 pos = m_name.rfind( (char)SC_HIERARCHY_CHAR ); 89 return ( pos == m_name.npos ) ? m_name.c_str() : &(m_name.c_str()[pos+1]); 90} 91 92void 93sc_object::print(::std::ostream& os) const 94{ 95 os << name(); 96} 97 98void 99sc_object::dump(::std::ostream& os) const 100{ 101 os << "name = " << name() << "\n"; 102 os << "kind = " << kind() << "\n"; 103} 104 105static int sc_object_num = 0; 106 107static std::string 108sc_object_newname() 109{ 110 char buffer[64]; 111 std::string result; 112 113 std::sprintf(buffer, "{%d}", sc_object_num); 114 sc_object_num++; 115 result = buffer; 116 117 return result; 118} 119 120// +---------------------------------------------------------------------------- 121// |"sc_object::remove_child_event" 122// | 123// | This virtual method removes the supplied event from the list of child 124// | events if it is present. 125// | 126// | Arguments: 127// | event_p -> event to be removed. 128// | Returns true if the event was present, false if not. 129// +---------------------------------------------------------------------------- 130bool 131sc_object::remove_child_event( sc_event* event_p ) 132{ 133 int size = m_child_events.size(); 134 for( int i = 0; i < size; ++ i ) { 135 if( event_p == m_child_events[i] ) { 136 m_child_events[i] = m_child_events[size - 1]; 137 m_child_events.pop_back(); 138 return true; 139 } 140 } 141 return false; 142} 143 144// +---------------------------------------------------------------------------- 145// |"sc_object::remove_child_object" 146// | 147// | This virtual method removes the supplied object from the list of child 148// | objects if it is present. 149// | 150// | Arguments: 151// | object_p -> object to be removed. 152// | Returns true if the object was present, false if not. 153// +---------------------------------------------------------------------------- 154bool 155sc_object::remove_child_object( sc_object* object_p ) 156{ 157 int size = m_child_objects.size(); 158 for( int i = 0; i < size; ++ i ) { 159 if( object_p == m_child_objects[i] ) { 160 m_child_objects[i] = m_child_objects[size - 1]; 161 m_child_objects.pop_back(); 162 object_p->m_parent = NULL; 163 return true; 164 } 165 } 166 return false; 167} 168 169// +---------------------------------------------------------------------------- 170// |"sc_object::sc_object_init" 171// | 172// | This method initializes this object instance and places it in to the 173// | object hierarchy if the supplied name is not NULL. 174// | 175// | Arguments: 176// | nm = leaf name for the object. 177// +---------------------------------------------------------------------------- 178void 179sc_object::sc_object_init(const char* nm) 180{ 181 // SET UP POINTERS TO OBJECT MANAGER, PARENT, AND SIMULATION CONTEXT: 182 // 183 // Make the current simcontext the simcontext for this object 184 185 m_simc = sc_get_curr_simcontext(); 186 m_attr_cltn_p = 0; 187 sc_object_manager* object_manager = m_simc->get_object_manager(); 188 m_parent = m_simc->active_object(); 189 190 // CONSTRUCT PATHNAME TO OBJECT BEING CREATED: 191 // 192 // If there is not a leaf name generate one. 193 194 m_name = object_manager->create_name(nm ? nm : sc_object_newname().c_str()); 195 196 197 // PLACE THE OBJECT INTO THE HIERARCHY 198 199 object_manager->insert_object(m_name, this); 200 if ( m_parent ) 201 m_parent->add_child_object( this ); 202 else 203 m_simc->add_child_object( this ); 204} 205 206sc_object::sc_object() : 207 m_attr_cltn_p(0), m_child_events(), m_child_objects(), m_name(), 208 m_parent(0), m_simc(0) 209{ 210 sc_object_init( sc_gen_unique_name("object") ); 211} 212 213sc_object::sc_object( const sc_object& that ) : 214 m_attr_cltn_p(0), m_child_events(), m_child_objects(), m_name(), 215 m_parent(0), m_simc(0) 216{ 217 sc_object_init( sc_gen_unique_name( that.basename() ) ); 218} 219 220 221static bool 222object_name_illegal_char(char ch) 223{ 224 return (ch == SC_HIERARCHY_CHAR) || isspace(ch); 225} 226 227sc_object::sc_object(const char* nm) : 228 m_attr_cltn_p(0), m_child_events(), m_child_objects(), m_name(), 229 m_parent(0), m_simc(0) 230{ 231 int namebuf_alloc = 0; 232 char* namebuf = 0; 233 const char* p; 234 235 // null name or "" uses machine generated name. 236 237 if ( !nm || !*nm ) 238 nm = sc_gen_unique_name("object"); 239 p = nm; 240 241 if (nm && sc_enable_name_checking) { 242 namebuf_alloc = 1 + strlen(nm); 243 namebuf = (char*) sc_mempool::allocate(namebuf_alloc); 244 char* q = namebuf; 245 const char* r = nm; 246 bool has_illegal_char = false; 247 while (*r) { 248 if (object_name_illegal_char(*r)) { 249 has_illegal_char = true; 250 *q = '_'; 251 } else { 252 *q = *r; 253 } 254 r++; 255 q++; 256 } 257 *q = '\0'; 258 p = namebuf; 259 if (has_illegal_char) 260 { 261 std::string message = nm; 262 message += " substituted by "; 263 message += namebuf; 264 SC_REPORT_WARNING( SC_ID_ILLEGAL_CHARACTERS_, message.c_str()); 265 } 266 } 267 sc_object_init(p); 268 sc_mempool::release( namebuf, namebuf_alloc ); 269} 270 271sc_object::~sc_object() 272{ 273#if SC_HAS_PHASE_CALLBACKS_ 274 unregister_simulation_phase_callback( SC_STATUS_ANY ); 275#endif 276 detach(); 277 delete m_attr_cltn_p; 278} 279 280//------------------------------------------------------------------------------ 281//"sc_object::detach" 282// 283// This method detaches this object instance from the object hierarchy. 284// It is called in two places: ~sc_object() and sc_process_b::kill_process(). 285//------------------------------------------------------------------------------ 286void sc_object::detach() 287{ 288 if (m_simc) { 289 290 // REMOVE OBJECT FROM THE OBJECT MANAGER: 291 292 sc_object_manager* object_manager = m_simc->get_object_manager(); 293 object_manager->remove_object(m_name); 294 295 // REMOVE OBJECT FROM PARENT'S LIST OF OBJECTS: 296 297 if ( m_parent ) 298 m_parent->remove_child_object( this ); 299 else 300 m_simc->remove_child_object( this ); 301 302 // ORPHAN THIS OBJECT'S CHILDREN: 303 304#if 0 // #### 305 ::std::<sc_object*> children_p = &get_child_objects(); 306 int child_n = children_p->size(); 307 sc_object* parent_p; 308 309 for ( int child_i = 0; child_i < child_n; child_i++ ) 310 { 311 (*children_p)[child_i]->m_parent = 0; 312 } 313#endif 314 315 } 316} 317 318// +---------------------------------------------------------------------------- 319// |"sc_object::orphan_child_events" 320// | 321// | This method moves the children of this object instance to be children 322// | of the simulator. 323// +---------------------------------------------------------------------------- 324void sc_object::orphan_child_events() 325{ 326 std::vector< sc_event* > const & events = get_child_events(); 327 328 std::vector< sc_event* >::const_iterator 329 it = events.begin(), end = events.end(); 330 331 for( ; it != end; ++it ) 332 { 333 (*it)->m_parent_p = NULL; 334 simcontext()->add_child_event(*it); 335 } 336} 337 338// +---------------------------------------------------------------------------- 339// |"sc_object::orphan_child_objects" 340// | 341// | This method moves the children of this object instance to be children 342// | of the simulator. 343// +---------------------------------------------------------------------------- 344void sc_object::orphan_child_objects() 345{ 346 std::vector< sc_object* > const & children = get_child_objects(); 347 348 std::vector< sc_object* >::const_iterator 349 it = children.begin(), end = children.end(); 350 351 for( ; it != end; ++it ) 352 { 353 (*it)->m_parent = NULL; 354 simcontext()->add_child_object(*it); 355 } 356} 357 358void 359sc_object::trace( sc_trace_file * /* unused */) const 360{ 361 /* This space is intentionally left blank */ 362} 363 364 365// add attribute 366 367bool 368sc_object::add_attribute( sc_attr_base& attribute_ ) 369{ 370 if ( !m_attr_cltn_p ) m_attr_cltn_p = new sc_attr_cltn; 371 return ( m_attr_cltn_p->push_back( &attribute_ ) ); 372} 373 374 375// get attribute by name 376 377sc_attr_base* 378sc_object::get_attribute( const std::string& name_ ) 379{ 380 if ( !m_attr_cltn_p ) m_attr_cltn_p = new sc_attr_cltn; 381 return ( (*m_attr_cltn_p)[name_] ); 382} 383 384const sc_attr_base* 385sc_object::get_attribute( const std::string& name_ ) const 386{ 387 if ( !m_attr_cltn_p ) m_attr_cltn_p = new sc_attr_cltn; 388 return ( (*m_attr_cltn_p)[name_] ); 389} 390 391 392// remove attribute by name 393 394sc_attr_base* 395sc_object::remove_attribute( const std::string& name_ ) 396{ 397 if ( m_attr_cltn_p ) 398 return ( m_attr_cltn_p->remove( name_ ) ); 399 else 400 return 0; 401} 402 403 404// remove all attributes 405 406void 407sc_object::remove_all_attributes() 408{ 409 if ( m_attr_cltn_p ) 410 m_attr_cltn_p->remove_all(); 411} 412 413 414// get the number of attributes 415 416int 417sc_object::num_attributes() const 418{ 419 if ( m_attr_cltn_p ) 420 return ( m_attr_cltn_p->size() ); 421 else 422 return 0; 423} 424 425 426// get the attribute collection 427 428sc_attr_cltn& 429sc_object::attr_cltn() 430{ 431 if ( !m_attr_cltn_p ) m_attr_cltn_p = new sc_attr_cltn; 432 return *m_attr_cltn_p; 433} 434 435const sc_attr_cltn& 436sc_object::attr_cltn() const 437{ 438 if ( !m_attr_cltn_p ) m_attr_cltn_p = new sc_attr_cltn; 439 return *m_attr_cltn_p; 440} 441 442sc_object* 443sc_object::get_parent() const 444{ 445 static bool warn_sc_get_parent_deprecated=true; 446 if ( warn_sc_get_parent_deprecated ) 447 { 448 warn_sc_get_parent_deprecated=false; 449 SC_REPORT_INFO(sc_core::SC_ID_IEEE_1666_DEPRECATION_, 450 "sc_object::get_parent() is deprecated, " 451 "use get_parent_object() instead"); 452 } 453 return get_parent_object(); 454} 455 456// ---------------------------------------------------------------------------- 457// simulation phase callbacks 458 459 460sc_object::phase_cb_mask 461sc_object::register_simulation_phase_callback( phase_cb_mask mask ) 462{ 463 mask = simcontext()->m_phase_cb_registry 464 ->register_callback(*this, mask); 465 return mask; 466} 467 468 469sc_object::phase_cb_mask 470sc_object::unregister_simulation_phase_callback( phase_cb_mask mask ) 471{ 472 mask = simcontext()->m_phase_cb_registry 473 ->unregister_callback(*this, mask); 474 return mask; 475} 476 477 478void 479sc_object::simulation_phase_callback() 480{ 481 SC_REPORT_WARNING( SC_ID_PHASE_CALLBACK_NOT_IMPLEMENTED_, name() ); 482} 483 484 485} // namespace sc_core 486 487/***************************************************************************** 488 489 MODIFICATION LOG - modifiers, enter your name, affiliation, date and 490 changes you are making here. 491 492 Name, Affiliation, Date: Bishnupriya Bhattacharya, Cadence Design Systems, 493 25 August, 2003 494 Description of Modification: if module name hierarchy is empty, sc_object 495 ctor assumes the currently executing process 496 as the parent object to support dynamic process 497 creation similar to other sc_objects 498 499 Name, Affiliation, Date: Andy Goodrich, Forte Design Systems 500 5 September 2003 501 Description of Modification: - Made creation of attributes structure 502 conditional on its being used. This eliminates 503 100 bytes of storage for each normal sc_object. 504 505 *****************************************************************************/ 506 507 508// $Log: sc_object.cpp,v $ 509// Revision 1.16 2011/08/29 18:04:32 acg 510// Philipp A. Hartmann: miscellaneous clean ups. 511// 512// Revision 1.15 2011/08/26 20:46:10 acg 513// Andy Goodrich: moved the modification log to the end of the file to 514// eliminate source line number skew when check-ins are done. 515// 516// Revision 1.14 2011/08/24 22:05:51 acg 517// Torsten Maehne: initialization changes to remove warnings. 518// 519// Revision 1.13 2011/04/01 21:24:57 acg 520// Andy Goodrich: removed unused code. 521// 522// Revision 1.12 2011/03/06 15:55:11 acg 523// Andy Goodrich: Changes for named events. 524// 525// Revision 1.11 2011/03/05 19:44:20 acg 526// Andy Goodrich: changes for object and event naming and structures. 527// 528// Revision 1.10 2011/03/05 04:45:16 acg 529// Andy Goodrich: moved active process calculation to the sc_simcontext class. 530// 531// Revision 1.9 2011/03/05 01:39:21 acg 532// Andy Goodrich: changes for named events. 533// 534// Revision 1.8 2011/02/18 20:27:14 acg 535// Andy Goodrich: Updated Copyrights. 536// 537// Revision 1.7 2011/02/13 21:47:37 acg 538// Andy Goodrich: update copyright notice. 539// 540// Revision 1.6 2011/01/25 20:50:37 acg 541// Andy Goodrich: changes for IEEE 1666 2011. 542// 543// Revision 1.5 2011/01/18 20:10:44 acg 544// Andy Goodrich: changes for IEEE1666_2011 semantics. 545// 546// Revision 1.4 2010/08/03 17:02:39 acg 547// Andy Goodrich: formatting changes. 548// 549// Revision 1.3 2009/02/28 00:26:58 acg 550// Andy Goodrich: changed boost name space to sc_boost to allow use with 551// full boost library applications. 552// 553// Revision 1.2 2008/05/22 17:06:26 acg 554// Andy Goodrich: updated copyright notice to include 2008. 555// 556// Revision 1.1.1.1 2006/12/15 20:20:05 acg 557// SystemC 2.3 558// 559// Revision 1.5 2006/04/20 17:08:17 acg 560// Andy Goodrich: 3.0 style process changes. 561// 562// Revision 1.4 2006/03/21 00:00:34 acg 563// Andy Goodrich: changed name of sc_get_current_process_base() to be 564// sc_get_current_process_b() since its returning an sc_process_b instance. 565// 566// Revision 1.3 2006/01/13 18:44:30 acg 567// Added $Log to record CVS changes into the source. 568// 569