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