summaryrefslogtreecommitdiff
path: root/ext/dsent/model/Model.cc
diff options
context:
space:
mode:
Diffstat (limited to 'ext/dsent/model/Model.cc')
-rw-r--r--ext/dsent/model/Model.cc698
1 files changed, 698 insertions, 0 deletions
diff --git a/ext/dsent/model/Model.cc b/ext/dsent/model/Model.cc
new file mode 100644
index 000000000..5a7bfe391
--- /dev/null
+++ b/ext/dsent/model/Model.cc
@@ -0,0 +1,698 @@
+#include "model/Model.h"
+
+#include <vector>
+
+#include "util/Result.h"
+
+namespace DSENT
+{
+ using std::vector;
+ using LibUtil::deletePtrMap;
+ using LibUtil::clonePtrMap;
+
+ Model::SubModel::SubModel(Model* model_, double num_models_)
+ : m_model_(model_), m_num_models_(num_models_)
+ {}
+
+ Model::SubModel::~SubModel()
+ {
+ delete m_model_;
+ }
+
+ Model* Model::SubModel::getModel()
+ {
+ return m_model_;
+ }
+
+ const Model* Model::SubModel::getModel() const
+ {
+ return m_model_;
+ }
+
+ double Model::SubModel::getNumModels() const
+ {
+ return m_num_models_;
+ }
+
+ Model::SubModel* Model::SubModel::clone() const
+ {
+ return new SubModel(*this);
+ }
+
+ Model::SubModel::SubModel(const SubModel& sub_model_)
+ {
+ m_model_ = sub_model_.m_model_->clone();
+ m_num_models_ = sub_model_.m_num_models_;
+ }
+
+ const char Model::TYPE_SEPARATOR[] = ">>";
+ const char Model::HIERARCHY_SEPARATOR[] = "->";
+ const char Model::SUBFIELD_SEPARATOR[] = ":";
+ const char Model::DETAIL_SEPARATOR[] = "@";
+
+ Model::Model(const String& instance_name_, const TechModel* tech_model_)
+ : m_instance_name_(instance_name_), m_tech_model_(tech_model_),
+ m_constructed_(false), m_updated_(false), m_evaluated_(false)
+ {
+ m_property_names_ = new vector<String>;
+ m_parameter_names_ = new vector<String>;
+ m_parameters_ = new ParameterMap();
+ m_properties_ = new PropertyMap();
+ m_generated_properties_ = new PropertyMap();
+ m_sub_instances_ = new Map<SubModel*>();
+ m_event_map_ = new Map<Result*>();
+ m_area_map_ = new Map<Result*>();
+ m_ndd_power_map_ = new Map<Result*>();
+ }
+
+ Model::~Model()
+ {
+ // Clear parameter names
+ delete m_parameter_names_;
+ // Clear property name
+ delete m_property_names_;
+
+ // Clear parameters
+ delete m_parameters_;
+ m_parameters_ = NULL;
+ // Clear input properties
+ delete m_properties_;
+ m_properties_ = NULL;
+
+ // Clear generated properties
+ delete m_generated_properties_;
+ m_generated_properties_ = NULL;
+
+ // Clear sub models
+ deletePtrMap<SubModel>(m_sub_instances_);
+ m_sub_instances_ = NULL;
+
+ // Clear all results
+ deletePtrMap<Result>(m_event_map_);
+ m_event_map_ = NULL;
+ deletePtrMap<Result>(m_area_map_);
+ m_area_map_ = NULL;
+ deletePtrMap<Result>(m_ndd_power_map_);
+ m_ndd_power_map_ = NULL;
+ }
+
+ void Model::setInstanceName(const String& instance_name_)
+ {
+ m_instance_name_ = instance_name_;
+ return;
+ }
+
+ const String& Model::getInstanceName() const
+ {
+ return m_instance_name_;
+ }
+
+ void Model::setIsTopModel(bool is_top_model_)
+ {
+ m_is_top_model_ = is_top_model_;
+ return;
+ }
+
+ bool Model::getIsTopModel() const
+ {
+ return m_is_top_model_;
+ }
+
+ //-------------------------------------------------------------------------
+ // Parameters and properties checks
+ //-------------------------------------------------------------------------
+ void Model::addParameterName(const String& parameter_name_)
+ {
+ ASSERT(!m_constructed_, "[Error] " + getInstanceName() +
+ " -> Cannot add additional parameters names after model is constructed!");
+ m_parameter_names_->push_back(parameter_name_);
+
+ return;
+ }
+
+ void Model::addParameterName(const String& parameter_name_, const String& parameter_default_)
+ {
+ ASSERT(!m_constructed_, "[Error] " + getInstanceName() +
+ " -> Cannot add additional parameters names after model is constructed!");
+ m_parameter_names_->push_back(parameter_name_);
+ setParameter(parameter_name_, parameter_default_);
+ return;
+ }
+
+ const vector<String>* Model::getParameterNames() const
+ {
+ return m_parameter_names_;
+ }
+
+ void Model::addPropertyName(const String& property_name_)
+ {
+ ASSERT(!m_constructed_, "[Error] " + getInstanceName() +
+ " -> Cannot add additional property names after model is constructed!");
+ m_property_names_->push_back(property_name_);
+ return;
+ }
+
+ void Model::addPropertyName(const String& property_name_, const String& property_default_)
+ {
+ ASSERT(!m_constructed_, "[Error] " + getInstanceName() +
+ " -> Cannot add additional property names after model is constructed!");
+ m_property_names_->push_back(property_name_);
+ setProperty(property_name_, property_default_);
+ return;
+ }
+
+ const vector<String>* Model::getPropertyNames() const
+ {
+ return m_property_names_;
+ }
+
+ void Model::checkParameters() const
+ {
+ String missing_parameters = "";
+
+ for(int i = 0; i < (int)m_parameter_names_->size(); ++i)
+ {
+ const String& parameter_name = m_parameter_names_->at(i);
+ if (!m_parameters_->keyExist(parameter_name))
+ missing_parameters += " " + parameter_name + "\n";
+ }
+
+ ASSERT(missing_parameters.size() == 0, "[Error] " + m_instance_name_ +
+ " -> Missing parameters:\n" + missing_parameters);
+ return;
+ }
+
+ void Model::checkProperties() const
+ {
+ String missing_properties = "";
+
+ for(int i = 0; i < (int)m_property_names_->size(); ++i)
+ {
+ const String& property_name = m_property_names_->at(i);
+ if (!m_properties_->keyExist(property_name))
+ missing_properties += " " + property_name + "\n";
+ }
+
+ ASSERT(missing_properties.size() == 0, "[Error] " + m_instance_name_ +
+ " -> Missing properties:\n" + missing_properties);
+ return;
+ }
+ //-------------------------------------------------------------------------
+
+ //-------------------------------------------------------------------------
+ // Parameters Manipulation
+ //-------------------------------------------------------------------------
+ const ParameterMap* Model::getParameters() const
+ {
+ return m_parameters_;
+ }
+
+ const String Model::getParameter(const String& parameter_name_) const
+ {
+ return m_parameters_->get(parameter_name_);
+ }
+
+ void Model::setParameter(const String& parameter_name_, const String& parameter_value_)
+ {
+ ASSERT(!m_constructed_, "[Error] " + getInstanceName() +
+ " -> Cannot set parameters after model is constructed!");
+ m_parameters_->set(parameter_name_, parameter_value_);
+ }
+ //-------------------------------------------------------------------------
+
+ //-------------------------------------------------------------------------
+ // Properties Manipulation
+ //-------------------------------------------------------------------------
+ const PropertyMap* Model::getProperties() const
+ {
+ return m_properties_;
+ }
+
+ const String Model::getProperty(const String& property_name_) const
+ {
+ return m_properties_->get(property_name_);
+ }
+
+ void Model::setProperty(const String& property_name_, const String& property_value_)
+ {
+ // If any properties changed, reset updated and evaluated flags
+ m_updated_ = false;
+ m_evaluated_ = false;
+ m_properties_->set(property_name_, property_value_);
+ }
+ //-------------------------------------------------------------------------
+
+ PropertyMap* Model::getGenProperties()
+ {
+ return m_generated_properties_;
+ }
+
+ const PropertyMap* Model::getGenProperties() const
+ {
+ return m_generated_properties_;
+ }
+
+ void Model::addSubInstances(Model* sub_instance_, double num_sub_instances_)
+ {
+ // Get instance name
+ const String& sub_instance_name = sub_instance_->getInstanceName();
+
+ // Check if the instance exists
+ if(m_sub_instances_->keyExist(sub_instance_name))
+ {
+ const String& error_msg = "[Error] " + m_instance_name_ +
+ " -> Instance exists (" + sub_instance_name + ")";
+ throw Exception(error_msg);
+ }
+
+ // Check if the num_sub_instances_ is a positive number
+ ASSERT((num_sub_instances_ >= 0), "[Error] " + m_instance_name_ +
+ " -> Invalid number of instance (" + String(num_sub_instances_) + ")");
+
+ // Add the instance
+ m_sub_instances_->set(sub_instance_name, new SubModel(sub_instance_, num_sub_instances_));
+ return;
+ }
+
+ Model* Model::getSubInstance(const String& sub_instance_name_)
+ {
+ // Throw an Exception if the instance already exists
+ if(!m_sub_instances_->keyExist(sub_instance_name_))
+ {
+ const String& error_msg = "[Error] " + m_instance_name_ +
+ " -> Instance not exists (" + sub_instance_name_ + ")";
+ throw Exception(error_msg);
+ }
+
+ return m_sub_instances_->get(sub_instance_name_)->getModel();
+ }
+
+ const Model* Model::getSubInstance(const String& sub_instance_name_) const
+ {
+ // Throw an Exception if the instance does not exist
+ if(!m_sub_instances_->keyExist(sub_instance_name_))
+ {
+ const String& error_msg = "[Error] " + m_instance_name_ +
+ " -> Instance not exists (" + sub_instance_name_ + ")";
+ throw Exception(error_msg);
+ }
+
+ return m_sub_instances_->get(sub_instance_name_)->getModel();
+ }
+
+ bool Model::hasSubInstance(const String& sub_instance_name_) const
+ {
+ return m_sub_instances_->keyExist(sub_instance_name_);
+ }
+
+ void Model::addAreaResult(Result* area_)
+ {
+ const String& area_name = area_->getName();
+
+ // Throw an Exception if the area already exists
+ if(m_area_map_->keyExist(area_name))
+ {
+ const String& error_msg = "Internal error: area (" + area_name +
+ ") exists";
+ throw Exception(error_msg);
+ }
+
+ // Add the area
+ m_area_map_->set(area_name, area_);
+ return;
+ }
+
+ Result* Model::getAreaResult(const String& area_name_)
+ {
+ return m_area_map_->get(area_name_);
+ }
+
+ const Result* Model::getAreaResult(const String& area_name_) const
+ {
+ return m_area_map_->get(area_name_);
+ }
+
+ bool Model::hasAreaResult(const String& area_name_) const
+ {
+ return m_area_map_->keyExist(area_name_);
+ }
+
+ void Model::addNddPowerResult(Result* ndd_power_)
+ {
+ const String& ndd_power_name = ndd_power_->getName();
+
+ // Throw an Exception if the ndd_power already exists
+ if(m_ndd_power_map_->keyExist(ndd_power_name))
+ {
+ const String& error_msg = "Internal error: ndd_power (" + ndd_power_name +
+ ") exists";
+ throw Exception(error_msg);
+ }
+
+ // Add the ndd_power
+ m_ndd_power_map_->set(ndd_power_name, ndd_power_);
+ return;
+ }
+
+ Result* Model::getNddPowerResult(const String& ndd_power_name_)
+ {
+ return m_ndd_power_map_->get(ndd_power_name_);
+ }
+
+ const Result* Model::getNddPowerResult(const String& ndd_power_name_) const
+ {
+ return m_ndd_power_map_->get(ndd_power_name_);
+ }
+
+ bool Model::hasNddPowerResult(const String& ndd_power_name_) const
+ {
+ return m_ndd_power_map_->keyExist(ndd_power_name_);
+ }
+
+ void Model::addEventResult(Result* event_)
+ {
+ const String& event_name = event_->getName();
+
+ // Throw an Exception if the event already exists
+ if(m_event_map_->keyExist(event_name))
+ {
+ const String& error_msg = "Internal error: event (" + event_name +
+ ") exists";
+ throw Exception(error_msg);
+ }
+
+ // Add the event
+ m_event_map_->set(event_name, event_);
+ return;
+ }
+
+ Result* Model::getEventResult(const String& event_name_)
+ {
+ return m_event_map_->get(event_name_);
+ }
+
+ const Result* Model::getEventResult(const String& event_name_) const
+ {
+ return m_event_map_->get(event_name_);
+ }
+
+ bool Model::hasEventResult(const String& event_name_) const
+ {
+ return m_event_map_->keyExist(event_name_);
+ }
+
+ const TechModel* Model::getTechModel() const
+ {
+ return m_tech_model_;
+ }
+
+ const void* Model::parseQuery(const String& query_type_, const String& query_hier_, const String& query_sub_field_)
+ {
+ // Break query by hierarchy separator
+ vector<String> hier_split = query_hier_.splitByString(HIERARCHY_SEPARATOR);
+
+ // Check if the query_hier matches the instance name
+ ASSERT((hier_split[0] == m_instance_name_), "[Error] " +
+ m_instance_name_ + " -> Mismatch in instance name (" +
+ hier_split[0] + ")");
+
+ // If there is no more hierarchy separator, this process the query
+ if(hier_split.size() == 1)
+ {
+ // Query the model
+ return processQuery(query_type_, query_sub_field_);
+ }
+ else
+ {
+ // Reconstruct the query
+ String temp_query_hier = hier_split[1];
+ for(int i = 2; i < (int)hier_split.size(); ++i)
+ {
+ temp_query_hier += HIERARCHY_SEPARATOR + hier_split[i];
+ }
+
+ // Get sub instance's name
+ const String& temp_sub_instance_name = hier_split[1];
+ ASSERT(m_sub_instances_->keyExist(temp_sub_instance_name), "[Error] " +
+ m_instance_name_ + " -> No sub-instances queried (" +
+ temp_sub_instance_name + ")");
+
+ return m_sub_instances_->get(temp_sub_instance_name)->getModel()->parseQuery(query_type_, temp_query_hier, query_sub_field_);
+ }
+ }
+
+ const void* Model::processQuery(const String& query_type_, const String& query_sub_field_)
+ {
+ if(query_type_ == "Property")
+ {
+ return getProperties();
+ }
+ else if(query_type_ == "Parameter")
+ {
+ return getParameters();
+ }
+ else if(query_type_.contain("Hier"))
+ {
+ return this;
+ }
+ else if(query_type_ == "Area")
+ {
+ return queryArea(query_sub_field_);
+ }
+ else if(query_type_ == "NddPower")
+ {
+ return queryNddPower(query_sub_field_);
+ }
+ else if(query_type_ == "Energy")
+ {
+ return queryEventEnergyCost(query_sub_field_);
+ }
+ else
+ {
+ const String& error_msg = "[Error] " + m_instance_name_ + " -> Unknown query type (" + query_type_ + ")";
+ throw Exception(error_msg);
+ return NULL;
+ }
+ }
+
+ const Result* Model::queryArea(const String& area_name_) const
+ {
+ ASSERT(m_area_map_->keyExist(area_name_), "[Error] " + m_instance_name_ +
+ " -> Unknown queried area name (" + area_name_ + ")");
+ return m_area_map_->get(area_name_);
+ }
+
+ const Result* Model::queryNddPower(const String& ndd_power_name_)
+ {
+ ASSERT(m_ndd_power_map_->keyExist(ndd_power_name_), "[Error] " + m_instance_name_ +
+ " -> Unknown queried ndd power name (" + ndd_power_name_ + ")");
+
+ use("Idle");
+ return m_ndd_power_map_->get(ndd_power_name_);
+ }
+
+ const Result* Model::queryEventEnergyCost(const String& event_name_)
+ {
+ ASSERT(m_event_map_->keyExist(event_name_), "[Error] " + m_instance_name_ +
+ " -> Unknown queried event name (" + event_name_ + ")");
+
+ use(event_name_);
+ return m_event_map_->get(event_name_);
+ }
+
+ // Update checks whether the model needs updating, whether all properties have been specified,
+ // and calls updateModel if update is necessary
+ void Model::construct()
+ {
+ // Model should not be constructed yet
+ ASSERT(!m_constructed_, "[Error] " + getInstanceName() + " -> Cannot construct an already contructed model!");
+ // Check if whether all needed parameters are defined
+ checkParameters();
+ constructModel();
+ m_constructed_ = true;
+ m_updated_ = false;
+ m_evaluated_ = false;
+ return;
+ }
+
+ // Update checks whether the model needs updating, whether all properties have been specified,
+ // and calls updateModel if update is necessary
+ void Model::update()
+ {
+ // Model should be constructed
+ ASSERT(m_constructed_, "[Error] " + getInstanceName() + " -> Cannot update an unconstructed model!");
+ // If the model needs updating (due to property change)
+ // an update is necessary
+ if (!m_updated_)
+ {
+ // Check if all properties needed exist
+ checkProperties();
+ updateModel();
+ m_updated_ = true;
+ m_evaluated_ = false;
+ }
+ return;
+ }
+
+ // Evaluate checks whether the model needs to be evaluated.
+ void Model::evaluate()
+ {
+ // Model should be constructed
+ ASSERT(m_constructed_, "[Error] " + getInstanceName() + " -> Cannot evaluate an unconstructed model!");
+ // Model should be updated
+ ASSERT(m_updated_, "[Error] " + getInstanceName() + " -> Cannot evaluate without first updating!");
+ // If the model needs evaluating
+ if (!m_evaluated_)
+ {
+ evaluateModel();
+ m_evaluated_ = true;
+ }
+
+ return;
+ }
+
+ void Model::use(const String& event_name_)
+ {
+ useModel(event_name_);
+ return;
+ }
+
+ void Model::use()
+ {
+ useModel();
+ return;
+ }
+
+ // By default, update model will iterate through all sub-instances and do updateModel on them
+ void Model::updateModel()
+ {
+ Map<SubModel*>::Iterator iter = m_sub_instances_->begin();
+ Map<SubModel*>::Iterator end = m_sub_instances_->end();
+ while (iter != end)
+ {
+ iter->second->getModel()->update();
+ iter++;
+ }
+ return;
+ }
+
+ // By default, update model will iterate through all sub-instances and do updateModel on them
+ void Model::evaluateModel()
+ {
+ Map<SubModel*>::Iterator iter = m_sub_instances_->begin();
+ Map<SubModel*>::Iterator end = m_sub_instances_->end();
+ while (iter != end)
+ {
+ iter->second->getModel()->evaluate();
+ iter++;
+ }
+ return;
+ }
+
+ void Model::useModel(const String& /* event_name_ */)
+ {}
+
+ void Model::useModel()
+ {}
+
+ void Model::printHierarchy(const String& query_type_, const String& query_sub_field_, const String& prepend_str_, int detail_level_, ostream& ost_) const
+ {
+ if(query_type_ == "InstHier")
+ {
+ ost_ << prepend_str_ << getInstanceName() << endl;
+ printInstHierarchy(prepend_str_, detail_level_, ost_);
+ //if(detail_level_ > 0)
+ //{
+ //for(Map<SubModel*>::ConstIterator it = m_sub_instances_->begin(); it != m_sub_instances_->end(); ++it)
+ //{
+ //const Model* sub_model = (it->second)->getModel();
+ //String temp_prepend_str = prepend_str_ + " ";
+ //sub_model->printHierarchy(query_type_, query_sub_field_, temp_prepend_str, detail_level_ - 1, ost_);
+ //}
+ //}
+ }
+ else
+ {
+ const Map<Result*>* result_map;
+
+ if(query_type_ == "AreaHier")
+ {
+ result_map = m_area_map_;
+ }
+ else if(query_type_ == "NddPowerHier")
+ {
+ result_map = m_ndd_power_map_;
+ }
+ else if(query_type_ == "EventHier")
+ {
+ result_map = m_event_map_;
+ }
+ else
+ {
+ const String& error_msg = "[Error] " + m_instance_name_ + " -> Unknown query type (" + query_type_ + ")";
+ throw Exception(error_msg);
+ return;
+ }
+
+ if(query_sub_field_ == "")
+ {
+ for(Map<Result*>::ConstIterator it = result_map->begin(); it != result_map->end(); ++it)
+ {
+ const Result* result = it->second;
+ ost_ << prepend_str_ << getInstanceName() << "->" << result->getName() << endl;
+ result->printHierarchy(prepend_str_, detail_level_, ost_);
+ }
+ }
+ else
+ {
+ const Result* result = result_map->get(query_sub_field_);
+ ost_ << prepend_str_ << getInstanceName() << "->" << result->getName() << endl;
+ result->printHierarchy(prepend_str_, detail_level_, ost_);
+ }
+ }
+ return;
+ }
+
+ void Model::printInstHierarchy(const String& prepend_str_, int detail_level_, ostream& ost_) const
+ {
+ if(detail_level_ > 0)
+ {
+ for(Map<SubModel*>::ConstIterator it = m_sub_instances_->begin(); it != m_sub_instances_->end(); ++it)
+ {
+ const Model* sub_model = it->second->getModel();
+ String temp_prepend_str = prepend_str_ + " ";
+
+ ost_ << prepend_str_ << " |--" << sub_model->getInstanceName() << endl;
+ sub_model->printInstHierarchy(temp_prepend_str, detail_level_ - 1, ost_);
+ }
+ }
+ return;
+ }
+
+ Model* Model::clone() const
+ {
+ throw Exception(getInstanceName() + " -> Cannot be cloned!");
+ }
+
+ Model::Model(const Model& model_)
+ {
+ // Copy instance's name
+ m_instance_name_ = model_.m_instance_name_;
+
+ // Clone properties
+ m_properties_ = model_.m_properties_->clone();
+
+ // Clone instances
+ m_sub_instances_ = clonePtrMap(model_.m_sub_instances_);
+
+ // Clone events, area, ndd_power
+ m_event_map_ = clonePtrMap(model_.m_event_map_);
+ m_area_map_ = clonePtrMap(model_.m_area_map_);
+ m_ndd_power_map_ = clonePtrMap(model_.m_ndd_power_map_);
+
+ // Copy tech model pointer
+ m_tech_model_ = model_.m_tech_model_;
+ }
+
+} // namespace DSENT
+