Deleted Added
sdiff udiff text old ( 3092:7ed45e2f407e ) new ( 3100:fdd6113d7226 )
full compact
1# Copyright (c) 2004-2006 The Regents of The University of Michigan
2# All rights reserved.
3#
4# Redistribution and use in source and binary forms, with or without
5# modification, are permitted provided that the following conditions are
6# met: redistributions of source code must retain the above copyright
7# notice, this list of conditions and the following disclaimer;
8# redistributions in binary form must reproduce the above copyright

--- 127 unchanged lines hidden (view full) ---

136# that derive from SimObject are instantiated, and provides inherited
137# class behavior (just like a class controls how instances of that
138# class are instantiated, and provides inherited instance behavior).
139class MetaSimObject(type):
140 # Attributes that can be set only at initialization time
141 init_keywords = { 'abstract' : types.BooleanType,
142 'type' : types.StringType }
143 # Attributes that can be set any time
144 keywords = { 'check' : types.FunctionType }
145
146 # __new__ is called before __init__, and is where the statements
147 # in the body of the class definition get loaded into the class's
148 # __dict__. We intercept this to filter out parameter & port assignments
149 # and only allow "private" attributes to be passed to the base
150 # __new__ (starting with underscore).
151 def __new__(mcls, name, bases, dict):
152 # Copy "private" attributes, functions, and classes to the

--- 66 unchanged lines hidden (view full) ---

219 # init-time-only keywords
220 elif cls.init_keywords.has_key(key):
221 cls._set_keyword(key, val, cls.init_keywords[key])
222
223 # default: use normal path (ends up in __setattr__)
224 else:
225 setattr(cls, key, val)
226
227 def _set_keyword(cls, keyword, val, kwtype):
228 if not isinstance(val, kwtype):
229 raise TypeError, 'keyword %s has bad type %s (expecting %s)' % \
230 (keyword, type(val), kwtype)
231 if isinstance(val, types.FunctionType):
232 val = classmethod(val)
233 type.__setattr__(cls, keyword, val)
234
235 def _new_param(cls, name, value):
236 cls._params[name] = value
237 if hasattr(value, 'default'):
238 setattr(cls, name, value.default)
239
240 # Set attribute (called on foo.attr = value when foo is an
241 # instance of class cls).
242 def __setattr__(cls, attr, value):
243 # normal processing for private attributes
244 if attr.startswith('_'):
245 type.__setattr__(cls, attr, value)
246 return

--- 31 unchanged lines hidden (view full) ---

278
279 def __getattr__(cls, attr):
280 if cls._values.has_key(attr):
281 return cls._values[attr]
282
283 raise AttributeError, \
284 "object '%s' has no attribute '%s'" % (cls.__name__, attr)
285
286# The SimObject class is the root of the special hierarchy. Most of
287# the code in this class deals with the configuration hierarchy itself
288# (parent/child node relationships).
289class SimObject(object):
290 # Specify metaclass. Any class inheriting from SimObject will
291 # get this metaclass.
292 __metaclass__ = MetaSimObject
293
294 # Initialize new instance. For objects with SimObject-valued
295 # children, we need to recursively clone the classes represented
296 # by those param values as well in a consistent "deep copy"-style
297 # fashion. That is, we want to make sure that each instance is
298 # cloned only once, and that if there are multiple references to
299 # the same original object, we end up with the corresponding
300 # cloned references all pointing to the same cloned instance.
301 def __init__(self, **kwargs):

--- 488 unchanged lines hidden (view full) ---

790# MetaSimObject._new_param()); after that point they aren't used.
791#
792#####################################################################
793
794# Dummy base class to identify types that are legitimate for SimObject
795# parameters.
796class ParamValue(object):
797
798 # default for printing to .ini file is regular string conversion.
799 # will be overridden in some cases
800 def ini_str(self):
801 return str(self)
802
803 # allows us to blithely call unproxy() on things without checking
804 # if they're really proxies or not
805 def unproxy(self, base):

--- 54 unchanged lines hidden (view full) ---

860 # we're just assigning a null pointer
861 return value
862 if isinstance(value, self.ptype):
863 return value
864 if isNullPointer(value) and issubclass(self.ptype, SimObject):
865 return value
866 return self.ptype(value)
867
868# Vector-valued parameter description. Just like ParamDesc, except
869# that the value is a vector (list) of the specified type instead of a
870# single value.
871
872class VectorParamValue(list):
873 def ini_str(self):
874 return ' '.join([v.ini_str() for v in self])
875

--- 16 unchanged lines hidden (view full) ---

892 return SimObjVector(tmp_list)
893 else:
894 return VectorParamValue(tmp_list)
895 else:
896 # singleton: leave it be (could coerce to a single-element
897 # list here, but for some historical reason we don't...
898 return ParamDesc.convert(self, value)
899
900
901class ParamFactory(object):
902 def __init__(self, param_desc_class, ptype_str = None):
903 self.param_desc_class = param_desc_class
904 self.ptype_str = ptype_str
905
906 def __getattr__(self, attr):
907 if self.ptype_str:
908 attr = self.ptype_str + '.' + attr

--- 13 unchanged lines hidden (view full) ---

922 # if name isn't defined yet, assume it's a SimObject, and
923 # try to resolve it later
924 pass
925 return self.param_desc_class(self.ptype_str, ptype, *args, **kwargs)
926
927Param = ParamFactory(ParamDesc)
928VectorParam = ParamFactory(VectorParamDesc)
929
930#####################################################################
931#
932# Parameter Types
933#
934# Though native Python types could be used to specify parameter types
935# (the 'ptype' field of the Param and VectorParam classes), it's more
936# flexible to define our own set of types. This gives us more control
937# over how Python expressions are converted to values (via the

--- 32 unchanged lines hidden (view full) ---

970 return newobj
971
972 def __sub__(self, other):
973 newobj = self.__class__(self)
974 newobj.value -= other
975 newobj._check()
976 return newobj
977
978class Range(ParamValue):
979 type = int # default; can be overridden in subclasses
980 def __init__(self, *args, **kwargs):
981
982 def handle_kwargs(self, kwargs):
983 if 'end' in kwargs:
984 self.second = self.type(kwargs.pop('end'))
985 elif 'size' in kwargs:
986 self.second = self.first + self.type(kwargs.pop('size')) - 1
987 else:
988 raise TypeError, "Either end or size must be specified"
989
990 if len(args) == 0:
991 self.first = self.type(kwargs.pop('start'))
992 handle_kwargs(self, kwargs)
993
994 elif len(args) == 1:
995 if kwargs:
996 self.first = self.type(args[0])
997 handle_kwargs(self, kwargs)
998 elif isinstance(args[0], Range):
999 self.first = self.type(args[0].first)
1000 self.second = self.type(args[0].second)
1001 else:
1002 self.first = self.type(0)
1003 self.second = self.type(args[0]) - 1
1004
1005 elif len(args) == 2:
1006 self.first = self.type(args[0])
1007 self.second = self.type(args[1])
1008 else:
1009 raise TypeError, "Too many arguments specified"
1010
1011 if kwargs:
1012 raise TypeError, "too many keywords: %s" % kwargs.keys()
1013
1014 def __str__(self):
1015 return '%s:%s' % (self.first, self.second)
1016
1017# Metaclass for bounds-checked integer parameters. See CheckedInt.
1018class CheckedIntType(type):
1019 def __init__(cls, name, bases, dict):
1020 super(CheckedIntType, cls).__init__(name, bases, dict)
1021
1022 # CheckedInt is an abstract base class, so we actually don't
1023 # want to do any processing on it... the rest of this code is
1024 # just for classes that derive from CheckedInt.
1025 if name == 'CheckedInt':
1026 return
1027
1028 if not (hasattr(cls, 'min') and hasattr(cls, 'max')):
1029 if not (hasattr(cls, 'size') and hasattr(cls, 'unsigned')):
1030 panic("CheckedInt subclass %s must define either\n" \
1031 " 'min' and 'max' or 'size' and 'unsigned'\n" \
1032 % name);
1033 if cls.unsigned:
1034 cls.min = 0
1035 cls.max = 2 ** cls.size - 1

--- 15 unchanged lines hidden (view full) ---

1051
1052 def __init__(self, value):
1053 if isinstance(value, str):
1054 self.value = toInteger(value)
1055 elif isinstance(value, (int, long, float)):
1056 self.value = long(value)
1057 self._check()
1058
1059class Int(CheckedInt): size = 32; unsigned = False
1060class Unsigned(CheckedInt): size = 32; unsigned = True
1061
1062class Int8(CheckedInt): size = 8; unsigned = False
1063class UInt8(CheckedInt): size = 8; unsigned = True
1064class Int16(CheckedInt): size = 16; unsigned = False
1065class UInt16(CheckedInt): size = 16; unsigned = True
1066class Int32(CheckedInt): size = 32; unsigned = False
1067class UInt32(CheckedInt): size = 32; unsigned = True
1068class Int64(CheckedInt): size = 64; unsigned = False
1069class UInt64(CheckedInt): size = 64; unsigned = True
1070
1071class Counter(CheckedInt): size = 64; unsigned = True
1072class Tick(CheckedInt): size = 64; unsigned = True
1073class TcpPort(CheckedInt): size = 16; unsigned = True
1074class UdpPort(CheckedInt): size = 16; unsigned = True
1075
1076class Percent(CheckedInt): min = 0; max = 100
1077
1078class Float(ParamValue, float):
1079 pass
1080
1081class MemorySize(CheckedInt):
1082 size = 64
1083 unsigned = True
1084 def __init__(self, value):
1085 if isinstance(value, MemorySize):
1086 self.value = value.value
1087 else:
1088 self.value = toMemorySize(value)
1089 self._check()

--- 4 unchanged lines hidden (view full) ---

1094 def __init__(self, value):
1095 if isinstance(value, MemorySize):
1096 self.value = value.value
1097 else:
1098 self.value = toMemorySize(value)
1099 self._check()
1100
1101class Addr(CheckedInt):
1102 size = 64
1103 unsigned = True
1104 def __init__(self, value):
1105 if isinstance(value, Addr):
1106 self.value = value.value
1107 else:
1108 try:
1109 self.value = toMemorySize(value)
1110 except TypeError:
1111 self.value = long(value)
1112 self._check()
1113
1114class AddrRange(Range):
1115 type = Addr
1116
1117# String-valued parameter. Just mixin the ParamValue class
1118# with the built-in str class.
1119class String(ParamValue,str):
1120 pass
1121
1122# Boolean parameter type. Python doesn't let you subclass bool, since
1123# it doesn't want to let you create multiple instances of True and
1124# False. Thus this is a little more complicated than String.
1125class Bool(ParamValue):
1126 def __init__(self, value):
1127 try:
1128 self.value = toBool(value)
1129 except TypeError:
1130 self.value = bool(value)
1131
1132 def __str__(self):
1133 return str(self.value)

--- 18 unchanged lines hidden (view full) ---

1152class NextEthernetAddr(object):
1153 addr = "00:90:00:00:00:01"
1154
1155 def __init__(self, inc = 1):
1156 self.value = NextEthernetAddr.addr
1157 NextEthernetAddr.addr = IncEthernetAddr(NextEthernetAddr.addr, inc)
1158
1159class EthernetAddr(ParamValue):
1160 def __init__(self, value):
1161 if value == NextEthernetAddr:
1162 self.value = value
1163 return
1164
1165 if not isinstance(value, str):
1166 raise TypeError, "expected an ethernet address and didn't get one"
1167

--- 80 unchanged lines hidden (view full) ---

1248 # build string->value map from vals sequence
1249 cls.map = {}
1250 for idx,val in enumerate(cls.vals):
1251 cls.map[val] = idx
1252 else:
1253 raise TypeError, "Enum-derived class must define "\
1254 "attribute 'map' or 'vals'"
1255
1256 super(MetaEnum, cls).__init__(name, bases, init_dict)
1257
1258 def cpp_declare(cls):
1259 s = 'enum %s {\n ' % cls.__name__
1260 s += ',\n '.join(['%s = %d' % (v,cls.map[v]) for v in cls.vals])
1261 s += '\n};\n'
1262 return s
1263
1264# Base class for enum types.
1265class Enum(ParamValue):
1266 __metaclass__ = MetaEnum
1267 vals = []
1268
1269 def __init__(self, value):

--- 35 unchanged lines hidden (view full) ---

1305 try:
1306 return 1 / toFrequency(value)
1307 except ValueError:
1308 pass # fall through
1309 raise ValueError, "Invalid Frequency/Latency value '%s'" % value
1310
1311
1312class Latency(NumericParamValue):
1313 def __init__(self, value):
1314 self.value = getLatency(value)
1315
1316 def __getattr__(self, attr):
1317 if attr in ('latency', 'period'):
1318 return self
1319 if attr == 'frequency':
1320 return Frequency(self)
1321 raise AttributeError, "Latency object has no attribute '%s'" % attr
1322
1323 # convert latency to ticks
1324 def ini_str(self):
1325 return str(tick_check(self.value * ticks_per_sec))
1326
1327class Frequency(NumericParamValue):
1328 def __init__(self, value):
1329 self.value = 1 / getLatency(value)
1330
1331 def __getattr__(self, attr):
1332 if attr == 'frequency':
1333 return self
1334 if attr in ('latency', 'period'):
1335 return Latency(self)
1336 raise AttributeError, "Frequency object has no attribute '%s'" % attr
1337
1338 # convert frequency to ticks per period
1339 def ini_str(self):
1340 return self.period.ini_str()
1341
1342# Just like Frequency, except ini_str() is absolute # of ticks per sec (Hz).
1343# We can't inherit from Frequency because we don't want it to be directly
1344# assignable to a regular Frequency parameter.
1345class RootClock(ParamValue):
1346 def __init__(self, value):
1347 self.value = 1 / getLatency(value)
1348
1349 def __getattr__(self, attr):
1350 if attr == 'frequency':
1351 return Frequency(self)
1352 if attr in ('latency', 'period'):
1353 return Latency(self)
1354 raise AttributeError, "Frequency object has no attribute '%s'" % attr
1355
1356 def ini_str(self):
1357 return str(tick_check(self.value))
1358
1359# A generic frequency and/or Latency value. Value is stored as a latency,
1360# but to avoid ambiguity this object does not support numeric ops (* or /).
1361# An explicit conversion to a Latency or Frequency must be made first.
1362class Clock(ParamValue):
1363 def __init__(self, value):
1364 self.value = getLatency(value)
1365
1366 def __getattr__(self, attr):
1367 if attr == 'frequency':
1368 return Frequency(self)
1369 if attr in ('latency', 'period'):
1370 return Latency(self)
1371 raise AttributeError, "Frequency object has no attribute '%s'" % attr
1372
1373 def ini_str(self):
1374 return self.period.ini_str()
1375
1376class NetworkBandwidth(float,ParamValue):
1377 def __new__(cls, value):
1378 val = toNetworkBandwidth(value) / 8.0
1379 return super(cls, NetworkBandwidth).__new__(cls, val)
1380
1381 def __str__(self):
1382 return str(self.val)
1383
1384 def ini_str(self):
1385 return '%f' % (ticks_per_sec / float(self))
1386
1387class MemoryBandwidth(float,ParamValue):
1388 def __new__(self, value):
1389 val = toMemoryBandwidth(value)
1390 return super(cls, MemoryBandwidth).__new__(cls, val)
1391
1392 def __str__(self):
1393 return str(self.val)
1394
1395 def ini_str(self):

--- 119 unchanged lines hidden (view full) ---

1515 'Enum', 'Bool', 'String', 'Float',
1516 'Int', 'Unsigned', 'Int8', 'UInt8', 'Int16', 'UInt16',
1517 'Int32', 'UInt32', 'Int64', 'UInt64',
1518 'Counter', 'Addr', 'Tick', 'Percent',
1519 'TcpPort', 'UdpPort', 'EthernetAddr',
1520 'MemorySize', 'MemorySize32',
1521 'Latency', 'Frequency', 'RootClock', 'Clock',
1522 'NetworkBandwidth', 'MemoryBandwidth',
1523 'Range', 'AddrRange', 'MaxAddr', 'MaxTick', 'AllMemory',
1524 'Null', 'NULL',
1525 'NextEthernetAddr',
1526 'Port', 'VectorPort']
1527