summaryrefslogtreecommitdiff
path: root/ext/dsent/DSENT.cc
diff options
context:
space:
mode:
Diffstat (limited to 'ext/dsent/DSENT.cc')
-rw-r--r--ext/dsent/DSENT.cc478
1 files changed, 199 insertions, 279 deletions
diff --git a/ext/dsent/DSENT.cc b/ext/dsent/DSENT.cc
index 576cbbebc..da9163a50 100644
--- a/ext/dsent/DSENT.cc
+++ b/ext/dsent/DSENT.cc
@@ -1,237 +1,209 @@
-#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.
+ */
#include <cstdlib>
#include <iostream>
-namespace DSENT
-{
- Model* DSENT::ms_model_ = NULL;
- bool DSENT::ms_is_verbose_ = false;
-
- void DSENT::run(int argc_, char** argv_)
- {
- // Initialize DSENT framework (setup log file, config file, ...)
- initialize(argc_, argv_);
-
- // Build the specified model in the config file
- buildModel();
-
- // Process the specified queries
- processQuery();
- // Process the specified evaluation
- processEvaluate();
-
- // 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'.");
+#include "DSENT.h"
+#include "model/std_cells/StdCellLib.h"
- 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'.");
+using namespace std;
- 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_)
+namespace DSENT
+{
+ static void performTimingOpt(const map<String, String> &params,
+ Model *ms_model)
{
- OptionParser* option_parser = new OptionParser();
+ // Get the frequency it is optimizing to
+ double freq = params.at("Frequency").toDouble();
- // Init the option parser and setup available options
- setRuntimeOptions(option_parser);
+ // Get all the starting net names
+ const vector<String>& start_net_names =
+ params.at("TimingOptimization->StartNetNames").split("[,]");
- // Parse the options
- option_parser->parseArguments(argc_, argv_);
+ ASSERT((start_net_names.size() > 0),
+ "[Error] Expecting net names in TimingOptimization->StartNetNames");
- // 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] == "*")
{
- ModelGen::printAvailableModels();
- exit(0);
- }
-
- // Init the log file
- Log::allocate(option_parser->get("LogFilename"));
-
- // Init the config file
- Config::allocate(option_parser->get("ConfigFilename"));
- Config* dsent_config = Config::getSingleton();
-
- // Overwrite the existing options
- dsent_config->readString(option_parser->get("OverwriteString"));
-
- // Overwrite the technology file
- dsent_config->constructTechModel(option_parser->get("OverwriteTechString"));
+ // Optimize from all input ports
+ ElectricalModel* electrical_model = (ElectricalModel*)ms_model;
- ms_is_verbose_ = option_parser->get("IsVerbose").toBool();
+ ElectricalTimingOptimizer timing_optimizer(
+ "Optimizer", electrical_model->getTechModel());
+ timing_optimizer.setModel(electrical_model);
+ timing_optimizer.construct();
+ timing_optimizer.update();
- // 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"));
- }
+ ElectricalTimingTree timing_tree(
+ timing_optimizer.getInstanceName(), &timing_optimizer);
- // 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)
{
- 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);
}
- cout << *dsent_config;
- if(ms_is_verbose_)
+ // Loop the second times
+ for(it = it_begin; it != it_end; ++it)
{
- cout << "==============" << endl;
+ const String& net_name = it->first;
+ Log::printLine("Optimizing net: " + net_name);
}
}
+ 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);
- 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);
+ }
+ }
}
- void DSENT::buildModel()
+ static void reportTiming(const map<String, String> &params, Model *ms_model)
{
- Config* dsent_config = Config::getSingleton();
+ // Get all the starting net names
+ const vector<String>& start_net_names =
+ params.at("ReportTiming->StartNetNames").split("[,]");
+
+ 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)
+ {
// Create the model specified
- 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);
// Construct the model
// Read all parameters the model requires
- const vector<String>* parameter_names = ms_model_->getParameterNames();
+ const vector<String>* parameter_names = ms_model->getParameterNames();
// For all parameters, grab values from the config file
- 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)
{
const String& parameter_name = *it;
// If it exists in the config file, set the parameter
- if(dsent_config->keyExist(parameter_name))
+ if(params.count(parameter_name) > 0)
{
- ms_model_->setParameter(parameter_name, dsent_config->get(parameter_name));
+ ms_model->setParameter(parameter_name,
+ params.at(parameter_name));
}
}
- ms_model_->construct();
+
+ ms_model->construct();
// Update the model
// Read all properties the model requires
- const vector<String>* property_names = ms_model_->getPropertyNames();
+ const vector<String>* property_names = ms_model->getPropertyNames();
// For all properties, grab values from the config file
- 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)
{
const String& property_name = *it;
// If it exists in the config file, set the parameter
- if(dsent_config->keyExist(property_name))
+ if(params.count(property_name) > 0)
{
- ms_model_->setProperty(property_name, dsent_config->get(property_name));
+ ms_model->setProperty(property_name,
+ params.at(property_name));
}
}
- ms_model_->update();
+ ms_model->update();
// Evaluate the model
// Perform timing optimization if needed
- if(dsent_config->getIfKeyExist("IsPerformTimingOptimization", "false").toBool())
+ if(params.find("IsPerformTimingOptimization") != params.end() &&
+ params.at("IsPerformTimingOptimization").toBool())
{
- performTimingOpt();
+ performTimingOpt(params, ms_model);
}
- ms_model_->evaluate();
+ ms_model->evaluate();
// Report timing if needed
- if(dsent_config->getIfKeyExist("IsReportTiming", "false").toBool())
+ if(params.count("IsReportTiming") > 0 &&
+ params.at("IsReportTiming") != "false")
{
- reportTiming();
+ reportTiming(params, ms_model);
}
- return;
- }
-
- void DSENT::processQuery()
- {
- 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;
+ return ms_model;
}
- const void* DSENT::processQuery(const String& query_str_, bool is_print_)
+ static const void* processQuery(const String& query_str_,
+ Model *ms_model, bool is_print_)
{
vector<String> type_split = query_str_.splitByString(Model::TYPE_SEPARATOR);
ASSERT((type_split.size() == 2), "[Error] Invalid query format: " + query_str_);
String query_type = type_split[0];
- vector<String> detail_split = type_split[1].splitByString(Model::DETAIL_SEPARATOR);
+ vector<String> detail_split =
+ type_split[1].splitByString(Model::DETAIL_SEPARATOR);
+
ASSERT((detail_split.size() == 2), "[Error] Invalid query format: " + query_str_);
String query_detail = detail_split[1];
- 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_);
+
String query_hier = subfield_split[0];
String query_subfield = "";
+
if(subfield_split.size() == 2)
{
query_subfield = subfield_split[1];
}
- 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);
if(query_type == "Property")
{
const PropertyMap* property = (const PropertyMap*)query_result;
@@ -268,156 +240,104 @@ namespace DSENT
return query_result;
}
- void DSENT::finalize()
+ void processQuery(const vector<String> &queries,
+ Model *ms_model, vector<String> &outputs)
{
- // Release the constructed model
- delete ms_model_;
- ms_model_ = NULL;
-
- // Release the config file
- Config::release();
-
- // Release the log file
- Log::release();
+ for(unsigned int i = 0; i < queries.size(); ++i)
+ {
+ const String& curr_query = queries[i];
+ processQuery(curr_query, ms_model, true);
- return;
+ }
}
- void DSENT::performTimingOpt()
+ static TechModel* constructTechModel(const map<String, String>& params)
{
- Config* dsent_config = Config::getSingleton();
+ // Allocate static TechModel instance
+ const String& electrical_tech_model_filename =
+ params.at("ElectricalTechModelFilename");
- // 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);
- // Get all the starting net names
- const vector<String>& start_net_names = dsent_config->get("TimingOptimization->StartNetNames").split("[,]");
-
- ASSERT((start_net_names.size() > 0), "[Error] Expecting net names in TimingOptimization->StartNetNames");
-
- 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();
+ if (params.count("PhotonicTechModelFilename") != 0) {
+ const String& photonic_tech_model_filename =
+ params.at("PhotonicTechModelFilename");
+ tech_model->readFile(photonic_tech_model_filename);
+ }
- ElectricalTimingTree timing_tree(timing_optimizer.getInstanceName(), &timing_optimizer);
+ // Allocate static StdCellLib instance
+ StdCellLib* std_cell_lib = new StdCellLib(tech_model);
- 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;
}
- void DSENT::reportTiming()
+ Model *initialize(const char *config_file_name, map<String, String> &config)
{
- Config* dsent_config = Config::getSingleton();
+ // Init the log file
+ Log::allocate("/tmp/dsent.log");
- // 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);
- ElectricalModel* electrical_model = (ElectricalModel*)ms_model_;
- ElectricalTimingTree timing_tree(electrical_model->getInstanceName(), electrical_model);
+ // Overwrite the technology file
+ TechModel *tech_model = constructTechModel(config);
- 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);
}
- void DSENT::processEvaluate()
+ void finalize(map<String, String> &config, Model *ms_model)
{
- Config* dsent_config = Config::getSingleton();
-
- // Return if EvaluatString is empty or not exists
- if(!dsent_config->keyExist("EvaluateString")) return;
+ // Delete the model
+ delete ms_model;
- String eval_str = dsent_config->get("EvaluateString");
+ // Discard all the (key, value) pairs.
+ config.clear();
- if(eval_str == "") return;
+ // Release the log file
+ Log::release();
+ }
- 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;
}
- //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;
- if(ms_is_verbose_)
- {
- cout << "==============" << endl;
+ if (eval_str == "") {
+ return;
}
- return;
- return;
+
+ DSENTCalculator calc;
+ calc.evaluateString(eval_str, params, ms_model, outputs);
}
- DSENT::DSENTCalculator::DSENTCalculator()
- {}
+ DSENTCalculator::DSENTCalculator() {}
- DSENT::DSENTCalculator::~DSENTCalculator()
- {}
+ DSENTCalculator::~DSENTCalculator() {}
- 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
{
- if(m_var_.keyExist(var_name_))
- {
+ if (m_var_.keyExist(var_name_)) {
return m_var_.get(var_name_);
- }
- 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);
return result->calculateSum();
}
}
} // namespace DSENT
-