config.py (2667:fe64b8353b1c) | config.py (2711:2cbc3999ec58) |
---|---|
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 --- 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-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 --- 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 |
30from __future__ import generators | |
31import os, re, sys, types, inspect 32 33import m5 | 30import os, re, sys, types, inspect 31 32import m5 |
34panic = m5.panic | 33from m5 import panic |
35from convert import * 36from multidict import multidict 37 38noDot = False 39try: 40 import pydot 41except: 42 noDot = True --- 89 unchanged lines hidden (view full) --- 132# metaclass to define most of the SimObject parameter behavior for 133# this class hierarchy. 134# 135##################################################################### 136 137def isSimObject(value): 138 return isinstance(value, SimObject) 139 | 34from convert import * 35from multidict import multidict 36 37noDot = False 38try: 39 import pydot 40except: 41 noDot = True --- 89 unchanged lines hidden (view full) --- 131# metaclass to define most of the SimObject parameter behavior for 132# this class hierarchy. 133# 134##################################################################### 135 136def isSimObject(value): 137 return isinstance(value, SimObject) 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 |
|
140def isSimObjSequence(value): 141 if not isinstance(value, (list, tuple)): 142 return False 143 144 for val in value: 145 if not isNullPointer(val) and not isSimObject(val): 146 return False 147 148 return True 149 | 146def isSimObjSequence(value): 147 if not isinstance(value, (list, tuple)): 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 isSimObjClassSequence(value): 157 if not isinstance(value, (list, tuple)): 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 |
|
150def isNullPointer(value): 151 return isinstance(value, NullSimObject) 152 153# The metaclass for ConfigNode (and thus for everything that derives 154# from ConfigNode, including SimObject). This class controls how new 155# classes that derive from ConfigNode are instantiated, and provides 156# inherited class behavior (just like a class controls how instances 157# of that class are instantiated, and provides inherited instance --- 7 unchanged lines hidden (view full) --- 165 'children' : types.ListType } 166 167 # __new__ is called before __init__, and is where the statements 168 # in the body of the class definition get loaded into the class's 169 # __dict__. We intercept this to filter out parameter assignments 170 # and only allow "private" attributes to be passed to the base 171 # __new__ (starting with underscore). 172 def __new__(mcls, name, bases, dict): | 166def isNullPointer(value): 167 return isinstance(value, NullSimObject) 168 169# The metaclass for ConfigNode (and thus for everything that derives 170# from ConfigNode, including SimObject). This class controls how new 171# classes that derive from ConfigNode are instantiated, and provides 172# inherited class behavior (just like a class controls how instances 173# of that class are instantiated, and provides inherited instance --- 7 unchanged lines hidden (view full) --- 181 'children' : types.ListType } 182 183 # __new__ is called before __init__, and is where the statements 184 # in the body of the class definition get loaded into the class's 185 # __dict__. We intercept this to filter out parameter assignments 186 # and only allow "private" attributes to be passed to the base 187 # __new__ (starting with underscore). 188 def __new__(mcls, name, bases, dict): |
173 # Copy "private" attributes (including special methods such as __new__) 174 # to the official dict. Everything else goes in _init_dict to be 175 # filtered in __init__. 176 cls_dict = {} 177 for key,val in dict.items(): 178 if key.startswith('_'): 179 cls_dict[key] = val 180 del dict[key] 181 cls_dict['_init_dict'] = dict | 189 if dict.has_key('_init_dict'): 190 # must have been called from makeSubclass() rather than 191 # via Python class declaration; bypass filtering process. 192 cls_dict = dict 193 else: 194 # Copy "private" attributes (including special methods 195 # such as __new__) to the official dict. Everything else 196 # goes in _init_dict to be filtered in __init__. 197 cls_dict = {} 198 for key,val in dict.items(): 199 if key.startswith('_'): 200 cls_dict[key] = val 201 del dict[key] 202 cls_dict['_init_dict'] = dict |
182 return super(MetaSimObject, mcls).__new__(mcls, name, bases, cls_dict) 183 | 203 return super(MetaSimObject, mcls).__new__(mcls, name, bases, cls_dict) 204 |
184 # initialization | 205 # subclass initialization |
185 def __init__(cls, name, bases, dict): | 206 def __init__(cls, name, bases, dict): |
207 # calls type.__init__()... I think that's a no-op, but leave 208 # it here just in case it's not. |
|
186 super(MetaSimObject, cls).__init__(name, bases, dict) 187 188 # initialize required attributes 189 cls._params = multidict() 190 cls._values = multidict() 191 cls._anon_subclass_counter = 0 192 193 # We don't support multiple inheritance. If you want to, you 194 # must fix multidict to deal with it properly. 195 if len(bases) > 1: 196 raise TypeError, "SimObjects do not support multiple inheritance" 197 198 base = bases[0] 199 | 209 super(MetaSimObject, cls).__init__(name, bases, dict) 210 211 # initialize required attributes 212 cls._params = multidict() 213 cls._values = multidict() 214 cls._anon_subclass_counter = 0 215 216 # We don't support multiple inheritance. If you want to, you 217 # must fix multidict to deal with it properly. 218 if len(bases) > 1: 219 raise TypeError, "SimObjects do not support multiple inheritance" 220 221 base = bases[0] 222 |
223 # the only time the following is not true is when we define 224 # the SimObject class itself |
|
200 if isinstance(base, MetaSimObject): 201 cls._params.parent = base._params 202 cls._values.parent = base._values 203 | 225 if isinstance(base, MetaSimObject): 226 cls._params.parent = base._params 227 cls._values.parent = base._values 228 |
204 # If your parent has a value in it that's a config node, clone 205 # it. Do this now so if we update any of the values' 206 # attributes we are updating the clone and not the original. 207 for key,val in base._values.iteritems(): 208 209 # don't clone if (1) we're about to overwrite it with 210 # a local setting or (2) we've already cloned a copy 211 # from an earlier (more derived) base 212 if cls._init_dict.has_key(key) or cls._values.has_key(key): 213 continue 214 215 if isSimObject(val): 216 cls._values[key] = val() 217 elif isSimObjSequence(val) and len(val): 218 cls._values[key] = [ v() for v in val ] 219 220 # now process remaining _init_dict items | 229 # now process the _init_dict items |
221 for key,val in cls._init_dict.items(): 222 if isinstance(val, (types.FunctionType, types.TypeType)): 223 type.__setattr__(cls, key, val) 224 225 # param descriptions 226 elif isinstance(val, ParamDesc): 227 cls._new_param(key, val) 228 229 # init-time-only keywords 230 elif cls.init_keywords.has_key(key): 231 cls._set_keyword(key, val, cls.init_keywords[key]) 232 233 # default: use normal path (ends up in __setattr__) 234 else: 235 setattr(cls, key, val) 236 | 230 for key,val in cls._init_dict.items(): 231 if isinstance(val, (types.FunctionType, types.TypeType)): 232 type.__setattr__(cls, key, val) 233 234 # param descriptions 235 elif isinstance(val, ParamDesc): 236 cls._new_param(key, val) 237 238 # init-time-only keywords 239 elif cls.init_keywords.has_key(key): 240 cls._set_keyword(key, val, cls.init_keywords[key]) 241 242 # default: use normal path (ends up in __setattr__) 243 else: 244 setattr(cls, key, val) 245 |
246 # Pull the deep-copy memoization dict out of the class dict if 247 # it's there... 248 memo = cls.__dict__.get('_memo', {}) 249 250 # Handle SimObject values 251 for key,val in cls._values.iteritems(): 252 # SimObject instances need to be promoted to classes. 253 # Existing classes should not have any instance values, so 254 # these can only occur at the lowest level dict (the 255 # parameters just being set in this class definition). 256 if isSimObject(val): 257 assert(val == cls._values.local[key]) 258 cls._values[key] = val.makeClass(memo) 259 elif isSimObjSequence(val) and len(val): 260 assert(val == cls._values.local[key]) 261 cls._values[key] = [ v.makeClass(memo) for v in val ] 262 # SimObject classes need to be subclassed so that 263 # parameters that get set at this level only affect this 264 # level and derivatives. 265 elif isSimObjectClass(val): 266 assert(not cls._values.local.has_key(key)) 267 cls._values[key] = val.makeSubclass({}, memo) 268 elif isSimObjClassSequence(val) and len(val): 269 assert(not cls._values.local.has_key(key)) 270 cls._values[key] = [ v.makeSubclass({}, memo) for v in val ] 271 272 |
|
237 def _set_keyword(cls, keyword, val, kwtype): 238 if not isinstance(val, kwtype): 239 raise TypeError, 'keyword %s has bad type %s (expecting %s)' % \ 240 (keyword, type(val), kwtype) 241 if isinstance(val, types.FunctionType): 242 val = classmethod(val) 243 type.__setattr__(cls, keyword, val) 244 --- 34 unchanged lines hidden (view full) --- 279 280 def __getattr__(cls, attr): 281 if cls._values.has_key(attr): 282 return cls._values[attr] 283 284 raise AttributeError, \ 285 "object '%s' has no attribute '%s'" % (cls.__name__, attr) 286 | 273 def _set_keyword(cls, keyword, val, kwtype): 274 if not isinstance(val, kwtype): 275 raise TypeError, 'keyword %s has bad type %s (expecting %s)' % \ 276 (keyword, type(val), kwtype) 277 if isinstance(val, types.FunctionType): 278 val = classmethod(val) 279 type.__setattr__(cls, keyword, val) 280 --- 34 unchanged lines hidden (view full) --- 315 316 def __getattr__(cls, attr): 317 if cls._values.has_key(attr): 318 return cls._values[attr] 319 320 raise AttributeError, \ 321 "object '%s' has no attribute '%s'" % (cls.__name__, attr) 322 |
323 # Create a subclass of this class. Basically a function interface 324 # to the standard Python class definition mechanism, primarily for 325 # internal use. 'memo' dict param supports "deep copy" (really 326 # "deep subclass") operations... within a given operation, 327 # multiple references to a class should result in a single 328 # subclass object with multiple references to it (as opposed to 329 # mutiple unique subclasses). 330 def makeSubclass(cls, init_dict, memo = {}): 331 subcls = memo.get(cls) 332 if not subcls: 333 name = cls.__name__ + '_' + str(cls._anon_subclass_counter) 334 cls._anon_subclass_counter += 1 335 subcls = MetaSimObject(name, (cls,), 336 { '_init_dict': init_dict, '_memo': memo }) 337 return subcls 338 |
|
287# The ConfigNode class is the root of the special hierarchy. Most of 288# the code in this class deals with the configuration hierarchy itself 289# (parent/child node relationships). 290class SimObject(object): 291 # Specify metaclass. Any class inheriting from SimObject will 292 # get this metaclass. 293 __metaclass__ = MetaSimObject 294 | 339# The ConfigNode class is the root of the special hierarchy. Most of 340# the code in this class deals with the configuration hierarchy itself 341# (parent/child node relationships). 342class SimObject(object): 343 # Specify metaclass. Any class inheriting from SimObject will 344 # get this metaclass. 345 __metaclass__ = MetaSimObject 346 |
295 def __init__(self, _value_parent = None, **kwargs): | 347 # __new__ operator allocates new instances of the class. We 348 # override it here just to support "deep instantiation" operation 349 # via the _memo dict. When recursively instantiating an object 350 # hierarchy we want to make sure that each class is instantiated 351 # only once, and that if there are multiple references to the same 352 # original class, we end up with the corresponding instantiated 353 # references all pointing to the same instance. 354 def __new__(cls, _memo = None, **kwargs): 355 if _memo is not None and _memo.has_key(cls): 356 # return previously instantiated object 357 assert(len(kwargs) == 0) 358 return _memo[cls] 359 else: 360 # Need a new one... if it needs to be memoized, this will 361 # happen in __init__. We defer the insertion until then 362 # so __init__ can use the memo dict to tell whether or not 363 # to perform the initialization. 364 return super(SimObject, cls).__new__(cls, **kwargs) 365 366 # Initialize new instance previously allocated by __new__. For 367 # objects with SimObject-valued params, we need to recursively 368 # instantiate the classes represented by those param values as 369 # well (in a consistent "deep copy"-style fashion; see comment 370 # above). 371 def __init__(self, _memo = None, **kwargs): 372 if _memo is not None: 373 # We're inside a "deep instantiation" 374 assert(isinstance(_memo, dict)) 375 assert(len(kwargs) == 0) 376 if _memo.has_key(self.__class__): 377 # __new__ returned an existing, already initialized 378 # instance, so there's nothing to do here 379 assert(_memo[self.__class__] == self) 380 return 381 # no pre-existing object, so remember this one here 382 _memo[self.__class__] = self 383 else: 384 # This is a new top-level instantiation... don't memoize 385 # this objcet, but prepare to memoize any recursively 386 # instantiated objects. 387 _memo = {} 388 |
296 self._children = {} | 389 self._children = {} |
297 if _value_parent and type(_value_parent) != type(self): 298 # this was called as a type conversion rather than a clone 299 raise TypeError, "Cannot convert %s to %s" % \ 300 (_value_parent.__class__.__name__, self.__class__.__name__) 301 if not _value_parent: 302 _value_parent = self.__class__ 303 # clone values 304 self._values = multidict(_value_parent._values) 305 for key,val in _value_parent._values.iteritems(): 306 if isSimObject(val): 307 setattr(self, key, val()) 308 elif isSimObjSequence(val) and len(val): 309 setattr(self, key, [ v() for v in val ]) | 390 # Inherit parameter values from class using multidict so 391 # individual value settings can be overridden. 392 self._values = multidict(self.__class__._values) 393 # For SimObject-valued parameters, the class should have 394 # classes (not instances) for the values. We need to 395 # instantiate these classes rather than just inheriting the 396 # class object. 397 for key,val in self.__class__._values.iteritems(): 398 if isSimObjectClass(val): 399 setattr(self, key, val(_memo)) 400 elif isSimObjClassSequence(val) and len(val): 401 setattr(self, key, [ v(_memo) for v in val ]) |
310 # apply attribute assignments from keyword args, if any 311 for key,val in kwargs.iteritems(): 312 setattr(self, key, val) 313 | 402 # apply attribute assignments from keyword args, if any 403 for key,val in kwargs.iteritems(): 404 setattr(self, key, val) 405 |
406 # Use this instance as a template to create a new class. 407 def makeClass(self, memo = {}): 408 cls = memo.get(self) 409 if not cls: 410 cls = self.__class__.makeSubclass(self._values.local) 411 memo[self] = cls 412 return cls 413 414 # Direct instantiation of instances (cloning) is no longer 415 # allowed; must generate class from instance first. |
|
314 def __call__(self, **kwargs): | 416 def __call__(self, **kwargs): |
315 return self.__class__(_value_parent = self, **kwargs) | 417 raise TypeError, "cannot instantiate SimObject; "\ 418 "use makeClass() to make class first" |
316 317 def __getattr__(self, attr): 318 if self._values.has_key(attr): 319 return self._values[attr] 320 321 raise AttributeError, "object '%s' has no attribute '%s'" \ 322 % (self.__class__.__name__, attr) 323 --- 740 unchanged lines hidden (view full) --- 1064 1065 def unproxy(self, base): 1066 if self.value == NextEthernetAddr: 1067 self.addr = self.value().value 1068 return self 1069 1070 def __str__(self): 1071 if self.value == NextEthernetAddr: | 419 420 def __getattr__(self, attr): 421 if self._values.has_key(attr): 422 return self._values[attr] 423 424 raise AttributeError, "object '%s' has no attribute '%s'" \ 425 % (self.__class__.__name__, attr) 426 --- 740 unchanged lines hidden (view full) --- 1167 1168 def unproxy(self, base): 1169 if self.value == NextEthernetAddr: 1170 self.addr = self.value().value 1171 return self 1172 1173 def __str__(self): 1174 if self.value == NextEthernetAddr: |
1072 return self.addr | 1175 if hasattr(self, 'addr'): 1176 return self.addr 1177 else: 1178 return "NextEthernetAddr (unresolved)" |
1073 else: 1074 return self.value 1075 1076# Special class for NULL pointers. Note the special check in 1077# make_param_value() above that lets these be assigned where a 1078# SimObject is required. 1079# only one copy of a particular node 1080class NullSimObject(object): --- 229 unchanged lines hidden --- | 1179 else: 1180 return self.value 1181 1182# Special class for NULL pointers. Note the special check in 1183# make_param_value() above that lets these be assigned where a 1184# SimObject is required. 1185# only one copy of a particular node 1186class NullSimObject(object): --- 229 unchanged lines hidden --- |