46#include "debug/CxxConfig.hh" 47#include "mem/mem_object.hh" 48#include "sim/serialize.hh" 49 50CxxConfigManager::CxxConfigManager(CxxConfigFileBase &configFile_) : 51 configFile(configFile_), flags(configFile_.getFlags()), 52 simObjectResolver(*this) 53{ 54} 55 56const CxxConfigDirectoryEntry & 57CxxConfigManager::findObjectType(const std::string &object_name, 58 std::string &object_type) 59{ 60 if (!configFile.objectExists(object_name)) 61 throw Exception(object_name, "Can't find sim object"); 62 63 if (!configFile.getParam(object_name, "type", object_type)) 64 throw Exception(object_name, "Sim object has no 'type' field"); 65 66 if (cxx_config_directory.find(object_type) == 67 cxx_config_directory.end()) 68 { 69 throw Exception(object_name, csprintf( 70 "No sim object type %s is available", object_type)); 71 } 72 73 const CxxConfigDirectoryEntry *entry = cxx_config_directory[object_type]; 74 75 return *entry; 76} 77 78std::string 79CxxConfigManager::rename(const std::string &from_name) 80{ 81 for (auto i = renamings.begin(); i != renamings.end(); ++ i) { 82 const Renaming &renaming = *i; 83 84 if (from_name.find(renaming.fromPrefix) == 0) { 85 return renaming.toPrefix + 86 from_name.substr(renaming.fromPrefix.length()); 87 } 88 } 89 90 return from_name; 91} 92 93std::string 94CxxConfigManager::unRename(const std::string &to_name) 95{ 96 for (auto i = renamings.begin(); i != renamings.end(); ++ i) { 97 const Renaming &renaming = *i; 98 99 if (to_name.find(renaming.toPrefix) == 0) { 100 return renaming.fromPrefix + 101 to_name.substr(renaming.toPrefix.length()); 102 } 103 } 104 105 return to_name; 106} 107 108static 109std::string formatParamList(const std::vector<std::string> ¶m_values) 110{ 111 std::ostringstream params; 112 113 auto i = param_values.begin(); 114 auto end_i = param_values.end(); 115 116 params << '['; 117 while (i != end_i) { 118 params << (*i); 119 ++i; 120 121 if (i != end_i) 122 params << ", "; 123 } 124 params << ']'; 125 126 return params.str(); 127} 128 129SimObject * 130CxxConfigManager::findObject(const std::string &object_name, 131 bool visit_children) 132{ 133 std::string instance_name = rename(object_name); 134 135 if (object_name == "Null") 136 return NULL; 137 138 /* Already constructed */ 139 if (objectsByName.find(instance_name) != objectsByName.end()) 140 return objectsByName[instance_name]; 141 142 if (inVisit.find(instance_name) != inVisit.end()) 143 throw Exception(instance_name, "Cycle in configuration"); 144 145 std::string object_type; 146 const CxxConfigDirectoryEntry &entry = 147 findObjectType(object_name, object_type); 148 149 SimObject *object = NULL; 150 151 CxxConfigParams *object_params = findObjectParams(object_name); 152 153 try { 154 DPRINTF(CxxConfig, "Configuring sim object references for: %s" 155 " (%s from object %s)\n", instance_name, object_type, 156 object_name); 157 158 /* Remember the path back to the top of the recursion to detect 159 * cycles */ 160 inVisit.insert(instance_name); 161 162 /* Resolve pointed-to SimObjects by recursing into them */ 163 for (auto i = entry.parameters.begin(); 164 i != entry.parameters.end(); ++i) 165 { 166 const CxxConfigDirectoryEntry::ParamDesc *param = (*i).second; 167 168 if (param->isSimObject) { 169 if (param->isVector) { 170 std::vector<std::string> sub_object_names; 171 172 if (!configFile.getParamVector(object_name, param->name, 173 sub_object_names)) 174 { 175 throw Exception(object_name, csprintf( 176 "Element not found: %s", param->name)); 177 } 178 179 std::vector<SimObject *> sub_objects; 180 181 for (auto n = sub_object_names.begin(); 182 n != sub_object_names.end(); ++n) 183 { 184 SimObject *sub_object = findObject(*n, 185 visit_children); 186 187 if (sub_object) 188 sub_objects.push_back(sub_object); 189 } 190 191 if (!object_params->setSimObjectVector(param->name, 192 sub_objects)) 193 { 194 throw Exception(object_name, csprintf( 195 "Can't assign sim object element %s from \"%s\"", 196 param->name, formatParamList(sub_object_names))); 197 } 198 199 DPRINTF(CxxConfig, "Setting sim object(s): %s.%s=%s\n", 200 object_name, param->name, 201 formatParamList(sub_object_names)); 202 } else { 203 std::string sub_object_name; 204 205 if (!configFile.getParam(object_name, param->name, 206 sub_object_name)) 207 { 208 throw Exception(object_name, csprintf( 209 "Element not found: %s", param->name)); 210 } 211 212 SimObject *sub_object = findObject(sub_object_name, 213 visit_children); 214 215 if (sub_object) { 216 if (!object_params->setSimObject(param->name, 217 sub_object)) 218 { 219 throw Exception(object_name, csprintf( 220 "Can't assign sim object element %s from" 221 " \"%s\"", param->name, sub_object_name)); 222 } 223 } 224 225 DPRINTF(CxxConfig, "Setting sim object(s):" 226 " %s.%s=%s\n", object_name, param->name, 227 sub_object_name); 228 } 229 } 230 } 231 232 DPRINTF(CxxConfig, "Creating SimObject: %s\n", instance_name); 233 object = object_params->simObjectCreate(); 234 235 if (!object) { 236 throw Exception(object_name, csprintf("Couldn't create object of" 237 " type: %s", object_type)); 238 } 239 240 objectsByName[instance_name] = object; 241 objectParamsByName[instance_name] = object_params; 242 243 if (visit_children) { 244 std::vector<std::string> children; 245 configFile.getObjectChildren(object_name, children, true); 246 247 /* Visit all your children */ 248 for (auto i = children.begin(); i != children.end(); ++i) 249 findObject(*i, visit_children); 250 } 251 } catch (Exception &) { 252 delete object_params; 253 throw; 254 } 255 256 /* Mark that we've exited object 257 * construction and so 'find'ing this object again won't be a 258 * configuration loop */ 259 inVisit.erase(object_name); 260 return object; 261} 262 263CxxConfigParams * 264CxxConfigManager::findObjectParams(const std::string &object_name) 265{ 266 std::string instance_name = rename(object_name); 267 268 /* Already constructed */ 269 if (objectParamsByName.find(instance_name) != objectParamsByName.end()) 270 return objectParamsByName[instance_name]; 271 272 std::string object_type; 273 const CxxConfigDirectoryEntry &entry = 274 findObjectType(object_name, object_type); 275 276 DPRINTF(CxxConfig, "Configuring parameters of object: %s (%s)\n", 277 instance_name, object_type); 278 279 CxxConfigParams *object_params = entry.makeParamsObject(); 280 281 try { 282 /* Fill in the implicit parameters that don't necessarily 283 * appear in config files */ 284 object_params->setName(instance_name); 285 286 /* Fill in parameters */ 287 for (auto i = entry.parameters.begin(); 288 i != entry.parameters.end(); ++i) 289 { 290 const CxxConfigDirectoryEntry::ParamDesc *param = (*i).second; 291 292 if (!param->isSimObject) { 293 /* Only handle non-SimObject parameters here (see below) */ 294 295 if (param->isVector) { 296 std::vector<std::string> param_values; 297 298 if (!configFile.getParamVector(object_name, param->name, 299 param_values)) 300 { 301 throw Exception(object_name, csprintf( 302 "Element not found for parameter: %s", 303 param->name)); 304 } 305 306 if (!object_params->setParamVector(param->name, 307 param_values, flags)) 308 { 309 throw Exception(instance_name, csprintf( 310 "Bad parameter value: .%s=X=\"%s\"", 311 param->name, formatParamList(param_values))); 312 } 313 314 DPRINTF(CxxConfig, "Setting parameter" 315 " %s.%s=%s\n", instance_name, param->name, 316 formatParamList(param_values)); 317 } else { 318 std::string param_value; 319 320 if (!configFile.getParam(object_name, param->name, 321 param_value)) 322 { 323 throw Exception(object_name, csprintf( 324 "Element not found for parameter: %s", 325 param->name)); 326 } 327 328 if (!object_params->setParam(param->name, param_value, 329 flags)) 330 { 331 throw Exception(instance_name, csprintf( 332 "Bad parameter value: .%s=X=\"%s\"", 333 param->name, param_value)); 334 } 335 336 DPRINTF(CxxConfig, "Setting parameter %s.%s=%s\n", 337 instance_name, param->name, param_value); 338 } 339 } 340 } 341 342 /* Find the number of ports that will need binding and set the 343 * appropriate port_..._connection_count parameters */ 344 for (auto i = entry.ports.begin(); i != entry.ports.end(); ++i) { 345 const CxxConfigDirectoryEntry::PortDesc *port = (*i).second; 346 std::vector<std::string> peers; 347 348 if (!configFile.getPortPeers(object_name, port->name, peers)) { 349 DPRINTF(CxxConfig, "Port not found: %s.%s," 350 " assuming there are no connections\n", 351 instance_name, port->name); 352 } 353 354 unsigned int peer_count = peers.size(); 355 356 /* It would be more efficient to split the peer list and 357 * save the values for peer binding later but that would 358 * require another annoying intermediate structure to 359 * hold for little performance increase */ 360 361 if (!object_params->setPortConnectionCount(port->name, 362 peer_count)) 363 { 364 throw Exception(instance_name, csprintf( 365 "Unconnected port: %s", port->name)); 366 } 367 368 DPRINTF(CxxConfig, "Setting port connection count" 369 " for: %s.%s to %d\n", 370 instance_name, port->name, peer_count); 371 } 372 373 /* Set pointed-to SimObjects to NULL */ 374 for (auto i = entry.parameters.begin(); 375 i != entry.parameters.end(); ++i) 376 { 377 const CxxConfigDirectoryEntry::ParamDesc *param = (*i).second; 378 379 if (param->isSimObject) { 380 bool ret; 381 382 DPRINTF(CxxConfig, "Nulling sim object reference: %s.%s\n", 383 instance_name, param->name); 384 385 if (param->isVector) { 386 /* Clear the reference list. */ 387 std::vector<SimObject *> empty; 388 ret = object_params->setSimObjectVector(param->name, 389 empty); 390 } else { 391 ret = object_params->setSimObject(param->name, NULL); 392 } 393 394 if (!ret) { 395 throw Exception(instance_name, csprintf( 396 "Error nulling sim object reference(s): %s", 397 param->name)); 398 } 399 } 400 } 401 } catch (Exception &) { 402 delete object_params; 403 throw; 404 } 405 406 objectParamsByName[instance_name] = object_params; 407 408 return object_params; 409} 410 411void 412CxxConfigManager::findAllObjects() 413{ 414 std::vector<std::string> objects; 415 configFile.getAllObjectNames(objects); 416 417 /* Sort the object names to get a consistent initialisation order 418 * even with config file reorganisation */ 419 std::sort(objects.begin(), objects.end()); 420 421 for (auto i = objects.begin(); i != objects.end(); ++i) 422 findObject(*i); 423 424 /* Set the traversal order for further iterators */ 425 objectsInOrder.clear(); 426 findTraversalOrder("root"); 427} 428 429void 430CxxConfigManager::findTraversalOrder(const std::string &object_name) 431{ 432 SimObject *object = findObject(object_name); 433 434 if (object) { 435 objectsInOrder.push_back(object); 436 437 std::vector<std::string> children; 438 configFile.getObjectChildren(object_name, children, true); 439 440 /* Visit all your children */ 441 for (auto i = children.begin(); i != children.end(); ++i) 442 findTraversalOrder(*i); 443 } 444} 445 446void 447CxxConfigManager::bindAllPorts() 448{ 449 for (auto i = objectsInOrder.begin(); i != objectsInOrder.end(); ++i) 450 bindObjectPorts(*i); 451} 452 453void 454CxxConfigManager::bindPort( 455 SimObject *master_object, const std::string &master_port_name, 456 PortID master_port_index, 457 SimObject *slave_object, const std::string &slave_port_name, 458 PortID slave_port_index) 459{ 460 MemObject *master_mem_object = dynamic_cast<MemObject *>(master_object); 461 MemObject *slave_mem_object = dynamic_cast<MemObject *>(slave_object); 462 463 if (!master_mem_object) { 464 throw Exception(master_object->name(), csprintf( 465 "Object isn't a mem object and so can have master port:" 466 " %s[%d]", master_port_name, master_port_index)); 467 } 468 469 if (!slave_mem_object) { 470 throw Exception(slave_object->name(), csprintf( 471 "Object isn't a mem object and so can have slave port:" 472 " %s[%d]", slave_port_name, slave_port_index)); 473 } 474 475 /* FIXME, check slave_port_index against connection_count 476 * defined for port, need getPortConnectionCount and a 477 * getCxxConfigDirectoryEntry for each object. */ 478 479 /* It would be nice to be able to catch the errors from these calls. */ 480 BaseMasterPort &master_port = master_mem_object->getMasterPort( 481 master_port_name, master_port_index); 482 BaseSlavePort &slave_port = slave_mem_object->getSlavePort( 483 slave_port_name, slave_port_index); 484 485 if (master_port.isConnected()) { 486 throw Exception(master_object->name(), csprintf( 487 "Master port: %s[%d] is already connected\n", master_port_name, 488 master_port_index)); 489 } 490 491 if (slave_port.isConnected()) { 492 throw Exception(slave_object->name(), csprintf( 493 "Slave port: %s[%d] is already connected\n", slave_port_name, 494 slave_port_index)); 495 } 496 497 DPRINTF(CxxConfig, "Binding port %s.%s[%d]" 498 " to %s:%s[%d]\n", 499 master_object->name(), master_port_name, master_port_index, 500 slave_object->name(), slave_port_name, slave_port_index); 501 502 master_port.bind(slave_port); 503} 504 505void 506CxxConfigManager::bindMasterPort(SimObject *object, 507 const CxxConfigDirectoryEntry::PortDesc &port, 508 const std::vector<std::string> &peers) 509{ 510 unsigned int master_port_index = 0; 511 512 for (auto peer_i = peers.begin(); peer_i != peers.end(); 513 ++peer_i) 514 { 515 const std::string &peer = *peer_i; 516 std::string slave_object_name; 517 std::string slave_port_name; 518 unsigned int slave_port_index; 519 520 parsePort(peer, slave_object_name, slave_port_name, 521 slave_port_index); 522 523 std::string slave_instance_name = rename(slave_object_name); 524 525 if (objectsByName.find(slave_instance_name) == objectsByName.end()) { 526 throw Exception(object->name(), csprintf( 527 "Can't find slave port object: %s", slave_instance_name)); 528 } 529 530 SimObject *slave_object = objectsByName[slave_instance_name]; 531 532 bindPort(object, port.name, master_port_index, 533 slave_object, slave_port_name, slave_port_index); 534 535 master_port_index++; 536 } 537} 538 539void 540CxxConfigManager::bindObjectPorts(SimObject *object) 541{ 542 /* We may want to separate object->name() from the name in configuration 543 * later to allow (for example) repetition of fragments of configs */ 544 const std::string &instance_name = object->name(); 545 546 std::string object_name = unRename(instance_name); 547 548 std::string object_type; 549 const CxxConfigDirectoryEntry &entry = 550 findObjectType(object_name, object_type); 551 552 DPRINTF(CxxConfig, "Binding ports of object: %s (%s)\n", 553 instance_name, object_type); 554 555 for (auto i = entry.ports.begin(); i != entry.ports.end(); ++i) { 556 const CxxConfigDirectoryEntry::PortDesc *port = (*i).second; 557 558 DPRINTF(CxxConfig, "Binding port: %s.%s\n", instance_name, 559 port->name); 560 561 std::vector<std::string> peers; 562 configFile.getPortPeers(object_name, port->name, peers); 563 564 /* Only handle master ports as binding only needs to happen once 565 * for each observed pair of ports */ 566 if (port->isMaster) { 567 if (!port->isVector && peers.size() > 1) { 568 throw Exception(instance_name, csprintf( 569 "Too many connections to non-vector port %s (%d)\n", 570 port->name, peers.size())); 571 } 572 573 bindMasterPort(object, *port, peers); 574 } 575 } 576} 577 578void 579CxxConfigManager::parsePort(const std::string &inp, 580 std::string &path, std::string &port, unsigned int &index) 581{ 582 std::size_t dot_i = inp.rfind('.'); 583 std::size_t open_square_i = inp.rfind('['); 584 585 if (dot_i == std::string::npos) { 586 DPRINTF(CxxConfig, "Bad port string: %s\n", inp); 587 path = ""; 588 port = ""; 589 index = 0; 590 } else { 591 path = std::string(inp, 0, dot_i); 592 593 if (open_square_i == std::string::npos) { 594 /* Singleton port */ 595 port = std::string(inp, dot_i + 1, inp.length() - dot_i); 596 index = 0; 597 } else { 598 /* Vectored port elemnt */ 599 port = std::string(inp, dot_i + 1, (open_square_i - 1) - dot_i); 600 index = std::atoi(inp.c_str() + open_square_i + 1); 601 } 602 } 603} 604 605void 606CxxConfigManager::forEachObject(void (SimObject::*mem_func)()) 607{ 608 for (auto i = objectsInOrder.begin(); i != objectsInOrder.end(); ++i) 609 ((*i)->*mem_func)(); 610} 611 612void 613CxxConfigManager::instantiate(bool build_all) 614{ 615 if (build_all) { 616 findAllObjects(); 617 bindAllPorts(); 618 } 619 620 DPRINTF(CxxConfig, "Initialising all objects\n"); 621 forEachObject(&SimObject::init); 622 623 DPRINTF(CxxConfig, "Registering stats\n"); 624 forEachObject(&SimObject::regStats); 625 626 DPRINTF(CxxConfig, "Registering probe points\n"); 627 forEachObject(&SimObject::regProbePoints); 628 629 DPRINTF(CxxConfig, "Connecting probe listeners\n"); 630 forEachObject(&SimObject::regProbeListeners); 631} 632 633void 634CxxConfigManager::initState() 635{ 636 DPRINTF(CxxConfig, "Calling initState on all objects\n"); 637 forEachObject(&SimObject::initState); 638} 639 640void 641CxxConfigManager::startup() 642{ 643 DPRINTF(CxxConfig, "Starting up all objects\n"); 644 forEachObject(&SimObject::startup); 645} 646 647unsigned int 648CxxConfigManager::drain() 649{ 650 return DrainManager::instance().tryDrain() ? 0 : 1; 651} 652 653void 654CxxConfigManager::drainResume() 655{ 656 DrainManager::instance().resume(); 657} 658 659void 660CxxConfigManager::serialize(std::ostream &os) 661{ 662 for (auto i = objectsInOrder.begin(); i != objectsInOrder.end(); ++ i) { 663 // (*i)->nameOut(os); FIXME, change access spec. for nameOut 664 os << '[' << (*i)->name() << "]\n"; 665 (*i)->serialize(os); 666 } 667} 668 669void 670CxxConfigManager::loadState(CheckpointIn &checkpoint) 671{ 672 for (auto i = objectsInOrder.begin(); i != objectsInOrder.end(); ++ i) 673 (*i)->loadState(checkpoint); 674} 675 676void 677CxxConfigManager::deleteObjects() 678{ 679 for (auto i = objectsInOrder.rbegin(); i != objectsInOrder.rend(); ++i) { 680 DPRINTF(CxxConfig, "Freeing sim object: %s\n", (*i)->name()); 681 delete *i; 682 } 683 684 for (auto i = objectParamsByName.rbegin(); 685 i != objectParamsByName.rend(); ++i) 686 { 687 CxxConfigParams *params = (*i).second; 688 689 DPRINTF(CxxConfig, "Freeing sim object params: %s\n", 690 params->getName()); 691 delete params; 692 } 693 694 objectsInOrder.clear(); 695 objectsByName.clear(); 696} 697 698void 699CxxConfigManager::setParam(const std::string &object_name, 700 const std::string ¶m_name, const std::string ¶m_value) 701{ 702 CxxConfigParams *params = findObjectParams(object_name); 703 704 if (!params->setParam(param_name, param_value, flags)) { 705 throw Exception(object_name, csprintf("Bad parameter value:" 706 " .%s=X=\"%s\"", param_name, param_value)); 707 } else { 708 std::string instance_name = rename(object_name); 709 710 DPRINTF(CxxConfig, "Setting parameter %s.%s=%s\n", 711 instance_name, param_name, param_value); 712 } 713} 714 715void 716CxxConfigManager::setParamVector(const std::string &object_name, 717 const std::string ¶m_name, 718 const std::vector<std::string> ¶m_values) 719{ 720 CxxConfigParams *params = findObjectParams(object_name); 721 722 if (!params->setParamVector(param_name, param_values, flags)) { 723 throw Exception(object_name, csprintf("Bad vector parameter value:" 724 " .%s=X=\"%s\"", param_name, formatParamList(param_values))); 725 } else { 726 std::string instance_name = rename(object_name); 727 728 DPRINTF(CxxConfig, "Setting parameter %s.%s=\"%s\"\n", 729 instance_name, param_name, formatParamList(param_values)); 730 } 731} 732 733void CxxConfigManager::addRenaming(const Renaming &renaming) 734{ 735 renamings.push_back(renaming); 736}
| 47#include "debug/CxxConfig.hh" 48#include "mem/mem_object.hh" 49#include "sim/serialize.hh" 50 51CxxConfigManager::CxxConfigManager(CxxConfigFileBase &configFile_) : 52 configFile(configFile_), flags(configFile_.getFlags()), 53 simObjectResolver(*this) 54{ 55} 56 57const CxxConfigDirectoryEntry & 58CxxConfigManager::findObjectType(const std::string &object_name, 59 std::string &object_type) 60{ 61 if (!configFile.objectExists(object_name)) 62 throw Exception(object_name, "Can't find sim object"); 63 64 if (!configFile.getParam(object_name, "type", object_type)) 65 throw Exception(object_name, "Sim object has no 'type' field"); 66 67 if (cxx_config_directory.find(object_type) == 68 cxx_config_directory.end()) 69 { 70 throw Exception(object_name, csprintf( 71 "No sim object type %s is available", object_type)); 72 } 73 74 const CxxConfigDirectoryEntry *entry = cxx_config_directory[object_type]; 75 76 return *entry; 77} 78 79std::string 80CxxConfigManager::rename(const std::string &from_name) 81{ 82 for (auto i = renamings.begin(); i != renamings.end(); ++ i) { 83 const Renaming &renaming = *i; 84 85 if (from_name.find(renaming.fromPrefix) == 0) { 86 return renaming.toPrefix + 87 from_name.substr(renaming.fromPrefix.length()); 88 } 89 } 90 91 return from_name; 92} 93 94std::string 95CxxConfigManager::unRename(const std::string &to_name) 96{ 97 for (auto i = renamings.begin(); i != renamings.end(); ++ i) { 98 const Renaming &renaming = *i; 99 100 if (to_name.find(renaming.toPrefix) == 0) { 101 return renaming.fromPrefix + 102 to_name.substr(renaming.toPrefix.length()); 103 } 104 } 105 106 return to_name; 107} 108 109static 110std::string formatParamList(const std::vector<std::string> ¶m_values) 111{ 112 std::ostringstream params; 113 114 auto i = param_values.begin(); 115 auto end_i = param_values.end(); 116 117 params << '['; 118 while (i != end_i) { 119 params << (*i); 120 ++i; 121 122 if (i != end_i) 123 params << ", "; 124 } 125 params << ']'; 126 127 return params.str(); 128} 129 130SimObject * 131CxxConfigManager::findObject(const std::string &object_name, 132 bool visit_children) 133{ 134 std::string instance_name = rename(object_name); 135 136 if (object_name == "Null") 137 return NULL; 138 139 /* Already constructed */ 140 if (objectsByName.find(instance_name) != objectsByName.end()) 141 return objectsByName[instance_name]; 142 143 if (inVisit.find(instance_name) != inVisit.end()) 144 throw Exception(instance_name, "Cycle in configuration"); 145 146 std::string object_type; 147 const CxxConfigDirectoryEntry &entry = 148 findObjectType(object_name, object_type); 149 150 SimObject *object = NULL; 151 152 CxxConfigParams *object_params = findObjectParams(object_name); 153 154 try { 155 DPRINTF(CxxConfig, "Configuring sim object references for: %s" 156 " (%s from object %s)\n", instance_name, object_type, 157 object_name); 158 159 /* Remember the path back to the top of the recursion to detect 160 * cycles */ 161 inVisit.insert(instance_name); 162 163 /* Resolve pointed-to SimObjects by recursing into them */ 164 for (auto i = entry.parameters.begin(); 165 i != entry.parameters.end(); ++i) 166 { 167 const CxxConfigDirectoryEntry::ParamDesc *param = (*i).second; 168 169 if (param->isSimObject) { 170 if (param->isVector) { 171 std::vector<std::string> sub_object_names; 172 173 if (!configFile.getParamVector(object_name, param->name, 174 sub_object_names)) 175 { 176 throw Exception(object_name, csprintf( 177 "Element not found: %s", param->name)); 178 } 179 180 std::vector<SimObject *> sub_objects; 181 182 for (auto n = sub_object_names.begin(); 183 n != sub_object_names.end(); ++n) 184 { 185 SimObject *sub_object = findObject(*n, 186 visit_children); 187 188 if (sub_object) 189 sub_objects.push_back(sub_object); 190 } 191 192 if (!object_params->setSimObjectVector(param->name, 193 sub_objects)) 194 { 195 throw Exception(object_name, csprintf( 196 "Can't assign sim object element %s from \"%s\"", 197 param->name, formatParamList(sub_object_names))); 198 } 199 200 DPRINTF(CxxConfig, "Setting sim object(s): %s.%s=%s\n", 201 object_name, param->name, 202 formatParamList(sub_object_names)); 203 } else { 204 std::string sub_object_name; 205 206 if (!configFile.getParam(object_name, param->name, 207 sub_object_name)) 208 { 209 throw Exception(object_name, csprintf( 210 "Element not found: %s", param->name)); 211 } 212 213 SimObject *sub_object = findObject(sub_object_name, 214 visit_children); 215 216 if (sub_object) { 217 if (!object_params->setSimObject(param->name, 218 sub_object)) 219 { 220 throw Exception(object_name, csprintf( 221 "Can't assign sim object element %s from" 222 " \"%s\"", param->name, sub_object_name)); 223 } 224 } 225 226 DPRINTF(CxxConfig, "Setting sim object(s):" 227 " %s.%s=%s\n", object_name, param->name, 228 sub_object_name); 229 } 230 } 231 } 232 233 DPRINTF(CxxConfig, "Creating SimObject: %s\n", instance_name); 234 object = object_params->simObjectCreate(); 235 236 if (!object) { 237 throw Exception(object_name, csprintf("Couldn't create object of" 238 " type: %s", object_type)); 239 } 240 241 objectsByName[instance_name] = object; 242 objectParamsByName[instance_name] = object_params; 243 244 if (visit_children) { 245 std::vector<std::string> children; 246 configFile.getObjectChildren(object_name, children, true); 247 248 /* Visit all your children */ 249 for (auto i = children.begin(); i != children.end(); ++i) 250 findObject(*i, visit_children); 251 } 252 } catch (Exception &) { 253 delete object_params; 254 throw; 255 } 256 257 /* Mark that we've exited object 258 * construction and so 'find'ing this object again won't be a 259 * configuration loop */ 260 inVisit.erase(object_name); 261 return object; 262} 263 264CxxConfigParams * 265CxxConfigManager::findObjectParams(const std::string &object_name) 266{ 267 std::string instance_name = rename(object_name); 268 269 /* Already constructed */ 270 if (objectParamsByName.find(instance_name) != objectParamsByName.end()) 271 return objectParamsByName[instance_name]; 272 273 std::string object_type; 274 const CxxConfigDirectoryEntry &entry = 275 findObjectType(object_name, object_type); 276 277 DPRINTF(CxxConfig, "Configuring parameters of object: %s (%s)\n", 278 instance_name, object_type); 279 280 CxxConfigParams *object_params = entry.makeParamsObject(); 281 282 try { 283 /* Fill in the implicit parameters that don't necessarily 284 * appear in config files */ 285 object_params->setName(instance_name); 286 287 /* Fill in parameters */ 288 for (auto i = entry.parameters.begin(); 289 i != entry.parameters.end(); ++i) 290 { 291 const CxxConfigDirectoryEntry::ParamDesc *param = (*i).second; 292 293 if (!param->isSimObject) { 294 /* Only handle non-SimObject parameters here (see below) */ 295 296 if (param->isVector) { 297 std::vector<std::string> param_values; 298 299 if (!configFile.getParamVector(object_name, param->name, 300 param_values)) 301 { 302 throw Exception(object_name, csprintf( 303 "Element not found for parameter: %s", 304 param->name)); 305 } 306 307 if (!object_params->setParamVector(param->name, 308 param_values, flags)) 309 { 310 throw Exception(instance_name, csprintf( 311 "Bad parameter value: .%s=X=\"%s\"", 312 param->name, formatParamList(param_values))); 313 } 314 315 DPRINTF(CxxConfig, "Setting parameter" 316 " %s.%s=%s\n", instance_name, param->name, 317 formatParamList(param_values)); 318 } else { 319 std::string param_value; 320 321 if (!configFile.getParam(object_name, param->name, 322 param_value)) 323 { 324 throw Exception(object_name, csprintf( 325 "Element not found for parameter: %s", 326 param->name)); 327 } 328 329 if (!object_params->setParam(param->name, param_value, 330 flags)) 331 { 332 throw Exception(instance_name, csprintf( 333 "Bad parameter value: .%s=X=\"%s\"", 334 param->name, param_value)); 335 } 336 337 DPRINTF(CxxConfig, "Setting parameter %s.%s=%s\n", 338 instance_name, param->name, param_value); 339 } 340 } 341 } 342 343 /* Find the number of ports that will need binding and set the 344 * appropriate port_..._connection_count parameters */ 345 for (auto i = entry.ports.begin(); i != entry.ports.end(); ++i) { 346 const CxxConfigDirectoryEntry::PortDesc *port = (*i).second; 347 std::vector<std::string> peers; 348 349 if (!configFile.getPortPeers(object_name, port->name, peers)) { 350 DPRINTF(CxxConfig, "Port not found: %s.%s," 351 " assuming there are no connections\n", 352 instance_name, port->name); 353 } 354 355 unsigned int peer_count = peers.size(); 356 357 /* It would be more efficient to split the peer list and 358 * save the values for peer binding later but that would 359 * require another annoying intermediate structure to 360 * hold for little performance increase */ 361 362 if (!object_params->setPortConnectionCount(port->name, 363 peer_count)) 364 { 365 throw Exception(instance_name, csprintf( 366 "Unconnected port: %s", port->name)); 367 } 368 369 DPRINTF(CxxConfig, "Setting port connection count" 370 " for: %s.%s to %d\n", 371 instance_name, port->name, peer_count); 372 } 373 374 /* Set pointed-to SimObjects to NULL */ 375 for (auto i = entry.parameters.begin(); 376 i != entry.parameters.end(); ++i) 377 { 378 const CxxConfigDirectoryEntry::ParamDesc *param = (*i).second; 379 380 if (param->isSimObject) { 381 bool ret; 382 383 DPRINTF(CxxConfig, "Nulling sim object reference: %s.%s\n", 384 instance_name, param->name); 385 386 if (param->isVector) { 387 /* Clear the reference list. */ 388 std::vector<SimObject *> empty; 389 ret = object_params->setSimObjectVector(param->name, 390 empty); 391 } else { 392 ret = object_params->setSimObject(param->name, NULL); 393 } 394 395 if (!ret) { 396 throw Exception(instance_name, csprintf( 397 "Error nulling sim object reference(s): %s", 398 param->name)); 399 } 400 } 401 } 402 } catch (Exception &) { 403 delete object_params; 404 throw; 405 } 406 407 objectParamsByName[instance_name] = object_params; 408 409 return object_params; 410} 411 412void 413CxxConfigManager::findAllObjects() 414{ 415 std::vector<std::string> objects; 416 configFile.getAllObjectNames(objects); 417 418 /* Sort the object names to get a consistent initialisation order 419 * even with config file reorganisation */ 420 std::sort(objects.begin(), objects.end()); 421 422 for (auto i = objects.begin(); i != objects.end(); ++i) 423 findObject(*i); 424 425 /* Set the traversal order for further iterators */ 426 objectsInOrder.clear(); 427 findTraversalOrder("root"); 428} 429 430void 431CxxConfigManager::findTraversalOrder(const std::string &object_name) 432{ 433 SimObject *object = findObject(object_name); 434 435 if (object) { 436 objectsInOrder.push_back(object); 437 438 std::vector<std::string> children; 439 configFile.getObjectChildren(object_name, children, true); 440 441 /* Visit all your children */ 442 for (auto i = children.begin(); i != children.end(); ++i) 443 findTraversalOrder(*i); 444 } 445} 446 447void 448CxxConfigManager::bindAllPorts() 449{ 450 for (auto i = objectsInOrder.begin(); i != objectsInOrder.end(); ++i) 451 bindObjectPorts(*i); 452} 453 454void 455CxxConfigManager::bindPort( 456 SimObject *master_object, const std::string &master_port_name, 457 PortID master_port_index, 458 SimObject *slave_object, const std::string &slave_port_name, 459 PortID slave_port_index) 460{ 461 MemObject *master_mem_object = dynamic_cast<MemObject *>(master_object); 462 MemObject *slave_mem_object = dynamic_cast<MemObject *>(slave_object); 463 464 if (!master_mem_object) { 465 throw Exception(master_object->name(), csprintf( 466 "Object isn't a mem object and so can have master port:" 467 " %s[%d]", master_port_name, master_port_index)); 468 } 469 470 if (!slave_mem_object) { 471 throw Exception(slave_object->name(), csprintf( 472 "Object isn't a mem object and so can have slave port:" 473 " %s[%d]", slave_port_name, slave_port_index)); 474 } 475 476 /* FIXME, check slave_port_index against connection_count 477 * defined for port, need getPortConnectionCount and a 478 * getCxxConfigDirectoryEntry for each object. */ 479 480 /* It would be nice to be able to catch the errors from these calls. */ 481 BaseMasterPort &master_port = master_mem_object->getMasterPort( 482 master_port_name, master_port_index); 483 BaseSlavePort &slave_port = slave_mem_object->getSlavePort( 484 slave_port_name, slave_port_index); 485 486 if (master_port.isConnected()) { 487 throw Exception(master_object->name(), csprintf( 488 "Master port: %s[%d] is already connected\n", master_port_name, 489 master_port_index)); 490 } 491 492 if (slave_port.isConnected()) { 493 throw Exception(slave_object->name(), csprintf( 494 "Slave port: %s[%d] is already connected\n", slave_port_name, 495 slave_port_index)); 496 } 497 498 DPRINTF(CxxConfig, "Binding port %s.%s[%d]" 499 " to %s:%s[%d]\n", 500 master_object->name(), master_port_name, master_port_index, 501 slave_object->name(), slave_port_name, slave_port_index); 502 503 master_port.bind(slave_port); 504} 505 506void 507CxxConfigManager::bindMasterPort(SimObject *object, 508 const CxxConfigDirectoryEntry::PortDesc &port, 509 const std::vector<std::string> &peers) 510{ 511 unsigned int master_port_index = 0; 512 513 for (auto peer_i = peers.begin(); peer_i != peers.end(); 514 ++peer_i) 515 { 516 const std::string &peer = *peer_i; 517 std::string slave_object_name; 518 std::string slave_port_name; 519 unsigned int slave_port_index; 520 521 parsePort(peer, slave_object_name, slave_port_name, 522 slave_port_index); 523 524 std::string slave_instance_name = rename(slave_object_name); 525 526 if (objectsByName.find(slave_instance_name) == objectsByName.end()) { 527 throw Exception(object->name(), csprintf( 528 "Can't find slave port object: %s", slave_instance_name)); 529 } 530 531 SimObject *slave_object = objectsByName[slave_instance_name]; 532 533 bindPort(object, port.name, master_port_index, 534 slave_object, slave_port_name, slave_port_index); 535 536 master_port_index++; 537 } 538} 539 540void 541CxxConfigManager::bindObjectPorts(SimObject *object) 542{ 543 /* We may want to separate object->name() from the name in configuration 544 * later to allow (for example) repetition of fragments of configs */ 545 const std::string &instance_name = object->name(); 546 547 std::string object_name = unRename(instance_name); 548 549 std::string object_type; 550 const CxxConfigDirectoryEntry &entry = 551 findObjectType(object_name, object_type); 552 553 DPRINTF(CxxConfig, "Binding ports of object: %s (%s)\n", 554 instance_name, object_type); 555 556 for (auto i = entry.ports.begin(); i != entry.ports.end(); ++i) { 557 const CxxConfigDirectoryEntry::PortDesc *port = (*i).second; 558 559 DPRINTF(CxxConfig, "Binding port: %s.%s\n", instance_name, 560 port->name); 561 562 std::vector<std::string> peers; 563 configFile.getPortPeers(object_name, port->name, peers); 564 565 /* Only handle master ports as binding only needs to happen once 566 * for each observed pair of ports */ 567 if (port->isMaster) { 568 if (!port->isVector && peers.size() > 1) { 569 throw Exception(instance_name, csprintf( 570 "Too many connections to non-vector port %s (%d)\n", 571 port->name, peers.size())); 572 } 573 574 bindMasterPort(object, *port, peers); 575 } 576 } 577} 578 579void 580CxxConfigManager::parsePort(const std::string &inp, 581 std::string &path, std::string &port, unsigned int &index) 582{ 583 std::size_t dot_i = inp.rfind('.'); 584 std::size_t open_square_i = inp.rfind('['); 585 586 if (dot_i == std::string::npos) { 587 DPRINTF(CxxConfig, "Bad port string: %s\n", inp); 588 path = ""; 589 port = ""; 590 index = 0; 591 } else { 592 path = std::string(inp, 0, dot_i); 593 594 if (open_square_i == std::string::npos) { 595 /* Singleton port */ 596 port = std::string(inp, dot_i + 1, inp.length() - dot_i); 597 index = 0; 598 } else { 599 /* Vectored port elemnt */ 600 port = std::string(inp, dot_i + 1, (open_square_i - 1) - dot_i); 601 index = std::atoi(inp.c_str() + open_square_i + 1); 602 } 603 } 604} 605 606void 607CxxConfigManager::forEachObject(void (SimObject::*mem_func)()) 608{ 609 for (auto i = objectsInOrder.begin(); i != objectsInOrder.end(); ++i) 610 ((*i)->*mem_func)(); 611} 612 613void 614CxxConfigManager::instantiate(bool build_all) 615{ 616 if (build_all) { 617 findAllObjects(); 618 bindAllPorts(); 619 } 620 621 DPRINTF(CxxConfig, "Initialising all objects\n"); 622 forEachObject(&SimObject::init); 623 624 DPRINTF(CxxConfig, "Registering stats\n"); 625 forEachObject(&SimObject::regStats); 626 627 DPRINTF(CxxConfig, "Registering probe points\n"); 628 forEachObject(&SimObject::regProbePoints); 629 630 DPRINTF(CxxConfig, "Connecting probe listeners\n"); 631 forEachObject(&SimObject::regProbeListeners); 632} 633 634void 635CxxConfigManager::initState() 636{ 637 DPRINTF(CxxConfig, "Calling initState on all objects\n"); 638 forEachObject(&SimObject::initState); 639} 640 641void 642CxxConfigManager::startup() 643{ 644 DPRINTF(CxxConfig, "Starting up all objects\n"); 645 forEachObject(&SimObject::startup); 646} 647 648unsigned int 649CxxConfigManager::drain() 650{ 651 return DrainManager::instance().tryDrain() ? 0 : 1; 652} 653 654void 655CxxConfigManager::drainResume() 656{ 657 DrainManager::instance().resume(); 658} 659 660void 661CxxConfigManager::serialize(std::ostream &os) 662{ 663 for (auto i = objectsInOrder.begin(); i != objectsInOrder.end(); ++ i) { 664 // (*i)->nameOut(os); FIXME, change access spec. for nameOut 665 os << '[' << (*i)->name() << "]\n"; 666 (*i)->serialize(os); 667 } 668} 669 670void 671CxxConfigManager::loadState(CheckpointIn &checkpoint) 672{ 673 for (auto i = objectsInOrder.begin(); i != objectsInOrder.end(); ++ i) 674 (*i)->loadState(checkpoint); 675} 676 677void 678CxxConfigManager::deleteObjects() 679{ 680 for (auto i = objectsInOrder.rbegin(); i != objectsInOrder.rend(); ++i) { 681 DPRINTF(CxxConfig, "Freeing sim object: %s\n", (*i)->name()); 682 delete *i; 683 } 684 685 for (auto i = objectParamsByName.rbegin(); 686 i != objectParamsByName.rend(); ++i) 687 { 688 CxxConfigParams *params = (*i).second; 689 690 DPRINTF(CxxConfig, "Freeing sim object params: %s\n", 691 params->getName()); 692 delete params; 693 } 694 695 objectsInOrder.clear(); 696 objectsByName.clear(); 697} 698 699void 700CxxConfigManager::setParam(const std::string &object_name, 701 const std::string ¶m_name, const std::string ¶m_value) 702{ 703 CxxConfigParams *params = findObjectParams(object_name); 704 705 if (!params->setParam(param_name, param_value, flags)) { 706 throw Exception(object_name, csprintf("Bad parameter value:" 707 " .%s=X=\"%s\"", param_name, param_value)); 708 } else { 709 std::string instance_name = rename(object_name); 710 711 DPRINTF(CxxConfig, "Setting parameter %s.%s=%s\n", 712 instance_name, param_name, param_value); 713 } 714} 715 716void 717CxxConfigManager::setParamVector(const std::string &object_name, 718 const std::string ¶m_name, 719 const std::vector<std::string> ¶m_values) 720{ 721 CxxConfigParams *params = findObjectParams(object_name); 722 723 if (!params->setParamVector(param_name, param_values, flags)) { 724 throw Exception(object_name, csprintf("Bad vector parameter value:" 725 " .%s=X=\"%s\"", param_name, formatParamList(param_values))); 726 } else { 727 std::string instance_name = rename(object_name); 728 729 DPRINTF(CxxConfig, "Setting parameter %s.%s=\"%s\"\n", 730 instance_name, param_name, formatParamList(param_values)); 731 } 732} 733 734void CxxConfigManager::addRenaming(const Renaming &renaming) 735{ 736 renamings.push_back(renaming); 737}
|