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_manager.cpp -- Manager of objects (naming, &c.) 23 24 Original Author: Stan Y. Liao, Synopsys, Inc. 25 26 CHANGE LOG AT THE END OF THE FILE 27 *****************************************************************************/ 28 29 30#include <stdio.h> 31#include <cstdlib> 32#include <cassert> 33#include <ctype.h> 34#include <stddef.h> 35#include <algorithm> // pick up std::sort. 36 37#include "sysc/utils/sc_iostream.h" 38#include "sysc/kernel/sc_object.h" 39#include "sysc/utils/sc_hash.h" 40#include "sysc/utils/sc_list.h" 41#include "sysc/utils/sc_mempool.h" 42#include "sysc/kernel/sc_simcontext.h" 43#include "sysc/kernel/sc_object_manager.h" 44#include "sysc/kernel/sc_kernel_ids.h" 45#include "sysc/kernel/sc_process.h" 46#include "sysc/kernel/sc_module_name.h" 47 48namespace sc_core { 49 50// ---------------------------------------------------------------------------- 51// CLASS : sc_object_manager 52// 53// Manager of objects. 54// ---------------------------------------------------------------------------- 55 56sc_object_manager::sc_object_manager() : 57 m_event_it(), 58 m_event_walk_ok(0), 59 m_instance_table(), 60 m_module_name_stack(0), 61 m_object_it(), 62 m_object_stack(), 63 m_object_walk_ok() 64{ 65} 66 67// +---------------------------------------------------------------------------- 68// |"sc_object_manager::~sc_object_manager" 69// | 70// | This is the object instance destructor for this class. It goes through 71// | each sc_object instance in the instance table and sets its m_simc field 72// | to NULL. 73// +---------------------------------------------------------------------------- 74sc_object_manager::~sc_object_manager() 75{ 76 instance_table_t::iterator it; // instance table iterator. 77 78 for ( it = m_instance_table.begin(); it != m_instance_table.end(); it++) 79 { 80 sc_object* obj_p = it->second.m_object_p; 81 if ( obj_p ) obj_p->m_simc = 0; 82 } 83} 84 85// +---------------------------------------------------------------------------- 86// |"sc_object_manager::create_name" 87// | 88// | This method creates a hierarchical name based on the name of the active 89// | object and the supplied leaf name. If the resultant name is not unique it 90// | will be made unique and a warning message issued. 91// | 92// | Arguments: 93// | leaf_name = name to use for the leaf of the hierarchy. 94// | Result is an std::string containing the name. 95// +---------------------------------------------------------------------------- 96std::string sc_object_manager::create_name(const char* leaf_name) 97{ 98 bool clash; // true if path name exists in obj table 99 std::string leafname_string; // string containing the leaf name. 100 std::string parentname_string; // parent path name 101 sc_object* parent_p; // parent for this instance or NULL. 102 std::string result_orig_string; // save for warning message. 103 std::string result_string; // name to return. 104 105 // CONSTRUCT PATHNAME TO THE NAME TO BE RETURNED: 106 // 107 // If there is not a leaf name generate one. 108 109 parent_p = sc_get_curr_simcontext()->active_object(); 110 parentname_string = parent_p ? parent_p->name() : ""; 111 leafname_string = leaf_name; 112 if (parent_p) { 113 result_string = parentname_string; 114 result_string += SC_HIERARCHY_CHAR; 115 result_string += leafname_string; 116 } else { 117 result_string = leafname_string; 118 } 119 120 // SAVE the original path name 121 122 result_orig_string = result_string; 123 124 // MAKE SURE THE ENTITY NAME IS UNIQUE: 125 // 126 // If not use unique name generator to make it unique. 127 128 clash = false; 129 for (;;) 130 { 131 instance_table_t::iterator it = m_instance_table.find(result_string); 132 if ( it == m_instance_table.end() || 133 (it->second.m_event_p == NULL && it->second.m_object_p == NULL ) ) 134 { 135 break; 136 } 137 clash = true; 138 leafname_string = sc_gen_unique_name(leafname_string.c_str(), false); 139 if (parent_p) { 140 result_string = parentname_string; 141 result_string += SC_HIERARCHY_CHAR; 142 result_string += leafname_string; 143 } else { 144 result_string = leafname_string; 145 } 146 } 147 if (clash) { 148 std::string message = result_orig_string; 149 message += ". Latter declaration will be renamed to "; 150 message += result_string; 151 SC_REPORT_WARNING( SC_ID_INSTANCE_EXISTS_, message.c_str()); 152 } 153 154 return result_string; 155} 156 157// +---------------------------------------------------------------------------- 158// |"sc_object_manager::find_event" 159// | 160// | This method returns the sc_event with the supplied name, or a NULL if 161// | the event does not exist. 162// | 163// | Arguments: 164// | name = name of the event 165// | Result is a pointer to the event or NULL if it does not exist. 166// +---------------------------------------------------------------------------- 167sc_event* 168sc_object_manager::find_event(const char* name) 169{ 170 instance_table_t::iterator it; 171 it = m_instance_table.find(name); 172 return it == m_instance_table.end() ? NULL : it->second.m_event_p; 173} 174 175// +---------------------------------------------------------------------------- 176// |"sc_object_manager::find_object" 177// | 178// | This method returns the sc_object with the supplied name, or a NULL if 179// | the object does not exist. 180// | 181// | Arguments: 182// | name = name of the object 183// | Result is a pointer to the object or NULL if it does not exist. 184// +---------------------------------------------------------------------------- 185sc_object* 186sc_object_manager::find_object(const char* name) 187{ 188 instance_table_t::iterator it; 189 it = m_instance_table.find(name); 190 return it == m_instance_table.end() ? NULL : it->second.m_object_p; 191} 192 193 194// +---------------------------------------------------------------------------- 195// |"sc_object_manager::first_object" 196// | 197// | This method initializes the object iterator to point to the first object 198// | in the instance table, and returns its address. If there are no objects 199// | in the table a NULL value is returned. 200// +---------------------------------------------------------------------------- 201sc_object* 202sc_object_manager::first_object() 203{ 204 sc_object* result_p; // result to return. 205 206 m_object_walk_ok = true; 207 result_p = NULL; 208 for ( m_object_it = m_instance_table.begin(); 209 m_object_it != m_instance_table.end(); 210 m_object_it++ ) 211 { 212 result_p = m_object_it->second.m_object_p; 213 if ( result_p ) break; 214 } 215 return result_p; 216} 217 218// +---------------------------------------------------------------------------- 219// |"sc_object_manager::hierarchy_curr" 220// | 221// | This method returns the current object in the object hierarchy or NULL 222// | if it does not exist. 223// +---------------------------------------------------------------------------- 224sc_object* 225sc_object_manager::hierarchy_curr() 226{ 227 size_t hierarchy_n; // current size of the hierarchy. 228 229 hierarchy_n = m_object_stack.size(); 230 return hierarchy_n ? m_object_stack[hierarchy_n-1] : 0; 231} 232 233// +---------------------------------------------------------------------------- 234// |"sc_object_manager::hierarchy_pop" 235// | 236// | This method pops the current object off the object hierarchy and returns 237// | it. 238// +---------------------------------------------------------------------------- 239sc_object* 240sc_object_manager::hierarchy_pop() 241{ 242 size_t hierarchy_n; // current size of the hierarchy. 243 sc_object* result_p; // object to return. 244 245 hierarchy_n = m_object_stack.size(); 246 if ( hierarchy_n == 0 ) return NULL; 247 hierarchy_n--; 248 result_p = m_object_stack[hierarchy_n]; 249 m_object_stack.pop_back(); 250 return result_p; 251} 252 253// +---------------------------------------------------------------------------- 254// |"sc_object_manager::hierarchy_push" 255// | 256// | This method pushes down the sc_object hierarchy to make the supplied 257// | object the current object in the hierarchy. 258// | 259// | Arguments: 260// | object_p -> object to become the new current object in the hierarchy. 261// +---------------------------------------------------------------------------- 262void 263sc_object_manager::hierarchy_push(sc_object* object_p) 264{ 265 m_object_stack.push_back(object_p); 266} 267 268 269// +---------------------------------------------------------------------------- 270// |"sc_object_manager::hierarchy_size" 271// | 272// | This method returns the current size of the object hierarchy stack. 273// +---------------------------------------------------------------------------- 274int 275sc_object_manager::hierarchy_size() 276{ 277 return m_object_stack.size(); 278} 279 280// +---------------------------------------------------------------------------- 281// |"sc_object_manager::insert_event" 282// | 283// | This method inserts the supplied sc_event instance into the instance 284// | table using the supplied name. 285// | 286// | Arguments: 287// | name = name of the event to be inserted. 288// | event_p -> event to be inserted. 289// +---------------------------------------------------------------------------- 290void 291sc_object_manager::insert_event(const std::string& name, sc_event* event_p) 292{ 293 m_instance_table[name].m_event_p = event_p; 294} 295 296// +---------------------------------------------------------------------------- 297// |"sc_object_manager::insert_object" 298// | 299// | This method inserts the supplied sc_object instance into the instance 300// | table using the supplied name. 301// | 302// | Arguments: 303// | name = name of the event to be inserted. 304// | object_p -> object to be inserted. 305// +---------------------------------------------------------------------------- 306void 307sc_object_manager::insert_object(const std::string& name, sc_object* object_p) 308{ 309 m_instance_table[name].m_object_p = object_p; 310} 311 312// +---------------------------------------------------------------------------- 313// |"sc_object_manager::next_object" 314// | 315// | This method returns the next object pointed to by the instance iterator. 316// +---------------------------------------------------------------------------- 317sc_object* 318sc_object_manager::next_object() 319{ 320 sc_object* result_p; // result to return. 321 322 assert( m_object_walk_ok ); 323 324 if ( m_object_it == m_instance_table.end() ) return NULL; 325 m_object_it++; 326 327 for ( result_p = NULL; m_object_it != m_instance_table.end(); 328 m_object_it++ ) 329 { 330 result_p = m_object_it->second.m_object_p; 331 if ( result_p ) break; 332 } 333 return result_p; 334} 335 336// +---------------------------------------------------------------------------- 337// |"sc_object_manager::pop_module_name" 338// | 339// | This method pops an entry off the module name stack and returns it. 340// +---------------------------------------------------------------------------- 341sc_module_name* 342sc_object_manager::pop_module_name() 343{ 344 sc_module_name* mod_name = m_module_name_stack; 345 m_module_name_stack = m_module_name_stack->m_next; 346 mod_name->m_next = 0; 347 return mod_name; 348} 349 350// +---------------------------------------------------------------------------- 351// |"sc_object_manager::push_module_name" 352// | 353// | This method pushes the supplied entry onto the module name stack. 354// | 355// | Arguments: 356// | mod_name_p -> entry to push onto the module name stack. 357// +---------------------------------------------------------------------------- 358void 359sc_object_manager::push_module_name(sc_module_name* mod_name_p) 360{ 361 mod_name_p->m_next = m_module_name_stack; 362 m_module_name_stack = mod_name_p; 363} 364 365// +---------------------------------------------------------------------------- 366// |"sc_object_manager::top_of_module_name_stack" 367// | 368// | This method returns the module name that is on the top of the module 369// | name stack. 370// +---------------------------------------------------------------------------- 371sc_module_name* 372sc_object_manager::top_of_module_name_stack() 373{ 374 if( m_module_name_stack == 0 ) { 375 SC_REPORT_ERROR( SC_ID_MODULE_NAME_STACK_EMPTY_, 0 ); 376 } 377 return m_module_name_stack; 378} 379 380// +---------------------------------------------------------------------------- 381// |"sc_object_manager::remove_event" 382// | 383// | This method removes the sc_event instance with the supplied name from 384// | the table of instances. Note we just clear the pointer since if the name 385// | was for an sc_object the m_event_p pointer will be null anyway. 386// | 387// | Arguments: 388// | name = name of the event to be removed. 389// +---------------------------------------------------------------------------- 390void 391sc_object_manager::remove_event(const std::string& name) 392{ 393 instance_table_t::iterator it; // instance table iterator. 394 it = m_instance_table.find(name); 395 if ( it != m_instance_table.end() ) it->second.m_event_p = NULL; 396} 397 398// +---------------------------------------------------------------------------- 399// |"sc_object_manager::remove_object" 400// | 401// | This method removes the sc_object instance with the supplied name from 402// | the table of instances. Note we just clear the pointer since if the name 403// | was for an sc_event the m_object_p pointer will be null anyway. 404// | 405// | Arguments: 406// | name = name of the object to be removed. 407// +---------------------------------------------------------------------------- 408void 409sc_object_manager::remove_object(const std::string& name) 410{ 411 instance_table_t::iterator it; // instance table iterator. 412 it = m_instance_table.find(name); 413 if ( it != m_instance_table.end() ) it->second.m_object_p = NULL; 414} 415 416} // namespace sc_core 417 418// $Log: sc_object_manager.cpp,v $ 419// Revision 1.13 2011/08/26 20:46:10 acg 420// Andy Goodrich: moved the modification log to the end of the file to 421// eliminate source line number skew when check-ins are done. 422// 423// Revision 1.12 2011/08/24 22:05:51 acg 424// Torsten Maehne: initialization changes to remove warnings. 425// 426// Revision 1.11 2011/06/25 17:08:39 acg 427// Andy Goodrich: Jerome Cornet's changes to use libtool to build the 428// library. 429// 430// Revision 1.10 2011/04/01 21:27:54 acg 431// Andy Goodrich: documentation of event and object insertion methods. 432// 433// Revision 1.9 2011/03/06 15:55:11 acg 434// Andy Goodrich: Changes for named events. 435// 436// Revision 1.8 2011/03/05 19:44:20 acg 437// Andy Goodrich: changes for object and event naming and structures. 438// 439// Revision 1.7 2011/03/05 04:45:16 acg 440// Andy Goodrich: moved active process calculation to the sc_simcontext class. 441// 442// Revision 1.6 2011/03/05 01:39:21 acg 443// Andy Goodrich: changes for named events. 444// 445// Revision 1.5 2011/02/18 20:27:14 acg 446// Andy Goodrich: Updated Copyrights. 447// 448// Revision 1.4 2011/02/13 21:47:37 acg 449// Andy Goodrich: update copyright notice. 450// 451// Revision 1.3 2010/07/22 20:02:33 acg 452// Andy Goodrich: bug fixes. 453// 454// Revision 1.2 2008/05/22 17:06:26 acg 455// Andy Goodrich: updated copyright notice to include 2008. 456// 457// Revision 1.1.1.1 2006/12/15 20:20:05 acg 458// SystemC 2.3 459// 460// Revision 1.3 2006/01/13 18:44:30 acg 461// Added $Log to record CVS changes into the source. 462// 463