Don't use magic numbers.
[gem5.git] / sim / param.hh
1 /*
2 * Copyright (c) 2002-2003 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 #ifndef __PARAM_HH__
30 #define __PARAM_HH__
31
32 #include <list>
33 #include <string>
34 #include <vector>
35
36 #include "sim/configfile.hh"
37
38 // forward decls
39 class BaseParam;
40 class SimObject;
41
42 //
43 // The context of a parameter definition... usually a subclass of
44 // SimObjectBuilder (which derives from ParamContext), but abstracted
45 // here to support more global simulator control parameters as well.
46 //
47 class ParamContext
48 {
49 private:
50
51 // static list of all ParamContext objects, built as a side effect
52 // of the ParamContext constructor
53 static std::list<ParamContext *> *ctxList;
54
55 protected:
56
57 // .ini file (database) for parameter lookup... initialized on call
58 // to parseParams()
59 IniFile *iniFilePtr;
60
61 // .ini file section for parameter lookup
62 const std::string iniSection;
63
64 typedef std::vector<BaseParam *> ParamList;
65
66 // list of parameters defined in this context
67 ParamList *paramList;
68
69 ParamList *getParamList() {
70 if (!paramList)
71 paramList = new ParamList;
72 return paramList;
73 }
74
75 public:
76
77 /// Initialization phases for ParamContext objects.
78 enum InitPhase {
79 NoAutoInit = -1, ///< Don't initialize at all... params
80 /// will be parsed later (used by
81 /// SimObjectBuilder, which parses
82 /// params in SimObject::create().
83 OutputInitPhase = 0, ///< Output stream initialization
84 TraceInitPhase = 1, ///< Trace context initialization:
85 /// depends on output streams, but
86 /// needs to come before others so we
87 /// can use tracing in other
88 /// ParamContext init code
89 StatsInitPhase = 2, ///< Stats output initialization
90 DefaultInitPhase = 3 ///< Everything else
91 };
92
93 /// Records the initialization phase for this ParamContext.
94 InitPhase initPhase;
95
96 /// Constructor.
97 /// @param _iniSection Name of .ini section corresponding to this context.
98 /// @param _initPhase Initialization phase (see InitPhase).
99 ParamContext(const std::string &_iniSection,
100 InitPhase _initPhase = DefaultInitPhase);
101
102 virtual ~ParamContext() {}
103
104 // add a parameter to the context... called from the parameter
105 // object's constructor (see BaseParam::BaseParam())
106 void addParam(BaseParam *);
107
108 // call parse() on all params in this context to convert string
109 // representations to parameter values
110 virtual void parseParams(IniFile &iniFile);
111
112 // Check parameter values for validity & consistency. Default
113 // implementation is no-op; derive subclass & override to add
114 // actual functionality here
115 virtual void checkParams();
116
117 // Clean up at end of execution: close file descriptors, etc.
118 // Default implementation is no-op; derive subclass & override to
119 // add actual functionality here
120 virtual void cleanup();
121
122 // dump parameter descriptions
123 void describeParams(std::ostream &);
124
125 // Display the parameters & values used
126 void showParams(std::ostream &);
127
128 // print context information for parameter error
129 virtual void printErrorProlog(std::ostream &);
130
131 // resolve a SimObject name in this context to an object pointer.
132 virtual SimObject *resolveSimObject(const std::string &name);
133
134 // generate the name for this instance of this context (used as a
135 // prefix to create unique names in resolveSimObject()
136 virtual const std::string &getInstanceName() { return iniSection; }
137
138 // return the configuration hierarchy node for this context. Bare
139 // ParamContext objects have no corresponding node, so the default
140 // implementation returns NULL.
141 virtual ConfigNode *getConfigNode() { return NULL; }
142
143 // Parse all parameters registered with all ParamContext objects.
144 static void parseAllContexts(IniFile &iniFile);
145
146 // Check all parameters registered with all ParamContext objects.
147 // (calls checkParams() on each)
148 static void checkAllContexts();
149
150 // Print all parameter values on indicated ostream.
151 static void showAllContexts(std::ostream &os);
152
153 // Clean up all registered ParamContext objects. (calls cleanup()
154 // on each)
155 static void cleanupAllContexts();
156
157 // print descriptions of all parameters registered with all
158 // ParamContext objects
159 static void describeAllContexts(std::ostream &os);
160 };
161
162
163 //
164 // Base class for all parameter objects
165 //
166 class BaseParam
167 {
168 public:
169
170 ParamContext *context;
171 std::string name;
172 std::string description; // text description for help message
173 bool wasSet; // true if parameter was set by user
174 bool hasDefault; // true if parameter has default value
175
176 BaseParam(ParamContext *_context, const std::string &_name,
177 const std::string &_description, bool _hasDefault)
178 : context(_context), name(_name), description(_description),
179 wasSet(false), hasDefault(_hasDefault)
180 {
181 context->addParam(this);
182 }
183
184 virtual ~BaseParam() {}
185
186 // a parameter is valid only if its value was set by the user or
187 // it has a default value
188 bool isValid() const
189 {
190 return (wasSet || hasDefault);
191 }
192
193 // set value by parsing string
194 virtual void parse(const std::string &s) = 0;
195
196 // display value to stream
197 virtual void showValue(std::ostream &) const = 0;
198
199 // display type to stream
200 virtual void showType(std::ostream &) const = 0;
201
202 // signal parse or usage error
203 virtual void die(const std::string &err) const;
204 };
205
206 //
207 // Template classes to specialize parameters to specific types.
208 //
209 // Param<T> is for single-valued (scalar) parameters of type T.
210 // VectorParam<T> is for multi-valued (vector) parameters of type T.
211 // These are specified in the .ini file as a space-delimited list of
212 // arguments.
213 //
214 template <class T>
215 class Param : public BaseParam
216 {
217 protected:
218
219 T value;
220
221 public:
222
223 // Param with default value: set value to default
224 Param(ParamContext *context,
225 const std::string &name, const std::string &description, T dfltValue)
226 : BaseParam(context, name, description, true),
227 value(dfltValue)
228 {
229 }
230
231 // Param with no default value: leave value uninitialized
232 Param(ParamContext *context,
233 const std::string &name, const std::string &description)
234 : BaseParam(context, name, description, false)
235 {
236 }
237
238 virtual ~Param() {}
239
240 operator T&()
241 {
242 // if we attempt to reference an invalid parameter (i.e., one
243 // with no default value that was not set by the user), die.
244 if (!isValid())
245 die("not found");
246 return value;
247 }
248
249 // display value to stream
250 virtual void showValue(std::ostream &os) const;
251
252 // display type to stream
253 virtual void showType(std::ostream &) const;
254
255 // set value by parsing string
256 virtual void parse(const std::string &s);
257 };
258
259
260 //
261 // Template class for vector-valued parameters (lists)
262 //
263 template <class T>
264 class VectorParam : public BaseParam
265 {
266 protected:
267
268 std::vector<T> value;
269
270 public:
271
272 typedef typename std::vector<T>::size_type size_type;
273
274 // Param with default value: set value to default
275 VectorParam(ParamContext *context, const std::string &name,
276 const std::string &description,
277 const std::vector<T> &dfltValue)
278 : BaseParam(context, name, description, true),
279 value(dfltValue)
280 {
281 }
282
283 // Param with no default value: leave value uninitialized
284 VectorParam(ParamContext *context,
285 const std::string &name, const std::string &description)
286 : BaseParam(context, name, description, false)
287 {
288 }
289
290 virtual ~VectorParam() {}
291
292 // basic vector access methods
293 size_type size() const
294 {
295 if (!isValid())
296 die("not found");
297 return value.size();
298 }
299
300 const T &operator[](size_type n) const
301 {
302 if (!isValid())
303 die("not found");
304 return value[n];
305 }
306
307 // return reference to value vector
308 operator std::vector<T>&()
309 {
310 if (!isValid())
311 die("not found");
312 return value;
313 }
314
315 // display value to stream
316 virtual void showValue(std::ostream &os) const;
317
318 // display type to stream
319 virtual void showType(std::ostream &) const;
320
321 // set value by parsing string
322 virtual void parse(const std::string &s);
323 };
324
325 //
326 // Specialization of Param<int> and VectorParam<int> to handle
327 // enumerated types is done in two ways, using SimpleEnumParam and
328 // MappedEnumParam (and their vector counterparts,
329 // SimpleEnumVectorParam and MappedEnumVectorParam). SimpleEnumParam
330 // takes an array of strings and maps them to integers based on array
331 // index. MappedEnumParam takes an array of string-to-int mappings,
332 // allowing for mapping strings to non-contiguous integer values, or
333 // mapping multiple strings to the same integer value.
334 //
335 // Both SimpleEnumParam and MappedEnumParam are implemented using a
336 // single template class, EnumParam<Map>, which takes the type of the map
337 // as a parameter (const char * or EnumParamMap). Similarly,
338 // SimpleEnumVectorParam and MappedEnumVectorParam are both
339 // implemented using EnumVectorParam<Map>.
340 //
341 template <class Map>
342 class EnumParam : public Param<int>
343 {
344 const int num_values;
345 const Map *map;
346
347 public:
348
349 // Param with default value: set value to default
350 EnumParam(ParamContext *context,
351 const std::string &name, const std::string &description,
352 const Map *_map, int _num_values,
353 int dfltValue)
354 : Param<int>(context, name, description, dfltValue),
355 num_values(_num_values), map(_map)
356 {
357 }
358
359 // Param with no default value: leave value uninitialized
360 EnumParam(ParamContext *context,
361 const std::string &name, const std::string &description,
362 const Map *_map, int _num_values)
363 : Param<int>(context, name, description),
364 num_values(_num_values), map(_map)
365 {
366 }
367
368 virtual ~EnumParam() {}
369
370 // display value to stream
371 virtual void showValue(std::ostream &os) const;
372
373 // display type to stream
374 virtual void showType(std::ostream &) const;
375
376 // set value by parsing string
377 virtual void parse(const std::string &s);
378 };
379
380 //
381 // Vector counterpart to SimpleEnumParam
382 //
383 template <class Map>
384 class EnumVectorParam : public VectorParam<int>
385 {
386 const int num_values;
387 const Map *map;
388
389 public:
390
391 // Param with default value: set value to default
392 EnumVectorParam(ParamContext *context,
393 const std::string &name, const std::string &description,
394 const Map *_map, int _num_values,
395 std::vector<int> &dfltValue)
396 : VectorParam<int>(context, name, description, dfltValue),
397 num_values(_num_values), map(_map)
398 {
399 }
400
401 // Param with no default value: leave value uninitialized
402 EnumVectorParam(ParamContext *context,
403 const std::string &name, const std::string &description,
404 const Map *_map, int _num_values)
405 : VectorParam<int>(context, name, description),
406 num_values(_num_values), map(_map)
407 {
408 }
409
410 virtual ~EnumVectorParam() {}
411
412 // display value to stream
413 virtual void showValue(std::ostream &os) const;
414
415 // display type to stream
416 virtual void showType(std::ostream &) const;
417
418 // set value by parsing string
419 virtual void parse(const std::string &s);
420 };
421
422 // Specialize EnumParam for a particular enumeration type ENUM
423 // (automates casting to get value of enum type)
424
425 template <class ENUM>
426 class SimpleEnumParam : public EnumParam<const char *>
427 {
428 public:
429
430 SimpleEnumParam(ParamContext *context,
431 const std::string &name, const std::string &description,
432 const char **_map, int _num_values,
433 ENUM dfltValue)
434 : EnumParam<const char *>(context, name, description,
435 _map, _num_values, (int)dfltValue)
436 {
437 }
438
439 SimpleEnumParam(ParamContext *context,
440 const std::string &name, const std::string &description,
441 const char **_map, int _num_values)
442 : EnumParam<const char *>(context, name, description,
443 _map, _num_values)
444 {
445 }
446
447 operator ENUM() const
448 {
449 if (!isValid())
450 die("not found");
451 return (ENUM)value;
452 }
453 };
454
455
456 // Specialize EnumParam for a particular enumeration type ENUM
457 // (automates casting to get value of enum type)
458
459 template <class ENUM>
460 class SimpleEnumVectorParam : public EnumVectorParam<const char *>
461 {
462 public:
463
464 // skip default value constructor: too much pain to convert
465 // vector<ENUM> initializer to vector<int>
466
467
468 SimpleEnumVectorParam(ParamContext *context,
469 const std::string &name,
470 const std::string &description,
471 const char **_map, int _num_values)
472 : EnumVectorParam<const char *>(context, name, description,
473 _map, _num_values)
474 {
475 }
476
477 ENUM operator[](size_type n)
478 {
479 if (!isValid())
480 die("not found");
481 return (ENUM)value[n];
482 }
483 };
484
485
486 //
487 // Handle enums via string-to-int map (see comment above).
488 //
489
490 // An array of string-to-int mappings must be supplied using the
491 // following type.
492 typedef struct {
493 const char *name;
494 int value;
495 } EnumParamMap;
496
497 // Specialize EnumParam for a particular enumeration type ENUM
498 // (automates casting to get value of enum type)
499
500 template <class ENUM>
501 class MappedEnumParam : public EnumParam<EnumParamMap>
502 {
503 public:
504
505 MappedEnumParam(ParamContext *context,
506 const std::string &name, const std::string &description,
507 const EnumParamMap *_map, int _num_values,
508 ENUM dfltValue)
509 : EnumParam<EnumParamMap>(context, name, description,
510 _map, _num_values, (int)dfltValue)
511 {
512 }
513
514 MappedEnumParam(ParamContext *context,
515 const std::string &name, const std::string &description,
516 const EnumParamMap *_map, int _num_values)
517 : EnumParam<EnumParamMap>(context, name, description,
518 _map, _num_values)
519 {
520 }
521
522 operator ENUM()
523 {
524 if (!isValid())
525 die("not found");
526 return (ENUM)value[n];
527 }
528 };
529
530
531 // Specialize EnumParam for a particular enumeration type ENUM
532 // (automates casting to get value of enum type)
533
534 template <class ENUM>
535 class MappedEnumVectorParam : public EnumVectorParam<EnumParamMap>
536 {
537 public:
538
539 // skip default value constructor: too much pain to convert
540 // vector<ENUM> initializer to vector<int>
541
542
543 MappedEnumVectorParam(ParamContext *context,
544 const std::string &name,
545 const std::string &description,
546 const EnumParamMap *_map, int _num_values)
547 : EnumVectorParam<EnumParamMap>(context, name, description,
548 _map, _num_values)
549 {
550 }
551
552 ENUM operator[](size_type n)
553 {
554 if (!isValid())
555 die("not found");
556 return (ENUM)value[n];
557 }
558 };
559
560
561 //
562 // Parameters that point to other simulation objects (e.g. caches,
563 // busses, etc.) are handled by specializing SimObjectBaseParam to the
564 // specific subtype. The main purpose of SimObjectBaseParam is to
565 // provide a place to stick several helper functions common to all
566 // SimObject-derived parameters.
567 //
568 class SimObjectBaseParam : public BaseParam
569 {
570 public:
571
572 SimObjectBaseParam(ParamContext *context, const std::string &name,
573 const std::string &description, bool hasDefault)
574 : BaseParam(context, name, description, hasDefault)
575 {
576 }
577
578 virtual ~SimObjectBaseParam() {}
579
580 // helper function for SimObjectParam<T>::showValue()
581 void showValue(std::ostream &os, SimObject *obj) const;
582
583 // helper function for SimObjectParam<T>::parse()
584 void parse(const std::string &s, SimObject *&value);
585
586 // helper function for SimObjectParam<T>::parse()
587 void parse(const std::string &s, std::vector<SimObject *>&value_vec);
588 };
589
590
591 //
592 // Parameter to a specific type of SimObject. Note that T must be a
593 // pointer to a class derived from SimObject (e.g., <CPU *>).
594 //
595
596 template <class T> class SimObjectParam;
597
598 template <class T>
599 class SimObjectParam<T *> : public SimObjectBaseParam
600 {
601 protected:
602
603 T *value;
604
605 public:
606
607 // initialization w/o default
608 SimObjectParam(ParamContext *context,
609 const std::string &name, const std::string &description)
610 : SimObjectBaseParam(context, name, description, false)
611 {
612 }
613
614 // initialization wit=h default
615 SimObjectParam(ParamContext *context,
616 const std::string &name, const std::string &description,
617 T *dfltValue)
618 : SimObjectBaseParam(context, name, description, true),
619 value(dfltValue)
620 {
621 }
622
623 virtual ~SimObjectParam() {}
624
625 // convert to pointer
626 operator T*()
627 {
628 if (!isValid())
629 die("not found");
630 return value;
631 }
632
633 T *operator->() const
634 {
635 if (!isValid())
636 die("not found");
637 return value;
638 }
639
640 // display value to stream
641 virtual void showValue(std::ostream &os) const
642 {
643 SimObjectBaseParam::showValue(os, value);
644 }
645
646 // display type to stream: see REGISTER_SIM_OBJECT macro in
647 // sim_object.hh for declaration
648 virtual void showType(std::ostream &os) const;
649
650 // set value by parsing string
651 virtual void parse(const std::string &s)
652 {
653 SimObject *so_ptr;
654 // first parse to generic SimObject *
655 SimObjectBaseParam::parse(s, so_ptr);
656 // now dynamic_cast to specific derived type
657 value = dynamic_cast<T *>(so_ptr);
658 // check for failure of dynamic_cast
659 if (value == NULL && so_ptr != NULL)
660 die("not of appropriate type");
661 }
662 };
663
664
665 //
666 // Vector counterpart to SimObjectParam<T>
667 //
668
669 template <class T> class SimObjectVectorParam;
670
671 template <class T>
672 class SimObjectVectorParam<T *> : public SimObjectBaseParam
673 {
674 protected:
675
676 std::vector<T *> value;
677
678 public:
679
680 typedef typename std::vector<T *>::size_type size_type;
681
682 SimObjectVectorParam(ParamContext *context,
683 const std::string &name,
684 const std::string &description)
685 : SimObjectBaseParam(context, name, description, false)
686 {
687 }
688
689 SimObjectVectorParam(ParamContext *context,
690 const std::string &name,
691 const std::string &description,
692 std::vector<T *> dfltValue)
693 : SimObjectBaseParam(context, name, description, true),
694 value(dfltValue)
695 {
696 }
697
698 virtual ~SimObjectVectorParam() {}
699
700 // basic vector access methods
701 size_type size() const
702 {
703 if (!isValid())
704 die("not found");
705 return value.size();
706 }
707
708 T *&operator[](size_type n)
709 {
710 if (!isValid())
711 die("not found");
712 return value[n];
713 }
714
715 // return reference to value vector
716 operator std::vector<T *>&()
717 {
718 if (!isValid())
719 die("not found");
720 return value;
721 }
722
723 // display value to stream
724 virtual void showValue(std::ostream &os) const
725 {
726 for (int i = 0; i < value.size(); i++) {
727 if (i != 0)
728 os << " ";
729 SimObjectBaseParam::showValue(os, value[i]);
730 }
731 }
732
733 // display type to stream: see
734 virtual void showType(std::ostream &os) const;
735
736 // set value by parsing string
737 virtual void parse(const std::string &s)
738 {
739 std::vector<SimObject *> so_ptr_vec;
740 // first parse to generic SimObject * vector (from SimObjectBaseParam)
741 SimObjectBaseParam::parse(s, so_ptr_vec);
742
743 value.resize(so_ptr_vec.size());
744
745 for (int i = 0; i < so_ptr_vec.size(); ++i) {
746 // now dynamic_cast to specific derived type
747 value[i] = dynamic_cast<T *>(so_ptr_vec[i]);
748 // check for failure of dynamic_cast
749 if (value[i] == NULL && so_ptr_vec[i] != NULL)
750 die("not of appropriate type");
751 }
752 }
753 };
754
755 //
756 // Macro to define showType() methods for SimObjectParam &
757 // SimObjectVectorParam. Can't do this automatically as it requires a
758 // string name for the type, which you can't get from a template
759 // argument. For concrete derived SimObject types, this macro is
760 // automatically invoked by REGISTER_SIM_OBJECT() (see sim_object.hh).
761 //
762 #define DEFINE_SIM_OBJECT_CLASS_NAME(CLASS_NAME, OBJ_CLASS) \
763 void \
764 SimObjectParam<OBJ_CLASS *>::showType(std::ostream &os) const \
765 { \
766 os << CLASS_NAME; \
767 } \
768 \
769 void \
770 SimObjectVectorParam<OBJ_CLASS *>::showType(std::ostream &os) const \
771 { \
772 os << "vector of " << CLASS_NAME; \
773 }
774
775
776 //
777 // Declarations for low-level parsing & displaying functions. These
778 // are used internally, but should not be used directly by clients of
779 // the parameter mechanism, but are declared here so they can be
780 // shared with the serialization code (see sim/serialize.cc).
781 template <class T> bool parseParam(const std::string &str, T &data);
782 template <class T> void showParam(std::ostream &os, const T &data);
783
784 #endif // _PARAM_HH