summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--python/m5/config.py125
-rw-r--r--python/m5/convert.py205
-rw-r--r--python/m5/objects/Bus.mpy2
-rw-r--r--python/m5/objects/Root.mpy2
-rw-r--r--python/m5/smartdict.py156
5 files changed, 310 insertions, 180 deletions
diff --git a/python/m5/config.py b/python/m5/config.py
index 3b5d94b15..a791bbebf 100644
--- a/python/m5/config.py
+++ b/python/m5/config.py
@@ -1160,8 +1160,24 @@ class MemorySize(CheckedInt):
return '%d' % value
_string = classmethod(_string)
-class Addr(MemorySize):
- pass
+class Addr(CheckedInt):
+ cppname = 'Addr'
+ size = 64
+ unsigned = True
+ def __new__(cls, value):
+ try:
+ value = long(toMemorySize(value))
+ except TypeError:
+ value = long(value)
+ return super(Addr, cls).__new__(cls, value)
+
+ def _convert(cls, value):
+ return cls(value)
+ _convert = classmethod(_convert)
+
+ def _string(cls, value):
+ return '%d' % value
+ _string = classmethod(_string)
class AddrRange(Range):
type = Addr
@@ -1169,15 +1185,18 @@ class AddrRange(Range):
# Boolean parameter type.
class Bool(ParamType):
_cpp_param_decl = 'bool'
- #def __new__(cls, value):
- # return super(MemorySize, cls).__new__(cls, toBool(value))
+ def __init__(self, value):
+ try:
+ self.value = toBool(value)
+ except TypeError:
+ self.value = bool(value)
def _convert(cls, value):
- return toBool(value)
+ return cls(value)
_convert = classmethod(_convert)
def _string(cls, value):
- if value:
+ if value.value:
return "true"
else:
return "false"
@@ -1344,42 +1363,109 @@ class Enum(ParamType):
def _string(self, value):
return str(value)
_string = classmethod(_string)
+
+root_frequency = None
+
#
# "Constants"... handy aliases for various values.
#
+class RootFrequency(float,ParamType):
+ _cpp_param_decl = 'Tick'
-class Frequency(int,ParamType):
+ def __new__(cls, value):
+ return super(cls, RootFrequency).__new__(cls, toFrequency(value))
+
+ def _convert(cls, value):
+ return cls(value)
+ _convert = classmethod(_convert)
+
+ def _string(cls, value):
+ return '%d' % int(value)
+ _string = classmethod(_string)
+
+class ClockPeriod(float,ParamType):
+ _cpp_param_decl = 'Tick'
+ def __new__(cls, value):
+ relative = False
+ try:
+ val = toClockPeriod(value)
+ except ValueError, e:
+ relative = True
+ if value.endswith('f'):
+ val = float(value[:-1])
+ if val:
+ val = 1 / val
+ elif value.endswith('c'):
+ val = float(value[:-1])
+ else:
+ raise e
+
+ self = super(cls, ClockPeriod).__new__(cls, val)
+ self.relative = relative
+ return self
+
+ def _convert(cls, value):
+ return cls(value)
+ _convert = classmethod(_convert)
+
+ def _string(cls, value):
+ if not value.relative:
+ value *= root_frequency
+
+ return '%d' % int(value)
+ _string = classmethod(_string)
+
+class Frequency(float,ParamType):
_cpp_param_decl = 'Tick'
def __new__(cls, value):
- if isinstance(value, basestring):
- val = int(env['FREQUENCY'] / toFrequency(value))
- else:
+ relative = False
+ try:
val = toFrequency(value)
- return super(cls, Frequency).__new__(cls, val)
+ except ValueError, e:
+ if value.endswith('f'):
+ val = float(value[:-1])
+ relative = True
+ else:
+ raise e
+ self = super(cls, Frequency).__new__(cls, val)
+ self.relative = relative
+ return self
def _convert(cls, value):
return cls(value)
_convert = classmethod(_convert)
def _string(cls, value):
- return '%d' % value
+ if not value.relative:
+ value = root_frequency / value
+
+ return '%d' % int(value)
_string = classmethod(_string)
-class Latency(int,ParamType):
+class Latency(float,ParamType):
_cpp_param_decl = 'Tick'
def __new__(cls, value):
- if isinstance(value, basestring):
- val = int(env['FREQUENCY'] * toLatency(value))
- else:
+ relative = False
+ try:
val = toLatency(value)
- return super(cls, Latency).__new__(cls, val)
+ except ValueError, e:
+ if value.endswith('c'):
+ val = float(value[:-1])
+ relative = True
+ else:
+ raise e
+ self = super(cls, Latency).__new__(cls, val)
+ self.relative = relative
+ return self
def _convert(cls, value):
return cls(value)
_convert = classmethod(_convert)
def _string(cls, value):
+ if not value.relative:
+ value *= root_frequency
return '%d' % value
_string = classmethod(_string)
@@ -1394,7 +1480,9 @@ AllMemory = AddrRange(0, MaxAddr)
# The final hook to generate .ini files. Called from configuration
# script once config is built.
def instantiate(root):
+ global root_frequency
instance = root.instantiate('root')
+ root_frequency = RootFrequency._convert(root.frequency._getattr())
instance.fixup()
instance.display()
if not noDot:
@@ -1427,6 +1515,7 @@ __all__ = ['ConfigNode', 'SimObject', 'ParamContext', 'Param', 'VectorParam',
'Int', 'Unsigned', 'Int8', 'UInt8', 'Int16', 'UInt16',
'Int32', 'UInt32', 'Int64', 'UInt64',
'Counter', 'Addr', 'Tick', 'Percent',
- 'MemorySize', 'Frequency', 'Latency',
+ 'MemorySize', 'RootFrequency', 'Frequency', 'Latency',
+ 'ClockPeriod',
'Range', 'AddrRange', 'MaxAddr', 'MaxTick', 'AllMemory', 'NULL',
'NextEthernetAddr', 'instantiate']
diff --git a/python/m5/convert.py b/python/m5/convert.py
index 4a4492af7..6ccefd2fc 100644
--- a/python/m5/convert.py
+++ b/python/m5/convert.py
@@ -22,162 +22,185 @@ pebi = tebi * 1024
exbi = pebi * 1024
# memory size configuration stuff
-def toInteger(value):
+def toFloat(value):
if not isinstance(value, str):
- result = int(value)
- elif value.endswith('Ei'):
- result = int(value[:-2]) * exbi
+ raise TypeError, "wrong type '%s' should be str" % type(value)
+
+ if value.endswith('Ei'):
+ return float(value[:-2]) * exbi
elif value.endswith('Pi'):
- result = int(value[:-2]) * pebi
+ return float(value[:-2]) * pebi
elif value.endswith('Ti'):
- result = int(value[:-2]) * tebi
+ return float(value[:-2]) * tebi
elif value.endswith('Gi'):
- result = int(value[:-2]) * gibi
+ return float(value[:-2]) * gibi
elif value.endswith('Mi'):
- result = int(value[:-2]) * mebi
+ return float(value[:-2]) * mebi
elif value.endswith('ki'):
- result = int(value[:-2]) * kibi
+ return float(value[:-2]) * kibi
elif value.endswith('E'):
- result = int(value[:-1]) * exa
+ return float(value[:-1]) * exa
elif value.endswith('P'):
- result = int(value[:-1]) * peta
+ return float(value[:-1]) * peta
elif value.endswith('T'):
- result = int(value[:-1]) * tera
+ return float(value[:-1]) * tera
elif value.endswith('G'):
- result = int(value[:-1]) * giga
+ return float(value[:-1]) * giga
elif value.endswith('M'):
- result = int(value[:-1]) * mega
+ return float(value[:-1]) * mega
elif value.endswith('k'):
- result = int(value[:-1]) * kilo
+ return float(value[:-1]) * kilo
elif value.endswith('m'):
- result = int(value[:-1]) * milli
+ return float(value[:-1]) * milli
elif value.endswith('u'):
- result = int(value[:-1]) * micro
+ return float(value[:-1]) * micro
elif value.endswith('n'):
- result = int(value[:-1]) * nano
+ return float(value[:-1]) * nano
elif value.endswith('p'):
- result = int(value[:-1]) * pico
+ return float(value[:-1]) * pico
elif value.endswith('f'):
- result = int(value[:-1]) * femto
+ return float(value[:-1]) * femto
else:
- result = int(float(value))
+ return float(value)
+
+def toLong(value):
+ value = toFloat(value)
+ result = int(value)
+ if value != result:
+ raise ValueError, "cannot convert '%s' to long" % value
return result
-def toBool(val):
- t = type(val)
- if t == bool:
- return val
+def toInteger(value):
+ value = toFloat(value)
+ result = int(value)
+ if value != result:
+ raise ValueError, "cannot convert '%s' to integer" % value
- if t == None:
- return False
+ return result
- if t == int or t == long:
- return bool(val)
+def toBool(value):
+ if not isinstance(value, str):
+ raise TypeError, "wrong type '%s' should be str" % type(value)
- if t == str:
- val = val.lower()
- if val == "true" or val == "t" or val == "yes" or val == "y":
- return True
- elif val == "false" or val == "f" or val == "no" or val == "n":
- return False
- elif val == "":
- return False
+ value = value.lower()
+ if value == "true" or value == "t" or value == "yes" or value == "y":
+ return True
+ elif value == "false" or value == "f" or value == "no" or value == "n":
+ return False
- return toInteger(val) != 0
+ raise ValueError, "cannot convert '%s' to bool" % value
def toFrequency(value):
if not isinstance(value, str):
- result = float(value)
- elif value.endswith('THz'):
- result = float(value[:-3]) * tera
+ raise TypeError, "wrong type '%s' should be str" % type(value)
+
+ if value.endswith('THz'):
+ return float(value[:-3]) * tera
elif value.endswith('GHz'):
- result = float(value[:-3]) * giga
+ return float(value[:-3]) * giga
elif value.endswith('MHz'):
- result = float(value[:-3]) * mega
+ return float(value[:-3]) * mega
elif value.endswith('kHz'):
- result = float(value[:-3]) * kilo
+ return float(value[:-3]) * kilo
elif value.endswith('Hz'):
- result = float(value[:-2])
- else:
- result = float(value)
+ return float(value[:-2])
- return result
+ raise ValueError, "cannot convert '%s' to frequency" % value
def toLatency(value):
if not isinstance(value, str):
- result = float(value)
- elif value.endswith('c'):
- result = float(value[:-1])
- elif value.endswith('ps'):
- result = float(value[:-2]) * pico
+ raise TypeError, "wrong type '%s' should be str" % type(value)
+
+ if value.endswith('ps'):
+ return float(value[:-2]) * pico
elif value.endswith('ns'):
- result = float(value[:-2]) * nano
+ return float(value[:-2]) * nano
elif value.endswith('us'):
- result = float(value[:-2]) * micro
+ return float(value[:-2]) * micro
elif value.endswith('ms'):
- result = float(value[:-2]) * milli
+ return float(value[:-2]) * milli
elif value.endswith('s'):
- result = float(value[:-1])
- else:
- result = float(value)
+ return float(value[:-1])
+
+ raise ValueError, "cannot convert '%s' to latency" % value
+
+def toClockPeriod(value):
+ """result is a clock period"""
+
+ if not isinstance(value, str):
+ raise TypeError, "wrong type '%s' should be str" % type(value)
+
+ try:
+ val = toFrequency(value)
+ if val != 0:
+ val = 1 / val
+ return val
+ except ValueError:
+ pass
+
+ try:
+ val = toLatency(value)
+ return val
+ except ValueError:
+ pass
+
+ raise ValueError, "cannot convert '%s' to clock period" % value
- return result;
def toNetworkBandwidth(value):
if not isinstance(value, str):
- result = float(value)
- elif value.endswith('Tbps'):
- result = float(value[:-3]) * tera
+ raise TypeError, "wrong type '%s' should be str" % type(value)
+
+ if value.endswith('Tbps'):
+ return float(value[:-3]) * tera
elif value.endswith('Gbps'):
- result = float(value[:-3]) * giga
+ return float(value[:-3]) * giga
elif value.endswith('Mbps'):
- result = float(value[:-3]) * mega
+ return float(value[:-3]) * mega
elif value.endswith('kbps'):
- result = float(value[:-3]) * kilo
+ return float(value[:-3]) * kilo
elif value.endswith('bps'):
- result = float(value[:-2])
+ return float(value[:-2])
else:
- result = float(value)
+ return float(value)
- return result
+ raise ValueError, "cannot convert '%s' to network bandwidth" % value
def toMemoryBandwidth(value):
if not isinstance(value, str):
- result = int(value)
- elif value.endswith('PB/s'):
- result = int(value[:-4]) * pebi
+ raise TypeError, "wrong type '%s' should be str" % type(value)
+
+ if value.endswith('PB/s'):
+ return float(value[:-4]) * pebi
elif value.endswith('TB/s'):
- result = int(value[:-4]) * tebi
+ return float(value[:-4]) * tebi
elif value.endswith('GB/s'):
- result = int(value[:-4]) * gibi
+ return float(value[:-4]) * gibi
elif value.endswith('MB/s'):
- result = int(value[:-4]) * mebi
+ return float(value[:-4]) * mebi
elif value.endswith('kB/s'):
- result = int(value[:-4]) * kibi
+ return float(value[:-4]) * kibi
elif value.endswith('B/s'):
- result = int(value[:-3])
- else:
- result = int(value)
+ return float(value[:-3])
- return result
+ raise ValueError, "cannot convert '%s' to memory bandwidth" % value
def toMemorySize(value):
if not isinstance(value, str):
- result = int(value)
- elif value.endswith('PB'):
- result = int(value[:-2]) * pebi
+ raise TypeError, "wrong type '%s' should be str" % type(value)
+
+ if value.endswith('PB'):
+ return float(value[:-2]) * pebi
elif value.endswith('TB'):
- result = int(value[:-2]) * tebi
+ return float(value[:-2]) * tebi
elif value.endswith('GB'):
- result = int(value[:-2]) * gibi
+ return float(value[:-2]) * gibi
elif value.endswith('MB'):
- result = int(value[:-2]) * mebi
+ return float(value[:-2]) * mebi
elif value.endswith('kB'):
- result = int(value[:-2]) * kibi
+ return float(value[:-2]) * kibi
elif value.endswith('B'):
- result = int(value[:-1])
- else:
- result = int(value)
+ return float(value[:-1])
- return result
+ raise ValueError, "cannot convert '%s' to memory size" % value
diff --git a/python/m5/objects/Bus.mpy b/python/m5/objects/Bus.mpy
index 330a2c82b..aa12f757a 100644
--- a/python/m5/objects/Bus.mpy
+++ b/python/m5/objects/Bus.mpy
@@ -2,5 +2,5 @@ from BaseHier import BaseHier
simobj Bus(BaseHier):
type = 'Bus'
- clock_ratio = Param.Frequency("ratio of CPU to bus frequency")
+ clock_ratio = Param.ClockPeriod("ratio of CPU to bus frequency")
width = Param.Int("bus width in bytes")
diff --git a/python/m5/objects/Root.mpy b/python/m5/objects/Root.mpy
index 0e531054b..c535bd2dc 100644
--- a/python/m5/objects/Root.mpy
+++ b/python/m5/objects/Root.mpy
@@ -5,7 +5,7 @@ from Trace import Trace
simobj Root(SimObject):
type = 'Root'
- frequency = Param.Tick(200000000, "tick frequency")
+ frequency = Param.RootFrequency('200MHz', "tick frequency")
output_file = Param.String('cout', "file to dump simulator output to")
full_system = Param.Bool("Full system simulation?")
hier = HierParams(do_data = False, do_events = True)
diff --git a/python/m5/smartdict.py b/python/m5/smartdict.py
index 0dbcc50b0..a2661c279 100644
--- a/python/m5/smartdict.py
+++ b/python/m5/smartdict.py
@@ -16,93 +16,111 @@
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"""
- class Proxy(str):
- def __int__(self):
- return int(toInteger(str(self)))
- def __long__(self):
- return long(toInteger(str(self)))
- def __float__(self):
- return float(toInteger(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)
-
-
- # __getitem__ uses dict.get() to return 'False' if the key is not
- # found (rather than raising KeyError). Note that this does *not*
- # set the key's value to 'False' in 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).
def __getitem__(self, key):
- return self.Proxy(dict.get(self, key, 'False'))
+ """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 [ self.Proxy(v) for v in dict.values(self) ]
+ return [ Variable(v) for v in dict.values(self) ]
def itervalues(self):
for value in dict.itervalues(self):
- yield self.Proxy(value)
+ yield Variable(value)
def items(self):
- return [ (k, self.Proxy(v)) for k,v in dict.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, self.Proxy(value)
+ yield key, Variable(value)
def get(self, key, default='False'):
- return self.Proxy(dict.get(self, key, str(default)))
+ return Variable(dict.get(self, key, str(default)))
def setdefault(self, key, default='False'):
- return self.Proxy(dict.setdefault(self, key, str(default)))
+ return Variable(dict.setdefault(self, key, str(default)))
+__all__ = [ 'SmartDict' ]