DSENT.cc revision 10447
1#include "DSENT.h" 2 3#include <cstdlib> 4#include <iostream> 5 6namespace DSENT 7{ 8 Model* DSENT::ms_model_ = NULL; 9 bool DSENT::ms_is_verbose_ = false; 10 11 void DSENT::run(int argc_, char** argv_) 12 { 13 // Initialize DSENT framework (setup log file, config file, ...) 14 initialize(argc_, argv_); 15 16 // Build the specified model in the config file 17 buildModel(); 18 19 // Process the specified queries 20 processQuery(); 21 // Process the specified evaluation 22 processEvaluate(); 23 24 // Finalize DSENT framework (close log file, ...) 25 finalize(); 26 return; 27 } 28 29 void DSENT::setRuntimeOptions(OptionParser* option_parser_) 30 { 31 option_parser_->addOption("-cfg", "ConfigFilename", true, "filename", false, "", 32 "Specify the config filename."); 33 34 option_parser_->addOption("-available_models", "IsListModels", false, "", true, "false", 35 "List available DSENT models."); 36 37 option_parser_->addOption("-log", "LogFilename", true, "filename", true, "./dsent.log", 38 "Specify the log filename."); 39 40 option_parser_->addOption("-overwrite", "OverwriteString", true, "options", true, "", 41 "Overwrite dynamically the options set in the config file. Options are separated by a comma (;)."); 42 43 option_parser_->addOption("-overwrite_tech", "OverwriteTechString", true, "options", true, "", 44 "Overwrite dynamically the options set in the technology file. Options are separated by a comma (;)."); 45 46 option_parser_->addOption("-print_config", "IsPrintConfig", false, "", true, "false", 47 "Print the config used at DSENT runtime."); 48 49 option_parser_->addOption("-query", "QueryString", true, "query string", true, "", 50 "Specify the list of items to query. This command is the same as owerwriting the 'QueryString'."); 51 52 option_parser_->addOption("-eval", "EvaluateString", true, "evaluate string", true, "", 53 "Specify the list of statements to evaluate. This command is the same as owerwriting the 'EvaluateString'."); 54 55 option_parser_->addOption("-verbose", "IsVerbose", false, "", true, "false", 56 "Enable verbose mode which prints out more detailed messages."); 57 return; 58 } 59 60 void DSENT::initialize(int argc_, char** argv_) 61 { 62 OptionParser* option_parser = new OptionParser(); 63 64 // Init the option parser and setup available options 65 setRuntimeOptions(option_parser); 66 67 // Parse the options 68 option_parser->parseArguments(argc_, argv_); 69 70 // If -available_models is specified, print out a list of available 71 // models and exit DSENT. 72 if(option_parser->get("IsListModels").toBool()) 73 { 74 ModelGen::printAvailableModels(); 75 exit(0); 76 } 77 78 // Init the log file 79 Log::allocate(option_parser->get("LogFilename")); 80 81 // Init the config file 82 Config::allocate(option_parser->get("ConfigFilename")); 83 Config* dsent_config = Config::getSingleton(); 84 85 // Overwrite the existing options 86 dsent_config->readString(option_parser->get("OverwriteString")); 87 88 // Overwrite the technology file 89 dsent_config->constructTechModel(option_parser->get("OverwriteTechString")); 90 91 ms_is_verbose_ = option_parser->get("IsVerbose").toBool(); 92 93 // Overwrite the query string if it is specified from command line 94 if(option_parser->get("QueryString").size() != 0) 95 { 96 dsent_config->set("QueryString", option_parser->get("QueryString")); 97 } 98 // Overwrite the evaluation string if it is specified from command line 99 if(option_parser->get("EvaluateString").size() != 0) 100 { 101 dsent_config->set("EvaluateString", option_parser->get("EvaluateString")); 102 } 103 104 // Print the config used for this run 105 if(option_parser->get("IsPrintConfig").toBool()) 106 { 107 if(ms_is_verbose_) 108 { 109 cout << "Configuration:" << endl; 110 cout << "==============" << endl; 111 } 112 cout << *dsent_config; 113 114 if(ms_is_verbose_) 115 { 116 cout << "==============" << endl; 117 } 118 } 119 120 delete option_parser; 121 return; 122 } 123 124 void DSENT::buildModel() 125 { 126 Config* dsent_config = Config::getSingleton(); 127 128 // Create the model specified 129 const String& model_name = dsent_config->get("ModelName"); 130 ms_model_ = ModelGen::createModel(model_name, model_name, dsent_config->getTechModel()); 131 132 // Construct the model 133 // Read all parameters the model requires 134 const vector<String>* parameter_names = ms_model_->getParameterNames(); 135 // For all parameters, grab values from the config file 136 for(vector<String>::const_iterator it = parameter_names->begin(); it != parameter_names->end(); ++it) 137 { 138 const String& parameter_name = *it; 139 // If it exists in the config file, set the parameter 140 if(dsent_config->keyExist(parameter_name)) 141 { 142 ms_model_->setParameter(parameter_name, dsent_config->get(parameter_name)); 143 } 144 } 145 ms_model_->construct(); 146 147 // Update the model 148 // Read all properties the model requires 149 const vector<String>* property_names = ms_model_->getPropertyNames(); 150 // For all properties, grab values from the config file 151 for(vector<String>::const_iterator it = property_names->begin(); it != property_names->end(); ++it) 152 { 153 const String& property_name = *it; 154 // If it exists in the config file, set the parameter 155 if(dsent_config->keyExist(property_name)) 156 { 157 ms_model_->setProperty(property_name, dsent_config->get(property_name)); 158 } 159 } 160 ms_model_->update(); 161 162 // Evaluate the model 163 // Perform timing optimization if needed 164 if(dsent_config->getIfKeyExist("IsPerformTimingOptimization", "false").toBool()) 165 { 166 performTimingOpt(); 167 } 168 ms_model_->evaluate(); 169 170 // Report timing if needed 171 if(dsent_config->getIfKeyExist("IsReportTiming", "false").toBool()) 172 { 173 reportTiming(); 174 } 175 176 return; 177 } 178 179 void DSENT::processQuery() 180 { 181 Config* dsent_config = Config::getSingleton(); 182 vector<String> queries = dsent_config->get("QueryString").split(" ;\r\n"); 183 184 if(ms_is_verbose_) 185 { 186 cout << "Query results:" << endl; 187 cout << "==============" << endl; 188 } 189 190 for(unsigned int i = 0; i < queries.size(); ++i) 191 { 192 const String& curr_query = queries[i]; 193 194 if(ms_is_verbose_) 195 { 196 String str = "Process query: '" + curr_query + "'"; 197 cout << str << endl; 198 cout << String(str.size(), '-') << endl; 199 } 200 201 processQuery(curr_query, true); 202 203 if(ms_is_verbose_) 204 { 205 cout << endl; 206 } 207 } 208 if(ms_is_verbose_) 209 { 210 cout << "==============" << endl; 211 } 212 return; 213 } 214 215 const void* DSENT::processQuery(const String& query_str_, bool is_print_) 216 { 217 vector<String> type_split = query_str_.splitByString(Model::TYPE_SEPARATOR); 218 ASSERT((type_split.size() == 2), "[Error] Invalid query format: " + query_str_); 219 String query_type = type_split[0]; 220 221 vector<String> detail_split = type_split[1].splitByString(Model::DETAIL_SEPARATOR); 222 ASSERT((detail_split.size() == 2), "[Error] Invalid query format: " + query_str_); 223 String query_detail = detail_split[1]; 224 225 vector<String> subfield_split = detail_split[0].splitByString(Model::SUBFIELD_SEPARATOR); 226 ASSERT(((subfield_split.size() == 2) || (subfield_split.size() == 1)), "[Error] Invalid query format: " + query_str_); 227 String query_hier = subfield_split[0]; 228 String query_subfield = ""; 229 if(subfield_split.size() == 2) 230 { 231 query_subfield = subfield_split[1]; 232 } 233 234 const void* query_result = ms_model_->parseQuery(query_type, query_hier, query_subfield); 235 if(query_type == "Property") 236 { 237 const PropertyMap* property = (const PropertyMap*)query_result; 238 if(is_print_) 239 { 240 cout << *property; 241 } 242 } 243 else if(query_type == "Parameter") 244 { 245 const ParameterMap* parameter = (const ParameterMap*)query_result; 246 if(is_print_) 247 { 248 cout << *parameter; 249 } 250 } 251 else if(query_type.contain("Hier")) 252 { 253 const Model* model = (const Model*)query_result; 254 if(is_print_) 255 { 256 model->printHierarchy(query_type, query_subfield, "", query_detail, cout); 257 } 258 } 259 else 260 { 261 const Result* result = (const Result*)query_result; 262 if(is_print_) 263 { 264 result->print(query_type + Model::TYPE_SEPARATOR + query_hier + 265 Model::SUBFIELD_SEPARATOR + query_subfield, query_detail, cout); 266 } 267 } 268 return query_result; 269 } 270 271 void DSENT::finalize() 272 { 273 // Release the constructed model 274 delete ms_model_; 275 ms_model_ = NULL; 276 277 // Release the config file 278 Config::release(); 279 280 // Release the log file 281 Log::release(); 282 283 return; 284 } 285 286 void DSENT::performTimingOpt() 287 { 288 Config* dsent_config = Config::getSingleton(); 289 290 // Get the frequency it is optimizing to 291 double freq = dsent_config->get("Frequency").toDouble(); 292 293 // Get all the starting net names 294 const vector<String>& start_net_names = dsent_config->get("TimingOptimization->StartNetNames").split("[,]"); 295 296 ASSERT((start_net_names.size() > 0), "[Error] Expecting net names in TimingOptimization->StartNetNames"); 297 298 if(start_net_names[0] == "*") 299 { 300 // Optimize from all input ports 301 ElectricalModel* electrical_model = (ElectricalModel*)ms_model_; 302 303 ElectricalTimingOptimizer timing_optimizer("Optimizer", electrical_model->getTechModel()); 304 timing_optimizer.setModel(electrical_model); 305 timing_optimizer.construct(); 306 timing_optimizer.update(); 307 308 ElectricalTimingTree timing_tree(timing_optimizer.getInstanceName(), &timing_optimizer); 309 310 const Map<PortInfo*>* input_ports = timing_optimizer.getInputs(); 311 Map<PortInfo*>::ConstIterator it_begin = input_ports->begin(); 312 Map<PortInfo*>::ConstIterator it_end = input_ports->end(); 313 Map<PortInfo*>::ConstIterator it; 314 for(it = it_begin; it != it_end; ++it) 315 { 316 const String& net_name = it->first; 317 Log::printLine("Optimizing net: " + net_name); 318 timing_tree.performTimingOpt(timing_optimizer.getNet(net_name, makeNetIndex(0)), 1.0 / freq); 319 //timing_tree.performTimingOpt(electrical_model->getNet(net_name, makeNetIndex(0)), 1.0 / freq); 320 } 321 // Loop the second times 322 for(it = it_begin; it != it_end; ++it) 323 { 324 const String& net_name = it->first; 325 Log::printLine("Optimizing net: " + net_name); 326 //timing_tree.performTimingOpt(timing_optimizer.getNet(net_name, makeNetIndex(0)), 1.0 / freq); 327 } 328 } 329 else 330 { 331 // TODO : parse the net name so that we could do hierarchical optimization 332 // Currently we can only optimize timing at the top level 333 ElectricalModel* electrical_model = (ElectricalModel*)ms_model_; 334 ElectricalTimingTree timing_tree(electrical_model->getInstanceName(), electrical_model); 335 for(unsigned int i = 0; i < start_net_names.size(); ++i) 336 { 337 const String& net_name = start_net_names[i]; 338 timing_tree.performTimingOpt(electrical_model->getNet(net_name), 1.0 / freq); 339 } 340 } 341 return; 342 } 343 344 void DSENT::reportTiming() 345 { 346 Config* dsent_config = Config::getSingleton(); 347 348 // Get all the starting net names 349 const vector<String>& start_net_names = dsent_config->get("ReportTiming->StartNetNames").split("[,]"); 350 351 ElectricalModel* electrical_model = (ElectricalModel*)ms_model_; 352 ElectricalTimingTree timing_tree(electrical_model->getInstanceName(), electrical_model); 353 354 cout << "Report timing:" << endl; 355 cout << "==============" << endl; 356 for(unsigned int i = 0; i < start_net_names.size(); ++i) 357 { 358 const String& net_name = start_net_names[i]; 359 double timing = timing_tree.performCritPathExtract(electrical_model->getNet(net_name)); 360 cout << net_name << " = " << timing << endl; 361 } 362 cout << "==============" << endl; 363 return; 364 } 365 366 void DSENT::processEvaluate() 367 { 368 Config* dsent_config = Config::getSingleton(); 369 370 // Return if EvaluatString is empty or not exists 371 if(!dsent_config->keyExist("EvaluateString")) return; 372 373 String eval_str = dsent_config->get("EvaluateString"); 374 375 if(eval_str == "") return; 376 377 if(ms_is_verbose_) 378 { 379 cout << "Eval results:" << endl; 380 cout << "==============" << endl; 381 } 382 383 //if(ms_is_verbose_) 384 //{ 385 // String str = "Process evaluation: '" + eval_str + "'"; 386 // cout << str << endl; 387 // cout << String(str.size(), '-') << endl; 388 //} 389 DSENTCalculator calc; 390 calc.evaluateString(eval_str); 391 392 if(ms_is_verbose_) 393 { 394 cout << "==============" << endl; 395 } 396 return; 397 return; 398 } 399 400 DSENT::DSENTCalculator::DSENTCalculator() 401 {} 402 403 DSENT::DSENTCalculator::~DSENTCalculator() 404 {} 405 406 double DSENT::DSENTCalculator::getEnvVar(const String& var_name_) const 407 { 408 if(m_var_.keyExist(var_name_)) 409 { 410 return m_var_.get(var_name_); 411 } 412 else if(Config::getSingleton()->keyExist(var_name_)) 413 { 414 return Config::getSingleton()->get(var_name_); 415 } 416 else 417 { 418 const Result* result = (const Result*)DSENT::processQuery(var_name_ + "@0", false); 419 return result->calculateSum(); 420 } 421 } 422} // namespace DSENT 423 424