Added support for exclusive state, defined the MESI and MOESI protocols
[gem5.git] / sim / param.cc
1 /*
2 * Copyright (c) 2002-2004 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
29 #include <algorithm>
30 #include <list>
31 #include <string>
32 #include <vector>
33 #include <stdio.h> // for sscanf()
34
35 #include <assert.h>
36
37 #include "sim/param.hh"
38 #include "sim/sim_object.hh"
39 #include "base/inifile.hh"
40 #include "sim/configfile.hh"
41 #include "sim/config_node.hh"
42 #include "base/misc.hh"
43 #include "base/str.hh"
44 #include "base/trace.hh"
45
46 using namespace std;
47
48
49 ////////////////////////////////////////////////////////////////////////
50 //
51 // BaseParam member definitions
52 //
53 ////////////////////////////////////////////////////////////////////////
54
55 void
56 BaseParam::die(const string &err) const
57 {
58 context->printErrorProlog(cerr);
59 cerr << " parameter '" << name << "': "
60 << err << endl;
61 abort();
62 }
63
64
65 ////////////////////////////////////////////////////////////////////////
66 //
67 // Param<T> and VectorParam<T> member definitions
68 //
69 // We implement parsing & displaying values for various parameter
70 // types T using a set of overloaded functions:
71 //
72 // - parseParam(string s, T &value) parses s into value
73 // - showParam(ostream &os, T &value) displays value on os
74 //
75 // By making these independent functions, we can reuse the same code
76 // for type T in both Param<T> and VectorParam<T>.
77 //
78 // For enum types, the parseParam function requires additional
79 // arguments, in which case we must specialize the Param<T>::parse and
80 // VectorParam<T>::parse calls as well.
81 //
82 // Type-specific instances come first, followed by more generic
83 // templated versions and their instantiations.
84 //
85 ////////////////////////////////////////////////////////////////////////
86
87 //
88 // The base implementations use to_number for parsing and '<<' for
89 // displaying, suitable for integer types.
90 //
91 template <class T>
92 bool
93 parseParam(const string &s, T &value)
94 {
95 return to_number(s, value);
96 }
97
98 template <class T>
99 void
100 showParam(ostream &os, T const &value)
101 {
102 os << value;
103 }
104
105 //
106 // Template specializations:
107 // - char (8-bit integer)
108 // - floating-point types
109 // - bool
110 // - string
111 //
112
113 // Treat 8-bit ints (chars) as ints on output, not as chars
114 template <>
115 void
116 showParam(ostream &os, const char &value)
117 {
118 os << (int)value;
119 }
120
121
122 template <>
123 void
124 showParam(ostream &os, const unsigned char &value)
125 {
126 os << (unsigned int)value;
127 }
128
129
130 // Use sscanf() for FP types as to_number() only handles integers
131 template <>
132 bool
133 parseParam(const string &s, float &value)
134 {
135 return (sscanf(s.c_str(), "%f", &value) == 1);
136 }
137
138 template <>
139 bool
140 parseParam(const string &s, double &value)
141 {
142 return (sscanf(s.c_str(), "%lf", &value) == 1);
143 }
144
145 // Be flexible about what we take for bool
146 template <>
147 bool
148 parseParam(const string &s, bool &value)
149 {
150 const string &ls = to_lower(s);
151
152 if (ls == "true" || ls == "t" || ls == "yes" || ls == "y" || ls == "1") {
153 value = true;
154 return true;
155 }
156
157 if (ls == "false" || ls == "f" || ls == "no" || ls == "n" || ls == "0") {
158 value = false;
159 return true;
160 }
161
162 return false;
163 }
164
165 // Display bools as strings
166 template <>
167 void
168 showParam(ostream &os, const bool &value)
169 {
170 os << (value ? "true" : "false");
171 }
172
173
174 // String requires no processing to speak of
175 template <>
176 bool
177 parseParam(const string &s, string &value)
178 {
179 value = s;
180 return true;
181 }
182
183 //
184 // End of parseParam/showParam definitions. Now we move on to
185 // incorporate them into the Param/VectorParam parse() and showValue()
186 // methods.
187 //
188
189 // These definitions for Param<T>::parse and VectorParam<T>::parse
190 // work for any type for which parseParam() takes only two arguments
191 // (i.e., all the fundamental types like int, bool, etc.), thanks to
192 // overloading.
193 template <class T>
194 void
195 Param<T>::parse(const string &s)
196 {
197 if (parseParam(s, value)) {
198 wasSet = true;
199 }
200 else {
201 string err("could not parse \"");
202
203 err += s;
204 err += "\"";
205
206 die(err);
207 }
208 }
209
210 template <class T>
211 void
212 VectorParam<T>::parse(const string &s)
213 {
214 if (s.empty()) {
215 wasSet = true;
216 return;
217 }
218
219 vector<string> tokens;
220
221 tokenize(tokens, s, ' ');
222
223 value.resize(tokens.size());
224
225 for (int i = 0; i < tokens.size(); i++) {
226 // need to parse into local variable to handle vector<bool>,
227 // for which operator[] returns a special reference class
228 // that's not the same as 'bool&', (since it's a packed
229 // vector)
230 T scalar_value;
231 if (!parseParam(tokens[i], scalar_value)) {
232 string err("could not parse \"");
233
234 err += s;
235 err += "\"";
236
237 die(err);
238 }
239
240 // assign parsed value to vector
241 value[i] = scalar_value;
242 }
243
244 wasSet = true;
245 }
246
247 // These definitions for Param<T>::showValue() and
248 // VectorParam<T>::showValue() work for any type where showParam()
249 // takes only two arguments (i.e., everything but the SimpleEnum and
250 // MappedEnum classes).
251 template <class T>
252 void
253 Param<T>::showValue(ostream &os) const
254 {
255 showParam(os, value);
256 }
257
258 template <class T>
259 void
260 VectorParam<T>::showValue(ostream &os) const
261 {
262 for (int i = 0; i < value.size(); i++) {
263 if (i != 0) {
264 os << " ";
265 }
266 showParam(os, value[i]);
267 }
268 }
269
270
271 #ifdef INSURE_BUILD
272 #define INSTANTIATE_PARAM_TEMPLATES(type, typestr) \
273 void Param<type>::showType(ostream &os) const { os << typestr; } \
274 void VectorParam<type>::showType(ostream &os) const { \
275 os << "vector of " << typestr; \
276 } \
277 template Param<type>; \
278 template VectorParam<type>;
279
280 #else
281 // instantiate all four methods (parse/show, scalar/vector) for basic
282 // types that can use the above templates
283 #define INSTANTIATE_PARAM_TEMPLATES(type, typestr) \
284 template bool parseParam<type>(const string &s, type &value); \
285 template void showParam<type>(ostream &os, type const &value); \
286 template void Param<type>::parse(const string &); \
287 template void VectorParam<type>::parse(const string &); \
288 template void Param<type>::showValue(ostream &) const; \
289 template void VectorParam<type>::showValue(ostream &) const; \
290 void Param<type>::showType(ostream &os) const { os << typestr; } \
291 void VectorParam<type>::showType(ostream &os) const { \
292 os << "vector of " << typestr; \
293 }
294 #endif
295
296 INSTANTIATE_PARAM_TEMPLATES(unsigned long long, "ull")
297 INSTANTIATE_PARAM_TEMPLATES(signed long long, "sll")
298 INSTANTIATE_PARAM_TEMPLATES(unsigned long, "uns long")
299 INSTANTIATE_PARAM_TEMPLATES(signed long, "long")
300 INSTANTIATE_PARAM_TEMPLATES(unsigned int, "uns")
301 INSTANTIATE_PARAM_TEMPLATES(signed int, "int")
302 INSTANTIATE_PARAM_TEMPLATES(unsigned short, "uns short")
303 INSTANTIATE_PARAM_TEMPLATES(signed short, "short")
304 INSTANTIATE_PARAM_TEMPLATES(unsigned char, "uns char")
305 INSTANTIATE_PARAM_TEMPLATES(signed char, "char")
306
307 INSTANTIATE_PARAM_TEMPLATES(float, "float")
308 INSTANTIATE_PARAM_TEMPLATES(double, "double")
309
310 INSTANTIATE_PARAM_TEMPLATES(bool, "bool")
311 INSTANTIATE_PARAM_TEMPLATES(string, "string")
312
313 #undef INSTANTIATE_PARAM_TEMPLATES
314
315 //
316 // SimpleEnumParam & MappedEnumParam must specialize their parse(),
317 // showValue(), and showType() methods.
318 //
319
320 //
321 // SimpleEnumParam & SimpleEnumVectorParam
322 //
323 bool
324 parseEnumParam(const char *const *map, const int num_values,
325 const string &s, int &value)
326 {
327 for (int i = 0; i < num_values; ++i) {
328 if (s == map[i]) {
329 value = i;
330 return true;
331 }
332 }
333
334 return false;
335 }
336
337 void
338 showEnumParam(ostream &os,
339 const char *const *map, const int num_values,
340 int value)
341 {
342 assert(0 <= value && value < num_values);
343 os << map[value];
344 }
345
346 void
347 showEnumType(ostream &os,
348 const char *const *map, const int num_values)
349 {
350 os << "{" << map[0];
351 for (int i = 1; i < num_values; ++i)
352 os << "," << map[i];
353
354 os << "}";
355 }
356
357
358 //
359 // MappedEnumParam & MappedEnumVectorParam
360 //
361 bool
362 parseEnumParam(const EnumParamMap *map, const int num_values,
363 const string &s, int &value)
364 {
365 for (int i = 0; i < num_values; ++i) {
366 if (s == map[i].name) {
367 value = map[i].value;
368 return true;
369 }
370 }
371
372 return false;
373 }
374
375 void
376 showEnumParam(ostream &os,
377 const EnumParamMap *map, const int num_values,
378 int value)
379 {
380 for (int i = 0; i < num_values; ++i) {
381 if (value == map[i].value) {
382 os << map[i].name;
383 return;
384 }
385 }
386
387 // if we can't find a reverse mapping just print the int value
388 os << value;
389 }
390
391 void
392 showEnumType(ostream &os,
393 const EnumParamMap *map, const int num_values)
394 {
395 os << "{" << map[0].name;
396 for (int i = 1; i < num_values; ++i)
397 os << "," << map[i].name;
398
399 os << "}";
400 }
401
402
403 template <class Map>
404 void
405 EnumParam<Map>::parse(const string &s)
406 {
407 if (parseEnumParam(map, num_values, s, value)) {
408 wasSet = true;
409 } else {
410 string err("no match for enum string \"");
411
412 err += s;
413 err += "\"";
414
415 die(err);
416 }
417 }
418
419 template <class Map>
420 void
421 EnumVectorParam<Map>::parse(const string &s)
422 {
423 vector<string> tokens;
424
425 tokenize(tokens, s, ' ');
426
427 value.resize(tokens.size());
428
429 for (int i = 0; i < tokens.size(); i++) {
430 if (!parseEnumParam(map, num_values, tokens[i], value[i])) {
431 string err("no match for enum string \"");
432
433 err += s;
434 err += "\"";
435
436 die(err);
437 }
438 }
439
440 wasSet = true;
441 }
442
443 template <class Map>
444 void
445 EnumParam<Map>::showValue(ostream &os) const
446 {
447 showEnumParam(os, map, num_values, value);
448 }
449
450 template <class Map>
451 void
452 EnumVectorParam<Map>::showValue(ostream &os) const
453 {
454 for (int i = 0; i < value.size(); i++) {
455 if (i != 0) {
456 os << " ";
457 }
458 showEnumParam(os, map, num_values, value[i]);
459 }
460 }
461
462 template <class Map>
463 void
464 EnumParam<Map>::showType(ostream &os) const
465 {
466 showEnumType(os, map, num_values);
467 }
468
469 template <class Map>
470 void
471 EnumVectorParam<Map>::showType(ostream &os) const
472 {
473 os << "vector of";
474 showEnumType(os, map, num_values);
475 }
476
477 template EnumParam<const char *>;
478 template EnumVectorParam<const char *>;
479
480 template EnumParam<EnumParamMap>;
481 template EnumVectorParam<EnumParamMap>;
482
483 ////////////////////////////////////////////////////////////////////////
484 //
485 // SimObjectBaseParam methods
486 //
487 ////////////////////////////////////////////////////////////////////////
488
489 bool
490 parseSimObjectParam(ParamContext *context, const string &s, SimObject *&value)
491 {
492 SimObject *obj;
493
494 if (to_lower(s) == "null") {
495 // explicitly set to null by user; assume that's OK
496 obj = NULL;
497 }
498 else {
499 obj = context->resolveSimObject(s);
500
501 if (obj == NULL)
502 return false;
503 }
504
505 value = obj;
506 return true;
507 }
508
509
510 void
511 SimObjectBaseParam::showValue(ostream &os, SimObject *value) const
512 {
513 os << (value ? value->name() : "null");
514 }
515
516 void
517 SimObjectBaseParam::parse(const string &s, SimObject *&value)
518 {
519 if (parseSimObjectParam(context, s, value)) {
520 wasSet = true;
521 }
522 else {
523 string err("could not resolve object name \"");
524
525 err += s;
526 err += "\"";
527
528 die(err);
529 }
530 }
531
532 void
533 SimObjectBaseParam::parse(const string &s, vector<SimObject *>&value)
534 {
535 vector<string> tokens;
536
537 tokenize(tokens, s, ' ');
538
539 value.resize(tokens.size());
540
541 for (int i = 0; i < tokens.size(); i++) {
542 if (!parseSimObjectParam(context, tokens[i], value[i])) {
543 string err("could not resolve object name \"");
544
545 err += s;
546 err += "\"";
547
548 die(err);
549 }
550 }
551
552 wasSet = true;
553 }
554
555 ////////////////////////////////////////////////////////////////////////
556 //
557 // ParamContext member definitions
558 //
559 ////////////////////////////////////////////////////////////////////////
560
561 list<ParamContext *> *ParamContext::ctxList = NULL;
562
563 ParamContext::ParamContext(const string &_iniSection, bool noAutoParse)
564 : iniFilePtr(NULL), // initialized on call to parseParams()
565 iniSection(_iniSection), paramList(NULL)
566 {
567 if (!noAutoParse) {
568 if (ctxList == NULL)
569 ctxList = new list<ParamContext *>();
570
571 (*ctxList).push_back(this);
572 }
573 }
574
575
576 void
577 ParamContext::addParam(BaseParam *param)
578 {
579 getParamList()->push_back(param);
580 }
581
582
583 void
584 ParamContext::parseParams(IniFile &iniFile)
585 {
586 iniFilePtr = &iniFile; // set object member
587
588 ParamList::iterator i;
589
590 for (i = getParamList()->begin(); i != getParamList()->end(); ++i) {
591 string string_value;
592
593 if (iniFile.findDefault(iniSection, (*i)->name, string_value)) {
594 (*i)->parse(string_value);
595 }
596 }
597 }
598
599
600 // Check parameter values for validity & consistency. Default
601 // implementation is no-op; derive subclass & override to add
602 // actual functionality here.
603 void
604 ParamContext::checkParams()
605 {
606 // nada
607 }
608
609
610 // Clean up context-related objects at end of execution. Default
611 // implementation is no-op; derive subclass & override to add actual
612 // functionality here.
613 void
614 ParamContext::cleanup()
615 {
616 // nada
617 }
618
619
620 void
621 ParamContext::describeParams(ostream &os)
622 {
623 ParamList::iterator i;
624
625 for (i = getParamList()->begin(); i != getParamList()->end(); ++i) {
626 BaseParam *p = *i;
627
628 os << p->name << " (";
629 p->showType(os);
630 os << "): " << p->description << "\n";
631 }
632 }
633
634
635
636 void
637 ParamContext::showParams(ostream &os)
638 {
639 ParamList::iterator i;
640
641 for (i = getParamList()->begin(); i != getParamList()->end(); ++i) {
642 BaseParam *p = *i;
643
644 if (p->isValid()) {
645 os << p->name << "=";
646 p->showValue(os);
647 os << endl;
648 }
649 else {
650 os << "// "<< p->name << " not specified" << endl;
651 }
652 }
653 }
654
655
656 void
657 ParamContext::printErrorProlog(ostream &os)
658 {
659 os << "Parameter error in section [" << iniSection << "]: " << endl;
660 }
661
662 //
663 // Resolve an object name to a SimObject pointer. The object will be
664 // created as a side-effect if necessary. If the name contains a
665 // colon (e.g., "iq:IQ"), then the object is local (invisible to
666 // outside this context). If there is no colon, the name needs to be
667 // resolved through the configuration hierarchy (only possible for
668 // SimObjectBuilder objects, which return non-NULL for configNode()).
669 //
670 SimObject *
671 ParamContext::resolveSimObject(const string &_name)
672 {
673 // look for a colon
674 string::size_type i = _name.find(':');
675 string name = _name;
676 if (i != string::npos) {
677 // colon found: local object
678 // add as child to current node and create it
679 name = _name.substr(0, i);
680 string objConfigClassName = _name.substr(i + 1);
681 getConfigNode()->addChild(name, objConfigClassName);
682 }
683 ConfigNode *n = getConfigNode();
684 return n ? n->resolveSimObject(name) : NULL;
685 }
686
687
688 //
689 // static method: call parseParams() on all registered contexts
690 //
691 void
692 ParamContext::parseAllContexts(IniFile &iniFile)
693 {
694 list<ParamContext *>::iterator iter;
695
696 for (iter = ctxList->begin(); iter != ctxList->end(); ++iter) {
697 ParamContext *pc = *iter;
698
699 pc->parseParams(iniFile);
700 }
701 }
702
703
704 //
705 // static method: call checkParams() on all registered contexts
706 //
707 void
708 ParamContext::checkAllContexts()
709 {
710 list<ParamContext *>::iterator iter;
711
712 for (iter = ctxList->begin(); iter != ctxList->end(); ++iter) {
713 ParamContext *pc = *iter;
714
715 pc->checkParams();
716 }
717 }
718
719
720 //
721 // static method: call showParams() on all registered contexts
722 //
723 void
724 ParamContext::showAllContexts(ostream &os)
725 {
726 list<ParamContext *>::iterator iter;
727
728 for (iter = ctxList->begin(); iter != ctxList->end(); ++iter) {
729 ParamContext *pc = *iter;
730
731 os << "[" << pc->iniSection << "]" << endl;
732 pc->showParams(os);
733 os << endl;
734 }
735 }
736
737
738 //
739 // static method: call cleanup() on all registered contexts
740 //
741 void
742 ParamContext::cleanupAllContexts()
743 {
744 list<ParamContext *>::iterator iter;
745
746 for (iter = ctxList->begin(); iter != ctxList->end(); ++iter) {
747 ParamContext *pc = *iter;
748
749 pc->cleanup();
750 }
751 }
752
753
754 //
755 // static method: call describeParams() on all registered contexts
756 //
757 void
758 ParamContext::describeAllContexts(ostream &os)
759 {
760 list<ParamContext *>::iterator iter;
761
762 for (iter = ctxList->begin(); iter != ctxList->end(); ++iter) {
763 ParamContext *pc = *iter;
764
765 os << "[" << pc->iniSection << "]\n";
766 pc->describeParams(os);
767 os << endl;
768 }
769 }