Model.cc revision 10447
1#include "model/Model.h" 2 3#include <vector> 4 5#include "util/Result.h" 6 7namespace DSENT 8{ 9 using std::vector; 10 using LibUtil::deletePtrMap; 11 using LibUtil::clonePtrMap; 12 13 Model::SubModel::SubModel(Model* model_, double num_models_) 14 : m_model_(model_), m_num_models_(num_models_) 15 {} 16 17 Model::SubModel::~SubModel() 18 { 19 delete m_model_; 20 } 21 22 Model* Model::SubModel::getModel() 23 { 24 return m_model_; 25 } 26 27 const Model* Model::SubModel::getModel() const 28 { 29 return m_model_; 30 } 31 32 double Model::SubModel::getNumModels() const 33 { 34 return m_num_models_; 35 } 36 37 Model::SubModel* Model::SubModel::clone() const 38 { 39 return new SubModel(*this); 40 } 41 42 Model::SubModel::SubModel(const SubModel& sub_model_) 43 { 44 m_model_ = sub_model_.m_model_->clone(); 45 m_num_models_ = sub_model_.m_num_models_; 46 } 47 48 const char Model::TYPE_SEPARATOR[] = ">>"; 49 const char Model::HIERARCHY_SEPARATOR[] = "->"; 50 const char Model::SUBFIELD_SEPARATOR[] = ":"; 51 const char Model::DETAIL_SEPARATOR[] = "@"; 52 53 Model::Model(const String& instance_name_, const TechModel* tech_model_) 54 : m_instance_name_(instance_name_), m_tech_model_(tech_model_), 55 m_constructed_(false), m_updated_(false), m_evaluated_(false) 56 { 57 m_property_names_ = new vector<String>; 58 m_parameter_names_ = new vector<String>; 59 m_parameters_ = new ParameterMap(); 60 m_properties_ = new PropertyMap(); 61 m_generated_properties_ = new PropertyMap(); 62 m_sub_instances_ = new Map<SubModel*>(); 63 m_event_map_ = new Map<Result*>(); 64 m_area_map_ = new Map<Result*>(); 65 m_ndd_power_map_ = new Map<Result*>(); 66 } 67 68 Model::~Model() 69 { 70 // Clear parameter names 71 delete m_parameter_names_; 72 // Clear property name 73 delete m_property_names_; 74 75 // Clear parameters 76 delete m_parameters_; 77 m_parameters_ = NULL; 78 // Clear input properties 79 delete m_properties_; 80 m_properties_ = NULL; 81 82 // Clear generated properties 83 delete m_generated_properties_; 84 m_generated_properties_ = NULL; 85 86 // Clear sub models 87 deletePtrMap<SubModel>(m_sub_instances_); 88 m_sub_instances_ = NULL; 89 90 // Clear all results 91 deletePtrMap<Result>(m_event_map_); 92 m_event_map_ = NULL; 93 deletePtrMap<Result>(m_area_map_); 94 m_area_map_ = NULL; 95 deletePtrMap<Result>(m_ndd_power_map_); 96 m_ndd_power_map_ = NULL; 97 } 98 99 void Model::setInstanceName(const String& instance_name_) 100 { 101 m_instance_name_ = instance_name_; 102 return; 103 } 104 105 const String& Model::getInstanceName() const 106 { 107 return m_instance_name_; 108 } 109 110 void Model::setIsTopModel(bool is_top_model_) 111 { 112 m_is_top_model_ = is_top_model_; 113 return; 114 } 115 116 bool Model::getIsTopModel() const 117 { 118 return m_is_top_model_; 119 } 120 121 //------------------------------------------------------------------------- 122 // Parameters and properties checks 123 //------------------------------------------------------------------------- 124 void Model::addParameterName(const String& parameter_name_) 125 { 126 ASSERT(!m_constructed_, "[Error] " + getInstanceName() + 127 " -> Cannot add additional parameters names after model is constructed!"); 128 m_parameter_names_->push_back(parameter_name_); 129 130 return; 131 } 132 133 void Model::addParameterName(const String& parameter_name_, const String& parameter_default_) 134 { 135 ASSERT(!m_constructed_, "[Error] " + getInstanceName() + 136 " -> Cannot add additional parameters names after model is constructed!"); 137 m_parameter_names_->push_back(parameter_name_); 138 setParameter(parameter_name_, parameter_default_); 139 return; 140 } 141 142 const vector<String>* Model::getParameterNames() const 143 { 144 return m_parameter_names_; 145 } 146 147 void Model::addPropertyName(const String& property_name_) 148 { 149 ASSERT(!m_constructed_, "[Error] " + getInstanceName() + 150 " -> Cannot add additional property names after model is constructed!"); 151 m_property_names_->push_back(property_name_); 152 return; 153 } 154 155 void Model::addPropertyName(const String& property_name_, const String& property_default_) 156 { 157 ASSERT(!m_constructed_, "[Error] " + getInstanceName() + 158 " -> Cannot add additional property names after model is constructed!"); 159 m_property_names_->push_back(property_name_); 160 setProperty(property_name_, property_default_); 161 return; 162 } 163 164 const vector<String>* Model::getPropertyNames() const 165 { 166 return m_property_names_; 167 } 168 169 void Model::checkParameters() const 170 { 171 String missing_parameters = ""; 172 173 for(int i = 0; i < (int)m_parameter_names_->size(); ++i) 174 { 175 const String& parameter_name = m_parameter_names_->at(i); 176 if (!m_parameters_->keyExist(parameter_name)) 177 missing_parameters += " " + parameter_name + "\n"; 178 } 179 180 ASSERT(missing_parameters.size() == 0, "[Error] " + m_instance_name_ + 181 " -> Missing parameters:\n" + missing_parameters); 182 return; 183 } 184 185 void Model::checkProperties() const 186 { 187 String missing_properties = ""; 188 189 for(int i = 0; i < (int)m_property_names_->size(); ++i) 190 { 191 const String& property_name = m_property_names_->at(i); 192 if (!m_properties_->keyExist(property_name)) 193 missing_properties += " " + property_name + "\n"; 194 } 195 196 ASSERT(missing_properties.size() == 0, "[Error] " + m_instance_name_ + 197 " -> Missing properties:\n" + missing_properties); 198 return; 199 } 200 //------------------------------------------------------------------------- 201 202 //------------------------------------------------------------------------- 203 // Parameters Manipulation 204 //------------------------------------------------------------------------- 205 const ParameterMap* Model::getParameters() const 206 { 207 return m_parameters_; 208 } 209 210 const String Model::getParameter(const String& parameter_name_) const 211 { 212 return m_parameters_->get(parameter_name_); 213 } 214 215 void Model::setParameter(const String& parameter_name_, const String& parameter_value_) 216 { 217 ASSERT(!m_constructed_, "[Error] " + getInstanceName() + 218 " -> Cannot set parameters after model is constructed!"); 219 m_parameters_->set(parameter_name_, parameter_value_); 220 } 221 //------------------------------------------------------------------------- 222 223 //------------------------------------------------------------------------- 224 // Properties Manipulation 225 //------------------------------------------------------------------------- 226 const PropertyMap* Model::getProperties() const 227 { 228 return m_properties_; 229 } 230 231 const String Model::getProperty(const String& property_name_) const 232 { 233 return m_properties_->get(property_name_); 234 } 235 236 void Model::setProperty(const String& property_name_, const String& property_value_) 237 { 238 // If any properties changed, reset updated and evaluated flags 239 m_updated_ = false; 240 m_evaluated_ = false; 241 m_properties_->set(property_name_, property_value_); 242 } 243 //------------------------------------------------------------------------- 244 245 PropertyMap* Model::getGenProperties() 246 { 247 return m_generated_properties_; 248 } 249 250 const PropertyMap* Model::getGenProperties() const 251 { 252 return m_generated_properties_; 253 } 254 255 void Model::addSubInstances(Model* sub_instance_, double num_sub_instances_) 256 { 257 // Get instance name 258 const String& sub_instance_name = sub_instance_->getInstanceName(); 259 260 // Check if the instance exists 261 if(m_sub_instances_->keyExist(sub_instance_name)) 262 { 263 const String& error_msg = "[Error] " + m_instance_name_ + 264 " -> Instance exists (" + sub_instance_name + ")"; 265 throw Exception(error_msg); 266 } 267 268 // Check if the num_sub_instances_ is a positive number 269 ASSERT((num_sub_instances_ >= 0), "[Error] " + m_instance_name_ + 270 " -> Invalid number of instance (" + String(num_sub_instances_) + ")"); 271 272 // Add the instance 273 m_sub_instances_->set(sub_instance_name, new SubModel(sub_instance_, num_sub_instances_)); 274 return; 275 } 276 277 Model* Model::getSubInstance(const String& sub_instance_name_) 278 { 279 // Throw an Exception if the instance already exists 280 if(!m_sub_instances_->keyExist(sub_instance_name_)) 281 { 282 const String& error_msg = "[Error] " + m_instance_name_ + 283 " -> Instance not exists (" + sub_instance_name_ + ")"; 284 throw Exception(error_msg); 285 } 286 287 return m_sub_instances_->get(sub_instance_name_)->getModel(); 288 } 289 290 const Model* Model::getSubInstance(const String& sub_instance_name_) const 291 { 292 // Throw an Exception if the instance does not exist 293 if(!m_sub_instances_->keyExist(sub_instance_name_)) 294 { 295 const String& error_msg = "[Error] " + m_instance_name_ + 296 " -> Instance not exists (" + sub_instance_name_ + ")"; 297 throw Exception(error_msg); 298 } 299 300 return m_sub_instances_->get(sub_instance_name_)->getModel(); 301 } 302 303 bool Model::hasSubInstance(const String& sub_instance_name_) const 304 { 305 return m_sub_instances_->keyExist(sub_instance_name_); 306 } 307 308 void Model::addAreaResult(Result* area_) 309 { 310 const String& area_name = area_->getName(); 311 312 // Throw an Exception if the area already exists 313 if(m_area_map_->keyExist(area_name)) 314 { 315 const String& error_msg = "Internal error: area (" + area_name + 316 ") exists"; 317 throw Exception(error_msg); 318 } 319 320 // Add the area 321 m_area_map_->set(area_name, area_); 322 return; 323 } 324 325 Result* Model::getAreaResult(const String& area_name_) 326 { 327 return m_area_map_->get(area_name_); 328 } 329 330 const Result* Model::getAreaResult(const String& area_name_) const 331 { 332 return m_area_map_->get(area_name_); 333 } 334 335 bool Model::hasAreaResult(const String& area_name_) const 336 { 337 return m_area_map_->keyExist(area_name_); 338 } 339 340 void Model::addNddPowerResult(Result* ndd_power_) 341 { 342 const String& ndd_power_name = ndd_power_->getName(); 343 344 // Throw an Exception if the ndd_power already exists 345 if(m_ndd_power_map_->keyExist(ndd_power_name)) 346 { 347 const String& error_msg = "Internal error: ndd_power (" + ndd_power_name + 348 ") exists"; 349 throw Exception(error_msg); 350 } 351 352 // Add the ndd_power 353 m_ndd_power_map_->set(ndd_power_name, ndd_power_); 354 return; 355 } 356 357 Result* Model::getNddPowerResult(const String& ndd_power_name_) 358 { 359 return m_ndd_power_map_->get(ndd_power_name_); 360 } 361 362 const Result* Model::getNddPowerResult(const String& ndd_power_name_) const 363 { 364 return m_ndd_power_map_->get(ndd_power_name_); 365 } 366 367 bool Model::hasNddPowerResult(const String& ndd_power_name_) const 368 { 369 return m_ndd_power_map_->keyExist(ndd_power_name_); 370 } 371 372 void Model::addEventResult(Result* event_) 373 { 374 const String& event_name = event_->getName(); 375 376 // Throw an Exception if the event already exists 377 if(m_event_map_->keyExist(event_name)) 378 { 379 const String& error_msg = "Internal error: event (" + event_name + 380 ") exists"; 381 throw Exception(error_msg); 382 } 383 384 // Add the event 385 m_event_map_->set(event_name, event_); 386 return; 387 } 388 389 Result* Model::getEventResult(const String& event_name_) 390 { 391 return m_event_map_->get(event_name_); 392 } 393 394 const Result* Model::getEventResult(const String& event_name_) const 395 { 396 return m_event_map_->get(event_name_); 397 } 398 399 bool Model::hasEventResult(const String& event_name_) const 400 { 401 return m_event_map_->keyExist(event_name_); 402 } 403 404 const TechModel* Model::getTechModel() const 405 { 406 return m_tech_model_; 407 } 408 409 const void* Model::parseQuery(const String& query_type_, const String& query_hier_, const String& query_sub_field_) 410 { 411 // Break query by hierarchy separator 412 vector<String> hier_split = query_hier_.splitByString(HIERARCHY_SEPARATOR); 413 414 // Check if the query_hier matches the instance name 415 ASSERT((hier_split[0] == m_instance_name_), "[Error] " + 416 m_instance_name_ + " -> Mismatch in instance name (" + 417 hier_split[0] + ")"); 418 419 // If there is no more hierarchy separator, this process the query 420 if(hier_split.size() == 1) 421 { 422 // Query the model 423 return processQuery(query_type_, query_sub_field_); 424 } 425 else 426 { 427 // Reconstruct the query 428 String temp_query_hier = hier_split[1]; 429 for(int i = 2; i < (int)hier_split.size(); ++i) 430 { 431 temp_query_hier += HIERARCHY_SEPARATOR + hier_split[i]; 432 } 433 434 // Get sub instance's name 435 const String& temp_sub_instance_name = hier_split[1]; 436 ASSERT(m_sub_instances_->keyExist(temp_sub_instance_name), "[Error] " + 437 m_instance_name_ + " -> No sub-instances queried (" + 438 temp_sub_instance_name + ")"); 439 440 return m_sub_instances_->get(temp_sub_instance_name)->getModel()->parseQuery(query_type_, temp_query_hier, query_sub_field_); 441 } 442 } 443 444 const void* Model::processQuery(const String& query_type_, const String& query_sub_field_) 445 { 446 if(query_type_ == "Property") 447 { 448 return getProperties(); 449 } 450 else if(query_type_ == "Parameter") 451 { 452 return getParameters(); 453 } 454 else if(query_type_.contain("Hier")) 455 { 456 return this; 457 } 458 else if(query_type_ == "Area") 459 { 460 return queryArea(query_sub_field_); 461 } 462 else if(query_type_ == "NddPower") 463 { 464 return queryNddPower(query_sub_field_); 465 } 466 else if(query_type_ == "Energy") 467 { 468 return queryEventEnergyCost(query_sub_field_); 469 } 470 else 471 { 472 const String& error_msg = "[Error] " + m_instance_name_ + " -> Unknown query type (" + query_type_ + ")"; 473 throw Exception(error_msg); 474 return NULL; 475 } 476 } 477 478 const Result* Model::queryArea(const String& area_name_) const 479 { 480 ASSERT(m_area_map_->keyExist(area_name_), "[Error] " + m_instance_name_ + 481 " -> Unknown queried area name (" + area_name_ + ")"); 482 return m_area_map_->get(area_name_); 483 } 484 485 const Result* Model::queryNddPower(const String& ndd_power_name_) 486 { 487 ASSERT(m_ndd_power_map_->keyExist(ndd_power_name_), "[Error] " + m_instance_name_ + 488 " -> Unknown queried ndd power name (" + ndd_power_name_ + ")"); 489 490 use("Idle"); 491 return m_ndd_power_map_->get(ndd_power_name_); 492 } 493 494 const Result* Model::queryEventEnergyCost(const String& event_name_) 495 { 496 ASSERT(m_event_map_->keyExist(event_name_), "[Error] " + m_instance_name_ + 497 " -> Unknown queried event name (" + event_name_ + ")"); 498 499 use(event_name_); 500 return m_event_map_->get(event_name_); 501 } 502 503 // Update checks whether the model needs updating, whether all properties have been specified, 504 // and calls updateModel if update is necessary 505 void Model::construct() 506 { 507 // Model should not be constructed yet 508 ASSERT(!m_constructed_, "[Error] " + getInstanceName() + " -> Cannot construct an already contructed model!"); 509 // Check if whether all needed parameters are defined 510 checkParameters(); 511 constructModel(); 512 m_constructed_ = true; 513 m_updated_ = false; 514 m_evaluated_ = false; 515 return; 516 } 517 518 // Update checks whether the model needs updating, whether all properties have been specified, 519 // and calls updateModel if update is necessary 520 void Model::update() 521 { 522 // Model should be constructed 523 ASSERT(m_constructed_, "[Error] " + getInstanceName() + " -> Cannot update an unconstructed model!"); 524 // If the model needs updating (due to property change) 525 // an update is necessary 526 if (!m_updated_) 527 { 528 // Check if all properties needed exist 529 checkProperties(); 530 updateModel(); 531 m_updated_ = true; 532 m_evaluated_ = false; 533 } 534 return; 535 } 536 537 // Evaluate checks whether the model needs to be evaluated. 538 void Model::evaluate() 539 { 540 // Model should be constructed 541 ASSERT(m_constructed_, "[Error] " + getInstanceName() + " -> Cannot evaluate an unconstructed model!"); 542 // Model should be updated 543 ASSERT(m_updated_, "[Error] " + getInstanceName() + " -> Cannot evaluate without first updating!"); 544 // If the model needs evaluating 545 if (!m_evaluated_) 546 { 547 evaluateModel(); 548 m_evaluated_ = true; 549 } 550 551 return; 552 } 553 554 void Model::use(const String& event_name_) 555 { 556 useModel(event_name_); 557 return; 558 } 559 560 void Model::use() 561 { 562 useModel(); 563 return; 564 } 565 566 // By default, update model will iterate through all sub-instances and do updateModel on them 567 void Model::updateModel() 568 { 569 Map<SubModel*>::Iterator iter = m_sub_instances_->begin(); 570 Map<SubModel*>::Iterator end = m_sub_instances_->end(); 571 while (iter != end) 572 { 573 iter->second->getModel()->update(); 574 iter++; 575 } 576 return; 577 } 578 579 // By default, update model will iterate through all sub-instances and do updateModel on them 580 void Model::evaluateModel() 581 { 582 Map<SubModel*>::Iterator iter = m_sub_instances_->begin(); 583 Map<SubModel*>::Iterator end = m_sub_instances_->end(); 584 while (iter != end) 585 { 586 iter->second->getModel()->evaluate(); 587 iter++; 588 } 589 return; 590 } 591 592 void Model::useModel(const String& /* event_name_ */) 593 {} 594 595 void Model::useModel() 596 {} 597 598 void Model::printHierarchy(const String& query_type_, const String& query_sub_field_, const String& prepend_str_, int detail_level_, ostream& ost_) const 599 { 600 if(query_type_ == "InstHier") 601 { 602 ost_ << prepend_str_ << getInstanceName() << endl; 603 printInstHierarchy(prepend_str_, detail_level_, ost_); 604 //if(detail_level_ > 0) 605 //{ 606 //for(Map<SubModel*>::ConstIterator it = m_sub_instances_->begin(); it != m_sub_instances_->end(); ++it) 607 //{ 608 //const Model* sub_model = (it->second)->getModel(); 609 //String temp_prepend_str = prepend_str_ + " "; 610 //sub_model->printHierarchy(query_type_, query_sub_field_, temp_prepend_str, detail_level_ - 1, ost_); 611 //} 612 //} 613 } 614 else 615 { 616 const Map<Result*>* result_map; 617 618 if(query_type_ == "AreaHier") 619 { 620 result_map = m_area_map_; 621 } 622 else if(query_type_ == "NddPowerHier") 623 { 624 result_map = m_ndd_power_map_; 625 } 626 else if(query_type_ == "EventHier") 627 { 628 result_map = m_event_map_; 629 } 630 else 631 { 632 const String& error_msg = "[Error] " + m_instance_name_ + " -> Unknown query type (" + query_type_ + ")"; 633 throw Exception(error_msg); 634 return; 635 } 636 637 if(query_sub_field_ == "") 638 { 639 for(Map<Result*>::ConstIterator it = result_map->begin(); it != result_map->end(); ++it) 640 { 641 const Result* result = it->second; 642 ost_ << prepend_str_ << getInstanceName() << "->" << result->getName() << endl; 643 result->printHierarchy(prepend_str_, detail_level_, ost_); 644 } 645 } 646 else 647 { 648 const Result* result = result_map->get(query_sub_field_); 649 ost_ << prepend_str_ << getInstanceName() << "->" << result->getName() << endl; 650 result->printHierarchy(prepend_str_, detail_level_, ost_); 651 } 652 } 653 return; 654 } 655 656 void Model::printInstHierarchy(const String& prepend_str_, int detail_level_, ostream& ost_) const 657 { 658 if(detail_level_ > 0) 659 { 660 for(Map<SubModel*>::ConstIterator it = m_sub_instances_->begin(); it != m_sub_instances_->end(); ++it) 661 { 662 const Model* sub_model = it->second->getModel(); 663 String temp_prepend_str = prepend_str_ + " "; 664 665 ost_ << prepend_str_ << " |--" << sub_model->getInstanceName() << endl; 666 sub_model->printInstHierarchy(temp_prepend_str, detail_level_ - 1, ost_); 667 } 668 } 669 return; 670 } 671 672 Model* Model::clone() const 673 { 674 throw Exception(getInstanceName() + " -> Cannot be cloned!"); 675 } 676 677 Model::Model(const Model& model_) 678 { 679 // Copy instance's name 680 m_instance_name_ = model_.m_instance_name_; 681 682 // Clone properties 683 m_properties_ = model_.m_properties_->clone(); 684 685 // Clone instances 686 m_sub_instances_ = clonePtrMap(model_.m_sub_instances_); 687 688 // Clone events, area, ndd_power 689 m_event_map_ = clonePtrMap(model_.m_event_map_); 690 m_area_map_ = clonePtrMap(model_.m_area_map_); 691 m_ndd_power_map_ = clonePtrMap(model_.m_ndd_power_map_); 692 693 // Copy tech model pointer 694 m_tech_model_ = model_.m_tech_model_; 695 } 696 697} // namespace DSENT 698 699