DSENT.cc (10447:a465576671d4) | DSENT.cc (10448:bc1a3b7ab5ef) |
---|---|
1#include "DSENT.h" | 1/* Copyright (c) 2012 Massachusetts Institute of Technology 2 * 3 * Permission is hereby granted, free of charge, to any person obtaining a copy 4 * of this software and associated documentation files (the "Software"), to deal 5 * in the Software without restriction, including without limitation the rights 6 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 * copies of the Software, and to permit persons to whom the Software is 8 * furnished to do so, subject to the following conditions: 9 * 10 * The above copyright notice and this permission notice shall be included in 11 * all copies or substantial portions of the Software. 12 * 13 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 * THE SOFTWARE. 20 */ |
2 3#include <cstdlib> 4#include <iostream> 5 | 21 22#include <cstdlib> 23#include <iostream> 24 |
25#include "DSENT.h" 26#include "model/std_cells/StdCellLib.h" 27 28using namespace std; 29 |
|
6namespace DSENT 7{ | 30namespace DSENT 31{ |
8 Model* DSENT::ms_model_ = NULL; 9 bool DSENT::ms_is_verbose_ = false; 10 11 void DSENT::run(int argc_, char** argv_) | 32 static void performTimingOpt(const map<String, String> ¶ms, 33 Model *ms_model) |
12 { | 34 { |
13 // Initialize DSENT framework (setup log file, config file, ...) 14 initialize(argc_, argv_); | 35 // Get the frequency it is optimizing to 36 double freq = params.at("Frequency").toDouble(); |
15 | 37 |
16 // Build the specified model in the config file 17 buildModel(); | 38 // Get all the starting net names 39 const vector<String>& start_net_names = 40 params.at("TimingOptimization->StartNetNames").split("[,]"); |
18 | 41 |
19 // Process the specified queries 20 processQuery(); 21 // Process the specified evaluation 22 processEvaluate(); | 42 ASSERT((start_net_names.size() > 0), 43 "[Error] Expecting net names in TimingOptimization->StartNetNames"); |
23 | 44 |
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()) | 45 if(start_net_names[0] == "*") |
73 { | 46 { |
74 ModelGen::printAvailableModels(); 75 exit(0); 76 } | 47 // Optimize from all input ports 48 ElectricalModel* electrical_model = (ElectricalModel*)ms_model; |
77 | 49 |
78 // Init the log file 79 Log::allocate(option_parser->get("LogFilename")); | 50 ElectricalTimingOptimizer timing_optimizer( 51 "Optimizer", electrical_model->getTechModel()); 52 timing_optimizer.setModel(electrical_model); 53 timing_optimizer.construct(); 54 timing_optimizer.update(); |
80 | 55 |
81 // Init the config file 82 Config::allocate(option_parser->get("ConfigFilename")); 83 Config* dsent_config = Config::getSingleton(); | 56 ElectricalTimingTree timing_tree( 57 timing_optimizer.getInstanceName(), &timing_optimizer); |
84 | 58 |
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_) | 59 const Map<PortInfo*>* input_ports = timing_optimizer.getInputs(); 60 Map<PortInfo*>::ConstIterator it_begin = input_ports->begin(); 61 Map<PortInfo*>::ConstIterator it_end = input_ports->end(); 62 Map<PortInfo*>::ConstIterator it; 63 for(it = it_begin; it != it_end; ++it) |
108 { | 64 { |
109 cout << "Configuration:" << endl; 110 cout << "==============" << endl; | 65 const String& net_name = it->first; 66 Log::printLine("Optimizing net: " + net_name); 67 timing_tree.performTimingOpt( 68 timing_optimizer.getNet(net_name, makeNetIndex(0)), 1.0 / freq); |
111 } | 69 } |
112 cout << *dsent_config; | |
113 | 70 |
114 if(ms_is_verbose_) | 71 // Loop the second times 72 for(it = it_begin; it != it_end; ++it) |
115 { | 73 { |
116 cout << "==============" << endl; | 74 const String& net_name = it->first; 75 Log::printLine("Optimizing net: " + net_name); |
117 } 118 } | 76 } 77 } |
78 else 79 { 80 // TODO : parse the net name so that we could do hierarchical optimization 81 // Currently we can only optimize timing at the top level 82 ElectricalModel* electrical_model = (ElectricalModel*)ms_model; 83 ElectricalTimingTree timing_tree( 84 electrical_model->getInstanceName(), electrical_model); |
|
119 | 85 |
120 delete option_parser; 121 return; | 86 for(unsigned int i = 0; i < start_net_names.size(); ++i) 87 { 88 const String& net_name = start_net_names[i]; 89 timing_tree.performTimingOpt( 90 electrical_model->getNet(net_name), 1.0 / freq); 91 } 92 } |
122 } 123 | 93 } 94 |
124 void DSENT::buildModel() | 95 static void reportTiming(const map<String, String> ¶ms, Model *ms_model) |
125 { | 96 { |
126 Config* dsent_config = Config::getSingleton(); | 97 // Get all the starting net names 98 const vector<String>& start_net_names = 99 params.at("ReportTiming->StartNetNames").split("[,]"); |
127 | 100 |
101 ElectricalModel* electrical_model = (ElectricalModel*)ms_model; 102 ElectricalTimingTree timing_tree( 103 electrical_model->getInstanceName(), electrical_model); 104 105 cout << "Report timing:" << endl; 106 cout << "==============" << endl; 107 for(unsigned int i = 0; i < start_net_names.size(); ++i) 108 { 109 const String& net_name = start_net_names[i]; 110 double timing = timing_tree.performCritPathExtract(electrical_model->getNet(net_name)); 111 cout << net_name << " = " << timing << endl; 112 } 113 cout << "==============" << endl; 114 } 115 116 static Model *buildModel(const map<String, String> ¶ms, 117 TechModel *tech_model) 118 { |
|
128 // Create the model specified | 119 // 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()); | 120 const String& model_name = params.at("ModelName"); 121 Model *ms_model = ModelGen::createModel(model_name, model_name, 122 tech_model); |
131 132 // Construct the model 133 // Read all parameters the model requires | 123 124 // Construct the model 125 // Read all parameters the model requires |
134 const vector<String>* parameter_names = ms_model_->getParameterNames(); | 126 const vector |
135 // For all parameters, grab values from the config file | 127 // For all parameters, grab values from the config file |
136 for(vector<String>::const_iterator it = parameter_names->begin(); it != parameter_names->end(); ++it) | 128 for(vector 129 it != parameter_names->end(); ++it) |
137 { 138 const String& parameter_name = *it; 139 // If it exists in the config file, set the parameter | 130 { 131 const String& parameter_name = *it; 132 // If it exists in the config file, set the parameter |
140 if(dsent_config->keyExist(parameter_name)) | 133 if(params.count(parameter_name) > 0) |
141 { | 134 { |
142 ms_model_->setParameter(parameter_name, dsent_config->get(parameter_name)); | 135 ms_model->setParameter(parameter_name, 136 params.at(parameter_name)); |
143 } 144 } | 137 } 138 } |
145 ms_model_->construct(); | |
146 | 139 |
140 ms_model->construct(); 141 |
|
147 // Update the model 148 // Read all properties the model requires | 142 // Update the model 143 // Read all properties the model requires |
149 const vector<String>* property_names = ms_model_->getPropertyNames(); | 144 const vector |
150 // For all properties, grab values from the config file | 145 // For all properties, grab values from the config file |
151 for(vector<String>::const_iterator it = property_names->begin(); it != property_names->end(); ++it) | 146 for(vector 147 it != property_names->end(); ++it) |
152 { 153 const String& property_name = *it; 154 // If it exists in the config file, set the parameter | 148 { 149 const String& property_name = *it; 150 // If it exists in the config file, set the parameter |
155 if(dsent_config->keyExist(property_name)) | 151 if(params.count(property_name) > 0) |
156 { | 152 { |
157 ms_model_->setProperty(property_name, dsent_config->get(property_name)); | 153 ms_model->setProperty(property_name, 154 params.at(property_name)); |
158 } 159 } | 155 } 156 } |
160 ms_model_->update(); | 157 ms_model->update(); |
161 162 // Evaluate the model 163 // Perform timing optimization if needed | 158 159 // Evaluate the model 160 // Perform timing optimization if needed |
164 if(dsent_config->getIfKeyExist("IsPerformTimingOptimization", "false").toBool()) | 161 if(params.find("IsPerformTimingOptimization") != params.end() && 162 params.at("IsPerformTimingOptimization").toBool()) |
165 { | 163 { |
166 performTimingOpt(); | 164 performTimingOpt(params, ms_model); |
167 } | 165 } |
168 ms_model_->evaluate(); | 166 ms_model->evaluate(); |
169 170 // Report timing if needed | 167 168 // Report timing if needed |
171 if(dsent_config->getIfKeyExist("IsReportTiming", "false").toBool()) | 169 if(params.count("IsReportTiming") > 0 && 170 params.at("IsReportTiming") != "false") |
172 { | 171 { |
173 reportTiming(); | 172 reportTiming(params, ms_model); |
174 } 175 | 173 } 174 |
176 return; | 175 return ms_model; |
177 } 178 | 176 } 177 |
179 void DSENT::processQuery() | 178 static const void* processQuery(const String& query_str_, 179 Model *ms_model, bool is_print_) |
180 { | 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 | 181 vector<String> type_split = query_str_.splitByString(Model::TYPE_SEPARATOR); 182 ASSERT((type_split.size() == 2), "[Error] Invalid query format: " + query_str_); 183 String query_type = type_split[0]; 184 |
221 vector<String> detail_split = type_split[1].splitByString(Model::DETAIL_SEPARATOR); | 185 vector 186 type_split[1].splitByString(Model::DETAIL_SEPARATOR); 187 |
222 ASSERT((detail_split.size() == 2), "[Error] Invalid query format: " + query_str_); 223 String query_detail = detail_split[1]; 224 | 188 ASSERT((detail_split.size() == 2), "[Error] Invalid query format: " + query_str_); 189 String query_detail = detail_split[1]; 190 |
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_); | 191 vector 192 detail_split[0].splitByString(Model::SUBFIELD_SEPARATOR); 193 194 ASSERT(((subfield_split.size() == 2) || (subfield_split.size() == 1)), 195 "[Error] Invalid query format: " + query_str_); 196 |
227 String query_hier = subfield_split[0]; 228 String query_subfield = ""; | 197 String query_hier = subfield_split[0]; 198 String query_subfield = ""; |
199 |
|
229 if(subfield_split.size() == 2) 230 { 231 query_subfield = subfield_split[1]; 232 } 233 | 200 if(subfield_split.size() == 2) 201 { 202 query_subfield = subfield_split[1]; 203 } 204 |
234 const void* query_result = ms_model_->parseQuery(query_type, query_hier, query_subfield); | 205 const void* query_result = ms_model->parseQuery(query_type, query_hier, 206 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 } --- 20 unchanged lines hidden (view full) --- 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 | 207 if(query_type == "Property") 208 { 209 const PropertyMap* property = (const PropertyMap*)query_result; 210 if(is_print_) 211 { 212 cout << *property; 213 } 214 } --- 20 unchanged lines hidden (view full) --- 235 { 236 result->print(query_type + Model::TYPE_SEPARATOR + query_hier + 237 Model::SUBFIELD_SEPARATOR + query_subfield, query_detail, cout); 238 } 239 } 240 return query_result; 241 } 242 |
271 void DSENT::finalize() | 243 void processQuery(const vector<String> &queries, 244 Model *ms_model, vector<String> &outputs) |
272 { | 245 { |
273 // Release the constructed model 274 delete ms_model_; 275 ms_model_ = NULL; | 246 for(unsigned int i = 0; i < queries.size(); ++i) 247 { 248 const String& curr_query = queries[i]; 249 processQuery(curr_query, ms_model, true); |
276 | 250 |
277 // Release the config file 278 Config::release(); 279 280 // Release the log file 281 Log::release(); 282 283 return; | 251 } |
284 } 285 | 252 } 253 |
286 void DSENT::performTimingOpt() | 254 static TechModel* constructTechModel(const map<String, String>& params) |
287 { | 255 { |
288 Config* dsent_config = Config::getSingleton(); | 256 // Allocate static TechModel instance 257 const String& electrical_tech_model_filename = 258 params.at("ElectricalTechModelFilename"); |
289 | 259 |
290 // Get the frequency it is optimizing to 291 double freq = dsent_config->get("Frequency").toDouble(); | 260 TechModel* tech_model = new TechModel(); 261 tech_model->readFile(electrical_tech_model_filename); |
292 | 262 |
293 // Get all the starting net names 294 const vector<String>& start_net_names = dsent_config->get("TimingOptimization->StartNetNames").split("[,]"); | 263 if (params.count("PhotonicTechModelFilename") != 0) { 264 const String& photonic_tech_model_filename = 265 params.at("PhotonicTechModelFilename"); 266 tech_model->readFile(photonic_tech_model_filename); 267 } |
295 | 268 |
296 ASSERT((start_net_names.size() > 0), "[Error] Expecting net names in TimingOptimization->StartNetNames"); | 269 // Allocate static StdCellLib instance 270 StdCellLib* std_cell_lib = new StdCellLib(tech_model); |
297 | 271 |
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; | 272 // Set the StdCellLib pointer in static TechModel instance 273 tech_model->setStdCellLib(std_cell_lib); 274 return tech_model; |
342 } 343 | 275 } 276 |
344 void DSENT::reportTiming() | 277 Model *initialize(const char *config_file_name, map<String, String> &config) |
345 { | 278 { |
346 Config* dsent_config = Config::getSingleton(); | 279 // Init the log file 280 Log::allocate("/tmp/dsent.log"); |
347 | 281 |
348 // Get all the starting net names 349 const vector<String>& start_net_names = dsent_config->get("ReportTiming->StartNetNames").split("[,]"); | 282 // Init the config file 283 LibUtil::readFile(config_file_name, config); |
350 | 284 |
351 ElectricalModel* electrical_model = (ElectricalModel*)ms_model_; 352 ElectricalTimingTree timing_tree(electrical_model->getInstanceName(), electrical_model); | 285 // Overwrite the technology file 286 TechModel *tech_model = constructTechModel(config); |
353 | 287 |
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; | 288 // Build the specified model in the config file 289 return buildModel(config, tech_model); |
364 } 365 | 290 } 291 |
366 void DSENT::processEvaluate() | 292 void finalize(map<String, String> &config, Model *ms_model) |
367 { | 293 { |
368 Config* dsent_config = Config::getSingleton(); | 294 // Delete the model 295 delete ms_model; |
369 | 296 |
370 // Return if EvaluatString is empty or not exists 371 if(!dsent_config->keyExist("EvaluateString")) return; | 297 // Discard all the (key, value) pairs. 298 config.clear(); |
372 | 299 |
373 String eval_str = dsent_config->get("EvaluateString"); | 300 // Release the log file 301 Log::release(); 302 } |
374 | 303 |
375 if(eval_str == "") return; 376 377 if(ms_is_verbose_) 378 { 379 cout << "Eval results:" << endl; 380 cout << "==============" << endl; | 304 void run(const map<String, String> ¶ms, Model *ms_model, 305 map<string, double> &outputs) 306 { 307 // Process the specified queries 308 const auto &it = params.find("EvaluateString"); 309 if(it == params.end()) { 310 return; |
381 } 382 | 311 } 312 |
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); | 313 String eval_str = it->second; |
391 | 314 |
392 if(ms_is_verbose_) 393 { 394 cout << "==============" << endl; | 315 if (eval_str == "") { 316 return; |
395 } | 317 } |
396 return; 397 return; | 318 319 DSENTCalculator calc; 320 calc.evaluateString(eval_str, params, ms_model, outputs); |
398 } 399 | 321 } 322 |
400 DSENT::DSENTCalculator::DSENTCalculator() 401 {} | 323 DSENTCalculator::DSENTCalculator() {} |
402 | 324 |
403 DSENT::DSENTCalculator::~DSENTCalculator() 404 {} | 325 DSENTCalculator::~DSENTCalculator() {} |
405 | 326 |
406 double DSENT::DSENTCalculator::getEnvVar(const String& var_name_) const | 327 double DSENTCalculator::getEnvVar(const String& var_name_, 328 const map<String, String> &config, 329 Model *ms_model) const |
407 { | 330 { |
408 if(m_var_.keyExist(var_name_)) 409 { | 331 if (m_var_.keyExist(var_name_)) { |
410 return m_var_.get(var_name_); | 332 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); | 333 } else if (config.count(var_name_) > 0) { 334 return config.at(var_name_); 335 } else { 336 // Wish there was a way to not have to pass in a stream if we aren't 337 // doing anything with it 338 const Result* result = (const Result*)DSENT::processQuery( 339 var_name_ + "@0", ms_model, false); |
419 return result->calculateSum(); 420 } 421 } 422} // namespace DSENT | 340 return result->calculateSum(); 341 } 342 } 343} // namespace DSENT |
423 | |