1# Copyright (c) 2004-2005 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 --- 129 unchanged lines hidden (view full) --- 138 139def isSimObjectClass(value): 140 try: 141 return issubclass(value, SimObject) 142 except TypeError: 143 # happens if value is not a class at all 144 return False 145 |
146def isSimObjectSequence(value): 147 if not isinstance(value, (list, tuple)) or len(value) == 0: |
148 return False 149 150 for val in value: 151 if not isNullPointer(val) and not isSimObject(val): 152 return False 153 154 return True 155 |
156def isSimObjectClassSequence(value): 157 if not isinstance(value, (list, tuple)) or len(value) == 0: |
158 return False 159 160 for val in value: 161 if not isNullPointer(val) and not isSimObjectClass(val): 162 return False 163 164 return True 165 |
166def isSimObjectOrSequence(value): 167 return isSimObject(value) or isSimObjectSequence(value) 168 169def isSimObjectClassOrSequence(value): 170 return isSimObjectClass(value) or isSimObjectClassSequence(value) 171 |
172def isNullPointer(value): 173 return isinstance(value, NullSimObject) 174 |
175# Apply method to object. 176# applyMethod(obj, 'meth', <args>) is equivalent to obj.meth(<args>) 177def applyMethod(obj, meth, *args, **kwargs): 178 return getattr(obj, meth)(*args, **kwargs) 179 180# If the first argument is an (non-sequence) object, apply the named 181# method with the given arguments. If the first argument is a 182# sequence, apply the method to each element of the sequence (a la 183# 'map'). 184def applyOrMap(objOrSeq, meth, *args, **kwargs): 185 if not isinstance(objOrSeq, (list, tuple)): 186 return applyMethod(objOrSeq, meth, *args, **kwargs) 187 else: 188 return [applyMethod(o, meth, *args, **kwargs) for o in objOrSeq] 189 190 |
191# The metaclass for ConfigNode (and thus for everything that derives 192# from ConfigNode, including SimObject). This class controls how new 193# classes that derive from ConfigNode are instantiated, and provides 194# inherited class behavior (just like a class controls how instances 195# of that class are instantiated, and provides inherited instance 196# behavior). 197class MetaSimObject(type): 198 # Attributes that can be set only at initialization time --- 73 unchanged lines hidden (view full) --- 272 memo = cls.__dict__.get('_memo', {}) 273 274 # Handle SimObject values 275 for key,val in cls._values.iteritems(): 276 # SimObject instances need to be promoted to classes. 277 # Existing classes should not have any instance values, so 278 # these can only occur at the lowest level dict (the 279 # parameters just being set in this class definition). |
280 if isSimObjectOrSequence(val): |
281 assert(val == cls._values.local[key]) |
282 cls._values[key] = applyOrMap(val, 'makeClass', memo) |
283 # SimObject classes need to be subclassed so that 284 # parameters that get set at this level only affect this 285 # level and derivatives. |
286 elif isSimObjectClassOrSequence(val): |
287 assert(not cls._values.local.has_key(key)) |
288 cls._values[key] = applyOrMap(val, 'makeSubclass', {}, memo) |
289 290 291 def _set_keyword(cls, keyword, val, kwtype): 292 if not isinstance(val, kwtype): 293 raise TypeError, 'keyword %s has bad type %s (expecting %s)' % \ 294 (keyword, type(val), kwtype) 295 if isinstance(val, types.FunctionType): 296 val = classmethod(val) --- 15 unchanged lines hidden (view full) --- 312 if cls.keywords.has_key(attr): 313 cls._set_keyword(attr, value, cls.keywords[attr]) 314 return 315 316 # must be SimObject param 317 param = cls._params.get(attr, None) 318 if param: 319 # It's ok: set attribute by delegating to 'object' class. |
320 if isSimObjectOrSequence(value) and cls._instantiated: |
321 raise AttributeError, \ 322 "Cannot set SimObject parameter '%s' after\n" \ 323 " class %s has been instantiated or subclassed" \ 324 % (attr, cls.__name__) 325 try: 326 cls._values[attr] = param.convert(value) 327 except Exception, e: 328 msg = "%s\nError setting param %s.%s to %s\n" % \ 329 (e, cls.__name__, attr, value) 330 e.args = (msg, ) 331 raise 332 # I would love to get rid of this |
333 elif isSimObjectOrSequence(value): |
334 cls._values[attr] = value 335 else: 336 raise AttributeError, \ 337 "Class %s has no parameter %s" % (cls.__name__, attr) 338 339 def __getattr__(cls, attr): 340 if cls._values.has_key(attr): 341 return cls._values[attr] --- 75 unchanged lines hidden (view full) --- 417 self._values = multidict(self.__class__._values) 418 # For SimObject-valued parameters, the class should have 419 # classes (not instances) for the values. We need to 420 # instantiate these classes rather than just inheriting the 421 # class object. 422 for key,val in self.__class__._values.iteritems(): 423 if isSimObjectClass(val): 424 setattr(self, key, val(_memo)) |
425 elif isSimObjectClassSequence(val) and len(val): |
426 setattr(self, key, [ v(_memo) for v in val ]) 427 # apply attribute assignments from keyword args, if any 428 for key,val in kwargs.iteritems(): 429 setattr(self, key, val) 430 431 # Use this instance as a template to create a new class. 432 def makeClass(self, memo = {}): 433 cls = memo.get(self) --- 30 unchanged lines hidden (view full) --- 464 try: 465 value = param.convert(value) 466 except Exception, e: 467 msg = "%s\nError setting param %s.%s to %s\n" % \ 468 (e, self.__class__.__name__, attr, value) 469 e.args = (msg, ) 470 raise 471 # I would love to get rid of this |
472 elif isSimObjectOrSequence(value): |
473 pass 474 else: 475 raise AttributeError, "Class %s has no parameter %s" \ 476 % (self.__class__.__name__, attr) 477 478 # clear out old child with this name, if any 479 self.clear_child(attr) 480 481 if isSimObject(value): 482 value.set_path(self, attr) |
483 elif isSimObjectSequence(value): |
484 value = SimObjVector(value) 485 [v.set_path(self, "%s%d" % (attr, i)) for i,v in enumerate(value)] 486 487 self._values[attr] = value 488 489 # this hack allows tacking a '[0]' onto parameters that may or may 490 # not be vectors, and always getting the first element (e.g. cpus) 491 def __getitem__(self, key): --- 406 unchanged lines hidden (view full) --- 898 899class VectorParamDesc(ParamDesc): 900 # Convert assigned value to appropriate type. If the RHS is not a 901 # list or tuple, it generates a single-element list. 902 def convert(self, value): 903 if isinstance(value, (list, tuple)): 904 # list: coerce each element into new list 905 tmp_list = [ ParamDesc.convert(self, v) for v in value ] |
906 if isSimObjectSequence(tmp_list): |
907 return SimObjVector(tmp_list) 908 else: 909 return VectorParamValue(tmp_list) 910 else: 911 # singleton: leave it be (could coerce to a single-element 912 # list here, but for some historical reason we don't... 913 return ParamDesc.convert(self, value) 914 --- 526 unchanged lines hidden --- |