Merge ktlim@zizzer.eecs.umich.edu:/bk/m5

into zamp.eecs.umich.edu:/z/ktlim2/m5

--HG--
extra : convert_revision : 0c750652cc2b59946160994d53c921cb021ceef4
This commit is contained in:
Kevin Lim 2005-03-22 15:34:08 -05:00
commit 2ec918362e
5 changed files with 246 additions and 152 deletions

View file

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

View file

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

View file

@ -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'):

158
python/m5/multidict.py Normal file
View file

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

View file

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