Deleted Added
sdiff udiff text old ( 10447:a465576671d4 ) new ( 10448:bc1a3b7ab5ef )
full compact
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 }

--- 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
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