SimObject.py (13356:913658aa619c) SimObject.py (13663:9b64aeabf9a5)
1# Copyright (c) 2017-2018 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

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

478 # We don't support multiple inheritance of sim objects. If you want
479 # to, you must fix multidict to deal with it properly. Non sim-objects
480 # are ok, though
481 bTotal = 0
482 for c in bases:
483 if isinstance(c, MetaSimObject):
484 bTotal += 1
485 if bTotal > 1:
1# Copyright (c) 2017-2018 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

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

478 # We don't support multiple inheritance of sim objects. If you want
479 # to, you must fix multidict to deal with it properly. Non sim-objects
480 # are ok, though
481 bTotal = 0
482 for c in bases:
483 if isinstance(c, MetaSimObject):
484 bTotal += 1
485 if bTotal > 1:
486 raise TypeError, \
487 "SimObjects do not support multiple inheritance"
486 raise TypeError(
487 "SimObjects do not support multiple inheritance")
488
489 base = bases[0]
490
491 # Set up general inheritance via multidicts. A subclass will
492 # inherit all its settings from the base class. The only time
493 # the following is not true is when we define the SimObject
494 # class itself (in which case the multidicts have no parent).
495 if isinstance(base, MetaSimObject):

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

538 cls._set_keyword(key, val, cls.init_keywords[key])
539
540 # default: use normal path (ends up in __setattr__)
541 else:
542 setattr(cls, key, val)
543
544 def _set_keyword(cls, keyword, val, kwtype):
545 if not isinstance(val, kwtype):
488
489 base = bases[0]
490
491 # Set up general inheritance via multidicts. A subclass will
492 # inherit all its settings from the base class. The only time
493 # the following is not true is when we define the SimObject
494 # class itself (in which case the multidicts have no parent).
495 if isinstance(base, MetaSimObject):

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

538 cls._set_keyword(key, val, cls.init_keywords[key])
539
540 # default: use normal path (ends up in __setattr__)
541 else:
542 setattr(cls, key, val)
543
544 def _set_keyword(cls, keyword, val, kwtype):
545 if not isinstance(val, kwtype):
546 raise TypeError, 'keyword %s has bad type %s (expecting %s)' % \
547 (keyword, type(val), kwtype)
546 raise TypeError('keyword %s has bad type %s (expecting %s)' % \
547 (keyword, type(val), kwtype))
548 if isinstance(val, FunctionType):
549 val = classmethod(val)
550 type.__setattr__(cls, keyword, val)
551
552 def _new_param(cls, name, pdesc):
553 # each param desc should be uniquely assigned to one variable
554 assert(not hasattr(pdesc, 'name'))
555 pdesc.name = name
556 cls._params[name] = pdesc
557 if hasattr(pdesc, 'default'):
558 cls._set_param(name, pdesc.default, pdesc)
559
560 def _set_param(cls, name, value, param):
561 assert(param.name == name)
562 try:
563 hr_value = value
564 value = param.convert(value)
548 if isinstance(val, FunctionType):
549 val = classmethod(val)
550 type.__setattr__(cls, keyword, val)
551
552 def _new_param(cls, name, pdesc):
553 # each param desc should be uniquely assigned to one variable
554 assert(not hasattr(pdesc, 'name'))
555 pdesc.name = name
556 cls._params[name] = pdesc
557 if hasattr(pdesc, 'default'):
558 cls._set_param(name, pdesc.default, pdesc)
559
560 def _set_param(cls, name, value, param):
561 assert(param.name == name)
562 try:
563 hr_value = value
564 value = param.convert(value)
565 except Exception, e:
565 except Exception as e:
566 msg = "%s\nError setting param %s.%s to %s\n" % \
567 (e, cls.__name__, name, value)
568 e.args = (msg, )
569 raise
570 cls._values[name] = value
571 # if param value is a SimObject, make it a child too, so that
572 # it gets cloned properly when the class is instantiated
573 if isSimObjectOrVector(value) and not value.has_parent():

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

617 cls._set_keyword(attr, value, cls.keywords[attr])
618 return
619
620 if cls._ports.has_key(attr):
621 cls._cls_get_port_ref(attr).connect(value)
622 return
623
624 if isSimObjectOrSequence(value) and cls._instantiated:
566 msg = "%s\nError setting param %s.%s to %s\n" % \
567 (e, cls.__name__, name, value)
568 e.args = (msg, )
569 raise
570 cls._values[name] = value
571 # if param value is a SimObject, make it a child too, so that
572 # it gets cloned properly when the class is instantiated
573 if isSimObjectOrVector(value) and not value.has_parent():

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

617 cls._set_keyword(attr, value, cls.keywords[attr])
618 return
619
620 if cls._ports.has_key(attr):
621 cls._cls_get_port_ref(attr).connect(value)
622 return
623
624 if isSimObjectOrSequence(value) and cls._instantiated:
625 raise RuntimeError, \
625 raise RuntimeError(
626 "cannot set SimObject parameter '%s' after\n" \
627 " class %s has been instantiated or subclassed" \
626 "cannot set SimObject parameter '%s' after\n" \
627 " class %s has been instantiated or subclassed" \
628 % (attr, cls.__name__)
628 % (attr, cls.__name__))
629
630 # check for param
631 param = cls._params.get(attr)
632 if param:
633 cls._set_param(attr, value, param)
634 return
635
636 if isSimObjectOrSequence(value):
637 # If RHS is a SimObject, it's an implicit child assignment.
638 cls._add_cls_child(attr, coerceSimObjectOrVector(value))
639 return
640
641 # no valid assignment... raise exception
629
630 # check for param
631 param = cls._params.get(attr)
632 if param:
633 cls._set_param(attr, value, param)
634 return
635
636 if isSimObjectOrSequence(value):
637 # If RHS is a SimObject, it's an implicit child assignment.
638 cls._add_cls_child(attr, coerceSimObjectOrVector(value))
639 return
640
641 # no valid assignment... raise exception
642 raise AttributeError, \
643 "Class %s has no parameter \'%s\'" % (cls.__name__, attr)
642 raise AttributeError(
643 "Class %s has no parameter \'%s\'" % (cls.__name__, attr))
644
645 def __getattr__(cls, attr):
646 if attr == 'cxx_class_path':
647 return cls.cxx_class.split('::')
648
649 if attr == 'cxx_class_name':
650 return cls.cxx_class_path[-1]
651
652 if attr == 'cxx_namespaces':
653 return cls.cxx_class_path[:-1]
654
655 if cls._values.has_key(attr):
656 return cls._values[attr]
657
658 if cls._children.has_key(attr):
659 return cls._children[attr]
660
644
645 def __getattr__(cls, attr):
646 if attr == 'cxx_class_path':
647 return cls.cxx_class.split('::')
648
649 if attr == 'cxx_class_name':
650 return cls.cxx_class_path[-1]
651
652 if attr == 'cxx_namespaces':
653 return cls.cxx_class_path[:-1]
654
655 if cls._values.has_key(attr):
656 return cls._values[attr]
657
658 if cls._children.has_key(attr):
659 return cls._children[attr]
660
661 raise AttributeError, \
662 "object '%s' has no attribute '%s'" % (cls.__name__, attr)
661 raise AttributeError(
662 "object '%s' has no attribute '%s'" % (cls.__name__, attr))
663
664 def __str__(cls):
665 return cls.__name__
666
667 # See ParamValue.cxx_predecls for description.
668 def cxx_predecls(cls, code):
669 code('#include "params/$cls.hh"')
670

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

1147 # "deep copy" recursive clone, check the _memo dict to see if
1148 # we've already cloned this instance.
1149 def __call__(self, **kwargs):
1150 memo_dict = kwargs.get('_memo')
1151 if memo_dict is None:
1152 # no memo_dict: must be top-level clone operation.
1153 # this is only allowed at the root of a hierarchy
1154 if self._parent:
663
664 def __str__(cls):
665 return cls.__name__
666
667 # See ParamValue.cxx_predecls for description.
668 def cxx_predecls(cls, code):
669 code('#include "params/$cls.hh"')
670

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

1147 # "deep copy" recursive clone, check the _memo dict to see if
1148 # we've already cloned this instance.
1149 def __call__(self, **kwargs):
1150 memo_dict = kwargs.get('_memo')
1151 if memo_dict is None:
1152 # no memo_dict: must be top-level clone operation.
1153 # this is only allowed at the root of a hierarchy
1154 if self._parent:
1155 raise RuntimeError, "attempt to clone object %s " \
1155 raise RuntimeError("attempt to clone object %s " \
1156 "not at the root of a tree (parent = %s)" \
1156 "not at the root of a tree (parent = %s)" \
1157 % (self, self._parent)
1157 % (self, self._parent))
1158 # create a new dict and use that.
1159 memo_dict = {}
1160 kwargs['_memo'] = memo_dict
1161 elif memo_dict.has_key(self):
1162 # clone already done & memoized
1163 return memo_dict[self]
1164 return self.__class__(_ancestor = self, **kwargs)
1165

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

1191
1192 err_string = "object '%s' has no attribute '%s'" \
1193 % (self.__class__.__name__, attr)
1194
1195 if not self._ccObject:
1196 err_string += "\n (C++ object is not yet constructed," \
1197 " so wrapped C++ methods are unavailable.)"
1198
1158 # create a new dict and use that.
1159 memo_dict = {}
1160 kwargs['_memo'] = memo_dict
1161 elif memo_dict.has_key(self):
1162 # clone already done & memoized
1163 return memo_dict[self]
1164 return self.__class__(_ancestor = self, **kwargs)
1165

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

1191
1192 err_string = "object '%s' has no attribute '%s'" \
1193 % (self.__class__.__name__, attr)
1194
1195 if not self._ccObject:
1196 err_string += "\n (C++ object is not yet constructed," \
1197 " so wrapped C++ methods are unavailable.)"
1198
1199 raise AttributeError, err_string
1199 raise AttributeError(err_string)
1200
1201 # Set attribute (called on foo.attr = value when foo is an
1202 # instance of class cls).
1203 def __setattr__(self, attr, value):
1204 # normal processing for private attributes
1205 if attr.startswith('_'):
1206 object.__setattr__(self, attr, value)
1207 return
1208
1209 if self._ports.has_key(attr):
1210 # set up port connection
1211 self._get_port_ref(attr).connect(value)
1212 return
1213
1214 param = self._params.get(attr)
1215 if param:
1216 try:
1217 hr_value = value
1218 value = param.convert(value)
1200
1201 # Set attribute (called on foo.attr = value when foo is an
1202 # instance of class cls).
1203 def __setattr__(self, attr, value):
1204 # normal processing for private attributes
1205 if attr.startswith('_'):
1206 object.__setattr__(self, attr, value)
1207 return
1208
1209 if self._ports.has_key(attr):
1210 # set up port connection
1211 self._get_port_ref(attr).connect(value)
1212 return
1213
1214 param = self._params.get(attr)
1215 if param:
1216 try:
1217 hr_value = value
1218 value = param.convert(value)
1219 except Exception, e:
1219 except Exception as e:
1220 msg = "%s\nError setting param %s.%s to %s\n" % \
1221 (e, self.__class__.__name__, attr, value)
1222 e.args = (msg, )
1223 raise
1224 self._values[attr] = value
1225 # implicitly parent unparented objects assigned as params
1226 if isSimObjectOrVector(value) and not value.has_parent():
1227 self.add_child(attr, value)

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

1235 return
1236
1237 # if RHS is a SimObject, it's an implicit child assignment
1238 if isSimObjectOrSequence(value):
1239 self.add_child(attr, value)
1240 return
1241
1242 # no valid assignment... raise exception
1220 msg = "%s\nError setting param %s.%s to %s\n" % \
1221 (e, self.__class__.__name__, attr, value)
1222 e.args = (msg, )
1223 raise
1224 self._values[attr] = value
1225 # implicitly parent unparented objects assigned as params
1226 if isSimObjectOrVector(value) and not value.has_parent():
1227 self.add_child(attr, value)

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

1235 return
1236
1237 # if RHS is a SimObject, it's an implicit child assignment
1238 if isSimObjectOrSequence(value):
1239 self.add_child(attr, value)
1240 return
1241
1242 # no valid assignment... raise exception
1243 raise AttributeError, "Class %s has no parameter %s" \
1244 % (self.__class__.__name__, attr)
1243 raise AttributeError("Class %s has no parameter %s" \
1244 % (self.__class__.__name__, attr))
1245
1246
1247 # this hack allows tacking a '[0]' onto parameters that may or may
1248 # not be vectors, and always getting the first element (e.g. cpus)
1249 def __getitem__(self, key):
1250 if key == 0:
1251 return self
1245
1246
1247 # this hack allows tacking a '[0]' onto parameters that may or may
1248 # not be vectors, and always getting the first element (e.g. cpus)
1249 def __getitem__(self, key):
1250 if key == 0:
1251 return self
1252 raise IndexError, "Non-zero index '%s' to SimObject" % key
1252 raise IndexError("Non-zero index '%s' to SimObject" % key)
1253
1254 # this hack allows us to iterate over a SimObject that may
1255 # not be a vector, so we can call a loop over it and get just one
1256 # element.
1257 def __len__(self):
1258 return 1
1259
1260 # Also implemented by SimObjectVector

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

1347 found_obj = None
1348 for child in self._children.itervalues():
1349 visited = False
1350 if hasattr(child, '_visited'):
1351 visited = getattr(child, '_visited')
1352
1353 if isinstance(child, ptype) and not visited:
1354 if found_obj != None and child != found_obj:
1253
1254 # this hack allows us to iterate over a SimObject that may
1255 # not be a vector, so we can call a loop over it and get just one
1256 # element.
1257 def __len__(self):
1258 return 1
1259
1260 # Also implemented by SimObjectVector

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

1347 found_obj = None
1348 for child in self._children.itervalues():
1349 visited = False
1350 if hasattr(child, '_visited'):
1351 visited = getattr(child, '_visited')
1352
1353 if isinstance(child, ptype) and not visited:
1354 if found_obj != None and child != found_obj:
1355 raise AttributeError, \
1355 raise AttributeError(
1356 'parent.any matched more than one: %s %s' % \
1356 'parent.any matched more than one: %s %s' % \
1357 (found_obj.path, child.path)
1357 (found_obj.path, child.path))
1358 found_obj = child
1359 # search param space
1360 for pname,pdesc in self._params.iteritems():
1361 if issubclass(pdesc.ptype, ptype):
1362 match_obj = self._values[pname]
1363 if found_obj != None and found_obj != match_obj:
1358 found_obj = child
1359 # search param space
1360 for pname,pdesc in self._params.iteritems():
1361 if issubclass(pdesc.ptype, ptype):
1362 match_obj = self._values[pname]
1363 if found_obj != None and found_obj != match_obj:
1364 raise AttributeError, \
1364 raise AttributeError(
1365 'parent.any matched more than one: %s and %s' % \
1365 'parent.any matched more than one: %s and %s' % \
1366 (found_obj.path, match_obj.path)
1366 (found_obj.path, match_obj.path))
1367 found_obj = match_obj
1368 return found_obj, found_obj != None
1369
1370 def find_all(self, ptype):
1371 all = {}
1372 # search children
1373 for child in self._children.itervalues():
1374 # a child could be a list, so ensure we visit each item

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

1528
1529 # Get C++ object corresponding to this object, calling C++ if
1530 # necessary to construct it. Does *not* recursively create
1531 # children.
1532 def getCCObject(self):
1533 if not self._ccObject:
1534 # Make sure this object is in the configuration hierarchy
1535 if not self._parent and not isRoot(self):
1367 found_obj = match_obj
1368 return found_obj, found_obj != None
1369
1370 def find_all(self, ptype):
1371 all = {}
1372 # search children
1373 for child in self._children.itervalues():
1374 # a child could be a list, so ensure we visit each item

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

1528
1529 # Get C++ object corresponding to this object, calling C++ if
1530 # necessary to construct it. Does *not* recursively create
1531 # children.
1532 def getCCObject(self):
1533 if not self._ccObject:
1534 # Make sure this object is in the configuration hierarchy
1535 if not self._parent and not isRoot(self):
1536 raise RuntimeError, "Attempt to instantiate orphan node"
1536 raise RuntimeError("Attempt to instantiate orphan node")
1537 # Cycles in the configuration hierarchy are not supported. This
1538 # will catch the resulting recursion and stop.
1539 self._ccObject = -1
1540 if not self.abstract:
1541 params = self.getCCParams()
1542 self._ccObject = params.create()
1543 elif self._ccObject == -1:
1537 # Cycles in the configuration hierarchy are not supported. This
1538 # will catch the resulting recursion and stop.
1539 self._ccObject = -1
1540 if not self.abstract:
1541 params = self.getCCParams()
1542 self._ccObject = params.create()
1543 elif self._ccObject == -1:
1544 raise RuntimeError, "%s: Cycle found in configuration hierarchy." \
1545 % self.path()
1544 raise RuntimeError("%s: Cycle found in configuration hierarchy." \
1545 % self.path())
1546 return self._ccObject
1547
1548 def descendants(self):
1549 yield self
1550 # The order of the dict is implementation dependent, so sort
1551 # it based on the key (name) to ensure the order is the same
1552 # on all hosts
1553 for (name, child) in sorted(self._children.iteritems()):

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

1645 return value
1646 if isSimObjectSequence(value):
1647 return SimObjectVector(value)
1648 return None
1649
1650def coerceSimObjectOrVector(value):
1651 value = tryAsSimObjectOrVector(value)
1652 if value is None:
1546 return self._ccObject
1547
1548 def descendants(self):
1549 yield self
1550 # The order of the dict is implementation dependent, so sort
1551 # it based on the key (name) to ensure the order is the same
1552 # on all hosts
1553 for (name, child) in sorted(self._children.iteritems()):

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

1645 return value
1646 if isSimObjectSequence(value):
1647 return SimObjectVector(value)
1648 return None
1649
1650def coerceSimObjectOrVector(value):
1651 value = tryAsSimObjectOrVector(value)
1652 if value is None:
1653 raise TypeError, "SimObject or SimObjectVector expected"
1653 raise TypeError("SimObject or SimObjectVector expected")
1654 return value
1655
1656baseClasses = allClasses.copy()
1657baseInstances = instanceDict.copy()
1658
1659def clear():
1660 global allClasses, instanceDict, noCxxHeader
1661

--- 13 unchanged lines hidden ---
1654 return value
1655
1656baseClasses = allClasses.copy()
1657baseInstances = instanceDict.copy()
1658
1659def clear():
1660 global allClasses, instanceDict, noCxxHeader
1661

--- 13 unchanged lines hidden ---