# Copyright (c) 2004-2006 The Regents of The University of Michigan
+# Copyright (c) 2010 Advanced Micro Devices, Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
import copy
import datetime
-import inspect
+import re
import sys
import time
+import math
-import convert
import proxy
import ticks
from util import *
+def isSimObject(*args, **kwargs):
+ return SimObject.isSimObject(*args, **kwargs)
+
+def isSimObjectSequence(*args, **kwargs):
+ return SimObject.isSimObjectSequence(*args, **kwargs)
+
+def isSimObjectClass(*args, **kwargs):
+ return SimObject.isSimObjectClass(*args, **kwargs)
+
+allParams = {}
+
+class MetaParamValue(type):
+ def __new__(mcls, name, bases, dct):
+ cls = super(MetaParamValue, mcls).__new__(mcls, name, bases, dct)
+ assert name not in allParams
+ allParams[name] = cls
+ return cls
+
+
# Dummy base class to identify types that are legitimate for SimObject
# parameters.
class ParamValue(object):
+ __metaclass__ = MetaParamValue
cxx_predecls = []
swig_predecls = []
# Regular parameter description.
class ParamDesc(object):
+ file_ext = 'ptype'
+
def __init__(self, ptype_str, ptype, *args, **kwargs):
self.ptype_str = ptype_str
# remember ptype only if it is provided
def __getattr__(self, attr):
if attr == 'ptype':
- try:
- ptype = eval(self.ptype_str, objects.__dict__)
- if not isinstance(ptype, type):
- raise NameError
- self.ptype = ptype
- return ptype
- except NameError:
- raise TypeError, \
- "Param qualifier '%s' is not a type" % self.ptype_str
+ ptype = SimObject.allClasses[self.ptype_str]
+ assert isSimObjectClass(ptype)
+ self.ptype = ptype
+ return ptype
+
raise AttributeError, "'%s' object has no attribute '%s'" % \
(type(self).__name__, attr)
# single value.
class VectorParamValue(list):
+ __metaclass__ = MetaParamValue
+ def __setattr__(self, attr, value):
+ raise AttributeError, \
+ "Not allowed to set %s on '%s'" % (attr, type(self).__name__)
+
def ini_str(self):
return ' '.join([v.ini_str() for v in self])
+ def getValue(self):
+ return [ v.getValue() for v in self ]
+
def unproxy(self, base):
return [v.unproxy(base) for v in self]
-class SimObjVector(VectorParamValue):
- def print_ini(self):
+class SimObjectVector(VectorParamValue):
+ # support clone operation
+ def __call__(self, **kwargs):
+ return SimObjectVector([v(**kwargs) for v in self])
+
+ def clear_parent(self, old_parent):
+ for v in self:
+ v.clear_parent(old_parent)
+
+ def set_parent(self, parent, name):
+ if len(self) == 1:
+ self[0].set_parent(parent, name)
+ else:
+ width = int(math.ceil(math.log(len(self))/math.log(10)))
+ for i,v in enumerate(self):
+ v.set_parent(parent, "%s%0*d" % (name, width, i))
+
+ def get_parent(self):
+ parent_set = set(v._parent for v in self)
+ if len(parent_set) != 1:
+ raise RuntimeError, \
+ "SimObjectVector elements have inconsistent parent value."
+ return parent_set.pop()
+
+ # return 'cpu0 cpu1' etc. for print_ini()
+ def get_name(self):
+ return ' '.join([v._name for v in self])
+
+ # By iterating through the constituent members of the vector here
+ # we can nicely handle iterating over all a SimObject's children
+ # without having to provide lots of special functions on
+ # SimObjectVector directly.
+ def descendants(self):
for v in self:
- v.print_ini()
+ for obj in v.descendants():
+ yield obj
class VectorParamDesc(ParamDesc):
+ file_ext = 'vptype'
+
# Convert assigned value to appropriate type. If the RHS is not a
# list or tuple, it generates a single-element list.
def convert(self, value):
if isinstance(value, (list, tuple)):
# list: coerce each element into new list
tmp_list = [ ParamDesc.convert(self, v) for v in value ]
- if isSimObjectSequence(tmp_list):
- return SimObjVector(tmp_list)
- else:
- return VectorParamValue(tmp_list)
else:
- # singleton: leave it be (could coerce to a single-element
- # list here, but for some historical reason we don't...
- return ParamDesc.convert(self, value)
+ # singleton: coerce to a single-element list
+ tmp_list = [ ParamDesc.convert(self, value) ]
- def cxx_predecls(self):
- return ['#include <vector>'] + self.ptype.cxx_predecls
+ if isSimObjectSequence(tmp_list):
+ return SimObjectVector(tmp_list)
+ else:
+ return VectorParamValue(tmp_list)
def swig_predecls(self):
- return ['%include "std_vector.i"'] + self.ptype.swig_predecls
+ return ['%%include "%s_vptype.i"' % self.ptype_str]
+
+ def swig_decl(self):
+ cxx_type = re.sub('std::', '', self.ptype.cxx_type)
+ vdecl = 'namespace std { %%template(vector_%s) vector< %s >; }' % \
+ (self.ptype_str, cxx_type)
+ return ['%include "std_vector.i"'] + self.ptype.swig_predecls + [vdecl]
+
+ def cxx_predecls(self):
+ return ['#include <vector>'] + self.ptype.cxx_predecls
def cxx_decl(self):
return 'std::vector< %s > %s;' % (self.ptype.cxx_type, self.name)
# E.g., Param.Int(5, "number of widgets")
def __call__(self, *args, **kwargs):
- caller_frame = inspect.currentframe().f_back
ptype = None
try:
- ptype = eval(self.ptype_str,
- caller_frame.f_globals, caller_frame.f_locals)
- if not isinstance(ptype, type):
- raise TypeError, \
- "Param qualifier is not a type: %s" % ptype
- except NameError:
+ ptype = allParams[self.ptype_str]
+ except KeyError:
# if name isn't defined yet, assume it's a SimObject, and
# try to resolve it later
pass
cxx_predecls = ['#include <string>']
swig_predecls = ['%include "std_string.i"\n' +
'%apply const std::string& {std::string *};']
- pass
+ swig_predecls = ['%include "std_string.i"' ]
+
+ def getValue(self):
+ return self
# superclass for "numeric" parameter values, to emulate math
# operations in a type-safe way. e.g., a Latency times an int returns
return newobj
# Metaclass for bounds-checked integer parameters. See CheckedInt.
-class CheckedIntType(type):
+class CheckedIntType(MetaParamValue):
def __init__(cls, name, bases, dict):
super(CheckedIntType, cls).__init__(name, bases, dict)
if not cls.cxx_predecls:
# most derived types require this, so we just do it here once
- cls.cxx_predecls = ['#include "sim/host.hh"']
+ cls.cxx_predecls = ['#include "base/types.hh"']
if not cls.swig_predecls:
# most derived types require this, so we just do it here once
- cls.swig_predecls = ['%import "python/m5/swig/stdint.i"\n' +
- '%import "sim/host.hh"']
+ cls.swig_predecls = ['%import "stdint.i"\n' +
+ '%import "base/types.hh"']
if not (hasattr(cls, 'min') and hasattr(cls, 'max')):
if not (hasattr(cls, 'size') and hasattr(cls, 'unsigned')):
panic("CheckedInt subclass %s must define either\n" \
- " 'min' and 'max' or 'size' and 'unsigned'\n" \
- % name);
+ " 'min' and 'max' or 'size' and 'unsigned'\n",
+ name);
if cls.unsigned:
cls.min = 0
cls.max = 2 ** cls.size - 1
% type(value).__name__
self._check()
+ def getValue(self):
+ return long(self.value)
+
class Int(CheckedInt): cxx_type = 'int'; size = 32; unsigned = False
class Unsigned(CheckedInt): cxx_type = 'unsigned'; size = 32; unsigned = True
class Float(ParamValue, float):
cxx_type = 'double'
+ def __init__(self, value):
+ if isinstance(value, (int, long, float, NumericParamValue, Float)):
+ self.value = float(value)
+ else:
+ raise TypeError, "Can't convert object of type %s to Float" \
+ % type(value).__name__
+
+ def getValue(self):
+ return float(self.value)
+
class MemorySize(CheckedInt):
cxx_type = 'uint64_t'
size = 64
class Addr(CheckedInt):
cxx_type = 'Addr'
- cxx_predecls = ['#include "targetarch/isa_traits.hh"']
size = 64
unsigned = True
def __init__(self, value):
return self.value + other
-class MetaRange(type):
+class MetaRange(MetaParamValue):
def __init__(cls, name, bases, dict):
super(MetaRange, cls).__init__(name, bases, dict)
if name == 'Range':
elif isinstance(args[0], Range):
self.first = self.type(args[0].first)
self.second = self.type(args[0].second)
+ elif isinstance(args[0], (list, tuple)):
+ self.first = self.type(args[0][0])
+ self.second = self.type(args[0][1])
else:
self.first = self.type(0)
self.second = self.type(args[0]) - 1
class AddrRange(Range):
type = Addr
+ swig_predecls = ['%include "python/swig/range.i"']
+
+ def getValue(self):
+ from m5.objects.params import AddrRange
+
+ value = AddrRange()
+ value.start = long(self.first)
+ value.end = long(self.second)
+ return value
class TickRange(Range):
type = Tick
+ swig_predecls = ['%include "python/swig/range.i"']
+
+ def getValue(self):
+ from m5.objects.params import TickRange
+
+ value = TickRange()
+ value.start = long(self.first)
+ value.end = long(self.second)
+ return value
# Boolean parameter type. Python doesn't let you subclass bool, since
# it doesn't want to let you create multiple instances of True and
except TypeError:
self.value = bool(value)
+ def getValue(self):
+ return bool(self.value)
+
def __str__(self):
return str(self.value)
class EthernetAddr(ParamValue):
cxx_type = 'Net::EthAddr'
cxx_predecls = ['#include "base/inet.hh"']
- swig_predecls = ['class Net::EthAddr;']
+ swig_predecls = ['%include "python/swig/inet.i"']
def __init__(self, value):
if value == NextEthernetAddr:
self.value = value
return EthernetAddr(self.value())
return self
+ def getValue(self):
+ from m5.objects.params import EthAddr
+ return EthAddr(self.value)
+
def ini_str(self):
return self.value
raise ValueError, "Could not parse '%s' as a time" % value
class Time(ParamValue):
- cxx_type = 'time_t'
+ cxx_type = 'tm'
+ cxx_predecls = [ '#include <time.h>' ]
+ swig_predecls = [ '%include "python/swig/time.i"' ]
def __init__(self, value):
self.value = parse_time(value)
+ def getValue(self):
+ from m5.objects.params import tm
+
+ c_time = tm()
+ py_time = self.value
+
+ # UNIX is years since 1900
+ c_time.tm_year = py_time.tm_year - 1900;
+
+ # Python starts at 1, UNIX starts at 0
+ c_time.tm_mon = py_time.tm_mon - 1;
+ c_time.tm_mday = py_time.tm_mday;
+ c_time.tm_hour = py_time.tm_hour;
+ c_time.tm_min = py_time.tm_min;
+ c_time.tm_sec = py_time.tm_sec;
+
+ # Python has 0 as Monday, UNIX is 0 as sunday
+ c_time.tm_wday = py_time.tm_wday + 1
+ if c_time.tm_wday > 6:
+ c_time.tm_wday -= 7;
+
+ # Python starts at 1, Unix starts at 0
+ c_time.tm_yday = py_time.tm_yday - 1;
+
+ return c_time
+
def __str__(self):
- tm = self.value
- return ' '.join([ str(tm[i]) for i in xrange(8)])
+ return time.asctime(self.value)
def ini_str(self):
return str(self)
# classes (_ListEnum and _DictEnum) to serve as base classes, then
# derive the new type from the appropriate base class on the fly.
-
+allEnums = {}
# Metaclass for Enum types
-class MetaEnum(type):
+class MetaEnum(MetaParamValue):
+ def __new__(mcls, name, bases, dict):
+ assert name not in allEnums
+
+ cls = super(MetaEnum, mcls).__new__(mcls, name, bases, dict)
+ allEnums[name] = cls
+ return cls
+
def __init__(cls, name, bases, init_dict):
if init_dict.has_key('map'):
if not isinstance(cls.map, dict):
raise TypeError, "Enum-derived class must define "\
"attribute 'map' or 'vals'"
- cls.cxx_type = name + '::Enum'
+ cls.cxx_type = 'Enums::%s' % name
super(MetaEnum, cls).__init__(name, bases, init_dict)
# Note that we wrap the enum in a class/struct to act as a namespace,
# so that the enum strings can be brief w/o worrying about collisions.
def cxx_decl(cls):
- s = 'struct %s {\n enum Enum {\n ' % cls.__name__
- s += ',\n '.join(['%s = %d' % (v,cls.map[v]) for v in cls.vals])
- s += '\n };\n};\n'
- return s
+ name = cls.__name__
+ code = "#ifndef __ENUM__%s\n" % name
+ code += '#define __ENUM__%s\n' % name
+ code += '\n'
+ code += 'namespace Enums {\n'
+ code += ' enum %s {\n' % name
+ for val in cls.vals:
+ code += ' %s = %d,\n' % (val, cls.map[val])
+ code += ' Num_%s = %d,\n' % (name, len(cls.vals))
+ code += ' };\n'
+ code += ' extern const char *%sStrings[Num_%s];\n' % (name, name)
+ code += '}\n'
+ code += '\n'
+ code += '#endif\n'
+ return code
+
+ def cxx_def(cls):
+ name = cls.__name__
+ code = '#include "enums/%s.hh"\n' % name
+ code += 'namespace Enums {\n'
+ code += ' const char *%sStrings[Num_%s] =\n' % (name, name)
+ code += ' {\n'
+ for val in cls.vals:
+ code += ' "%s",\n' % val
+ code += ' };\n'
+ code += '}\n'
+ return code
# Base class for enum types.
class Enum(ParamValue):
% (value, self.vals)
self.value = value
+ def getValue(self):
+ return int(self.map[self.value])
+
def __str__(self):
return self.value
class TickParamValue(NumericParamValue):
cxx_type = 'Tick'
- cxx_predecls = ['#include "sim/host.hh"']
- swig_predecls = ['%import "python/m5/swig/stdint.i"\n' +
- '%import "sim/host.hh"']
+ cxx_predecls = ['#include "base/types.hh"']
+ swig_predecls = ['%import "stdint.i"\n' +
+ '%import "base/types.hh"']
+
+ def getValue(self):
+ return long(self.value)
class Latency(TickParamValue):
def __init__(self, value):
return Frequency(self)
raise AttributeError, "Latency object has no attribute '%s'" % attr
- # convert latency to ticks
- def ini_str(self):
+ def getValue(self):
if self.ticks or self.value == 0:
- return '%d' % self.value
+ value = self.value
else:
- return '%d' % (ticks.fromSeconds(self.value))
+ value = ticks.fromSeconds(self.value)
+ return long(value)
+
+ # convert latency to ticks
+ def ini_str(self):
+ return '%d' % self.getValue()
class Frequency(TickParamValue):
def __init__(self, value):
raise AttributeError, "Frequency object has no attribute '%s'" % attr
# convert latency to ticks
- def ini_str(self):
+ def getValue(self):
if self.ticks or self.value == 0:
- return '%d' % self.value
+ value = self.value
else:
- return '%d' % (ticks.fromSeconds(1.0 / self.value))
+ value = ticks.fromSeconds(1.0 / self.value)
+ return long(value)
+
+ def ini_str(self):
+ return '%d' % self.getValue()
# A generic frequency and/or Latency value. Value is stored as a latency,
# but to avoid ambiguity this object does not support numeric ops (* or /).
# An explicit conversion to a Latency or Frequency must be made first.
class Clock(ParamValue):
cxx_type = 'Tick'
- cxx_predecls = ['#include "sim/host.hh"']
- swig_predecls = ['%import "python/m5/swig/stdint.i"\n' +
- '%import "sim/host.hh"']
+ cxx_predecls = ['#include "base/types.hh"']
+ swig_predecls = ['%import "stdint.i"\n' +
+ '%import "base/types.hh"']
def __init__(self, value):
if isinstance(value, (Latency, Clock)):
self.ticks = value.ticks
return Latency(self)
raise AttributeError, "Frequency object has no attribute '%s'" % attr
+ def getValue(self):
+ return self.period.getValue()
+
def ini_str(self):
return self.period.ini_str()
def __str__(self):
return str(self.val)
- def ini_str(self):
+ def getValue(self):
# convert to seconds per byte
value = 8.0 / float(self)
# convert to ticks per byte
- return '%f' % (ticks.fromSeconds(value))
+ value = ticks.fromSeconds(value)
+ return float(value)
+
+ def ini_str(self):
+ return '%f' % self.getValue()
class MemoryBandwidth(float,ParamValue):
cxx_type = 'float'
- def __new__(self, value):
+ def __new__(cls, value):
# we want the number of ticks per byte of data
val = convert.toMemoryBandwidth(value)
return super(cls, MemoryBandwidth).__new__(cls, val)
def __str__(self):
return str(self.val)
- def ini_str(self):
+ def getValue(self):
# convert to seconds per byte
- value = 1.0 / float(self)
+ value = float(self)
+ if value:
+ value = 1.0 / float(self)
# convert to ticks per byte
- return '%f' % (ticks.fromSeconds(value))
+ value = ticks.fromSeconds(value)
+ return float(value)
+
+ def ini_str(self):
+ return '%f' % self.getValue()
#
# "Constants"... handy aliases for various values.
def set_path(self, parent, name):
pass
+
def __str__(self):
return 'Null'
+ def getValue(self):
+ return None
+
# The only instance you'll ever need...
NULL = NullSimObject()
if self.peer and not proxy.isproxy(self.peer):
print "warning: overwriting port", self, \
"value", self.peer, "with", other
+ self.peer.peer = None
self.peer = other
if proxy.isproxy(other):
other.set_param_desc(PortParamDesc())
# Call C++ to create corresponding port connection between C++ objects
def ccConnect(self):
+ from m5.objects.params import connectPorts
+
if self.ccConnected: # already done this
return
peer = self.peer
- internal.sim_object.connectPorts(self.simobj.getCCObject(), self.name,
- self.index, peer.simobj.getCCObject(), peer.name, peer.index)
+ if not self.peer: # nothing to connect to
+ return
+ try:
+ connectPorts(self.simobj.getCCObject(), self.name, self.index,
+ peer.simobj.getCCObject(), peer.name, peer.index)
+ except:
+ print "Error connecting port %s.%s to %s.%s" % \
+ (self.simobj.path(), self.name,
+ peer.simobj.path(), peer.name)
+ raise
self.ccConnected = True
peer.ccConnected = True
ptype_str = 'Port'
ptype = Port
+baseEnums = allEnums.copy()
+baseParams = allParams.copy()
+
+def clear():
+ global allEnums, allParams
+
+ allEnums = baseEnums.copy()
+ allParams = baseParams.copy()
__all__ = ['Param', 'VectorParam',
'Enum', 'Bool', 'String', 'Float',
'NextEthernetAddr', 'NULL',
'Port', 'VectorPort']
-# see comment on imports at end of __init__.py.
-from SimObject import isSimObject, isSimObjectSequence, isSimObjectClass
-import objects
-import internal
+import SimObject