SimObject.py (7527:fe90827a663f) SimObject.py (7528:6efc3672733b)
1# Copyright (c) 2004-2006 The Regents of The University of Michigan
2# All rights reserved.
3#
4# Redistribution and use in source and binary forms, with or without
5# modification, are permitted provided that the following conditions are
6# met: redistributions of source code must retain the above copyright
7# notice, this list of conditions and the following disclaimer;
8# redistributions in binary form must reproduce the above copyright

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

22# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26#
27# Authors: Steve Reinhardt
28# Nathan Binkert
29
1# Copyright (c) 2004-2006 The Regents of The University of Michigan
2# All rights reserved.
3#
4# Redistribution and use in source and binary forms, with or without
5# modification, are permitted provided that the following conditions are
6# met: redistributions of source code must retain the above copyright
7# notice, this list of conditions and the following disclaimer;
8# redistributions in binary form must reproduce the above copyright

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

22# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26#
27# Authors: Steve Reinhardt
28# Nathan Binkert
29
30import math
31import sys
32from types import FunctionType
33
34try:
35 import pydot
36except:
37 pydot = False
38
39import m5
40from m5.util import *
41
42# Have to import params up top since Param is referenced on initial
43# load (when SimObject class references Param to create a class
44# variable, the 'name' param)...
45from m5.params import *
46# There are a few things we need that aren't in params.__all__ since
47# normal users don't need them
30import sys
31from types import FunctionType
32
33try:
34 import pydot
35except:
36 pydot = False
37
38import m5
39from m5.util import *
40
41# Have to import params up top since Param is referenced on initial
42# load (when SimObject class references Param to create a class
43# variable, the 'name' param)...
44from m5.params import *
45# There are a few things we need that aren't in params.__all__ since
46# normal users don't need them
48from m5.params import ParamDesc, VectorParamDesc, isNullPointer, SimObjVector
47from m5.params import ParamDesc, VectorParamDesc, \
48 isNullPointer, SimObjectVector
49
50from m5.proxy import *
51from m5.proxy import isproxy
52
53#####################################################################
54#
55# M5 Python Configuration Utility
56#

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

150 # initialize required attributes
151
152 # class-only attributes
153 cls._params = multidict() # param descriptions
154 cls._ports = multidict() # port descriptions
155
156 # class or instance attributes
157 cls._values = multidict() # param values
49
50from m5.proxy import *
51from m5.proxy import isproxy
52
53#####################################################################
54#
55# M5 Python Configuration Utility
56#

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

150 # initialize required attributes
151
152 # class-only attributes
153 cls._params = multidict() # param descriptions
154 cls._ports = multidict() # port descriptions
155
156 # class or instance attributes
157 cls._values = multidict() # param values
158 cls._children = multidict() # SimObject children
158 cls._port_refs = multidict() # port ref objects
159 cls._instantiated = False # really instantiated, cloned, or subclassed
160
161 # We don't support multiple inheritance. If you want to, you
162 # must fix multidict to deal with it properly.
163 if len(bases) > 1:
164 raise TypeError, "SimObjects do not support multiple inheritance"
165
166 base = bases[0]
167
168 # Set up general inheritance via multidicts. A subclass will
169 # inherit all its settings from the base class. The only time
170 # the following is not true is when we define the SimObject
171 # class itself (in which case the multidicts have no parent).
172 if isinstance(base, MetaSimObject):
173 cls._base = base
174 cls._params.parent = base._params
175 cls._ports.parent = base._ports
176 cls._values.parent = base._values
159 cls._port_refs = multidict() # port ref objects
160 cls._instantiated = False # really instantiated, cloned, or subclassed
161
162 # We don't support multiple inheritance. If you want to, you
163 # must fix multidict to deal with it properly.
164 if len(bases) > 1:
165 raise TypeError, "SimObjects do not support multiple inheritance"
166
167 base = bases[0]
168
169 # Set up general inheritance via multidicts. A subclass will
170 # inherit all its settings from the base class. The only time
171 # the following is not true is when we define the SimObject
172 # class itself (in which case the multidicts have no parent).
173 if isinstance(base, MetaSimObject):
174 cls._base = base
175 cls._params.parent = base._params
176 cls._ports.parent = base._ports
177 cls._values.parent = base._values
178 cls._children.parent = base._children
177 cls._port_refs.parent = base._port_refs
178 # mark base as having been subclassed
179 base._instantiated = True
180 else:
181 cls._base = None
182
183 # default keyword values
184 if 'type' in cls._value_dict:

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

300 # check for param
301 param = cls._params.get(attr)
302 if param:
303 cls._set_param(attr, value, param)
304 return
305
306 if isSimObjectOrSequence(value):
307 # If RHS is a SimObject, it's an implicit child assignment.
179 cls._port_refs.parent = base._port_refs
180 # mark base as having been subclassed
181 base._instantiated = True
182 else:
183 cls._base = None
184
185 # default keyword values
186 if 'type' in cls._value_dict:

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

302 # check for param
303 param = cls._params.get(attr)
304 if param:
305 cls._set_param(attr, value, param)
306 return
307
308 if isSimObjectOrSequence(value):
309 # If RHS is a SimObject, it's an implicit child assignment.
308 # Classes don't have children, so we just put this object
309 # in _values; later, each instance will do a 'setattr(self,
310 # attr, _values[attr])' in SimObject.__init__ which will
311 # add this object as a child.
312 cls._values[attr] = value
310 cls._children[attr] = coerceSimObjectOrVector(value)
313 return
314
315 # no valid assignment... raise exception
316 raise AttributeError, \
317 "Class %s has no parameter \'%s\'" % (cls.__name__, attr)
318
319 def __getattr__(cls, attr):
320 if cls._values.has_key(attr):
321 return cls._values[attr]
322
311 return
312
313 # no valid assignment... raise exception
314 raise AttributeError, \
315 "Class %s has no parameter \'%s\'" % (cls.__name__, attr)
316
317 def __getattr__(cls, attr):
318 if cls._values.has_key(attr):
319 return cls._values[attr]
320
321 if cls._children.has_key(attr):
322 return cls._children[attr]
323
323 raise AttributeError, \
324 "object '%s' has no attribute '%s'" % (cls.__name__, attr)
325
326 def __str__(cls):
327 return cls.__name__
328
329 def cxx_decl(cls):
330 code = "#ifndef __PARAMS__%s\n" % cls

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

460 memo_dict[ancestor] = self
461
462 if not ancestor:
463 ancestor = self.__class__
464 ancestor._instantiated = True
465
466 # initialize required attributes
467 self._parent = None
324 raise AttributeError, \
325 "object '%s' has no attribute '%s'" % (cls.__name__, attr)
326
327 def __str__(cls):
328 return cls.__name__
329
330 def cxx_decl(cls):
331 code = "#ifndef __PARAMS__%s\n" % cls

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

461 memo_dict[ancestor] = self
462
463 if not ancestor:
464 ancestor = self.__class__
465 ancestor._instantiated = True
466
467 # initialize required attributes
468 self._parent = None
468 self._children = {}
469 self._name = None
469 self._ccObject = None # pointer to C++ object
470 self._ccParams = None
471 self._instantiated = False # really "cloned"
472
473 # Inherit parameter values from class using multidict so
470 self._ccObject = None # pointer to C++ object
471 self._ccParams = None
472 self._instantiated = False # really "cloned"
473
474 # Inherit parameter values from class using multidict so
474 # individual value settings can be overridden.
475 # individual value settings can be overridden but we still
476 # inherit late changes to non-overridden class values.
475 self._values = multidict(ancestor._values)
476 # clone SimObject-valued parameters
477 for key,val in ancestor._values.iteritems():
477 self._values = multidict(ancestor._values)
478 # clone SimObject-valued parameters
479 for key,val in ancestor._values.iteritems():
478 if isSimObject(val):
479 setattr(self, key, val(_memo=memo_dict))
480 elif isSimObjectSequence(val) and len(val):
481 setattr(self, key, [ v(_memo=memo_dict) for v in val ])
480 val = tryAsSimObjectOrVector(val)
481 if val is not None:
482 self._values[key] = val(_memo=memo_dict)
483
484 # Clone children specified at class level. No need for a
485 # multidict here since we will be cloning everything.
486 self._children = {}
487 for key,val in ancestor._children.iteritems():
488 self.add_child(key, val(_memo=memo_dict))
489
482 # clone port references. no need to use a multidict here
483 # since we will be creating new references for all ports.
484 self._port_refs = {}
485 for key,val in ancestor._port_refs.iteritems():
486 self._port_refs[key] = val.clone(self, memo_dict)
487 # apply attribute assignments from keyword args, if any
488 for key,val in kwargs.iteritems():
489 setattr(self, key, val)

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

522
523 def __getattr__(self, attr):
524 if self._ports.has_key(attr):
525 return self._get_port_ref(attr)
526
527 if self._values.has_key(attr):
528 return self._values[attr]
529
490 # clone port references. no need to use a multidict here
491 # since we will be creating new references for all ports.
492 self._port_refs = {}
493 for key,val in ancestor._port_refs.iteritems():
494 self._port_refs[key] = val.clone(self, memo_dict)
495 # apply attribute assignments from keyword args, if any
496 for key,val in kwargs.iteritems():
497 setattr(self, key, val)

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

530
531 def __getattr__(self, attr):
532 if self._ports.has_key(attr):
533 return self._get_port_ref(attr)
534
535 if self._values.has_key(attr):
536 return self._values[attr]
537
538 if self._children.has_key(attr):
539 return self._children[attr]
540
530 # If the attribute exists on the C++ object, transparently
531 # forward the reference there. This is typically used for
532 # SWIG-wrapped methods such as init(), regStats(),
533 # regFormulas(), resetStats(), startup(), drain(), and
534 # resume().
535 if self._ccObject and hasattr(self._ccObject, attr):
536 return getattr(self._ccObject, attr)
537

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

551 self._get_port_ref(attr).connect(value)
552 return
553
554 if isSimObjectOrSequence(value) and self._instantiated:
555 raise RuntimeError, \
556 "cannot set SimObject parameter '%s' after\n" \
557 " instance been cloned %s" % (attr, `self`)
558
541 # If the attribute exists on the C++ object, transparently
542 # forward the reference there. This is typically used for
543 # SWIG-wrapped methods such as init(), regStats(),
544 # regFormulas(), resetStats(), startup(), drain(), and
545 # resume().
546 if self._ccObject and hasattr(self._ccObject, attr):
547 return getattr(self._ccObject, attr)
548

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

562 self._get_port_ref(attr).connect(value)
563 return
564
565 if isSimObjectOrSequence(value) and self._instantiated:
566 raise RuntimeError, \
567 "cannot set SimObject parameter '%s' after\n" \
568 " instance been cloned %s" % (attr, `self`)
569
559 # must be SimObject param
560 param = self._params.get(attr)
561 if param:
562 try:
563 value = param.convert(value)
564 except Exception, e:
565 msg = "%s\nError setting param %s.%s to %s\n" % \
566 (e, self.__class__.__name__, attr, value)
567 e.args = (msg, )
568 raise
570 param = self._params.get(attr)
571 if param:
572 try:
573 value = param.convert(value)
574 except Exception, e:
575 msg = "%s\nError setting param %s.%s to %s\n" % \
576 (e, self.__class__.__name__, attr, value)
577 e.args = (msg, )
578 raise
569 self._set_child(attr, value)
579 self._values[attr] = value
570 return
571
580 return
581
582 # if RHS is a SimObject, it's an implicit child assignment
572 if isSimObjectOrSequence(value):
583 if isSimObjectOrSequence(value):
573 self._set_child(attr, value)
584 self.add_child(attr, value)
574 return
575
576 # no valid assignment... raise exception
577 raise AttributeError, "Class %s has no parameter %s" \
578 % (self.__class__.__name__, attr)
579
580
581 # this hack allows tacking a '[0]' onto parameters that may or may
582 # not be vectors, and always getting the first element (e.g. cpus)
583 def __getitem__(self, key):
584 if key == 0:
585 return self
586 raise TypeError, "Non-zero index '%s' to SimObject" % key
587
585 return
586
587 # no valid assignment... raise exception
588 raise AttributeError, "Class %s has no parameter %s" \
589 % (self.__class__.__name__, attr)
590
591
592 # this hack allows tacking a '[0]' onto parameters that may or may
593 # not be vectors, and always getting the first element (e.g. cpus)
594 def __getitem__(self, key):
595 if key == 0:
596 return self
597 raise TypeError, "Non-zero index '%s' to SimObject" % key
598
588 # clear out children with given name, even if it's a vector
589 def clear_child(self, name):
590 if not self._children.has_key(name):
591 return
592 child = self._children[name]
593 if isinstance(child, SimObjVector):
594 for i in xrange(len(child)):
595 del self._children["s%d" % (name, i)]
596 del self._children[name]
599 # Also implemented by SimObjectVector
600 def clear_parent(self, old_parent):
601 assert self._parent is old_parent
602 self._parent = None
597
603
598 def add_child(self, name, value):
599 self._children[name] = value
604 # Also implemented by SimObjectVector
605 def set_parent(self, parent, name):
606 self._parent = parent
607 self._name = name
600
608
601 def _maybe_set_parent(self, parent, name):
602 if not self._parent:
603 self._parent = parent
604 self._name = name
605 parent.add_child(name, self)
609 # Also implemented by SimObjectVector
610 def get_name(self):
611 return self._name
606
612
607 def _set_child(self, attr, value):
608 # if RHS is a SimObject, it's an implicit child assignment
609 # clear out old child with this name, if any
610 self.clear_child(attr)
613 # use this rather than directly accessing _parent for symmetry
614 # with SimObjectVector
615 def get_parent(self):
616 return self._parent
611
617
612 if isSimObject(value):
613 value._maybe_set_parent(self, attr)
614 elif isSimObjectSequence(value):
615 value = SimObjVector(value)
616 if len(value) == 1:
617 value[0]._maybe_set_parent(self, attr)
618 else:
619 width = int(math.ceil(math.log(len(value))/math.log(10)))
620 for i,v in enumerate(value):
621 v._maybe_set_parent(self, "%s%0*d" % (attr, width, i))
618 # clear out child with given name
619 def clear_child(self, name):
620 child = self._children[name]
621 child.clear_parent(self)
622 del self._children[name]
622
623
623 self._values[attr] = value
624 # Add a new child to this object.
625 def add_child(self, name, child):
626 child = coerceSimObjectOrVector(child)
627 if child.get_parent():
628 raise RuntimeError, \
629 "add_child('%s'): child '%s' already has parent '%s'" % \
630 (name, child._name, child._parent)
631 if self._children.has_key(name):
632 clear_child(name)
633 child.set_parent(self, name)
634 self._children[name] = child
624
635
636 # Take SimObject-valued parameters that haven't been explicitly
637 # assigned as children and make them children of the object that
638 # they were assigned to as a parameter value. This guarantees
639 # that when we instantiate all the parameter objects we're still
640 # inside the configuration hierarchy.
641 def adoptOrphanParams(self):
642 for key,val in self._values.iteritems():
643 if not isSimObjectVector(val) and isSimObjectSequence(val):
644 # need to convert raw SimObject sequences to
645 # SimObjectVector class so we can call get_parent()
646 val = SimObjectVector(val)
647 self._values[key] = val
648 if isSimObjectOrVector(val) and not val.get_parent():
649 self.add_child(key, val)
650
625 def path(self):
626 if not self._parent:
627 return '(orphan)'
628 ppath = self._parent.path()
629 if ppath == 'root':
630 return self._name
631 return ppath + "." + self._name
632

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

688 instanceDict[self.path()] = self
689
690 if hasattr(self, 'type'):
691 print >>ini_file, 'type=%s' % self.type
692
693 child_names = self._children.keys()
694 child_names.sort()
695 if len(child_names):
651 def path(self):
652 if not self._parent:
653 return '(orphan)'
654 ppath = self._parent.path()
655 if ppath == 'root':
656 return self._name
657 return ppath + "." + self._name
658

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

714 instanceDict[self.path()] = self
715
716 if hasattr(self, 'type'):
717 print >>ini_file, 'type=%s' % self.type
718
719 child_names = self._children.keys()
720 child_names.sort()
721 if len(child_names):
696 print >>ini_file, 'children=%s' % ' '.join(child_names)
722 print >>ini_file, 'children=%s' % \
723 ' '.join(self._children[n].get_name() for n in child_names)
697
698 param_names = self._params.keys()
699 param_names.sort()
700 for param in param_names:
701 value = self._values.get(param)
702 if value != None:
703 print >>ini_file, '%s=%s' % (param,
704 self._values[param].ini_str())

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

851 return obj.getCCObject()
852
853def isSimObject(value):
854 return isinstance(value, SimObject)
855
856def isSimObjectClass(value):
857 return issubclass(value, SimObject)
858
724
725 param_names = self._params.keys()
726 param_names.sort()
727 for param in param_names:
728 value = self._values.get(param)
729 if value != None:
730 print >>ini_file, '%s=%s' % (param,
731 self._values[param].ini_str())

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

878 return obj.getCCObject()
879
880def isSimObject(value):
881 return isinstance(value, SimObject)
882
883def isSimObjectClass(value):
884 return issubclass(value, SimObject)
885
886def isSimObjectVector(value):
887 return isinstance(value, SimObjectVector)
888
859def isSimObjectSequence(value):
860 if not isinstance(value, (list, tuple)) or len(value) == 0:
861 return False
862
863 for val in value:
864 if not isNullPointer(val) and not isSimObject(val):
865 return False
866
867 return True
868
869def isSimObjectOrSequence(value):
870 return isSimObject(value) or isSimObjectSequence(value)
871
872def isRoot(obj):
873 from m5.objects import Root
874 return obj and obj is Root.getInstance()
875
889def isSimObjectSequence(value):
890 if not isinstance(value, (list, tuple)) or len(value) == 0:
891 return False
892
893 for val in value:
894 if not isNullPointer(val) and not isSimObject(val):
895 return False
896
897 return True
898
899def isSimObjectOrSequence(value):
900 return isSimObject(value) or isSimObjectSequence(value)
901
902def isRoot(obj):
903 from m5.objects import Root
904 return obj and obj is Root.getInstance()
905
906def isSimObjectOrVector(value):
907 return isSimObject(value) or isSimObjectVector(value)
908
909def tryAsSimObjectOrVector(value):
910 if isSimObjectOrVector(value):
911 return value
912 if isSimObjectSequence(value):
913 return SimObjectVector(value)
914 return None
915
916def coerceSimObjectOrVector(value):
917 value = tryAsSimObjectOrVector(value)
918 if value is None:
919 raise TypeError, "SimObject or SimObjectVector expected"
920 return value
921
876baseClasses = allClasses.copy()
877baseInstances = instanceDict.copy()
878
879def clear():
880 global allClasses, instanceDict
881
882 allClasses = baseClasses.copy()
883 instanceDict = baseInstances.copy()
884
885# __all__ defines the list of symbols that get exported when
886# 'from config import *' is invoked. Try to keep this reasonably
887# short to avoid polluting other namespaces.
888__all__ = [ 'SimObject' ]
922baseClasses = allClasses.copy()
923baseInstances = instanceDict.copy()
924
925def clear():
926 global allClasses, instanceDict
927
928 allClasses = baseClasses.copy()
929 instanceDict = baseInstances.copy()
930
931# __all__ defines the list of symbols that get exported when
932# 'from config import *' is invoked. Try to keep this reasonably
933# short to avoid polluting other namespaces.
934__all__ = [ 'SimObject' ]