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