Allow the fixwhite stuff to work when committing from a subdir
[gem5.git] / src / sim / param.cc
1 /*
2 * Copyright (c) 2002-2005 The Regents of The University of Michigan
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met: redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer;
9 * redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution;
12 * neither the name of the copyright holders nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 *
28 * Authors: Steve Reinhardt
29 */
30
31 #include <algorithm>
32 #include <cassert>
33 #include <list>
34 #include <string>
35 #include <vector>
36
37 #include "base/inifile.hh"
38 #include "base/misc.hh"
39 #include "base/range.hh"
40 #include "base/str.hh"
41 #include "base/trace.hh"
42 #include "sim/param.hh"
43 #include "sim/sim_object.hh"
44
45 using namespace std;
46
47
48 ////////////////////////////////////////////////////////////////////////
49 //
50 // BaseParam member definitions
51 //
52 ////////////////////////////////////////////////////////////////////////
53
54 void
55 BaseParam::die(const string &err) const
56 {
57 context->printErrorProlog(cerr);
58 cerr << " parameter '" << name << "': "
59 << err << endl;
60 abort();
61 }
62
63
64 ////////////////////////////////////////////////////////////////////////
65 //
66 // Param<T> and VectorParam<T> member definitions
67 //
68 // We implement parsing & displaying values for various parameter
69 // types T using a set of overloaded functions:
70 //
71 // - parseParam(string s, T &value) parses s into value
72 // - showParam(ostream &os, T &value) displays value on os
73 //
74 // By making these independent functions, we can reuse the same code
75 // for type T in both Param<T> and VectorParam<T>.
76 //
77 // For enum types, the parseParam function requires additional
78 // arguments, in which case we must specialize the Param<T>::parse and
79 // VectorParam<T>::parse calls as well.
80 //
81 // Type-specific instances come first, followed by more generic
82 // templated versions and their instantiations.
83 //
84 ////////////////////////////////////////////////////////////////////////
85
86 //
87 // The base implementations use to_number for parsing and '<<' for
88 // displaying, suitable for integer types.
89 //
90 template <class T>
91 bool
92 parseParam(const string &s, T &value)
93 {
94 return to_number(s, value);
95 }
96
97 template <class T>
98 void
99 showParam(ostream &os, T const &value)
100 {
101 os << value;
102 }
103
104 //
105 // Template specializations:
106 // - char (8-bit integer)
107 // - floating-point types
108 // - bool
109 // - string
110 //
111
112 // Treat 8-bit ints (chars) as ints on output, not as chars
113 template <>
114 void
115 showParam(ostream &os, const char &value)
116 {
117 os << (int)value;
118 }
119
120
121 template <>
122 void
123 showParam(ostream &os, const unsigned char &value)
124 {
125 os << (unsigned int)value;
126 }
127
128
129 // Use sscanf() for FP types as to_number() only handles integers
130 template <>
131 bool
132 parseParam(const string &s, float &value)
133 {
134 return (sscanf(s.c_str(), "%f", &value) == 1);
135 }
136
137 template <>
138 bool
139 parseParam(const string &s, double &value)
140 {
141 return (sscanf(s.c_str(), "%lf", &value) == 1);
142 }
143
144 // Be flexible about what we take for bool
145 template <>
146 bool
147 parseParam(const string &s, bool &value)
148 {
149 const string &ls = to_lower(s);
150
151 if (ls == "true" || ls == "t" || ls == "yes" || ls == "y" || ls == "1") {
152 value = true;
153 return true;
154 }
155
156 if (ls == "false" || ls == "f" || ls == "no" || ls == "n" || ls == "0") {
157 value = false;
158 return true;
159 }
160
161 return false;
162 }
163
164 // Display bools as strings
165 template <>
166 void
167 showParam(ostream &os, const bool &value)
168 {
169 os << (value ? "true" : "false");
170 }
171
172
173 // String requires no processing to speak of
174 template <>
175 bool
176 parseParam(const string &s, string &value)
177 {
178 value = s;
179 return true;
180 }
181
182 template <>
183 bool
184 parseParam(const string &s, Range<uint32_t> &value)
185 {
186 value = s;
187 return value.valid();
188 }
189
190 template <>
191 bool
192 parseParam(const string &s, Range<uint64_t> &value)
193 {
194 value = s;
195 return value.valid();
196 }
197
198 //
199 // End of parseParam/showParam definitions. Now we move on to
200 // incorporate them into the Param/VectorParam parse() and showValue()
201 // methods.
202 //
203
204 // These definitions for Param<T>::parse and VectorParam<T>::parse
205 // work for any type for which parseParam() takes only two arguments
206 // (i.e., all the fundamental types like int, bool, etc.), thanks to
207 // overloading.
208 template <class T>
209 void
210 Param<T>::parse(const string &s)
211 {
212 if (parseParam(s, value)) {
213 wasSet = true;
214 }
215 else {
216 string err("could not parse \"");
217
218 err += s;
219 err += "\"";
220
221 die(err);
222 }
223 }
224
225 template <class T>
226 void
227 VectorParam<T>::parse(const string &s)
228 {
229 if (s.empty()) {
230 wasSet = true;
231 return;
232 }
233
234 vector<string> tokens;
235
236 tokenize(tokens, s, ' ');
237
238 value.resize(tokens.size());
239
240 for (int i = 0; i < tokens.size(); i++) {
241 // need to parse into local variable to handle vector<bool>,
242 // for which operator[] returns a special reference class
243 // that's not the same as 'bool&', (since it's a packed
244 // vector)
245 T scalar_value;
246 if (!parseParam(tokens[i], scalar_value)) {
247 string err("could not parse \"");
248
249 err += s;
250 err += "\"";
251
252 die(err);
253 }
254
255 // assign parsed value to vector
256 value[i] = scalar_value;
257 }
258
259 wasSet = true;
260 }
261
262 // These definitions for Param<T>::showValue() and
263 // VectorParam<T>::showValue() work for any type where showParam()
264 // takes only two arguments (i.e., everything but the SimpleEnum and
265 // MappedEnum classes).
266 template <class T>
267 void
268 Param<T>::showValue(ostream &os) const
269 {
270 showParam(os, value);
271 }
272
273 template <class T>
274 void
275 VectorParam<T>::showValue(ostream &os) const
276 {
277 for (int i = 0; i < value.size(); i++) {
278 if (i != 0) {
279 os << " ";
280 }
281 showParam(os, value[i]);
282 }
283 }
284
285
286 #ifdef INSURE_BUILD
287 #define INSTANTIATE_PARAM_TEMPLATES(type, typestr) \
288 void Param<type>::showType(ostream &os) const { os << typestr; } \
289 void VectorParam<type>::showType(ostream &os) const { \
290 os << "vector of " << typestr; \
291 } \
292 template Param<type>; \
293 template VectorParam<type>;
294
295 #else
296 // instantiate all four methods (parse/show, scalar/vector) for basic
297 // types that can use the above templates
298 #define INSTANTIATE_PARAM_TEMPLATES(type, typestr) \
299 template bool parseParam<type>(const string &s, type &value); \
300 template void showParam<type>(ostream &os, type const &value); \
301 template void Param<type>::parse(const string &); \
302 template void VectorParam<type>::parse(const string &); \
303 template void Param<type>::showValue(ostream &) const; \
304 template void VectorParam<type>::showValue(ostream &) const; \
305 template <> void Param<type>::showType(ostream &os) const { os << typestr; } \
306 template <> void VectorParam<type>::showType(ostream &os) const { \
307 os << "vector of " << typestr; \
308 }
309 #endif
310
311 INSTANTIATE_PARAM_TEMPLATES(unsigned long long, "ull")
312 INSTANTIATE_PARAM_TEMPLATES(signed long long, "sll")
313 INSTANTIATE_PARAM_TEMPLATES(unsigned long, "uns long")
314 INSTANTIATE_PARAM_TEMPLATES(signed long, "long")
315 INSTANTIATE_PARAM_TEMPLATES(unsigned int, "uns")
316 INSTANTIATE_PARAM_TEMPLATES(signed int, "int")
317 INSTANTIATE_PARAM_TEMPLATES(unsigned short, "uns short")
318 INSTANTIATE_PARAM_TEMPLATES(signed short, "short")
319 INSTANTIATE_PARAM_TEMPLATES(unsigned char, "uns char")
320 INSTANTIATE_PARAM_TEMPLATES(signed char, "char")
321
322 INSTANTIATE_PARAM_TEMPLATES(float, "float")
323 INSTANTIATE_PARAM_TEMPLATES(double, "double")
324
325 INSTANTIATE_PARAM_TEMPLATES(bool, "bool")
326 INSTANTIATE_PARAM_TEMPLATES(string, "string")
327
328 INSTANTIATE_PARAM_TEMPLATES(Range<uint64_t>, "uint64 range")
329 INSTANTIATE_PARAM_TEMPLATES(Range<uint32_t>, "uint32 range")
330
331 #undef INSTANTIATE_PARAM_TEMPLATES
332
333 //
334 // SimpleEnumParam & MappedEnumParam must specialize their parse(),
335 // showValue(), and showType() methods.
336 //
337
338 //
339 // SimpleEnumParam & SimpleEnumVectorParam
340 //
341 bool
342 parseEnumParam(const char *const *map, const int num_values,
343 const string &s, int &value)
344 {
345 for (int i = 0; i < num_values; ++i) {
346 if (s == map[i]) {
347 value = i;
348 return true;
349 }
350 }
351
352 return false;
353 }
354
355 void
356 showEnumParam(ostream &os,
357 const char *const *map, const int num_values,
358 int value)
359 {
360 assert(0 <= value && value < num_values);
361 os << map[value];
362 }
363
364 void
365 showEnumType(ostream &os,
366 const char *const *map, const int num_values)
367 {
368 os << "{" << map[0];
369 for (int i = 1; i < num_values; ++i)
370 os << "," << map[i];
371
372 os << "}";
373 }
374
375
376 //
377 // MappedEnumParam & MappedEnumVectorParam
378 //
379 bool
380 parseEnumParam(const EnumParamMap *map, const int num_values,
381 const string &s, int &value)
382 {
383 for (int i = 0; i < num_values; ++i) {
384 if (s == map[i].name) {
385 value = map[i].value;
386 return true;
387 }
388 }
389
390 return false;
391 }
392
393 void
394 showEnumParam(ostream &os,
395 const EnumParamMap *map, const int num_values,
396 int value)
397 {
398 for (int i = 0; i < num_values; ++i) {
399 if (value == map[i].value) {
400 os << map[i].name;
401 return;
402 }
403 }
404
405 // if we can't find a reverse mapping just print the int value
406 os << value;
407 }
408
409 void
410 showEnumType(ostream &os,
411 const EnumParamMap *map, const int num_values)
412 {
413 os << "{" << map[0].name;
414 for (int i = 1; i < num_values; ++i)
415 os << "," << map[i].name;
416
417 os << "}";
418 }
419
420
421 template <class Map>
422 void
423 EnumParam<Map>::parse(const string &s)
424 {
425 if (parseEnumParam(map, num_values, s, value)) {
426 wasSet = true;
427 } else {
428 string err("no match for enum string \"");
429
430 err += s;
431 err += "\"";
432
433 die(err);
434 }
435 }
436
437 template <class Map>
438 void
439 EnumVectorParam<Map>::parse(const string &s)
440 {
441 vector<string> tokens;
442
443 if (s.empty()) {
444 wasSet = true;
445 return;
446 }
447
448 tokenize(tokens, s, ' ');
449
450 value.resize(tokens.size());
451
452 for (int i = 0; i < tokens.size(); i++) {
453 if (!parseEnumParam(map, num_values, tokens[i], value[i])) {
454 string err("no match for enum string \"");
455
456 err += s;
457 err += "\"";
458
459 die(err);
460 }
461 }
462
463 wasSet = true;
464 }
465
466 template <class Map>
467 void
468 EnumParam<Map>::showValue(ostream &os) const
469 {
470 showEnumParam(os, map, num_values, value);
471 }
472
473 template <class Map>
474 void
475 EnumVectorParam<Map>::showValue(ostream &os) const
476 {
477 for (int i = 0; i < value.size(); i++) {
478 if (i != 0) {
479 os << " ";
480 }
481 showEnumParam(os, map, num_values, value[i]);
482 }
483 }
484
485 template <class Map>
486 void
487 EnumParam<Map>::showType(ostream &os) const
488 {
489 showEnumType(os, map, num_values);
490 }
491
492 template <class Map>
493 void
494 EnumVectorParam<Map>::showType(ostream &os) const
495 {
496 os << "vector of";
497 showEnumType(os, map, num_values);
498 }
499
500 template class EnumParam<const char *>;
501 template class EnumVectorParam<const char *>;
502
503 template class EnumParam<EnumParamMap>;
504 template class EnumVectorParam<EnumParamMap>;
505
506 ////////////////////////////////////////////////////////////////////////
507 //
508 // SimObjectBaseParam methods
509 //
510 ////////////////////////////////////////////////////////////////////////
511
512 bool
513 parseSimObjectParam(ParamContext *context, const string &s, SimObject *&value)
514 {
515 SimObject *obj;
516
517 if (to_lower(s) == "null") {
518 // explicitly set to null by user; assume that's OK
519 obj = NULL;
520 }
521 else {
522 // defined in main.cc
523 extern SimObject *resolveSimObject(const string &);
524 obj = resolveSimObject(s);
525
526 if (obj == NULL)
527 return false;
528 }
529
530 value = obj;
531 return true;
532 }
533
534
535 void
536 SimObjectBaseParam::showValue(ostream &os, SimObject *value) const
537 {
538 os << (value ? value->name() : "null");
539 }
540
541 void
542 SimObjectBaseParam::parse(const string &s, SimObject *&value)
543 {
544 if (parseSimObjectParam(context, s, value)) {
545 wasSet = true;
546 }
547 else {
548 string err("could not resolve object name \"");
549
550 err += s;
551 err += "\"";
552
553 die(err);
554 }
555 }
556
557 void
558 SimObjectBaseParam::parse(const string &s, vector<SimObject *>&value)
559 {
560 vector<string> tokens;
561
562 tokenize(tokens, s, ' ');
563
564 value.resize(tokens.size());
565
566 for (int i = 0; i < tokens.size(); i++) {
567 if (!parseSimObjectParam(context, tokens[i], value[i])) {
568 string err("could not resolve object name \"");
569
570 err += s;
571 err += "\"";
572
573 die(err);
574 }
575 }
576
577 wasSet = true;
578 }
579
580 ////////////////////////////////////////////////////////////////////////
581 //
582 // ParamContext member definitions
583 //
584 ////////////////////////////////////////////////////////////////////////
585
586 ParamContext::ParamContext(const string &_iniSection)
587 : iniFilePtr(NULL), // initialized on call to parseParams()
588 iniSection(_iniSection), paramList(NULL)
589 {
590 }
591
592
593 void
594 ParamContext::addParam(BaseParam *param)
595 {
596 getParamList()->push_back(param);
597 }
598
599
600 void
601 ParamContext::parseParams(IniFile &iniFile)
602 {
603 iniFilePtr = &iniFile; // set object member
604
605 ParamList::iterator i;
606
607 for (i = getParamList()->begin(); i != getParamList()->end(); ++i) {
608 string string_value;
609
610 if (iniFile.find(iniSection, (*i)->name, string_value))
611 (*i)->parse(string_value);
612 }
613 }
614
615
616 // Check parameter values for validity & consistency. Default
617 // implementation is no-op; derive subclass & override to add
618 // actual functionality here.
619 void
620 ParamContext::checkParams()
621 {
622 // nada
623 }
624
625
626 // Clean up context-related objects at end of execution. Default
627 // implementation is no-op; derive subclass & override to add actual
628 // functionality here.
629 void
630 ParamContext::cleanup()
631 {
632 // nada
633 }
634
635
636 void
637 ParamContext::describeParams(ostream &os)
638 {
639 ParamList::iterator i;
640
641 for (i = getParamList()->begin(); i != getParamList()->end(); ++i) {
642 BaseParam *p = *i;
643
644 os << p->name << " (";
645 p->showType(os);
646 os << "): " << p->description << "\n";
647 }
648 }
649
650
651
652 void
653 ParamContext::showParams(ostream &os)
654 {
655 ParamList::iterator i;
656
657 for (i = getParamList()->begin(); i != getParamList()->end(); ++i) {
658 BaseParam *p = *i;
659
660 if (p->isValid()) {
661 os << p->name << "=";
662 p->showValue(os);
663 os << endl;
664 }
665 else {
666 os << "// "<< p->name << " not specified" << endl;
667 }
668 }
669 }
670
671
672 void
673 ParamContext::printErrorProlog(ostream &os)
674 {
675 os << "Parameter error in section [" << iniSection << "]: " << endl;
676 }
677
678 void
679 parseTime(const std::vector<int> &time, struct tm *tm)
680 {
681 memset(tm, 0, sizeof(struct tm));
682
683 // UNIX is years since 1900
684 tm->tm_year = time[0] - 1900;
685
686 // Python starts at 1, UNIX starts at 0
687 tm->tm_mon = time[1] - 1;
688 tm->tm_mday = time[2];
689 tm->tm_hour = time[3];
690 tm->tm_min = time[4];
691 tm->tm_sec = time[5];
692
693 // Python has 0 as Monday, UNIX is 0 as sunday
694 tm->tm_wday = time[6] + 1;
695 if (tm->tm_wday > 6)
696 tm->tm_wday -= 7;
697
698 // Python starts at 1, Unix starts at 0
699 tm->tm_yday = time[7] - 1;
700 }