110448Snilay@cs.wisc.edu/* Copyright (c) 2012 Massachusetts Institute of Technology 210448Snilay@cs.wisc.edu * 310448Snilay@cs.wisc.edu * Permission is hereby granted, free of charge, to any person obtaining a copy 410448Snilay@cs.wisc.edu * of this software and associated documentation files (the "Software"), to deal 510448Snilay@cs.wisc.edu * in the Software without restriction, including without limitation the rights 610448Snilay@cs.wisc.edu * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 710448Snilay@cs.wisc.edu * copies of the Software, and to permit persons to whom the Software is 810448Snilay@cs.wisc.edu * furnished to do so, subject to the following conditions: 910448Snilay@cs.wisc.edu * 1010448Snilay@cs.wisc.edu * The above copyright notice and this permission notice shall be included in 1110448Snilay@cs.wisc.edu * all copies or substantial portions of the Software. 1210448Snilay@cs.wisc.edu * 1310448Snilay@cs.wisc.edu * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 1410448Snilay@cs.wisc.edu * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 1510448Snilay@cs.wisc.edu * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 1610448Snilay@cs.wisc.edu * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 1710448Snilay@cs.wisc.edu * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 1810448Snilay@cs.wisc.edu * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 1910448Snilay@cs.wisc.edu * THE SOFTWARE. 2010448Snilay@cs.wisc.edu */ 2110447Snilay@cs.wisc.edu 2210447Snilay@cs.wisc.edu#include <cstdlib> 2310447Snilay@cs.wisc.edu#include <iostream> 2410447Snilay@cs.wisc.edu 2510448Snilay@cs.wisc.edu#include "DSENT.h" 2610448Snilay@cs.wisc.edu#include "model/std_cells/StdCellLib.h" 2710448Snilay@cs.wisc.edu 2810448Snilay@cs.wisc.eduusing namespace std; 2910448Snilay@cs.wisc.edu 3010447Snilay@cs.wisc.edunamespace DSENT 3110447Snilay@cs.wisc.edu{ 3210448Snilay@cs.wisc.edu static void performTimingOpt(const map<String, String> ¶ms, 3310448Snilay@cs.wisc.edu Model *ms_model) 3410448Snilay@cs.wisc.edu { 3510448Snilay@cs.wisc.edu // Get the frequency it is optimizing to 3610448Snilay@cs.wisc.edu double freq = params.at("Frequency").toDouble(); 3710447Snilay@cs.wisc.edu 3810448Snilay@cs.wisc.edu // Get all the starting net names 3910448Snilay@cs.wisc.edu const vector<String>& start_net_names = 4010448Snilay@cs.wisc.edu params.at("TimingOptimization->StartNetNames").split("[,]"); 4110447Snilay@cs.wisc.edu 4210448Snilay@cs.wisc.edu ASSERT((start_net_names.size() > 0), 4310448Snilay@cs.wisc.edu "[Error] Expecting net names in TimingOptimization->StartNetNames"); 4410447Snilay@cs.wisc.edu 4510448Snilay@cs.wisc.edu if(start_net_names[0] == "*") 4610448Snilay@cs.wisc.edu { 4710448Snilay@cs.wisc.edu // Optimize from all input ports 4810448Snilay@cs.wisc.edu ElectricalModel* electrical_model = (ElectricalModel*)ms_model; 4910447Snilay@cs.wisc.edu 5010448Snilay@cs.wisc.edu ElectricalTimingOptimizer timing_optimizer( 5110448Snilay@cs.wisc.edu "Optimizer", electrical_model->getTechModel()); 5210448Snilay@cs.wisc.edu timing_optimizer.setModel(electrical_model); 5310448Snilay@cs.wisc.edu timing_optimizer.construct(); 5410448Snilay@cs.wisc.edu timing_optimizer.update(); 5510448Snilay@cs.wisc.edu 5610448Snilay@cs.wisc.edu ElectricalTimingTree timing_tree( 5710448Snilay@cs.wisc.edu timing_optimizer.getInstanceName(), &timing_optimizer); 5810448Snilay@cs.wisc.edu 5910448Snilay@cs.wisc.edu const Map<PortInfo*>* input_ports = timing_optimizer.getInputs(); 6010448Snilay@cs.wisc.edu Map<PortInfo*>::ConstIterator it_begin = input_ports->begin(); 6110448Snilay@cs.wisc.edu Map<PortInfo*>::ConstIterator it_end = input_ports->end(); 6210448Snilay@cs.wisc.edu Map<PortInfo*>::ConstIterator it; 6310448Snilay@cs.wisc.edu for(it = it_begin; it != it_end; ++it) 6410448Snilay@cs.wisc.edu { 6510448Snilay@cs.wisc.edu const String& net_name = it->first; 6610448Snilay@cs.wisc.edu Log::printLine("Optimizing net: " + net_name); 6710448Snilay@cs.wisc.edu timing_tree.performTimingOpt( 6810448Snilay@cs.wisc.edu timing_optimizer.getNet(net_name, makeNetIndex(0)), 1.0 / freq); 6910448Snilay@cs.wisc.edu } 7010448Snilay@cs.wisc.edu 7110448Snilay@cs.wisc.edu // Loop the second times 7210448Snilay@cs.wisc.edu for(it = it_begin; it != it_end; ++it) 7310448Snilay@cs.wisc.edu { 7410448Snilay@cs.wisc.edu const String& net_name = it->first; 7510448Snilay@cs.wisc.edu Log::printLine("Optimizing net: " + net_name); 7610448Snilay@cs.wisc.edu } 7710448Snilay@cs.wisc.edu } 7810448Snilay@cs.wisc.edu else 7910448Snilay@cs.wisc.edu { 8010448Snilay@cs.wisc.edu // TODO : parse the net name so that we could do hierarchical optimization 8110448Snilay@cs.wisc.edu // Currently we can only optimize timing at the top level 8210448Snilay@cs.wisc.edu ElectricalModel* electrical_model = (ElectricalModel*)ms_model; 8310448Snilay@cs.wisc.edu ElectricalTimingTree timing_tree( 8410448Snilay@cs.wisc.edu electrical_model->getInstanceName(), electrical_model); 8510448Snilay@cs.wisc.edu 8610448Snilay@cs.wisc.edu for(unsigned int i = 0; i < start_net_names.size(); ++i) 8710448Snilay@cs.wisc.edu { 8810448Snilay@cs.wisc.edu const String& net_name = start_net_names[i]; 8910448Snilay@cs.wisc.edu timing_tree.performTimingOpt( 9010448Snilay@cs.wisc.edu electrical_model->getNet(net_name), 1.0 / freq); 9110448Snilay@cs.wisc.edu } 9210448Snilay@cs.wisc.edu } 9310447Snilay@cs.wisc.edu } 9410447Snilay@cs.wisc.edu 9510448Snilay@cs.wisc.edu static void reportTiming(const map<String, String> ¶ms, Model *ms_model) 9610447Snilay@cs.wisc.edu { 9710448Snilay@cs.wisc.edu // Get all the starting net names 9810448Snilay@cs.wisc.edu const vector<String>& start_net_names = 9910448Snilay@cs.wisc.edu params.at("ReportTiming->StartNetNames").split("[,]"); 10010447Snilay@cs.wisc.edu 10110448Snilay@cs.wisc.edu ElectricalModel* electrical_model = (ElectricalModel*)ms_model; 10210448Snilay@cs.wisc.edu ElectricalTimingTree timing_tree( 10310448Snilay@cs.wisc.edu electrical_model->getInstanceName(), electrical_model); 10410447Snilay@cs.wisc.edu 10510448Snilay@cs.wisc.edu cout << "Report timing:" << endl; 10610448Snilay@cs.wisc.edu cout << "==============" << endl; 10710448Snilay@cs.wisc.edu for(unsigned int i = 0; i < start_net_names.size(); ++i) 10810448Snilay@cs.wisc.edu { 10910448Snilay@cs.wisc.edu const String& net_name = start_net_names[i]; 11010448Snilay@cs.wisc.edu double timing = timing_tree.performCritPathExtract(electrical_model->getNet(net_name)); 11110448Snilay@cs.wisc.edu cout << net_name << " = " << timing << endl; 11210448Snilay@cs.wisc.edu } 11310448Snilay@cs.wisc.edu cout << "==============" << endl; 11410447Snilay@cs.wisc.edu } 11510447Snilay@cs.wisc.edu 11610448Snilay@cs.wisc.edu static Model *buildModel(const map<String, String> ¶ms, 11710448Snilay@cs.wisc.edu TechModel *tech_model) 11810447Snilay@cs.wisc.edu { 11910448Snilay@cs.wisc.edu // Create the model specified 12010448Snilay@cs.wisc.edu const String& model_name = params.at("ModelName"); 12110448Snilay@cs.wisc.edu Model *ms_model = ModelGen::createModel(model_name, model_name, 12210448Snilay@cs.wisc.edu tech_model); 12310447Snilay@cs.wisc.edu 12410448Snilay@cs.wisc.edu // Construct the model 12510448Snilay@cs.wisc.edu // Read all parameters the model requires 12610448Snilay@cs.wisc.edu const vector<String>* parameter_names = ms_model->getParameterNames(); 12710448Snilay@cs.wisc.edu // For all parameters, grab values from the config file 12810448Snilay@cs.wisc.edu for(vector<String>::const_iterator it = parameter_names->begin(); 12910448Snilay@cs.wisc.edu it != parameter_names->end(); ++it) 13010447Snilay@cs.wisc.edu { 13110448Snilay@cs.wisc.edu const String& parameter_name = *it; 13210448Snilay@cs.wisc.edu // If it exists in the config file, set the parameter 13310448Snilay@cs.wisc.edu if(params.count(parameter_name) > 0) 13410447Snilay@cs.wisc.edu { 13510448Snilay@cs.wisc.edu ms_model->setParameter(parameter_name, 13610448Snilay@cs.wisc.edu params.at(parameter_name)); 13710447Snilay@cs.wisc.edu } 13810447Snilay@cs.wisc.edu } 13910447Snilay@cs.wisc.edu 14010448Snilay@cs.wisc.edu ms_model->construct(); 14110447Snilay@cs.wisc.edu 14210447Snilay@cs.wisc.edu // Update the model 14310447Snilay@cs.wisc.edu // Read all properties the model requires 14410448Snilay@cs.wisc.edu const vector<String>* property_names = ms_model->getPropertyNames(); 14510447Snilay@cs.wisc.edu // For all properties, grab values from the config file 14610448Snilay@cs.wisc.edu for(vector<String>::const_iterator it = property_names->begin(); 14710448Snilay@cs.wisc.edu it != property_names->end(); ++it) 14810447Snilay@cs.wisc.edu { 14910447Snilay@cs.wisc.edu const String& property_name = *it; 15010447Snilay@cs.wisc.edu // If it exists in the config file, set the parameter 15110448Snilay@cs.wisc.edu if(params.count(property_name) > 0) 15210447Snilay@cs.wisc.edu { 15310448Snilay@cs.wisc.edu ms_model->setProperty(property_name, 15410448Snilay@cs.wisc.edu params.at(property_name)); 15510447Snilay@cs.wisc.edu } 15610447Snilay@cs.wisc.edu } 15710448Snilay@cs.wisc.edu ms_model->update(); 15810447Snilay@cs.wisc.edu 15910447Snilay@cs.wisc.edu // Evaluate the model 16010447Snilay@cs.wisc.edu // Perform timing optimization if needed 16110448Snilay@cs.wisc.edu if(params.find("IsPerformTimingOptimization") != params.end() && 16210448Snilay@cs.wisc.edu params.at("IsPerformTimingOptimization").toBool()) 16310447Snilay@cs.wisc.edu { 16410448Snilay@cs.wisc.edu performTimingOpt(params, ms_model); 16510447Snilay@cs.wisc.edu } 16610448Snilay@cs.wisc.edu ms_model->evaluate(); 16710447Snilay@cs.wisc.edu 16810447Snilay@cs.wisc.edu // Report timing if needed 16910448Snilay@cs.wisc.edu if(params.count("IsReportTiming") > 0 && 17010448Snilay@cs.wisc.edu params.at("IsReportTiming") != "false") 17110447Snilay@cs.wisc.edu { 17210448Snilay@cs.wisc.edu reportTiming(params, ms_model); 17310447Snilay@cs.wisc.edu } 17410447Snilay@cs.wisc.edu 17510448Snilay@cs.wisc.edu return ms_model; 17610447Snilay@cs.wisc.edu } 17710447Snilay@cs.wisc.edu 17810448Snilay@cs.wisc.edu static const void* processQuery(const String& query_str_, 17910448Snilay@cs.wisc.edu Model *ms_model, bool is_print_) 18010447Snilay@cs.wisc.edu { 18110447Snilay@cs.wisc.edu vector<String> type_split = query_str_.splitByString(Model::TYPE_SEPARATOR); 18210447Snilay@cs.wisc.edu ASSERT((type_split.size() == 2), "[Error] Invalid query format: " + query_str_); 18310447Snilay@cs.wisc.edu String query_type = type_split[0]; 18410447Snilay@cs.wisc.edu 18510448Snilay@cs.wisc.edu vector<String> detail_split = 18610448Snilay@cs.wisc.edu type_split[1].splitByString(Model::DETAIL_SEPARATOR); 18710448Snilay@cs.wisc.edu 18810447Snilay@cs.wisc.edu ASSERT((detail_split.size() == 2), "[Error] Invalid query format: " + query_str_); 18910447Snilay@cs.wisc.edu String query_detail = detail_split[1]; 19010447Snilay@cs.wisc.edu 19110448Snilay@cs.wisc.edu vector<String> subfield_split = 19210448Snilay@cs.wisc.edu detail_split[0].splitByString(Model::SUBFIELD_SEPARATOR); 19310448Snilay@cs.wisc.edu 19410448Snilay@cs.wisc.edu ASSERT(((subfield_split.size() == 2) || (subfield_split.size() == 1)), 19510448Snilay@cs.wisc.edu "[Error] Invalid query format: " + query_str_); 19610448Snilay@cs.wisc.edu 19710447Snilay@cs.wisc.edu String query_hier = subfield_split[0]; 19810447Snilay@cs.wisc.edu String query_subfield = ""; 19910448Snilay@cs.wisc.edu 20010447Snilay@cs.wisc.edu if(subfield_split.size() == 2) 20110447Snilay@cs.wisc.edu { 20210447Snilay@cs.wisc.edu query_subfield = subfield_split[1]; 20310447Snilay@cs.wisc.edu } 20410447Snilay@cs.wisc.edu 20510448Snilay@cs.wisc.edu const void* query_result = ms_model->parseQuery(query_type, query_hier, 20610448Snilay@cs.wisc.edu query_subfield); 20710447Snilay@cs.wisc.edu if(query_type == "Property") 20810447Snilay@cs.wisc.edu { 20910447Snilay@cs.wisc.edu const PropertyMap* property = (const PropertyMap*)query_result; 21010447Snilay@cs.wisc.edu if(is_print_) 21110447Snilay@cs.wisc.edu { 21210447Snilay@cs.wisc.edu cout << *property; 21310447Snilay@cs.wisc.edu } 21410447Snilay@cs.wisc.edu } 21510447Snilay@cs.wisc.edu else if(query_type == "Parameter") 21610447Snilay@cs.wisc.edu { 21710447Snilay@cs.wisc.edu const ParameterMap* parameter = (const ParameterMap*)query_result; 21810447Snilay@cs.wisc.edu if(is_print_) 21910447Snilay@cs.wisc.edu { 22010447Snilay@cs.wisc.edu cout << *parameter; 22110447Snilay@cs.wisc.edu } 22210447Snilay@cs.wisc.edu } 22310447Snilay@cs.wisc.edu else if(query_type.contain("Hier")) 22410447Snilay@cs.wisc.edu { 22510447Snilay@cs.wisc.edu const Model* model = (const Model*)query_result; 22610447Snilay@cs.wisc.edu if(is_print_) 22710447Snilay@cs.wisc.edu { 22810447Snilay@cs.wisc.edu model->printHierarchy(query_type, query_subfield, "", query_detail, cout); 22910447Snilay@cs.wisc.edu } 23010447Snilay@cs.wisc.edu } 23110447Snilay@cs.wisc.edu else 23210447Snilay@cs.wisc.edu { 23310447Snilay@cs.wisc.edu const Result* result = (const Result*)query_result; 23410447Snilay@cs.wisc.edu if(is_print_) 23510447Snilay@cs.wisc.edu { 23610447Snilay@cs.wisc.edu result->print(query_type + Model::TYPE_SEPARATOR + query_hier + 23710447Snilay@cs.wisc.edu Model::SUBFIELD_SEPARATOR + query_subfield, query_detail, cout); 23810447Snilay@cs.wisc.edu } 23910447Snilay@cs.wisc.edu } 24010447Snilay@cs.wisc.edu return query_result; 24110447Snilay@cs.wisc.edu } 24210447Snilay@cs.wisc.edu 24310448Snilay@cs.wisc.edu void processQuery(const vector<String> &queries, 24410448Snilay@cs.wisc.edu Model *ms_model, vector<String> &outputs) 24510447Snilay@cs.wisc.edu { 24610448Snilay@cs.wisc.edu for(unsigned int i = 0; i < queries.size(); ++i) 24710448Snilay@cs.wisc.edu { 24810448Snilay@cs.wisc.edu const String& curr_query = queries[i]; 24910448Snilay@cs.wisc.edu processQuery(curr_query, ms_model, true); 25010447Snilay@cs.wisc.edu 25110448Snilay@cs.wisc.edu } 25210448Snilay@cs.wisc.edu } 25310448Snilay@cs.wisc.edu 25410448Snilay@cs.wisc.edu static TechModel* constructTechModel(const map<String, String>& params) 25510448Snilay@cs.wisc.edu { 25610448Snilay@cs.wisc.edu // Allocate static TechModel instance 25710448Snilay@cs.wisc.edu const String& electrical_tech_model_filename = 25810448Snilay@cs.wisc.edu params.at("ElectricalTechModelFilename"); 25910448Snilay@cs.wisc.edu 26010448Snilay@cs.wisc.edu TechModel* tech_model = new TechModel(); 26110448Snilay@cs.wisc.edu tech_model->readFile(electrical_tech_model_filename); 26210448Snilay@cs.wisc.edu 26310448Snilay@cs.wisc.edu if (params.count("PhotonicTechModelFilename") != 0) { 26410448Snilay@cs.wisc.edu const String& photonic_tech_model_filename = 26510448Snilay@cs.wisc.edu params.at("PhotonicTechModelFilename"); 26610448Snilay@cs.wisc.edu tech_model->readFile(photonic_tech_model_filename); 26710448Snilay@cs.wisc.edu } 26810448Snilay@cs.wisc.edu 26910448Snilay@cs.wisc.edu // Allocate static StdCellLib instance 27010448Snilay@cs.wisc.edu StdCellLib* std_cell_lib = new StdCellLib(tech_model); 27110448Snilay@cs.wisc.edu 27210448Snilay@cs.wisc.edu // Set the StdCellLib pointer in static TechModel instance 27310448Snilay@cs.wisc.edu tech_model->setStdCellLib(std_cell_lib); 27410448Snilay@cs.wisc.edu return tech_model; 27510448Snilay@cs.wisc.edu } 27610448Snilay@cs.wisc.edu 27710448Snilay@cs.wisc.edu Model *initialize(const char *config_file_name, map<String, String> &config) 27810448Snilay@cs.wisc.edu { 27910448Snilay@cs.wisc.edu // Init the log file 28010448Snilay@cs.wisc.edu Log::allocate("/tmp/dsent.log"); 28110448Snilay@cs.wisc.edu 28210448Snilay@cs.wisc.edu // Init the config file 28310448Snilay@cs.wisc.edu LibUtil::readFile(config_file_name, config); 28410448Snilay@cs.wisc.edu 28510448Snilay@cs.wisc.edu // Overwrite the technology file 28610448Snilay@cs.wisc.edu TechModel *tech_model = constructTechModel(config); 28710448Snilay@cs.wisc.edu 28810448Snilay@cs.wisc.edu // Build the specified model in the config file 28910448Snilay@cs.wisc.edu return buildModel(config, tech_model); 29010448Snilay@cs.wisc.edu } 29110448Snilay@cs.wisc.edu 29210448Snilay@cs.wisc.edu void finalize(map<String, String> &config, Model *ms_model) 29310448Snilay@cs.wisc.edu { 29410448Snilay@cs.wisc.edu // Delete the model 29510448Snilay@cs.wisc.edu delete ms_model; 29610448Snilay@cs.wisc.edu 29710448Snilay@cs.wisc.edu // Discard all the (key, value) pairs. 29810448Snilay@cs.wisc.edu config.clear(); 29910447Snilay@cs.wisc.edu 30010447Snilay@cs.wisc.edu // Release the log file 30110447Snilay@cs.wisc.edu Log::release(); 30210447Snilay@cs.wisc.edu } 30310447Snilay@cs.wisc.edu 30410448Snilay@cs.wisc.edu void run(const map<String, String> ¶ms, Model *ms_model, 30510448Snilay@cs.wisc.edu map<string, double> &outputs) 30610447Snilay@cs.wisc.edu { 30710448Snilay@cs.wisc.edu // Process the specified queries 30810448Snilay@cs.wisc.edu const auto &it = params.find("EvaluateString"); 30910448Snilay@cs.wisc.edu if(it == params.end()) { 31010448Snilay@cs.wisc.edu return; 31110448Snilay@cs.wisc.edu } 31210447Snilay@cs.wisc.edu 31310448Snilay@cs.wisc.edu String eval_str = it->second; 31410447Snilay@cs.wisc.edu 31510448Snilay@cs.wisc.edu if (eval_str == "") { 31610448Snilay@cs.wisc.edu return; 31710448Snilay@cs.wisc.edu } 31810447Snilay@cs.wisc.edu 31910448Snilay@cs.wisc.edu DSENTCalculator calc; 32010448Snilay@cs.wisc.edu calc.evaluateString(eval_str, params, ms_model, outputs); 32110447Snilay@cs.wisc.edu } 32210447Snilay@cs.wisc.edu 32310448Snilay@cs.wisc.edu DSENTCalculator::DSENTCalculator() {} 32410448Snilay@cs.wisc.edu 32510448Snilay@cs.wisc.edu DSENTCalculator::~DSENTCalculator() {} 32610448Snilay@cs.wisc.edu 32710448Snilay@cs.wisc.edu double DSENTCalculator::getEnvVar(const String& var_name_, 32810448Snilay@cs.wisc.edu const map<String, String> &config, 32910448Snilay@cs.wisc.edu Model *ms_model) const 33010447Snilay@cs.wisc.edu { 33110448Snilay@cs.wisc.edu if (m_var_.keyExist(var_name_)) { 33210447Snilay@cs.wisc.edu return m_var_.get(var_name_); 33310448Snilay@cs.wisc.edu } else if (config.count(var_name_) > 0) { 33410448Snilay@cs.wisc.edu return config.at(var_name_); 33510448Snilay@cs.wisc.edu } else { 33610448Snilay@cs.wisc.edu // Wish there was a way to not have to pass in a stream if we aren't 33710448Snilay@cs.wisc.edu // doing anything with it 33810448Snilay@cs.wisc.edu const Result* result = (const Result*)DSENT::processQuery( 33910448Snilay@cs.wisc.edu var_name_ + "@0", ms_model, false); 34010447Snilay@cs.wisc.edu return result->calculateSum(); 34110447Snilay@cs.wisc.edu } 34210447Snilay@cs.wisc.edu } 34310447Snilay@cs.wisc.edu} // namespace DSENT 344