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 Frequency(int,ParamType): +class RootFrequency(float,ParamType): _cpp_param_decl = 'Tick' def __new__(cls, value): - if isinstance(value, basestring): - val = int(env['FREQUENCY'] / toFrequency(value)) - else: - val = toFrequency(value) - return super(cls, Frequency).__new__(cls, val) + return super(cls, RootFrequency).__new__(cls, toFrequency(value)) def _convert(cls, value): return cls(value) _convert = classmethod(_convert) def _string(cls, value): - return '%d' % value + return '%d' % int(value) _string = classmethod(_string) -class Latency(int,ParamType): +class ClockPeriod(float,ParamType): _cpp_param_decl = 'Tick' def __new__(cls, value): - if isinstance(value, basestring): - val = int(env['FREQUENCY'] * toLatency(value)) - else: - val = toLatency(value) - return super(cls, Latency).__new__(cls, val) + 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): + relative = False + try: + val = toFrequency(value) + 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): + if not value.relative: + value = root_frequency / value + + return '%d' % int(value) + _string = classmethod(_string) + +class Latency(float,ParamType): + _cpp_param_decl = 'Tick' + def __new__(cls, value): + relative = False + try: + val = toLatency(value) + 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 result + +def toBool(value): + if not isinstance(value, str): + raise TypeError, "wrong type '%s' should be str" % type(value) + + 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 - if t == int or t == long: - return bool(val) - - 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 - - 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 - elif value.endswith('GHz'): - result = float(value[:-3]) * giga - elif value.endswith('MHz'): - result = float(value[:-3]) * mega - elif value.endswith('kHz'): - result = float(value[:-3]) * kilo - elif value.endswith('Hz'): - result = float(value[:-2]) - else: - result = float(value) + raise TypeError, "wrong type '%s' should be str" % type(value) - return result + if value.endswith('THz'): + return float(value[:-3]) * tera + elif value.endswith('GHz'): + return float(value[:-3]) * giga + elif value.endswith('MHz'): + return float(value[:-3]) * mega + elif value.endswith('kHz'): + return float(value[:-3]) * kilo + elif value.endswith('Hz'): + return float(value[:-2]) + + 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 - elif value.endswith('ns'): - result = float(value[:-2]) * nano - elif value.endswith('us'): - result = float(value[:-2]) * micro - elif value.endswith('ms'): - result = float(value[:-2]) * milli - elif value.endswith('s'): - result = float(value[:-1]) - else: - result = float(value) + raise TypeError, "wrong type '%s' should be str" % type(value) + + if value.endswith('ps'): + return float(value[:-2]) * pico + elif value.endswith('ns'): + return float(value[:-2]) * nano + elif value.endswith('us'): + return float(value[:-2]) * micro + elif value.endswith('ms'): + return float(value[:-2]) * milli + elif value.endswith('s'): + 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 - elif value.endswith('Gbps'): - result = float(value[:-3]) * giga - elif value.endswith('Mbps'): - result = float(value[:-3]) * mega - elif value.endswith('kbps'): - result = float(value[:-3]) * kilo - elif value.endswith('bps'): - result = float(value[:-2]) - else: - result = float(value) + raise TypeError, "wrong type '%s' should be str" % type(value) - return result + if value.endswith('Tbps'): + return float(value[:-3]) * tera + elif value.endswith('Gbps'): + return float(value[:-3]) * giga + elif value.endswith('Mbps'): + return float(value[:-3]) * mega + elif value.endswith('kbps'): + return float(value[:-3]) * kilo + elif value.endswith('bps'): + return float(value[:-2]) + else: + return float(value) + + 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 - elif value.endswith('TB/s'): - result = int(value[:-4]) * tebi - elif value.endswith('GB/s'): - result = int(value[:-4]) * gibi - elif value.endswith('MB/s'): - result = int(value[:-4]) * mebi - elif value.endswith('kB/s'): - result = int(value[:-4]) * kibi - elif value.endswith('B/s'): - result = int(value[:-3]) - else: - result = int(value) + raise TypeError, "wrong type '%s' should be str" % type(value) - return result + if value.endswith('PB/s'): + return float(value[:-4]) * pebi + elif value.endswith('TB/s'): + return float(value[:-4]) * tebi + elif value.endswith('GB/s'): + return float(value[:-4]) * gibi + elif value.endswith('MB/s'): + return float(value[:-4]) * mebi + elif value.endswith('kB/s'): + return float(value[:-4]) * kibi + elif value.endswith('B/s'): + return float(value[:-3]) + + 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 - elif value.endswith('TB'): - result = int(value[:-2]) * tebi - elif value.endswith('GB'): - result = int(value[:-2]) * gibi - elif value.endswith('MB'): - result = int(value[:-2]) * mebi - elif value.endswith('kB'): - result = int(value[:-2]) * kibi - elif value.endswith('B'): - result = int(value[:-1]) - else: - result = int(value) + raise TypeError, "wrong type '%s' should be str" % type(value) - return result + if value.endswith('PB'): + return float(value[:-2]) * pebi + elif value.endswith('TB'): + return float(value[:-2]) * tebi + elif value.endswith('GB'): + return float(value[:-2]) * gibi + elif value.endswith('MB'): + return float(value[:-2]) * mebi + elif value.endswith('kB'): + return float(value[:-2]) * kibi + elif value.endswith('B'): + return float(value[:-1]) + + 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' ]