config: Add hooks to enable new config sys
This patch adds helper functions to SimObject.py, params.py and simulate.py to enable the new configuration system. Functions like enumerateParams() in SimObject lets the config system auto-generate command line options for simobjects to be modified on the command line. Params in params.py have __call__() added to their definition to allow the argparse module to use them as a type to check command input is in the proper format.
This commit is contained in:
parent
47313601c1
commit
09b5003815
2 changed files with 297 additions and 8 deletions
|
@ -172,6 +172,7 @@ class MetaSimObject(type):
|
||||||
|
|
||||||
# class or instance attributes
|
# class or instance attributes
|
||||||
cls._values = multidict() # param values
|
cls._values = multidict() # param values
|
||||||
|
cls._hr_values = multidict() # human readable param values
|
||||||
cls._children = multidict() # SimObject children
|
cls._children = multidict() # SimObject children
|
||||||
cls._port_refs = multidict() # port ref objects
|
cls._port_refs = multidict() # port ref objects
|
||||||
cls._instantiated = False # really instantiated, cloned, or subclassed
|
cls._instantiated = False # really instantiated, cloned, or subclassed
|
||||||
|
@ -197,6 +198,7 @@ class MetaSimObject(type):
|
||||||
cls._params.parent = base._params
|
cls._params.parent = base._params
|
||||||
cls._ports.parent = base._ports
|
cls._ports.parent = base._ports
|
||||||
cls._values.parent = base._values
|
cls._values.parent = base._values
|
||||||
|
cls._hr_values.parent = base._hr_values
|
||||||
cls._children.parent = base._children
|
cls._children.parent = base._children
|
||||||
cls._port_refs.parent = base._port_refs
|
cls._port_refs.parent = base._port_refs
|
||||||
# mark base as having been subclassed
|
# mark base as having been subclassed
|
||||||
|
@ -273,6 +275,7 @@ class MetaSimObject(type):
|
||||||
def _set_param(cls, name, value, param):
|
def _set_param(cls, name, value, param):
|
||||||
assert(param.name == name)
|
assert(param.name == name)
|
||||||
try:
|
try:
|
||||||
|
hr_value = value
|
||||||
value = param.convert(value)
|
value = param.convert(value)
|
||||||
except Exception, e:
|
except Exception, e:
|
||||||
msg = "%s\nError setting param %s.%s to %s\n" % \
|
msg = "%s\nError setting param %s.%s to %s\n" % \
|
||||||
|
@ -284,6 +287,11 @@ class MetaSimObject(type):
|
||||||
# it gets cloned properly when the class is instantiated
|
# it gets cloned properly when the class is instantiated
|
||||||
if isSimObjectOrVector(value) and not value.has_parent():
|
if isSimObjectOrVector(value) and not value.has_parent():
|
||||||
cls._add_cls_child(name, value)
|
cls._add_cls_child(name, value)
|
||||||
|
# update human-readable values of the param if it has a literal
|
||||||
|
# value and is not an object or proxy.
|
||||||
|
if not (isSimObjectOrVector(value) or\
|
||||||
|
isinstance(value, m5.proxy.BaseProxy)):
|
||||||
|
cls._hr_values[name] = hr_value
|
||||||
|
|
||||||
def _add_cls_child(cls, name, child):
|
def _add_cls_child(cls, name, child):
|
||||||
# It's a little funky to have a class as a parent, but these
|
# It's a little funky to have a class as a parent, but these
|
||||||
|
@ -585,6 +593,28 @@ struct PyObject;
|
||||||
def isSimObjectOrVector(value):
|
def isSimObjectOrVector(value):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
# This class holds information about each simobject parameter
|
||||||
|
# that should be displayed on the command line for use in the
|
||||||
|
# configuration system.
|
||||||
|
class ParamInfo(object):
|
||||||
|
def __init__(self, type, desc, type_str, example, default_val, access_str):
|
||||||
|
self.type = type
|
||||||
|
self.desc = desc
|
||||||
|
self.type_str = type_str
|
||||||
|
self.example_str = example
|
||||||
|
self.default_val = default_val
|
||||||
|
# The string representation used to access this param through python.
|
||||||
|
# The method to access this parameter presented on the command line may
|
||||||
|
# be different, so this needs to be stored for later use.
|
||||||
|
self.access_str = access_str
|
||||||
|
self.created = True
|
||||||
|
|
||||||
|
# Make it so we can only set attributes at initialization time
|
||||||
|
# and effectively make this a const object.
|
||||||
|
def __setattr__(self, name, value):
|
||||||
|
if not "created" in self.__dict__:
|
||||||
|
self.__dict__[name] = value
|
||||||
|
|
||||||
# The SimObject class is the root of the special hierarchy. Most of
|
# The SimObject class is the root of the special hierarchy. Most of
|
||||||
# the code in this class deals with the configuration hierarchy itself
|
# the code in this class deals with the configuration hierarchy itself
|
||||||
# (parent/child node relationships).
|
# (parent/child node relationships).
|
||||||
|
@ -621,6 +651,64 @@ class SimObject(object):
|
||||||
void startup();
|
void startup();
|
||||||
''')
|
''')
|
||||||
|
|
||||||
|
# Returns a dict of all the option strings that can be
|
||||||
|
# generated as command line options for this simobject instance
|
||||||
|
# by tracing all reachable params in the top level instance and
|
||||||
|
# any children it contains.
|
||||||
|
def enumerateParams(self, flags_dict = {},
|
||||||
|
cmd_line_str = "", access_str = ""):
|
||||||
|
if hasattr(self, "_paramEnumed"):
|
||||||
|
print "Cycle detected enumerating params"
|
||||||
|
else:
|
||||||
|
self._paramEnumed = True
|
||||||
|
# Scan the children first to pick up all the objects in this SimObj
|
||||||
|
for keys in self._children:
|
||||||
|
child = self._children[keys]
|
||||||
|
next_cmdline_str = cmd_line_str + keys
|
||||||
|
next_access_str = access_str + keys
|
||||||
|
if not isSimObjectVector(child):
|
||||||
|
next_cmdline_str = next_cmdline_str + "."
|
||||||
|
next_access_str = next_access_str + "."
|
||||||
|
flags_dict = child.enumerateParams(flags_dict,
|
||||||
|
next_cmdline_str,
|
||||||
|
next_access_str)
|
||||||
|
|
||||||
|
# Go through the simple params in the simobject in this level
|
||||||
|
# of the simobject hierarchy and save information about the
|
||||||
|
# parameter to be used for generating and processing command line
|
||||||
|
# options to the simulator to set these parameters.
|
||||||
|
for keys,values in self._params.items():
|
||||||
|
if values.isCmdLineSettable():
|
||||||
|
type_str = ''
|
||||||
|
ex_str = values.example_str()
|
||||||
|
ptype = None
|
||||||
|
if isinstance(values, VectorParamDesc):
|
||||||
|
type_str = 'Vector_%s' % values.ptype_str
|
||||||
|
ptype = values
|
||||||
|
else:
|
||||||
|
type_str = '%s' % values.ptype_str
|
||||||
|
ptype = values.ptype
|
||||||
|
|
||||||
|
if keys in self._hr_values\
|
||||||
|
and keys in self._values\
|
||||||
|
and not isinstance(self._values[keys], m5.proxy.BaseProxy):
|
||||||
|
cmd_str = cmd_line_str + keys
|
||||||
|
acc_str = access_str + keys
|
||||||
|
flags_dict[cmd_str] = ParamInfo(ptype,
|
||||||
|
self._params[keys].desc, type_str, ex_str,
|
||||||
|
values.pretty_print(self._hr_values[keys]),
|
||||||
|
acc_str)
|
||||||
|
elif not keys in self._hr_values\
|
||||||
|
and not keys in self._values:
|
||||||
|
# Empty param
|
||||||
|
cmd_str = cmd_line_str + keys
|
||||||
|
acc_str = access_str + keys
|
||||||
|
flags_dict[cmd_str] = ParamInfo(ptype,
|
||||||
|
self._params[keys].desc,
|
||||||
|
type_str, ex_str, '', acc_str)
|
||||||
|
|
||||||
|
return flags_dict
|
||||||
|
|
||||||
# Initialize new instance. For objects with SimObject-valued
|
# Initialize new instance. For objects with SimObject-valued
|
||||||
# children, we need to recursively clone the classes represented
|
# children, we need to recursively clone the classes represented
|
||||||
# by those param values as well in a consistent "deep copy"-style
|
# by those param values as well in a consistent "deep copy"-style
|
||||||
|
@ -661,6 +749,7 @@ class SimObject(object):
|
||||||
# individual value settings can be overridden but we still
|
# individual value settings can be overridden but we still
|
||||||
# inherit late changes to non-overridden class values.
|
# inherit late changes to non-overridden class values.
|
||||||
self._values = multidict(ancestor._values)
|
self._values = multidict(ancestor._values)
|
||||||
|
self._hr_values = multidict(ancestor._hr_values)
|
||||||
# clone SimObject-valued parameters
|
# clone SimObject-valued parameters
|
||||||
for key,val in ancestor._values.iteritems():
|
for key,val in ancestor._values.iteritems():
|
||||||
val = tryAsSimObjectOrVector(val)
|
val = tryAsSimObjectOrVector(val)
|
||||||
|
@ -751,6 +840,7 @@ class SimObject(object):
|
||||||
param = self._params.get(attr)
|
param = self._params.get(attr)
|
||||||
if param:
|
if param:
|
||||||
try:
|
try:
|
||||||
|
hr_value = value
|
||||||
value = param.convert(value)
|
value = param.convert(value)
|
||||||
except Exception, e:
|
except Exception, e:
|
||||||
msg = "%s\nError setting param %s.%s to %s\n" % \
|
msg = "%s\nError setting param %s.%s to %s\n" % \
|
||||||
|
@ -761,6 +851,13 @@ class SimObject(object):
|
||||||
# implicitly parent unparented objects assigned as params
|
# implicitly parent unparented objects assigned as params
|
||||||
if isSimObjectOrVector(value) and not value.has_parent():
|
if isSimObjectOrVector(value) and not value.has_parent():
|
||||||
self.add_child(attr, value)
|
self.add_child(attr, value)
|
||||||
|
# set the human-readable value dict if this is a param
|
||||||
|
# with a literal value and is not being set as an object
|
||||||
|
# or proxy.
|
||||||
|
if not (isSimObjectOrVector(value) or\
|
||||||
|
isinstance(value, m5.proxy.BaseProxy)):
|
||||||
|
self._hr_values[attr] = hr_value
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
# if RHS is a SimObject, it's an implicit child assignment
|
# if RHS is a SimObject, it's an implicit child assignment
|
||||||
|
@ -778,7 +875,13 @@ class SimObject(object):
|
||||||
def __getitem__(self, key):
|
def __getitem__(self, key):
|
||||||
if key == 0:
|
if key == 0:
|
||||||
return self
|
return self
|
||||||
raise TypeError, "Non-zero index '%s' to SimObject" % key
|
raise IndexError, "Non-zero index '%s' to SimObject" % key
|
||||||
|
|
||||||
|
# this hack allows us to iterate over a SimObject that may
|
||||||
|
# not be a vector, so we can call a loop over it and get just one
|
||||||
|
# element.
|
||||||
|
def __len__(self):
|
||||||
|
return 1
|
||||||
|
|
||||||
# Also implemented by SimObjectVector
|
# Also implemented by SimObjectVector
|
||||||
def clear_parent(self, old_parent):
|
def clear_parent(self, old_parent):
|
||||||
|
@ -1054,8 +1157,9 @@ class SimObject(object):
|
||||||
# Cycles in the configuration hierarchy are not supported. This
|
# Cycles in the configuration hierarchy are not supported. This
|
||||||
# will catch the resulting recursion and stop.
|
# will catch the resulting recursion and stop.
|
||||||
self._ccObject = -1
|
self._ccObject = -1
|
||||||
params = self.getCCParams()
|
if not self.abstract:
|
||||||
self._ccObject = params.create()
|
params = self.getCCParams()
|
||||||
|
self._ccObject = params.create()
|
||||||
elif self._ccObject == -1:
|
elif self._ccObject == -1:
|
||||||
raise RuntimeError, "%s: Cycle found in configuration hierarchy." \
|
raise RuntimeError, "%s: Cycle found in configuration hierarchy." \
|
||||||
% self.path()
|
% self.path()
|
||||||
|
|
|
@ -93,7 +93,7 @@ class MetaParamValue(type):
|
||||||
# parameters.
|
# parameters.
|
||||||
class ParamValue(object):
|
class ParamValue(object):
|
||||||
__metaclass__ = MetaParamValue
|
__metaclass__ = MetaParamValue
|
||||||
|
cmd_line_settable = False
|
||||||
|
|
||||||
# Generate the code needed as a prerequisite for declaring a C++
|
# Generate the code needed as a prerequisite for declaring a C++
|
||||||
# object of this type. Typically generates one or more #include
|
# object of this type. Typically generates one or more #include
|
||||||
|
@ -119,6 +119,10 @@ class ParamValue(object):
|
||||||
def unproxy(self, base):
|
def unproxy(self, base):
|
||||||
return self
|
return self
|
||||||
|
|
||||||
|
# Produce a human readable version of the stored value
|
||||||
|
def pretty_print(self, value):
|
||||||
|
return str(value)
|
||||||
|
|
||||||
# Regular parameter description.
|
# Regular parameter description.
|
||||||
class ParamDesc(object):
|
class ParamDesc(object):
|
||||||
def __init__(self, ptype_str, ptype, *args, **kwargs):
|
def __init__(self, ptype_str, ptype, *args, **kwargs):
|
||||||
|
@ -162,6 +166,19 @@ class ParamDesc(object):
|
||||||
raise AttributeError, "'%s' object has no attribute '%s'" % \
|
raise AttributeError, "'%s' object has no attribute '%s'" % \
|
||||||
(type(self).__name__, attr)
|
(type(self).__name__, attr)
|
||||||
|
|
||||||
|
def example_str(self):
|
||||||
|
if hasattr(self.ptype, "ex_str"):
|
||||||
|
return self.ptype.ex_str
|
||||||
|
else:
|
||||||
|
return self.ptype_str
|
||||||
|
|
||||||
|
# Is the param available to be exposed on the command line
|
||||||
|
def isCmdLineSettable(self):
|
||||||
|
if hasattr(self.ptype, "cmd_line_settable"):
|
||||||
|
return self.ptype.cmd_line_settable
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
def convert(self, value):
|
def convert(self, value):
|
||||||
if isinstance(value, proxy.BaseProxy):
|
if isinstance(value, proxy.BaseProxy):
|
||||||
value.set_param_desc(self)
|
value.set_param_desc(self)
|
||||||
|
@ -176,6 +193,13 @@ class ParamDesc(object):
|
||||||
return value
|
return value
|
||||||
return self.ptype(value)
|
return self.ptype(value)
|
||||||
|
|
||||||
|
def pretty_print(self, value):
|
||||||
|
if isinstance(value, proxy.BaseProxy):
|
||||||
|
return str(value)
|
||||||
|
if isNullPointer(value):
|
||||||
|
return NULL
|
||||||
|
return self.ptype(value).pretty_print(value)
|
||||||
|
|
||||||
def cxx_predecls(self, code):
|
def cxx_predecls(self, code):
|
||||||
code('#include <cstddef>')
|
code('#include <cstddef>')
|
||||||
self.ptype.cxx_predecls(code)
|
self.ptype.cxx_predecls(code)
|
||||||
|
@ -260,6 +284,26 @@ class SimObjectVector(VectorParamValue):
|
||||||
value.set_parent(val.get_parent(), val._name)
|
value.set_parent(val.get_parent(), val._name)
|
||||||
super(SimObjectVector, self).__setitem__(key, value)
|
super(SimObjectVector, self).__setitem__(key, value)
|
||||||
|
|
||||||
|
# Enumerate the params of each member of the SimObject vector. Creates
|
||||||
|
# strings that will allow indexing into the vector by the python code and
|
||||||
|
# allow it to be specified on the command line.
|
||||||
|
def enumerateParams(self, flags_dict = {},
|
||||||
|
cmd_line_str = "",
|
||||||
|
access_str = ""):
|
||||||
|
if hasattr(self, "_paramEnumed"):
|
||||||
|
print "Cycle detected enumerating params at %s?!" % (cmd_line_str)
|
||||||
|
else:
|
||||||
|
x = 0
|
||||||
|
for vals in self:
|
||||||
|
# Each entry in the SimObjectVector should be an
|
||||||
|
# instance of a SimObject
|
||||||
|
flags_dict = vals.enumerateParams(flags_dict,
|
||||||
|
cmd_line_str + "%d." % x,
|
||||||
|
access_str + "[%d]." % x)
|
||||||
|
x = x + 1
|
||||||
|
|
||||||
|
return flags_dict
|
||||||
|
|
||||||
class VectorParamDesc(ParamDesc):
|
class VectorParamDesc(ParamDesc):
|
||||||
# Convert assigned value to appropriate type. If the RHS is not a
|
# Convert assigned value to appropriate type. If the RHS is not a
|
||||||
# list or tuple, it generates a single-element list.
|
# list or tuple, it generates a single-element list.
|
||||||
|
@ -276,6 +320,39 @@ class VectorParamDesc(ParamDesc):
|
||||||
else:
|
else:
|
||||||
return VectorParamValue(tmp_list)
|
return VectorParamValue(tmp_list)
|
||||||
|
|
||||||
|
# Produce a human readable example string that describes
|
||||||
|
# how to set this vector parameter in the absence of a default
|
||||||
|
# value.
|
||||||
|
def example_str(self):
|
||||||
|
s = super(VectorParamDesc, self).example_str()
|
||||||
|
help_str = "[" + s + "," + s + ", ...]"
|
||||||
|
return help_str
|
||||||
|
|
||||||
|
# Produce a human readable representation of the value of this vector param.
|
||||||
|
def pretty_print(self, value):
|
||||||
|
if isinstance(value, (list, tuple)):
|
||||||
|
tmp_list = [ ParamDesc.pretty_print(self, v) for v in value ]
|
||||||
|
elif isinstance(value, str):
|
||||||
|
tmp_list = [ ParamDesc.pretty_print(self, v) for v in value.split(',') ]
|
||||||
|
else:
|
||||||
|
tmp_list = [ ParamDesc.pretty_print(self, value) ]
|
||||||
|
|
||||||
|
return tmp_list
|
||||||
|
|
||||||
|
# This is a helper function for the new config system
|
||||||
|
def __call__(self, value):
|
||||||
|
if isinstance(value, (list, tuple)):
|
||||||
|
# list: coerce each element into new list
|
||||||
|
tmp_list = [ ParamDesc.convert(self, v) for v in value ]
|
||||||
|
elif isinstance(value, str):
|
||||||
|
# If input is a csv string
|
||||||
|
tmp_list = [ ParamDesc.convert(self, v) for v in value.split(',') ]
|
||||||
|
else:
|
||||||
|
# singleton: coerce to a single-element list
|
||||||
|
tmp_list = [ ParamDesc.convert(self, value) ]
|
||||||
|
|
||||||
|
return VectorParamValue(tmp_list)
|
||||||
|
|
||||||
def swig_module_name(self):
|
def swig_module_name(self):
|
||||||
return "%s_vector" % self.ptype_str
|
return "%s_vector" % self.ptype_str
|
||||||
|
|
||||||
|
@ -349,6 +426,7 @@ VectorParam = ParamFactory(VectorParamDesc)
|
||||||
# built-in str class.
|
# built-in str class.
|
||||||
class String(ParamValue,str):
|
class String(ParamValue,str):
|
||||||
cxx_type = 'std::string'
|
cxx_type = 'std::string'
|
||||||
|
cmd_line_settable = True
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def cxx_predecls(self, code):
|
def cxx_predecls(self, code):
|
||||||
|
@ -358,6 +436,10 @@ class String(ParamValue,str):
|
||||||
def swig_predecls(cls, code):
|
def swig_predecls(cls, code):
|
||||||
code('%include "std_string.i"')
|
code('%include "std_string.i"')
|
||||||
|
|
||||||
|
def __call__(self, value):
|
||||||
|
self = value
|
||||||
|
return value
|
||||||
|
|
||||||
def getValue(self):
|
def getValue(self):
|
||||||
return self
|
return self
|
||||||
|
|
||||||
|
@ -430,6 +512,7 @@ class CheckedIntType(MetaParamValue):
|
||||||
# metaclass CheckedIntType.__init__.
|
# metaclass CheckedIntType.__init__.
|
||||||
class CheckedInt(NumericParamValue):
|
class CheckedInt(NumericParamValue):
|
||||||
__metaclass__ = CheckedIntType
|
__metaclass__ = CheckedIntType
|
||||||
|
cmd_line_settable = True
|
||||||
|
|
||||||
def _check(self):
|
def _check(self):
|
||||||
if not self.min <= self.value <= self.max:
|
if not self.min <= self.value <= self.max:
|
||||||
|
@ -446,6 +529,10 @@ class CheckedInt(NumericParamValue):
|
||||||
% type(value).__name__
|
% type(value).__name__
|
||||||
self._check()
|
self._check()
|
||||||
|
|
||||||
|
def __call__(self, value):
|
||||||
|
self.__init__(value)
|
||||||
|
return value
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def cxx_predecls(cls, code):
|
def cxx_predecls(cls, code):
|
||||||
# most derived types require this, so we just do it here once
|
# most derived types require this, so we just do it here once
|
||||||
|
@ -490,19 +577,25 @@ class Cycles(CheckedInt):
|
||||||
|
|
||||||
class Float(ParamValue, float):
|
class Float(ParamValue, float):
|
||||||
cxx_type = 'double'
|
cxx_type = 'double'
|
||||||
|
cmdLineSettable = True
|
||||||
|
|
||||||
def __init__(self, value):
|
def __init__(self, value):
|
||||||
if isinstance(value, (int, long, float, NumericParamValue, Float)):
|
if isinstance(value, (int, long, float, NumericParamValue, Float, str)):
|
||||||
self.value = float(value)
|
self.value = float(value)
|
||||||
else:
|
else:
|
||||||
raise TypeError, "Can't convert object of type %s to Float" \
|
raise TypeError, "Can't convert object of type %s to Float" \
|
||||||
% type(value).__name__
|
% type(value).__name__
|
||||||
|
|
||||||
|
def __call__(self, value):
|
||||||
|
self.__init__(value)
|
||||||
|
return value
|
||||||
|
|
||||||
def getValue(self):
|
def getValue(self):
|
||||||
return float(self.value)
|
return float(self.value)
|
||||||
|
|
||||||
class MemorySize(CheckedInt):
|
class MemorySize(CheckedInt):
|
||||||
cxx_type = 'uint64_t'
|
cxx_type = 'uint64_t'
|
||||||
|
ex_str = '512MB'
|
||||||
size = 64
|
size = 64
|
||||||
unsigned = True
|
unsigned = True
|
||||||
def __init__(self, value):
|
def __init__(self, value):
|
||||||
|
@ -514,6 +607,7 @@ class MemorySize(CheckedInt):
|
||||||
|
|
||||||
class MemorySize32(CheckedInt):
|
class MemorySize32(CheckedInt):
|
||||||
cxx_type = 'uint32_t'
|
cxx_type = 'uint32_t'
|
||||||
|
ex_str = '512MB'
|
||||||
size = 32
|
size = 32
|
||||||
unsigned = True
|
unsigned = True
|
||||||
def __init__(self, value):
|
def __init__(self, value):
|
||||||
|
@ -541,6 +635,12 @@ class Addr(CheckedInt):
|
||||||
return self.value + other.value
|
return self.value + other.value
|
||||||
else:
|
else:
|
||||||
return self.value + other
|
return self.value + other
|
||||||
|
def pretty_print(self, value):
|
||||||
|
try:
|
||||||
|
val = convert.toMemorySize(value)
|
||||||
|
except TypeError:
|
||||||
|
val = long(value)
|
||||||
|
return "0x%x" % long(val)
|
||||||
|
|
||||||
class AddrRange(ParamValue):
|
class AddrRange(ParamValue):
|
||||||
cxx_type = 'AddrRange'
|
cxx_type = 'AddrRange'
|
||||||
|
@ -624,12 +724,18 @@ class AddrRange(ParamValue):
|
||||||
# False. Thus this is a little more complicated than String.
|
# False. Thus this is a little more complicated than String.
|
||||||
class Bool(ParamValue):
|
class Bool(ParamValue):
|
||||||
cxx_type = 'bool'
|
cxx_type = 'bool'
|
||||||
|
cmd_line_settable = True
|
||||||
|
|
||||||
def __init__(self, value):
|
def __init__(self, value):
|
||||||
try:
|
try:
|
||||||
self.value = convert.toBool(value)
|
self.value = convert.toBool(value)
|
||||||
except TypeError:
|
except TypeError:
|
||||||
self.value = bool(value)
|
self.value = bool(value)
|
||||||
|
|
||||||
|
def __call__(self, value):
|
||||||
|
self.__init__(value)
|
||||||
|
return value
|
||||||
|
|
||||||
def getValue(self):
|
def getValue(self):
|
||||||
return bool(self.value)
|
return bool(self.value)
|
||||||
|
|
||||||
|
@ -668,6 +774,8 @@ def NextEthernetAddr():
|
||||||
|
|
||||||
class EthernetAddr(ParamValue):
|
class EthernetAddr(ParamValue):
|
||||||
cxx_type = 'Net::EthAddr'
|
cxx_type = 'Net::EthAddr'
|
||||||
|
ex_str = "00:90:00:00:00:01"
|
||||||
|
cmd_line_settable = True
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def cxx_predecls(cls, code):
|
def cxx_predecls(cls, code):
|
||||||
|
@ -695,6 +803,10 @@ class EthernetAddr(ParamValue):
|
||||||
|
|
||||||
self.value = value
|
self.value = value
|
||||||
|
|
||||||
|
def __call__(self, value):
|
||||||
|
self.__init__(value)
|
||||||
|
return value
|
||||||
|
|
||||||
def unproxy(self, base):
|
def unproxy(self, base):
|
||||||
if self.value == NextEthernetAddr:
|
if self.value == NextEthernetAddr:
|
||||||
return EthernetAddr(self.value())
|
return EthernetAddr(self.value())
|
||||||
|
@ -711,6 +823,8 @@ class EthernetAddr(ParamValue):
|
||||||
# the form "a.b.c.d", or an integer representing an IP.
|
# the form "a.b.c.d", or an integer representing an IP.
|
||||||
class IpAddress(ParamValue):
|
class IpAddress(ParamValue):
|
||||||
cxx_type = 'Net::IpAddress'
|
cxx_type = 'Net::IpAddress'
|
||||||
|
ex_str = "127.0.0.1"
|
||||||
|
cmd_line_settable = True
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def cxx_predecls(cls, code):
|
def cxx_predecls(cls, code):
|
||||||
|
@ -730,6 +844,10 @@ class IpAddress(ParamValue):
|
||||||
self.ip = long(value)
|
self.ip = long(value)
|
||||||
self.verifyIp()
|
self.verifyIp()
|
||||||
|
|
||||||
|
def __call__(self, value):
|
||||||
|
self.__init__(value)
|
||||||
|
return value
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
tup = [(self.ip >> i) & 0xff for i in (24, 16, 8, 0)]
|
tup = [(self.ip >> i) & 0xff for i in (24, 16, 8, 0)]
|
||||||
return '%d.%d.%d.%d' % tuple(tup)
|
return '%d.%d.%d.%d' % tuple(tup)
|
||||||
|
@ -761,6 +879,8 @@ class IpAddress(ParamValue):
|
||||||
# positional or keyword arguments.
|
# positional or keyword arguments.
|
||||||
class IpNetmask(IpAddress):
|
class IpNetmask(IpAddress):
|
||||||
cxx_type = 'Net::IpNetmask'
|
cxx_type = 'Net::IpNetmask'
|
||||||
|
ex_str = "127.0.0.0/24"
|
||||||
|
cmd_line_settable = True
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def cxx_predecls(cls, code):
|
def cxx_predecls(cls, code):
|
||||||
|
@ -806,6 +926,10 @@ class IpNetmask(IpAddress):
|
||||||
|
|
||||||
self.verify()
|
self.verify()
|
||||||
|
|
||||||
|
def __call__(self, value):
|
||||||
|
self.__init__(value)
|
||||||
|
return value
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return "%s/%d" % (super(IpNetmask, self).__str__(), self.netmask)
|
return "%s/%d" % (super(IpNetmask, self).__str__(), self.netmask)
|
||||||
|
|
||||||
|
@ -833,6 +957,8 @@ class IpNetmask(IpAddress):
|
||||||
# the form "a.b.c.d:p", or an ip and port as positional or keyword arguments.
|
# the form "a.b.c.d:p", or an ip and port as positional or keyword arguments.
|
||||||
class IpWithPort(IpAddress):
|
class IpWithPort(IpAddress):
|
||||||
cxx_type = 'Net::IpWithPort'
|
cxx_type = 'Net::IpWithPort'
|
||||||
|
ex_str = "127.0.0.1:80"
|
||||||
|
cmd_line_settable = True
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def cxx_predecls(cls, code):
|
def cxx_predecls(cls, code):
|
||||||
|
@ -878,6 +1004,10 @@ class IpWithPort(IpAddress):
|
||||||
|
|
||||||
self.verify()
|
self.verify()
|
||||||
|
|
||||||
|
def __call__(self, value):
|
||||||
|
self.__init__(value)
|
||||||
|
return value
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return "%s:%d" % (super(IpWithPort, self).__str__(), self.port)
|
return "%s:%d" % (super(IpWithPort, self).__str__(), self.port)
|
||||||
|
|
||||||
|
@ -953,6 +1083,10 @@ class Time(ParamValue):
|
||||||
def __init__(self, value):
|
def __init__(self, value):
|
||||||
self.value = parse_time(value)
|
self.value = parse_time(value)
|
||||||
|
|
||||||
|
def __call__(self, value):
|
||||||
|
self.__init__(value)
|
||||||
|
return value
|
||||||
|
|
||||||
def getValue(self):
|
def getValue(self):
|
||||||
from m5.internal.params import tm
|
from m5.internal.params import tm
|
||||||
|
|
||||||
|
@ -1111,6 +1245,7 @@ $wrapper $wrapper_name {
|
||||||
class Enum(ParamValue):
|
class Enum(ParamValue):
|
||||||
__metaclass__ = MetaEnum
|
__metaclass__ = MetaEnum
|
||||||
vals = []
|
vals = []
|
||||||
|
cmd_line_settable = True
|
||||||
|
|
||||||
# The name of the wrapping namespace or struct
|
# The name of the wrapping namespace or struct
|
||||||
wrapper_name = 'Enums'
|
wrapper_name = 'Enums'
|
||||||
|
@ -1127,6 +1262,10 @@ class Enum(ParamValue):
|
||||||
% (value, self.vals)
|
% (value, self.vals)
|
||||||
self.value = value
|
self.value = value
|
||||||
|
|
||||||
|
def __call__(self, value):
|
||||||
|
self.__init__(value)
|
||||||
|
return value
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def cxx_predecls(cls, code):
|
def cxx_predecls(cls, code):
|
||||||
code('#include "enums/$0.hh"', cls.__name__)
|
code('#include "enums/$0.hh"', cls.__name__)
|
||||||
|
@ -1146,6 +1285,8 @@ frequency_tolerance = 0.001 # 0.1%
|
||||||
|
|
||||||
class TickParamValue(NumericParamValue):
|
class TickParamValue(NumericParamValue):
|
||||||
cxx_type = 'Tick'
|
cxx_type = 'Tick'
|
||||||
|
ex_str = "1MHz"
|
||||||
|
cmd_line_settable = True
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def cxx_predecls(cls, code):
|
def cxx_predecls(cls, code):
|
||||||
|
@ -1156,10 +1297,16 @@ class TickParamValue(NumericParamValue):
|
||||||
code('%import "stdint.i"')
|
code('%import "stdint.i"')
|
||||||
code('%import "base/types.hh"')
|
code('%import "base/types.hh"')
|
||||||
|
|
||||||
|
def __call__(self, value):
|
||||||
|
self.__init__(value)
|
||||||
|
return value
|
||||||
|
|
||||||
def getValue(self):
|
def getValue(self):
|
||||||
return long(self.value)
|
return long(self.value)
|
||||||
|
|
||||||
class Latency(TickParamValue):
|
class Latency(TickParamValue):
|
||||||
|
ex_str = "100ns"
|
||||||
|
|
||||||
def __init__(self, value):
|
def __init__(self, value):
|
||||||
if isinstance(value, (Latency, Clock)):
|
if isinstance(value, (Latency, Clock)):
|
||||||
self.ticks = value.ticks
|
self.ticks = value.ticks
|
||||||
|
@ -1174,6 +1321,10 @@ class Latency(TickParamValue):
|
||||||
self.ticks = False
|
self.ticks = False
|
||||||
self.value = convert.toLatency(value)
|
self.value = convert.toLatency(value)
|
||||||
|
|
||||||
|
def __call__(self, value):
|
||||||
|
self.__init__(value)
|
||||||
|
return value
|
||||||
|
|
||||||
def __getattr__(self, attr):
|
def __getattr__(self, attr):
|
||||||
if attr in ('latency', 'period'):
|
if attr in ('latency', 'period'):
|
||||||
return self
|
return self
|
||||||
|
@ -1193,6 +1344,8 @@ class Latency(TickParamValue):
|
||||||
return '%d' % self.getValue()
|
return '%d' % self.getValue()
|
||||||
|
|
||||||
class Frequency(TickParamValue):
|
class Frequency(TickParamValue):
|
||||||
|
ex_str = "1GHz"
|
||||||
|
|
||||||
def __init__(self, value):
|
def __init__(self, value):
|
||||||
if isinstance(value, (Latency, Clock)):
|
if isinstance(value, (Latency, Clock)):
|
||||||
if value.value == 0:
|
if value.value == 0:
|
||||||
|
@ -1207,6 +1360,10 @@ class Frequency(TickParamValue):
|
||||||
self.ticks = False
|
self.ticks = False
|
||||||
self.value = convert.toFrequency(value)
|
self.value = convert.toFrequency(value)
|
||||||
|
|
||||||
|
def __call__(self, value):
|
||||||
|
self.__init__(value)
|
||||||
|
return value
|
||||||
|
|
||||||
def __getattr__(self, attr):
|
def __getattr__(self, attr):
|
||||||
if attr == 'frequency':
|
if attr == 'frequency':
|
||||||
return self
|
return self
|
||||||
|
@ -1242,6 +1399,13 @@ class Clock(TickParamValue):
|
||||||
self.ticks = False
|
self.ticks = False
|
||||||
self.value = convert.anyToLatency(value)
|
self.value = convert.anyToLatency(value)
|
||||||
|
|
||||||
|
def __call__(self, value):
|
||||||
|
self.__init__(value)
|
||||||
|
return value
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return "%s" % Latency(self)
|
||||||
|
|
||||||
def __getattr__(self, attr):
|
def __getattr__(self, attr):
|
||||||
if attr == 'frequency':
|
if attr == 'frequency':
|
||||||
return Frequency(self)
|
return Frequency(self)
|
||||||
|
@ -1257,13 +1421,21 @@ class Clock(TickParamValue):
|
||||||
|
|
||||||
class Voltage(float,ParamValue):
|
class Voltage(float,ParamValue):
|
||||||
cxx_type = 'double'
|
cxx_type = 'double'
|
||||||
|
ex_str = "1V"
|
||||||
|
cmd_line_settable = False
|
||||||
|
|
||||||
def __new__(cls, value):
|
def __new__(cls, value):
|
||||||
# convert to voltage
|
# convert to voltage
|
||||||
val = convert.toVoltage(value)
|
val = convert.toVoltage(value)
|
||||||
return super(cls, Voltage).__new__(cls, val)
|
return super(cls, Voltage).__new__(cls, val)
|
||||||
|
|
||||||
|
def __call__(self, value):
|
||||||
|
val = convert.toVoltage(value)
|
||||||
|
self.__init__(val)
|
||||||
|
return value
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return str(self.val)
|
return str(self.getValue())
|
||||||
|
|
||||||
def getValue(self):
|
def getValue(self):
|
||||||
value = float(self)
|
value = float(self)
|
||||||
|
@ -1274,6 +1446,9 @@ class Voltage(float,ParamValue):
|
||||||
|
|
||||||
class NetworkBandwidth(float,ParamValue):
|
class NetworkBandwidth(float,ParamValue):
|
||||||
cxx_type = 'float'
|
cxx_type = 'float'
|
||||||
|
ex_str = "1Gbps"
|
||||||
|
cmd_line_settable = True
|
||||||
|
|
||||||
def __new__(cls, value):
|
def __new__(cls, value):
|
||||||
# convert to bits per second
|
# convert to bits per second
|
||||||
val = convert.toNetworkBandwidth(value)
|
val = convert.toNetworkBandwidth(value)
|
||||||
|
@ -1282,6 +1457,11 @@ class NetworkBandwidth(float,ParamValue):
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return str(self.val)
|
return str(self.val)
|
||||||
|
|
||||||
|
def __call__(self, value):
|
||||||
|
val = convert.toNetworkBandwidth(value)
|
||||||
|
self.__init__(val)
|
||||||
|
return value
|
||||||
|
|
||||||
def getValue(self):
|
def getValue(self):
|
||||||
# convert to seconds per byte
|
# convert to seconds per byte
|
||||||
value = 8.0 / float(self)
|
value = 8.0 / float(self)
|
||||||
|
@ -1294,13 +1474,18 @@ class NetworkBandwidth(float,ParamValue):
|
||||||
|
|
||||||
class MemoryBandwidth(float,ParamValue):
|
class MemoryBandwidth(float,ParamValue):
|
||||||
cxx_type = 'float'
|
cxx_type = 'float'
|
||||||
|
ex_str = "1GB/s"
|
||||||
|
cmd_line_settable = True
|
||||||
|
|
||||||
def __new__(cls, value):
|
def __new__(cls, value):
|
||||||
# convert to bytes per second
|
# convert to bytes per second
|
||||||
val = convert.toMemoryBandwidth(value)
|
val = convert.toMemoryBandwidth(value)
|
||||||
return super(cls, MemoryBandwidth).__new__(cls, val)
|
return super(cls, MemoryBandwidth).__new__(cls, val)
|
||||||
|
|
||||||
def __str__(self):
|
def __call__(self, value):
|
||||||
return str(self.val)
|
val = convert.toMemoryBandwidth(value)
|
||||||
|
self.__init__(val)
|
||||||
|
return value
|
||||||
|
|
||||||
def getValue(self):
|
def getValue(self):
|
||||||
# convert to seconds per byte
|
# convert to seconds per byte
|
||||||
|
|
Loading…
Reference in a new issue