1c1,20
< #include "DSENT.h"
---
> /* Copyright (c) 2012 Massachusetts Institute of Technology
> *
> * Permission is hereby granted, free of charge, to any person obtaining a copy
> * of this software and associated documentation files (the "Software"), to deal
> * in the Software without restriction, including without limitation the rights
> * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
> * copies of the Software, and to permit persons to whom the Software is
> * furnished to do so, subject to the following conditions:
> *
> * The above copyright notice and this permission notice shall be included in
> * all copies or substantial portions of the Software.
> *
> * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
> * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
> * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
> * THE SOFTWARE.
> */
5a25,29
> #include "DSENT.h"
> #include "model/std_cells/StdCellLib.h"
>
> using namespace std;
>
8,11c32,33
< Model* DSENT::ms_model_ = NULL;
< bool DSENT::ms_is_verbose_ = false;
<
< void DSENT::run(int argc_, char** argv_)
---
> static void performTimingOpt(const map<String, String> &params,
> Model *ms_model)
13,14c35,36
< // Initialize DSENT framework (setup log file, config file, ...)
< initialize(argc_, argv_);
---
> // Get the frequency it is optimizing to
> double freq = params.at("Frequency").toDouble();
16,17c38,40
< // Build the specified model in the config file
< buildModel();
---
> // Get all the starting net names
> const vector<String>& start_net_names =
> params.at("TimingOptimization->StartNetNames").split("[,]");
19,22c42,43
< // Process the specified queries
< processQuery();
< // Process the specified evaluation
< processEvaluate();
---
> ASSERT((start_net_names.size() > 0),
> "[Error] Expecting net names in TimingOptimization->StartNetNames");
24,72c45
< // Finalize DSENT framework (close log file, ...)
< finalize();
< return;
< }
<
< void DSENT::setRuntimeOptions(OptionParser* option_parser_)
< {
< option_parser_->addOption("-cfg", "ConfigFilename", true, "filename", false, "",
< "Specify the config filename.");
<
< option_parser_->addOption("-available_models", "IsListModels", false, "", true, "false",
< "List available DSENT models.");
<
< option_parser_->addOption("-log", "LogFilename", true, "filename", true, "./dsent.log",
< "Specify the log filename.");
<
< option_parser_->addOption("-overwrite", "OverwriteString", true, "options", true, "",
< "Overwrite dynamically the options set in the config file. Options are separated by a comma (;).");
<
< option_parser_->addOption("-overwrite_tech", "OverwriteTechString", true, "options", true, "",
< "Overwrite dynamically the options set in the technology file. Options are separated by a comma (;).");
<
< option_parser_->addOption("-print_config", "IsPrintConfig", false, "", true, "false",
< "Print the config used at DSENT runtime.");
<
< option_parser_->addOption("-query", "QueryString", true, "query string", true, "",
< "Specify the list of items to query. This command is the same as owerwriting the 'QueryString'.");
<
< option_parser_->addOption("-eval", "EvaluateString", true, "evaluate string", true, "",
< "Specify the list of statements to evaluate. This command is the same as owerwriting the 'EvaluateString'.");
<
< option_parser_->addOption("-verbose", "IsVerbose", false, "", true, "false",
< "Enable verbose mode which prints out more detailed messages.");
< return;
< }
<
< void DSENT::initialize(int argc_, char** argv_)
< {
< OptionParser* option_parser = new OptionParser();
<
< // Init the option parser and setup available options
< setRuntimeOptions(option_parser);
<
< // Parse the options
< option_parser->parseArguments(argc_, argv_);
<
< // If -available_models is specified, print out a list of available
< // models and exit DSENT.
< if(option_parser->get("IsListModels").toBool())
---
> if(start_net_names[0] == "*")
74,76c47,48
< ModelGen::printAvailableModels();
< exit(0);
< }
---
> // Optimize from all input ports
> ElectricalModel* electrical_model = (ElectricalModel*)ms_model;
78,79c50,54
< // Init the log file
< Log::allocate(option_parser->get("LogFilename"));
---
> ElectricalTimingOptimizer timing_optimizer(
> "Optimizer", electrical_model->getTechModel());
> timing_optimizer.setModel(electrical_model);
> timing_optimizer.construct();
> timing_optimizer.update();
81,83c56,57
< // Init the config file
< Config::allocate(option_parser->get("ConfigFilename"));
< Config* dsent_config = Config::getSingleton();
---
> ElectricalTimingTree timing_tree(
> timing_optimizer.getInstanceName(), &timing_optimizer);
85,107c59,63
< // Overwrite the existing options
< dsent_config->readString(option_parser->get("OverwriteString"));
<
< // Overwrite the technology file
< dsent_config->constructTechModel(option_parser->get("OverwriteTechString"));
<
< ms_is_verbose_ = option_parser->get("IsVerbose").toBool();
<
< // Overwrite the query string if it is specified from command line
< if(option_parser->get("QueryString").size() != 0)
< {
< dsent_config->set("QueryString", option_parser->get("QueryString"));
< }
< // Overwrite the evaluation string if it is specified from command line
< if(option_parser->get("EvaluateString").size() != 0)
< {
< dsent_config->set("EvaluateString", option_parser->get("EvaluateString"));
< }
<
< // Print the config used for this run
< if(option_parser->get("IsPrintConfig").toBool())
< {
< if(ms_is_verbose_)
---
> const Map<PortInfo*>* input_ports = timing_optimizer.getInputs();
> Map<PortInfo*>::ConstIterator it_begin = input_ports->begin();
> Map<PortInfo*>::ConstIterator it_end = input_ports->end();
> Map<PortInfo*>::ConstIterator it;
> for(it = it_begin; it != it_end; ++it)
109,110c65,68
< cout << "Configuration:" << endl;
< cout << "==============" << endl;
---
> const String& net_name = it->first;
> Log::printLine("Optimizing net: " + net_name);
> timing_tree.performTimingOpt(
> timing_optimizer.getNet(net_name, makeNetIndex(0)), 1.0 / freq);
112d69
< cout << *dsent_config;
114c71,72
< if(ms_is_verbose_)
---
> // Loop the second times
> for(it = it_begin; it != it_end; ++it)
116c74,75
< cout << "==============" << endl;
---
> const String& net_name = it->first;
> Log::printLine("Optimizing net: " + net_name);
118a78,84
> else
> {
> // TODO : parse the net name so that we could do hierarchical optimization
> // Currently we can only optimize timing at the top level
> ElectricalModel* electrical_model = (ElectricalModel*)ms_model;
> ElectricalTimingTree timing_tree(
> electrical_model->getInstanceName(), electrical_model);
120,121c86,92
< delete option_parser;
< return;
---
> for(unsigned int i = 0; i < start_net_names.size(); ++i)
> {
> const String& net_name = start_net_names[i];
> timing_tree.performTimingOpt(
> electrical_model->getNet(net_name), 1.0 / freq);
> }
> }
124c95
< void DSENT::buildModel()
---
> static void reportTiming(const map<String, String> &params, Model *ms_model)
126c97,99
< Config* dsent_config = Config::getSingleton();
---
> // Get all the starting net names
> const vector<String>& start_net_names =
> params.at("ReportTiming->StartNetNames").split("[,]");
127a101,118
> ElectricalModel* electrical_model = (ElectricalModel*)ms_model;
> ElectricalTimingTree timing_tree(
> electrical_model->getInstanceName(), electrical_model);
>
> cout << "Report timing:" << endl;
> cout << "==============" << endl;
> for(unsigned int i = 0; i < start_net_names.size(); ++i)
> {
> const String& net_name = start_net_names[i];
> double timing = timing_tree.performCritPathExtract(electrical_model->getNet(net_name));
> cout << net_name << " = " << timing << endl;
> }
> cout << "==============" << endl;
> }
>
> static Model *buildModel(const map<String, String> &params,
> TechModel *tech_model)
> {
129,130c120,122
< const String& model_name = dsent_config->get("ModelName");
< ms_model_ = ModelGen::createModel(model_name, model_name, dsent_config->getTechModel());
---
> const String& model_name = params.at("ModelName");
> Model *ms_model = ModelGen::createModel(model_name, model_name,
> tech_model);
134c126
< const vector<String>* parameter_names = ms_model_->getParameterNames();
---
> const vector<String>* parameter_names = ms_model->getParameterNames();
136c128,129
< for(vector<String>::const_iterator it = parameter_names->begin(); it != parameter_names->end(); ++it)
---
> for(vector<String>::const_iterator it = parameter_names->begin();
> it != parameter_names->end(); ++it)
140c133
< if(dsent_config->keyExist(parameter_name))
---
> if(params.count(parameter_name) > 0)
142c135,136
< ms_model_->setParameter(parameter_name, dsent_config->get(parameter_name));
---
> ms_model->setParameter(parameter_name,
> params.at(parameter_name));
145d138
< ms_model_->construct();
146a140,141
> ms_model->construct();
>
149c144
< const vector<String>* property_names = ms_model_->getPropertyNames();
---
> const vector<String>* property_names = ms_model->getPropertyNames();
151c146,147
< for(vector<String>::const_iterator it = property_names->begin(); it != property_names->end(); ++it)
---
> for(vector<String>::const_iterator it = property_names->begin();
> it != property_names->end(); ++it)
155c151
< if(dsent_config->keyExist(property_name))
---
> if(params.count(property_name) > 0)
157c153,154
< ms_model_->setProperty(property_name, dsent_config->get(property_name));
---
> ms_model->setProperty(property_name,
> params.at(property_name));
160c157
< ms_model_->update();
---
> ms_model->update();
164c161,162
< if(dsent_config->getIfKeyExist("IsPerformTimingOptimization", "false").toBool())
---
> if(params.find("IsPerformTimingOptimization") != params.end() &&
> params.at("IsPerformTimingOptimization").toBool())
166c164
< performTimingOpt();
---
> performTimingOpt(params, ms_model);
168c166
< ms_model_->evaluate();
---
> ms_model->evaluate();
171c169,170
< if(dsent_config->getIfKeyExist("IsReportTiming", "false").toBool())
---
> if(params.count("IsReportTiming") > 0 &&
> params.at("IsReportTiming") != "false")
173c172
< reportTiming();
---
> reportTiming(params, ms_model);
176c175
< return;
---
> return ms_model;
179c178,179
< void DSENT::processQuery()
---
> static const void* processQuery(const String& query_str_,
> Model *ms_model, bool is_print_)
181,216d180
< Config* dsent_config = Config::getSingleton();
< vector<String> queries = dsent_config->get("QueryString").split(" ;\r\n");
<
< if(ms_is_verbose_)
< {
< cout << "Query results:" << endl;
< cout << "==============" << endl;
< }
<
< for(unsigned int i = 0; i < queries.size(); ++i)
< {
< const String& curr_query = queries[i];
<
< if(ms_is_verbose_)
< {
< String str = "Process query: '" + curr_query + "'";
< cout << str << endl;
< cout << String(str.size(), '-') << endl;
< }
<
< processQuery(curr_query, true);
<
< if(ms_is_verbose_)
< {
< cout << endl;
< }
< }
< if(ms_is_verbose_)
< {
< cout << "==============" << endl;
< }
< return;
< }
<
< const void* DSENT::processQuery(const String& query_str_, bool is_print_)
< {
221c185,187
< vector<String> detail_split = type_split[1].splitByString(Model::DETAIL_SEPARATOR);
---
> vector<String> detail_split =
> type_split[1].splitByString(Model::DETAIL_SEPARATOR);
>
225,226c191,196
< vector<String> subfield_split = detail_split[0].splitByString(Model::SUBFIELD_SEPARATOR);
< ASSERT(((subfield_split.size() == 2) || (subfield_split.size() == 1)), "[Error] Invalid query format: " + query_str_);
---
> vector<String> subfield_split =
> detail_split[0].splitByString(Model::SUBFIELD_SEPARATOR);
>
> ASSERT(((subfield_split.size() == 2) || (subfield_split.size() == 1)),
> "[Error] Invalid query format: " + query_str_);
>
228a199
>
234c205,206
< const void* query_result = ms_model_->parseQuery(query_type, query_hier, query_subfield);
---
> const void* query_result = ms_model->parseQuery(query_type, query_hier,
> query_subfield);
271c243,244
< void DSENT::finalize()
---
> void processQuery(const vector<String> &queries,
> Model *ms_model, vector<String> &outputs)
273,275c246,249
< // Release the constructed model
< delete ms_model_;
< ms_model_ = NULL;
---
> for(unsigned int i = 0; i < queries.size(); ++i)
> {
> const String& curr_query = queries[i];
> processQuery(curr_query, ms_model, true);
277,283c251
< // Release the config file
< Config::release();
<
< // Release the log file
< Log::release();
<
< return;
---
> }
286c254
< void DSENT::performTimingOpt()
---
> static TechModel* constructTechModel(const map<String, String>& params)
288c256,258
< Config* dsent_config = Config::getSingleton();
---
> // Allocate static TechModel instance
> const String& electrical_tech_model_filename =
> params.at("ElectricalTechModelFilename");
290,291c260,261
< // Get the frequency it is optimizing to
< double freq = dsent_config->get("Frequency").toDouble();
---
> TechModel* tech_model = new TechModel();
> tech_model->readFile(electrical_tech_model_filename);
293,294c263,267
< // Get all the starting net names
< const vector<String>& start_net_names = dsent_config->get("TimingOptimization->StartNetNames").split("[,]");
---
> if (params.count("PhotonicTechModelFilename") != 0) {
> const String& photonic_tech_model_filename =
> params.at("PhotonicTechModelFilename");
> tech_model->readFile(photonic_tech_model_filename);
> }
296c269,270
< ASSERT((start_net_names.size() > 0), "[Error] Expecting net names in TimingOptimization->StartNetNames");
---
> // Allocate static StdCellLib instance
> StdCellLib* std_cell_lib = new StdCellLib(tech_model);
298,341c272,274
< if(start_net_names[0] == "*")
< {
< // Optimize from all input ports
< ElectricalModel* electrical_model = (ElectricalModel*)ms_model_;
<
< ElectricalTimingOptimizer timing_optimizer("Optimizer", electrical_model->getTechModel());
< timing_optimizer.setModel(electrical_model);
< timing_optimizer.construct();
< timing_optimizer.update();
<
< ElectricalTimingTree timing_tree(timing_optimizer.getInstanceName(), &timing_optimizer);
<
< const Map<PortInfo*>* input_ports = timing_optimizer.getInputs();
< Map<PortInfo*>::ConstIterator it_begin = input_ports->begin();
< Map<PortInfo*>::ConstIterator it_end = input_ports->end();
< Map<PortInfo*>::ConstIterator it;
< for(it = it_begin; it != it_end; ++it)
< {
< const String& net_name = it->first;
< Log::printLine("Optimizing net: " + net_name);
< timing_tree.performTimingOpt(timing_optimizer.getNet(net_name, makeNetIndex(0)), 1.0 / freq);
< //timing_tree.performTimingOpt(electrical_model->getNet(net_name, makeNetIndex(0)), 1.0 / freq);
< }
< // Loop the second times
< for(it = it_begin; it != it_end; ++it)
< {
< const String& net_name = it->first;
< Log::printLine("Optimizing net: " + net_name);
< //timing_tree.performTimingOpt(timing_optimizer.getNet(net_name, makeNetIndex(0)), 1.0 / freq);
< }
< }
< else
< {
< // TODO : parse the net name so that we could do hierarchical optimization
< // Currently we can only optimize timing at the top level
< ElectricalModel* electrical_model = (ElectricalModel*)ms_model_;
< ElectricalTimingTree timing_tree(electrical_model->getInstanceName(), electrical_model);
< for(unsigned int i = 0; i < start_net_names.size(); ++i)
< {
< const String& net_name = start_net_names[i];
< timing_tree.performTimingOpt(electrical_model->getNet(net_name), 1.0 / freq);
< }
< }
< return;
---
> // Set the StdCellLib pointer in static TechModel instance
> tech_model->setStdCellLib(std_cell_lib);
> return tech_model;
344c277
< void DSENT::reportTiming()
---
> Model *initialize(const char *config_file_name, map<String, String> &config)
346c279,280
< Config* dsent_config = Config::getSingleton();
---
> // Init the log file
> Log::allocate("/tmp/dsent.log");
348,349c282,283
< // Get all the starting net names
< const vector<String>& start_net_names = dsent_config->get("ReportTiming->StartNetNames").split("[,]");
---
> // Init the config file
> LibUtil::readFile(config_file_name, config);
351,352c285,286
< ElectricalModel* electrical_model = (ElectricalModel*)ms_model_;
< ElectricalTimingTree timing_tree(electrical_model->getInstanceName(), electrical_model);
---
> // Overwrite the technology file
> TechModel *tech_model = constructTechModel(config);
354,363c288,289
< cout << "Report timing:" << endl;
< cout << "==============" << endl;
< for(unsigned int i = 0; i < start_net_names.size(); ++i)
< {
< const String& net_name = start_net_names[i];
< double timing = timing_tree.performCritPathExtract(electrical_model->getNet(net_name));
< cout << net_name << " = " << timing << endl;
< }
< cout << "==============" << endl;
< return;
---
> // Build the specified model in the config file
> return buildModel(config, tech_model);
366c292
< void DSENT::processEvaluate()
---
> void finalize(map<String, String> &config, Model *ms_model)
368c294,295
< Config* dsent_config = Config::getSingleton();
---
> // Delete the model
> delete ms_model;
370,371c297,298
< // Return if EvaluatString is empty or not exists
< if(!dsent_config->keyExist("EvaluateString")) return;
---
> // Discard all the (key, value) pairs.
> config.clear();
373c300,302
< String eval_str = dsent_config->get("EvaluateString");
---
> // Release the log file
> Log::release();
> }
375,380c304,310
< if(eval_str == "") return;
<
< if(ms_is_verbose_)
< {
< cout << "Eval results:" << endl;
< cout << "==============" << endl;
---
> void run(const map<String, String> &params, Model *ms_model,
> map<string, double> &outputs)
> {
> // Process the specified queries
> const auto &it = params.find("EvaluateString");
> if(it == params.end()) {
> return;
383,390c313
< //if(ms_is_verbose_)
< //{
< // String str = "Process evaluation: '" + eval_str + "'";
< // cout << str << endl;
< // cout << String(str.size(), '-') << endl;
< //}
< DSENTCalculator calc;
< calc.evaluateString(eval_str);
---
> String eval_str = it->second;
392,394c315,316
< if(ms_is_verbose_)
< {
< cout << "==============" << endl;
---
> if (eval_str == "") {
> return;
396,397c318,320
< return;
< return;
---
>
> DSENTCalculator calc;
> calc.evaluateString(eval_str, params, ms_model, outputs);
400,401c323
< DSENT::DSENTCalculator::DSENTCalculator()
< {}
---
> DSENTCalculator::DSENTCalculator() {}
403,404c325
< DSENT::DSENTCalculator::~DSENTCalculator()
< {}
---
> DSENTCalculator::~DSENTCalculator() {}
406c327,329
< double DSENT::DSENTCalculator::getEnvVar(const String& var_name_) const
---
> double DSENTCalculator::getEnvVar(const String& var_name_,
> const map<String, String> &config,
> Model *ms_model) const
408,409c331
< if(m_var_.keyExist(var_name_))
< {
---
> if (m_var_.keyExist(var_name_)) {
411,418c333,339
< }
< else if(Config::getSingleton()->keyExist(var_name_))
< {
< return Config::getSingleton()->get(var_name_);
< }
< else
< {
< const Result* result = (const Result*)DSENT::processQuery(var_name_ + "@0", false);
---
> } else if (config.count(var_name_) > 0) {
> return config.at(var_name_);
> } else {
> // Wish there was a way to not have to pass in a stream if we aren't
> // doing anything with it
> const Result* result = (const Result*)DSENT::processQuery(
> var_name_ + "@0", ms_model, false);
423d343
<