summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKevin Lim <ktlim@umich.edu>2005-03-22 15:34:08 -0500
committerKevin Lim <ktlim@umich.edu>2005-03-22 15:34:08 -0500
commit2ec918362ee1235cf0d36fb7aac3e3f4ce2d4ddc (patch)
tree33a71bd50ed74ce2127de696c69ee88c9b9c5d1c
parentcfa4221e19459d2179ba5601cf71a7a53753a3b1 (diff)
parent48e0b9ed4dd6f69cc41003d20bf755eeaf6fb633 (diff)
downloadgem5-2ec918362ee1235cf0d36fb7aac3e3f4ce2d4ddc.tar.xz
Merge ktlim@zizzer.eecs.umich.edu:/bk/m5
into zamp.eecs.umich.edu:/z/ktlim2/m5 --HG-- extra : convert_revision : 0c750652cc2b59946160994d53c921cb021ceef4
-rw-r--r--python/m5/__init__.py8
-rw-r--r--python/m5/config.py208
-rw-r--r--python/m5/convert.py16
-rw-r--r--python/m5/multidict.py158
-rw-r--r--python/m5/smartdict.py8
5 files changed, 246 insertions, 152 deletions
diff --git a/python/m5/__init__.py b/python/m5/__init__.py
index 16f48dba3..27bd91749 100644
--- a/python/m5/__init__.py
+++ b/python/m5/__init__.py
@@ -1,14 +1,14 @@
import sys, os
-# the mpy import code is added to the global import meta_path as a
-# side effect of this import
-from mpy_importer import AddToPath, LoadMpyFile
-
# define this here so we can use it right away if necessary
def panic(string):
print >>sys.stderr, 'panic:', string
sys.exit(1)
+# the mpy import code is added to the global import meta_path as a
+# side effect of this import
+from mpy_importer import AddToPath, LoadMpyFile
+
# find the m5 compile options: must be specified as a dict in
# __main__.m5_build_env.
import __main__
diff --git a/python/m5/config.py b/python/m5/config.py
index 64ec99490..f696adc79 100644
--- a/python/m5/config.py
+++ b/python/m5/config.py
@@ -29,6 +29,7 @@ import os, re, sys, types, inspect
from m5 import panic
from convert import *
+from multidict import multidict
noDot = False
try:
@@ -151,8 +152,11 @@ class Proxy(object):
self._multiplier = None
def __getattr__(self, attr):
+ # python uses __bases__ internally for inheritance
if attr == '__bases__':
return super(Proxy, self).__getattr__(self, attr)
+ if (self._path == None):
+ panic("Can't add attributes to 'any' proxy")
self._path.append((attr,None))
return self
@@ -198,6 +202,7 @@ class Proxy(object):
raise AttributeError, \
'Parent of %s type %s not found at path %s' \
% (base.name, ptype, self._path)
+
result, done = obj.find(ptype, self._path)
obj = obj.parent
@@ -322,17 +327,20 @@ class MetaConfigNode(type):
super(MetaConfigNode, cls).__init__(name, bases, dict)
# initialize required attributes
- cls._params = {}
- cls._values = {}
+ cls._params = multidict()
+ cls._values = multidict()
cls._param_types = {}
cls._bases = [c for c in cls.__mro__ if isConfigNode(c)]
cls._anon_subclass_counter = 0
- # If your parent has a value in it that's a config node, clone
- # it. Do this now so if we update any of the values'
- # attributes we are updating the clone and not the original.
- for base in cls._bases:
- for key,val in base._values.iteritems():
+ # We don't support multiple inheritence. If you want to, you
+ # must fix multidict to deal with it properly.
+ cnbase = [ base for base in bases if isConfigNode(base) ]
+ if len(cnbase) == 1:
+ # If your parent has a value in it that's a config node, clone
+ # it. Do this now so if we update any of the values'
+ # attributes we are updating the clone and not the original.
+ for key,val in cnbase[0]._values.iteritems():
# don't clone if (1) we're about to overwrite it with
# a local setting or (2) we've already cloned a copy
@@ -342,10 +350,17 @@ class MetaConfigNode(type):
if isConfigNode(val):
cls._values[key] = val()
- elif isSimObjSequence(val):
+ elif isSimObjSequence(val) and len(val):
cls._values[key] = [ v() for v in val ]
- elif isNullPointer(val):
- cls._values[key] = val
+
+ cls._params.parent = cnbase[0]._params
+ cls._values.parent = cnbase[0]._values
+
+ elif len(cnbase) > 1:
+ panic("""\
+The config hierarchy only supports single inheritence of SimObject
+classes. You're trying to derive from:
+%s""" % str(cnbase))
# process param types from _init_dict, as these may be needed
# by param descriptions also in _init_dict
@@ -359,9 +374,7 @@ class MetaConfigNode(type):
for key,val in cls._init_dict.items():
# param descriptions
if isinstance(val, _Param):
- cls._params[key] = val
- # try to resolve local param types in local param_types scope
- val.maybe_resolve_type(cls._param_types)
+ cls._new_param(key, val)
# init-time-only keywords
elif cls.init_keywords.has_key(key):
@@ -384,99 +397,6 @@ class MetaConfigNode(type):
else:
setattr(cls, key, val)
-
- def _isvalue(cls, name):
- for c in cls._bases:
- if c._params.has_key(name):
- return True
-
- for c in cls._bases:
- if c._values.has_key(name):
- return True
-
- return False
-
- # generator that iterates across all parameters for this class and
- # all classes it inherits from
- def _getparams(cls):
- params = {}
- for c in cls._bases:
- for p,v in c._params.iteritems():
- if not params.has_key(p):
- params[p] = v
- return params
-
- # Lookup a parameter description by name in the given class.
- def _getparam(cls, name, default = AttributeError):
- for c in cls._bases:
- if c._params.has_key(name):
- return c._params[name]
- if isSubClass(default, Exception):
- raise default, \
- "object '%s' has no attribute '%s'" % (cls.__name__, name)
- else:
- return default
-
- def _hasvalue(cls, name):
- for c in cls._bases:
- if c._values.has_key(name):
- return True
-
- return False
-
- def _getvalues(cls):
- values = {}
- for i,c in enumerate(cls._bases):
- for p,v in c._values.iteritems():
- if not values.has_key(p):
- values[p] = v
- for p,v in c._params.iteritems():
- if not values.has_key(p) and hasattr(v, 'default'):
- try:
- v.valid(v.default)
- except TypeError:
- panic("Invalid default %s for param %s in node %s"
- % (v.default,p,cls.__name__))
- v = v.default
- cls._setvalue(p, v)
- values[p] = v
-
- return values
-
- def _getvalue(cls, name, default = AttributeError):
- value = None
- for c in cls._bases:
- if c._values.has_key(name):
- value = c._values[name]
- break
- if value is not None:
- return value
-
- param = cls._getparam(name, None)
- if param is not None and hasattr(param, 'default'):
- param.valid(param.default)
- value = param.default
- cls._setvalue(name, value)
- return value
-
- if isSubClass(default, Exception):
- raise default, 'value for %s not found' % name
- else:
- return default
-
- def _setvalue(cls, name, value):
- cls._values[name] = value
-
- def __getattr__(cls, attr):
- if cls._isvalue(attr):
- return Value(cls, attr)
-
- if attr == '_cpp_param_decl' and hasattr(cls, 'type'):
- return cls.type + '*'
-
- raise AttributeError, \
- "object '%s' has no attribute '%s'" % (cls.__name__, attr)
-
def _set_keyword(cls, keyword, val, kwtype):
if not isinstance(val, kwtype):
raise TypeError, 'keyword %s has bad type %s (expecting %s)' % \
@@ -485,6 +405,13 @@ class MetaConfigNode(type):
val = classmethod(val)
type.__setattr__(cls, keyword, val)
+ def _new_param(cls, name, value):
+ cls._params[name] = value
+ if hasattr(value, 'default'):
+ cls._values[name] = value.default
+ # try to resolve local param types in local param_types scope
+ value.maybe_resolve_type(cls._param_types)
+
# Set attribute (called on foo.attr = value when foo is an
# instance of class cls).
def __setattr__(cls, attr, value):
@@ -498,23 +425,33 @@ class MetaConfigNode(type):
return
# must be SimObject param
- param = cls._getparam(attr, None)
+ param = cls._params.get(attr, None)
if param:
# It's ok: set attribute by delegating to 'object' class.
# Note the use of param.make_value() to verify/canonicalize
# the assigned value
try:
param.valid(value)
- except:
- panic("Error setting param %s.%s to %s\n" % \
- (cls.__name__, attr, value))
- cls._setvalue(attr, value)
+ except Exception, e:
+ panic("Exception: %s\nError setting param %s.%s to %s\n" % \
+ (e, cls.__name__, attr, value))
+ cls._values[attr] = value
elif isConfigNode(value) or isSimObjSequence(value):
- cls._setvalue(attr, value)
+ cls._values[attr] = value
else:
raise AttributeError, \
"Class %s has no parameter %s" % (cls.__name__, attr)
+ def __getattr__(cls, attr):
+ if cls._params.has_key(attr) or cls._values.has_key(attr):
+ return Value(cls, attr)
+
+ if attr == '_cpp_param_decl' and hasattr(cls, 'type'):
+ return cls.type + '*'
+
+ raise AttributeError, \
+ "object '%s' has no attribute '%s'" % (cls.__name__, attr)
+
def add_child(cls, instance, name, child):
if isNullPointer(child) or instance.top_child_names.has_key(name):
return
@@ -544,7 +481,7 @@ class MetaConfigNode(type):
if hasattr(cls, 'check'):
cls.check()
- for key,value in cls._getvalues().iteritems():
+ for key,value in cls._values.iteritems():
if isConfigNode(value):
cls.add_child(instance, key, value)
if isinstance(value, (list, tuple)):
@@ -552,11 +489,10 @@ class MetaConfigNode(type):
if len(vals):
cls.add_child(instance, key, vals)
- for pname,param in cls._getparams().iteritems():
- try:
- value = cls._getvalue(pname)
- except:
- panic('Error getting %s' % pname)
+ for pname,param in cls._params.iteritems():
+ value = cls._values.get(pname, None)
+ if value is None:
+ panic('Error getting %s from %s' % (pname, name))
try:
if isConfigNode(value):
@@ -573,10 +509,9 @@ class MetaConfigNode(type):
p = NodeParam(pname, param, value)
instance.params.append(p)
instance.param_names[pname] = p
- except:
- print 'Exception while evaluating %s.%s' % \
- (instance.path, pname)
- raise
+ except Exception, e:
+ raise e.__class__, 'Exception while evaluating %s.%s\n%s' % \
+ (instance.path, pname, e)
return instance
@@ -615,7 +550,7 @@ class ConfigNode(object):
cls._anon_subclass_counter += 1
return cls.__metaclass__(name, (cls, ), kwargs)
-class ParamContext(ConfigNode):
+class ParamContext(ConfigNode,ParamType):
pass
class MetaSimObject(MetaConfigNode):
@@ -757,9 +692,9 @@ class Node(object):
param.value = [ self.unproxy(pv, ptype) for pv in pval ]
else:
param.value = self.unproxy(pval, ptype)
- except:
- print 'Error while fixing up %s:%s' % (self.path, param.name)
- raise
+ except Exception, e:
+ raise e.__class__, 'Error while fixing up %s:%s\n%s' % \
+ (self.path, param.name, e)
for child in self.children:
assert(child != self)
@@ -778,9 +713,8 @@ class Node(object):
# before cpu0). Changing ordering can also influence timing
# in the current memory system, as caches get added to a bus
# in different orders which affects their priority in the
- # case of simulataneous requests. We should uncomment the
- # following line once we take care of that issue.
- # self.children.sort(lambda x,y: cmp(x.name, y.name))
+ # case of simulataneous requests.
+ self.children.sort(lambda x,y: cmp(x.name, y.name))
children = [ c.name for c in self.children if not c.paramcontext]
print 'children =', ' '.join(children)
@@ -792,9 +726,9 @@ class Node(object):
value = param.convert(param.value)
string = param.string(value)
- except:
- print 'exception in %s:%s' % (self.path, param.name)
- raise
+ except Exception, e:
+ raise e.__class__, 'exception in %s:%s\n%s' % \
+ (self.path, param.name, e)
print '%s = %s' % (param.name, string)
@@ -827,8 +761,9 @@ class Node(object):
value = param.convert(param.value)
string = param.string(value)
- except:
- print 'exception in %s:%s' % (self.name, param.name)
+ except Exception, e:
+ raise e.__class__, 'exception in %s:%s\n%s' % \
+ (self.name, param.name, e)
raise
if isConfigNode(param.ptype) and string != "Null":
simobjs.append(string)
@@ -837,7 +772,8 @@ class Node(object):
for so in simobjs:
label += "|<%s> %s" % (so, so)
- dot.add_edge(pydot.Edge("%s:%s" % (self.path, so), so, tailport="w"))
+ dot.add_edge(pydot.Edge("%s:%s" % (self.path, so), so,
+ tailport="w"))
label += '}'
dot.add_node(pydot.Node(self.path,shape="Mrecord",label=label))
@@ -877,7 +813,7 @@ class Value(object):
super(Value, self).__setattr__('obj', obj)
def _getattr(self):
- return self.obj._getvalue(self.attr)
+ return self.obj._values.get(self.attr)
def __setattr__(self, attr, value):
setattr(self._getattr(), attr, value)
diff --git a/python/m5/convert.py b/python/m5/convert.py
index b3f34e4ab..2ebe93889 100644
--- a/python/m5/convert.py
+++ b/python/m5/convert.py
@@ -22,7 +22,7 @@ pebi = tebi * 1024
exbi = pebi * 1024
# memory size configuration stuff
-def to_integer(value):
+def toInteger(value):
if not isinstance(value, str):
result = int(value)
elif value.endswith('Ei'):
@@ -64,7 +64,7 @@ def to_integer(value):
return result
-def to_bool(val):
+def toBool(val):
t = type(val)
if t == bool:
return val
@@ -82,9 +82,9 @@ def to_bool(val):
elif val == "false" or val == "f" or val == "no" or val == "n":
return False
- return to_integer(val) != 0
+ return toInteger(val) != 0
-def to_frequency(value):
+def toFrequency(value):
if not isinstance(value, str):
result = float(value)
elif value.endswith('THz'):
@@ -102,7 +102,7 @@ def to_frequency(value):
return result
-def to_latency(value):
+def toLatency(value):
if not isinstance(value, str):
result = float(value)
elif value.endswith('c'):
@@ -122,7 +122,7 @@ def to_latency(value):
return result;
-def to_network_bandwidth(value):
+def toNetworkBandwidth(value):
if not isinstance(value, str):
result = float(value)
elif value.endswith('Tbps'):
@@ -140,7 +140,7 @@ def to_network_bandwidth(value):
return result
-def to_memory_bandwidth(value):
+def toMemoryBandwidth(value):
if not isinstance(value, str):
result = int(value)
elif value.endswith('PB/s'):
@@ -160,7 +160,7 @@ def to_memory_bandwidth(value):
return result
-def to_memory_size(value):
+def toMemorySize(value):
if not isinstance(value, str):
result = int(value)
elif value.endswith('PB'):
diff --git a/python/m5/multidict.py b/python/m5/multidict.py
new file mode 100644
index 000000000..d0c27fa8e
--- /dev/null
+++ b/python/m5/multidict.py
@@ -0,0 +1,158 @@
+__all__ = [ 'multidict' ]
+
+class multidict(object):
+ __nodefault = object()
+ def __init__(self, parent = {}, **kwargs):
+ self.dict = dict(**kwargs)
+ self.parent = parent
+ self.deleted = {}
+
+ def __str__(self):
+ return str(dict(self.items()))
+
+ def __repr__(self):
+ return `dict(self.items())`
+
+ def __contains__(self, key):
+ return self.dict.has_key(key) or self.parent.has_key(key)
+
+ def __delitem__(self, key):
+ try:
+ del self.dict[key]
+ except KeyError, e:
+ if key in self.parent:
+ self.deleted[key] = True
+ else:
+ raise KeyError, e
+
+ def __setitem__(self, key, value):
+ self.deleted.pop(key, False)
+ self.dict[key] = value
+
+ def __getitem__(self, key):
+ try:
+ return self.dict[key]
+ except KeyError, e:
+ if not self.deleted.get(key, False) and key in self.parent:
+ return self.parent[key]
+ else:
+ raise KeyError, e
+
+ def __len__(self):
+ return len(self.dict) + len(self.parent)
+
+ def next(self):
+ for key,value in self.dict.items():
+ yield key,value
+
+ if self.parent:
+ for key,value in self.parent.next():
+ if key not in self.dict and key not in self.deleted:
+ yield key,value
+
+ def has_key(self, key):
+ return key in self
+
+ def iteritems(self):
+ for item in self.next():
+ yield item
+
+ def items(self):
+ return [ item for item in self.next() ]
+
+ def iterkeys(self):
+ for key,value in self.next():
+ yield key
+
+ def keys(self):
+ return [ key for key,value in self.next() ]
+
+ def itervalues(self):
+ for key,value in self.next():
+ yield value
+
+ def values(self):
+ return [ value for key,value in self.next() ]
+
+ def get(self, key, default=__nodefault):
+ try:
+ return self[key]
+ except KeyError, e:
+ if default != self.__nodefault:
+ return default
+ else:
+ raise KeyError, e
+
+ def setdefault(self, key, default):
+ try:
+ return self[key]
+ except KeyError:
+ self.deleted.pop(key, False)
+ self.dict[key] = default
+ return default
+
+ def _dump(self):
+ print 'multidict dump'
+ node = self
+ while isinstance(node, multidict):
+ print ' ', node.dict
+ node = node.parent
+
+ def _dumpkey(self, key):
+ values = []
+ node = self
+ while isinstance(node, multidict):
+ if key in node.dict:
+ values.append(node.dict[key])
+ node = node.parent
+ print key, values
+
+if __name__ == '__main__':
+ test1 = multidict()
+ test2 = multidict(test1)
+ test3 = multidict(test2)
+ test4 = multidict(test3)
+
+ test1['a'] = 'test1_a'
+ test1['b'] = 'test1_b'
+ test1['c'] = 'test1_c'
+ test1['d'] = 'test1_d'
+ test1['e'] = 'test1_e'
+
+ test2['a'] = 'test2_a'
+ del test2['b']
+ test2['c'] = 'test2_c'
+ del test1['a']
+
+ test2.setdefault('f', multidict)
+
+ print 'test1>', test1.items()
+ print 'test2>', test2.items()
+ #print test1['a']
+ print test1['b']
+ print test1['c']
+ print test1['d']
+ print test1['e']
+
+ print test2['a']
+ #print test2['b']
+ print test2['c']
+ print test2['d']
+ print test2['e']
+
+ for key in test2.iterkeys():
+ print key
+
+ test2.get('g', 'foo')
+ #test2.get('b')
+ test2.get('b', 'bar')
+ test2.setdefault('b', 'blah')
+ print test1
+ print test2
+ print `test2`
+
+ print len(test2)
+
+ test3['a'] = [ 0, 1, 2, 3 ]
+
+ print test4
diff --git a/python/m5/smartdict.py b/python/m5/smartdict.py
index 1ba5d8410..0dbcc50b0 100644
--- a/python/m5/smartdict.py
+++ b/python/m5/smartdict.py
@@ -20,13 +20,13 @@ class SmartDict(dict):
class Proxy(str):
def __int__(self):
- return int(to_integer(str(self)))
+ return int(toInteger(str(self)))
def __long__(self):
- return long(to_integer(str(self)))
+ return long(toInteger(str(self)))
def __float__(self):
- return float(to_integer(str(self)))
+ return float(toInteger(str(self)))
def __nonzero__(self):
- return to_bool(str(self))
+ return toBool(str(self))
def convert(self, other):
t = type(other)
if t == bool: