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' ] |