SimObject.py (10195:7d4d0cd3f7e5) SimObject.py (10267:ed97f6f2ed7a)
1# Copyright (c) 2012 ARM Limited
2# All rights reserved.
3#
4# The license below extends only to copyright in the software and shall
5# not be construed as granting a license to any other intellectual
6# property including but not limited to intellectual property relating
7# to a hardware implementation of the functionality of the software
8# licensed hereunder. You may use the software subject to the license

--- 158 unchanged lines hidden (view full) ---

167 # initialize required attributes
168
169 # class-only attributes
170 cls._params = multidict() # param descriptions
171 cls._ports = multidict() # port descriptions
172
173 # class or instance attributes
174 cls._values = multidict() # param values
1# Copyright (c) 2012 ARM Limited
2# All rights reserved.
3#
4# The license below extends only to copyright in the software and shall
5# not be construed as granting a license to any other intellectual
6# property including but not limited to intellectual property relating
7# to a hardware implementation of the functionality of the software
8# licensed hereunder. You may use the software subject to the license

--- 158 unchanged lines hidden (view full) ---

167 # initialize required attributes
168
169 # class-only attributes
170 cls._params = multidict() # param descriptions
171 cls._ports = multidict() # port descriptions
172
173 # class or instance attributes
174 cls._values = multidict() # param values
175 cls._hr_values = multidict() # human readable param values
175 cls._children = multidict() # SimObject children
176 cls._port_refs = multidict() # port ref objects
177 cls._instantiated = False # really instantiated, cloned, or subclassed
178
179 # We don't support multiple inheritance of sim objects. If you want
180 # to, you must fix multidict to deal with it properly. Non sim-objects
181 # are ok, though
182 bTotal = 0

--- 9 unchanged lines hidden (view full) ---

192 # inherit all its settings from the base class. The only time
193 # the following is not true is when we define the SimObject
194 # class itself (in which case the multidicts have no parent).
195 if isinstance(base, MetaSimObject):
196 cls._base = base
197 cls._params.parent = base._params
198 cls._ports.parent = base._ports
199 cls._values.parent = base._values
176 cls._children = multidict() # SimObject children
177 cls._port_refs = multidict() # port ref objects
178 cls._instantiated = False # really instantiated, cloned, or subclassed
179
180 # We don't support multiple inheritance of sim objects. If you want
181 # to, you must fix multidict to deal with it properly. Non sim-objects
182 # are ok, though
183 bTotal = 0

--- 9 unchanged lines hidden (view full) ---

193 # inherit all its settings from the base class. The only time
194 # the following is not true is when we define the SimObject
195 # class itself (in which case the multidicts have no parent).
196 if isinstance(base, MetaSimObject):
197 cls._base = base
198 cls._params.parent = base._params
199 cls._ports.parent = base._ports
200 cls._values.parent = base._values
201 cls._hr_values.parent = base._hr_values
200 cls._children.parent = base._children
201 cls._port_refs.parent = base._port_refs
202 # mark base as having been subclassed
203 base._instantiated = True
204 else:
205 cls._base = None
206
207 # default keyword values

--- 60 unchanged lines hidden (view full) ---

268 pdesc.name = name
269 cls._params[name] = pdesc
270 if hasattr(pdesc, 'default'):
271 cls._set_param(name, pdesc.default, pdesc)
272
273 def _set_param(cls, name, value, param):
274 assert(param.name == name)
275 try:
202 cls._children.parent = base._children
203 cls._port_refs.parent = base._port_refs
204 # mark base as having been subclassed
205 base._instantiated = True
206 else:
207 cls._base = None
208
209 # default keyword values

--- 60 unchanged lines hidden (view full) ---

270 pdesc.name = name
271 cls._params[name] = pdesc
272 if hasattr(pdesc, 'default'):
273 cls._set_param(name, pdesc.default, pdesc)
274
275 def _set_param(cls, name, value, param):
276 assert(param.name == name)
277 try:
278 hr_value = value
276 value = param.convert(value)
277 except Exception, e:
278 msg = "%s\nError setting param %s.%s to %s\n" % \
279 (e, cls.__name__, name, value)
280 e.args = (msg, )
281 raise
282 cls._values[name] = value
283 # if param value is a SimObject, make it a child too, so that
284 # it gets cloned properly when the class is instantiated
285 if isSimObjectOrVector(value) and not value.has_parent():
286 cls._add_cls_child(name, value)
279 value = param.convert(value)
280 except Exception, e:
281 msg = "%s\nError setting param %s.%s to %s\n" % \
282 (e, cls.__name__, name, value)
283 e.args = (msg, )
284 raise
285 cls._values[name] = value
286 # if param value is a SimObject, make it a child too, so that
287 # it gets cloned properly when the class is instantiated
288 if isSimObjectOrVector(value) and not value.has_parent():
289 cls._add_cls_child(name, value)
290 # update human-readable values of the param if it has a literal
291 # value and is not an object or proxy.
292 if not (isSimObjectOrVector(value) or\
293 isinstance(value, m5.proxy.BaseProxy)):
294 cls._hr_values[name] = hr_value
287
288 def _add_cls_child(cls, name, child):
289 # It's a little funky to have a class as a parent, but these
290 # objects should never be instantiated (only cloned, which
291 # clears the parent pointer), and this makes it clear that the
292 # object is not an orphan and can provide better error
293 # messages.
294 child.set_parent(cls, name)

--- 285 unchanged lines hidden (view full) ---

580# SimObject class definition to the MetaSimObject methods (in
581# particular _set_param, which gets called for parameters with default
582# values defined on the SimObject class itself). It will get
583# overridden by the permanent definition (which requires that
584# SimObject be defined) lower in this file.
585def isSimObjectOrVector(value):
586 return False
587
295
296 def _add_cls_child(cls, name, child):
297 # It's a little funky to have a class as a parent, but these
298 # objects should never be instantiated (only cloned, which
299 # clears the parent pointer), and this makes it clear that the
300 # object is not an orphan and can provide better error
301 # messages.
302 child.set_parent(cls, name)

--- 285 unchanged lines hidden (view full) ---

588# SimObject class definition to the MetaSimObject methods (in
589# particular _set_param, which gets called for parameters with default
590# values defined on the SimObject class itself). It will get
591# overridden by the permanent definition (which requires that
592# SimObject be defined) lower in this file.
593def isSimObjectOrVector(value):
594 return False
595
596# This class holds information about each simobject parameter
597# that should be displayed on the command line for use in the
598# configuration system.
599class ParamInfo(object):
600 def __init__(self, type, desc, type_str, example, default_val, access_str):
601 self.type = type
602 self.desc = desc
603 self.type_str = type_str
604 self.example_str = example
605 self.default_val = default_val
606 # The string representation used to access this param through python.
607 # The method to access this parameter presented on the command line may
608 # be different, so this needs to be stored for later use.
609 self.access_str = access_str
610 self.created = True
611
612 # Make it so we can only set attributes at initialization time
613 # and effectively make this a const object.
614 def __setattr__(self, name, value):
615 if not "created" in self.__dict__:
616 self.__dict__[name] = value
617
588# The SimObject class is the root of the special hierarchy. Most of
589# the code in this class deals with the configuration hierarchy itself
590# (parent/child node relationships).
591class SimObject(object):
592 # Specify metaclass. Any class inheriting from SimObject will
593 # get this metaclass.
594 __metaclass__ = MetaSimObject
595 type = 'SimObject'

--- 20 unchanged lines hidden (view full) ---

616 void initState();
617 void regStats();
618 void resetStats();
619 void regProbePoints();
620 void regProbeListeners();
621 void startup();
622''')
623
618# The SimObject class is the root of the special hierarchy. Most of
619# the code in this class deals with the configuration hierarchy itself
620# (parent/child node relationships).
621class SimObject(object):
622 # Specify metaclass. Any class inheriting from SimObject will
623 # get this metaclass.
624 __metaclass__ = MetaSimObject
625 type = 'SimObject'

--- 20 unchanged lines hidden (view full) ---

646 void initState();
647 void regStats();
648 void resetStats();
649 void regProbePoints();
650 void regProbeListeners();
651 void startup();
652''')
653
654 # Returns a dict of all the option strings that can be
655 # generated as command line options for this simobject instance
656 # by tracing all reachable params in the top level instance and
657 # any children it contains.
658 def enumerateParams(self, flags_dict = {},
659 cmd_line_str = "", access_str = ""):
660 if hasattr(self, "_paramEnumed"):
661 print "Cycle detected enumerating params"
662 else:
663 self._paramEnumed = True
664 # Scan the children first to pick up all the objects in this SimObj
665 for keys in self._children:
666 child = self._children[keys]
667 next_cmdline_str = cmd_line_str + keys
668 next_access_str = access_str + keys
669 if not isSimObjectVector(child):
670 next_cmdline_str = next_cmdline_str + "."
671 next_access_str = next_access_str + "."
672 flags_dict = child.enumerateParams(flags_dict,
673 next_cmdline_str,
674 next_access_str)
675
676 # Go through the simple params in the simobject in this level
677 # of the simobject hierarchy and save information about the
678 # parameter to be used for generating and processing command line
679 # options to the simulator to set these parameters.
680 for keys,values in self._params.items():
681 if values.isCmdLineSettable():
682 type_str = ''
683 ex_str = values.example_str()
684 ptype = None
685 if isinstance(values, VectorParamDesc):
686 type_str = 'Vector_%s' % values.ptype_str
687 ptype = values
688 else:
689 type_str = '%s' % values.ptype_str
690 ptype = values.ptype
691
692 if keys in self._hr_values\
693 and keys in self._values\
694 and not isinstance(self._values[keys], m5.proxy.BaseProxy):
695 cmd_str = cmd_line_str + keys
696 acc_str = access_str + keys
697 flags_dict[cmd_str] = ParamInfo(ptype,
698 self._params[keys].desc, type_str, ex_str,
699 values.pretty_print(self._hr_values[keys]),
700 acc_str)
701 elif not keys in self._hr_values\
702 and not keys in self._values:
703 # Empty param
704 cmd_str = cmd_line_str + keys
705 acc_str = access_str + keys
706 flags_dict[cmd_str] = ParamInfo(ptype,
707 self._params[keys].desc,
708 type_str, ex_str, '', acc_str)
709
710 return flags_dict
711
624 # Initialize new instance. For objects with SimObject-valued
625 # children, we need to recursively clone the classes represented
626 # by those param values as well in a consistent "deep copy"-style
627 # fashion. That is, we want to make sure that each instance is
628 # cloned only once, and that if there are multiple references to
629 # the same original object, we end up with the corresponding
630 # cloned references all pointing to the same cloned instance.
631 def __init__(self, **kwargs):

--- 24 unchanged lines hidden (view full) ---

656 self._children = {}
657 for key,val in ancestor._children.iteritems():
658 self.add_child(key, val(_memo=memo_dict))
659
660 # Inherit parameter values from class using multidict so
661 # individual value settings can be overridden but we still
662 # inherit late changes to non-overridden class values.
663 self._values = multidict(ancestor._values)
712 # Initialize new instance. For objects with SimObject-valued
713 # children, we need to recursively clone the classes represented
714 # by those param values as well in a consistent "deep copy"-style
715 # fashion. That is, we want to make sure that each instance is
716 # cloned only once, and that if there are multiple references to
717 # the same original object, we end up with the corresponding
718 # cloned references all pointing to the same cloned instance.
719 def __init__(self, **kwargs):

--- 24 unchanged lines hidden (view full) ---

744 self._children = {}
745 for key,val in ancestor._children.iteritems():
746 self.add_child(key, val(_memo=memo_dict))
747
748 # Inherit parameter values from class using multidict so
749 # individual value settings can be overridden but we still
750 # inherit late changes to non-overridden class values.
751 self._values = multidict(ancestor._values)
752 self._hr_values = multidict(ancestor._hr_values)
664 # clone SimObject-valued parameters
665 for key,val in ancestor._values.iteritems():
666 val = tryAsSimObjectOrVector(val)
667 if val is not None:
668 self._values[key] = val(_memo=memo_dict)
669
670 # clone port references. no need to use a multidict here
671 # since we will be creating new references for all ports.

--- 74 unchanged lines hidden (view full) ---

746 if self._ports.has_key(attr):
747 # set up port connection
748 self._get_port_ref(attr).connect(value)
749 return
750
751 param = self._params.get(attr)
752 if param:
753 try:
753 # clone SimObject-valued parameters
754 for key,val in ancestor._values.iteritems():
755 val = tryAsSimObjectOrVector(val)
756 if val is not None:
757 self._values[key] = val(_memo=memo_dict)
758
759 # clone port references. no need to use a multidict here
760 # since we will be creating new references for all ports.

--- 74 unchanged lines hidden (view full) ---

835 if self._ports.has_key(attr):
836 # set up port connection
837 self._get_port_ref(attr).connect(value)
838 return
839
840 param = self._params.get(attr)
841 if param:
842 try:
843 hr_value = value
754 value = param.convert(value)
755 except Exception, e:
756 msg = "%s\nError setting param %s.%s to %s\n" % \
757 (e, self.__class__.__name__, attr, value)
758 e.args = (msg, )
759 raise
760 self._values[attr] = value
761 # implicitly parent unparented objects assigned as params
762 if isSimObjectOrVector(value) and not value.has_parent():
763 self.add_child(attr, value)
844 value = param.convert(value)
845 except Exception, e:
846 msg = "%s\nError setting param %s.%s to %s\n" % \
847 (e, self.__class__.__name__, attr, value)
848 e.args = (msg, )
849 raise
850 self._values[attr] = value
851 # implicitly parent unparented objects assigned as params
852 if isSimObjectOrVector(value) and not value.has_parent():
853 self.add_child(attr, value)
854 # set the human-readable value dict if this is a param
855 # with a literal value and is not being set as an object
856 # or proxy.
857 if not (isSimObjectOrVector(value) or\
858 isinstance(value, m5.proxy.BaseProxy)):
859 self._hr_values[attr] = hr_value
860
764 return
765
766 # if RHS is a SimObject, it's an implicit child assignment
767 if isSimObjectOrSequence(value):
768 self.add_child(attr, value)
769 return
770
771 # no valid assignment... raise exception
772 raise AttributeError, "Class %s has no parameter %s" \
773 % (self.__class__.__name__, attr)
774
775
776 # this hack allows tacking a '[0]' onto parameters that may or may
777 # not be vectors, and always getting the first element (e.g. cpus)
778 def __getitem__(self, key):
779 if key == 0:
780 return self
861 return
862
863 # if RHS is a SimObject, it's an implicit child assignment
864 if isSimObjectOrSequence(value):
865 self.add_child(attr, value)
866 return
867
868 # no valid assignment... raise exception
869 raise AttributeError, "Class %s has no parameter %s" \
870 % (self.__class__.__name__, attr)
871
872
873 # this hack allows tacking a '[0]' onto parameters that may or may
874 # not be vectors, and always getting the first element (e.g. cpus)
875 def __getitem__(self, key):
876 if key == 0:
877 return self
781 raise TypeError, "Non-zero index '%s' to SimObject" % key
878 raise IndexError, "Non-zero index '%s' to SimObject" % key
782
879
880 # this hack allows us to iterate over a SimObject that may
881 # not be a vector, so we can call a loop over it and get just one
882 # element.
883 def __len__(self):
884 return 1
885
783 # Also implemented by SimObjectVector
784 def clear_parent(self, old_parent):
785 assert self._parent is old_parent
786 self._parent = None
787
788 # Also implemented by SimObjectVector
789 def set_parent(self, parent, name):
790 self._parent = parent

--- 258 unchanged lines hidden (view full) ---

1049 def getCCObject(self):
1050 if not self._ccObject:
1051 # Make sure this object is in the configuration hierarchy
1052 if not self._parent and not isRoot(self):
1053 raise RuntimeError, "Attempt to instantiate orphan node"
1054 # Cycles in the configuration hierarchy are not supported. This
1055 # will catch the resulting recursion and stop.
1056 self._ccObject = -1
886 # Also implemented by SimObjectVector
887 def clear_parent(self, old_parent):
888 assert self._parent is old_parent
889 self._parent = None
890
891 # Also implemented by SimObjectVector
892 def set_parent(self, parent, name):
893 self._parent = parent

--- 258 unchanged lines hidden (view full) ---

1152 def getCCObject(self):
1153 if not self._ccObject:
1154 # Make sure this object is in the configuration hierarchy
1155 if not self._parent and not isRoot(self):
1156 raise RuntimeError, "Attempt to instantiate orphan node"
1157 # Cycles in the configuration hierarchy are not supported. This
1158 # will catch the resulting recursion and stop.
1159 self._ccObject = -1
1057 params = self.getCCParams()
1058 self._ccObject = params.create()
1160 if not self.abstract:
1161 params = self.getCCParams()
1162 self._ccObject = params.create()
1059 elif self._ccObject == -1:
1060 raise RuntimeError, "%s: Cycle found in configuration hierarchy." \
1061 % self.path()
1062 return self._ccObject
1063
1064 def descendants(self):
1065 yield self
1066 for child in self._children.itervalues():

--- 78 unchanged lines hidden ---
1163 elif self._ccObject == -1:
1164 raise RuntimeError, "%s: Cycle found in configuration hierarchy." \
1165 % self.path()
1166 return self._ccObject
1167
1168 def descendants(self):
1169 yield self
1170 for child in self._children.itervalues():

--- 78 unchanged lines hidden ---