40bab977bc
python/m5/config.py: Addr is slightly different from memory size in that Addr will take non strings. Deal with the fact that the convert.toFoo functions only accept strings. Add RootFrequency as a special type for the Root.frequency parameter which is not scaled. Add ClockPeriod parameter type. python/m5/convert.py: Be more strict about what's allowed. Only accept strings as inputs for these conversion functions. If the user wants to accept something else, they need to deal with the failure and convert other types on their own. python/m5/objects/Bus.mpy: Use the new ClockPeriod parameter type python/m5/objects/Root.mpy: Can't use integers for frequency anymore python/m5/smartdict.py: rename SmartDict.Proxy to just Variable. Create a new class UndefinedVariable that is returned when the user tries to get a variable that is not in the dict. Undefined variable evaluates to false, and will cause an error elsewhere. --HG-- extra : convert_revision : 1d55246fd1af65106f102396234827d6401ef9ce
126 lines
4.3 KiB
Python
126 lines
4.3 KiB
Python
# The SmartDict class fixes a couple of issues with using the content
|
|
# of os.environ or similar dicts of strings as Python variables:
|
|
#
|
|
# 1) Undefined variables should return False rather than raising KeyError.
|
|
#
|
|
# 2) String values of 'False', '0', etc., should evaluate to False
|
|
# (not just the empty string).
|
|
#
|
|
# #1 is solved by overriding __getitem__, and #2 is solved by using a
|
|
# proxy class for values and overriding __nonzero__ on the proxy.
|
|
# Everything else is just to (a) make proxies behave like normal
|
|
# values otherwise, (b) make sure any dict operation returns a proxy
|
|
# rather than a normal value, and (c) coerce values written to the
|
|
# dict to be strings.
|
|
|
|
|
|
from convert import *
|
|
|
|
class Variable(str):
|
|
"""Intelligent proxy class for SmartDict. Variable will use the
|
|
various convert functions to attempt to convert values to useable
|
|
types"""
|
|
def __int__(self):
|
|
return toInteger(str(self))
|
|
def __long__(self):
|
|
return toLong(str(self))
|
|
def __float__(self):
|
|
return toFloat(str(self))
|
|
def __nonzero__(self):
|
|
return toBool(str(self))
|
|
def convert(self, other):
|
|
t = type(other)
|
|
if t == bool:
|
|
return bool(self)
|
|
if t == int:
|
|
return int(self)
|
|
if t == long:
|
|
return long(self)
|
|
if t == float:
|
|
return float(self)
|
|
return str(self)
|
|
def __lt__(self, other):
|
|
return self.convert(other) < other
|
|
def __le__(self, other):
|
|
return self.convert(other) <= other
|
|
def __eq__(self, other):
|
|
return self.convert(other) == other
|
|
def __ne__(self, other):
|
|
return self.convert(other) != other
|
|
def __gt__(self, other):
|
|
return self.convert(other) > other
|
|
def __ge__(self, other):
|
|
return self.convert(other) >= other
|
|
|
|
def __add__(self, other):
|
|
return self.convert(other) + other
|
|
def __sub__(self, other):
|
|
return self.convert(other) - other
|
|
def __mul__(self, other):
|
|
return self.convert(other) * other
|
|
def __div__(self, other):
|
|
return self.convert(other) / other
|
|
def __truediv__(self, other):
|
|
return self.convert(other) / other
|
|
|
|
def __radd__(self, other):
|
|
return other + self.convert(other)
|
|
def __rsub__(self, other):
|
|
return other - self.convert(other)
|
|
def __rmul__(self, other):
|
|
return other * self.convert(other)
|
|
def __rdiv__(self, other):
|
|
return other / self.convert(other)
|
|
def __rtruediv__(self, other):
|
|
return other / self.convert(other)
|
|
|
|
class UndefinedVariable(object):
|
|
"""Placeholder class to represent undefined variables. Will
|
|
generally cause an exception whenever it is used, but evaluates to
|
|
zero for boolean truth testing such as in an if statement"""
|
|
def __nonzero__(self):
|
|
return False
|
|
|
|
class SmartDict(dict):
|
|
"""Dictionary class that holds strings, but intelligently converts
|
|
those strings to other types depending on their usage"""
|
|
|
|
def __getitem__(self, key):
|
|
"""returns a Variable proxy if the values exists in the database and
|
|
returns an UndefinedVariable otherwise"""
|
|
|
|
if key in self:
|
|
return Variable(dict.get(self, key))
|
|
else:
|
|
# Note that this does *not* change the contents of the dict,
|
|
# so that even after we call env['foo'] we still get a
|
|
# meaningful answer from "'foo' in env" (which
|
|
# calls dict.__contains__, which we do not override).
|
|
return UndefinedVariable()
|
|
|
|
def __setitem__(self, key, item):
|
|
"""intercept the setting of any variable so that we always
|
|
store strings in the dict"""
|
|
dict.__setitem__(self, key, str(item))
|
|
|
|
def values(self):
|
|
return [ Variable(v) for v in dict.values(self) ]
|
|
|
|
def itervalues(self):
|
|
for value in dict.itervalues(self):
|
|
yield Variable(value)
|
|
|
|
def items(self):
|
|
return [ (k, Variable(v)) for k,v in dict.items(self) ]
|
|
|
|
def iteritems(self):
|
|
for key,value in dict.iteritems(self):
|
|
yield key, Variable(value)
|
|
|
|
def get(self, key, default='False'):
|
|
return Variable(dict.get(self, key, str(default)))
|
|
|
|
def setdefault(self, key, default='False'):
|
|
return Variable(dict.setdefault(self, key, str(default)))
|
|
|
|
__all__ = [ 'SmartDict' ]
|