2014-09-03 13:43:03 +02:00
|
|
|
# Copyright (c) 2012-2014 ARM Limited
|
2012-02-13 12:43:09 +01:00
|
|
|
# All rights reserved.
|
|
|
|
#
|
|
|
|
# The license below extends only to copyright in the software and shall
|
|
|
|
# not be construed as granting a license to any other intellectual
|
|
|
|
# property including but not limited to intellectual property relating
|
|
|
|
# to a hardware implementation of the functionality of the software
|
|
|
|
# licensed hereunder. You may use the software subject to the license
|
|
|
|
# terms below provided that you ensure that this notice is replicated
|
|
|
|
# unmodified and in its entirety in all distributions of the software,
|
|
|
|
# modified or unmodified, in source code or in binary form.
|
|
|
|
#
|
2006-09-04 19:52:26 +02:00
|
|
|
# Copyright (c) 2004-2006 The Regents of The University of Michigan
|
2011-09-23 03:58:14 +02:00
|
|
|
# Copyright (c) 2010-2011 Advanced Micro Devices, Inc.
|
2006-09-04 19:52:26 +02:00
|
|
|
# All rights reserved.
|
|
|
|
#
|
|
|
|
# Redistribution and use in source and binary forms, with or without
|
|
|
|
# modification, are permitted provided that the following conditions are
|
|
|
|
# met: redistributions of source code must retain the above copyright
|
|
|
|
# notice, this list of conditions and the following disclaimer;
|
|
|
|
# redistributions in binary form must reproduce the above copyright
|
|
|
|
# notice, this list of conditions and the following disclaimer in the
|
|
|
|
# documentation and/or other materials provided with the distribution;
|
|
|
|
# neither the name of the copyright holders nor the names of its
|
|
|
|
# contributors may be used to endorse or promote products derived from
|
|
|
|
# this software without specific prior written permission.
|
|
|
|
#
|
|
|
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
|
|
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
|
|
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
|
|
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
|
|
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
|
|
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
|
|
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
|
|
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
|
|
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
|
|
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
|
|
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
#
|
|
|
|
# Authors: Steve Reinhardt
|
|
|
|
# Nathan Binkert
|
2010-11-23 23:08:41 +01:00
|
|
|
# Gabe Black
|
2012-02-13 12:43:09 +01:00
|
|
|
# Andreas Hansson
|
2006-09-04 19:52:26 +02:00
|
|
|
|
|
|
|
#####################################################################
|
|
|
|
#
|
|
|
|
# Parameter description classes
|
|
|
|
#
|
|
|
|
# The _params dictionary in each class maps parameter names to either
|
|
|
|
# a Param or a VectorParam object. These objects contain the
|
|
|
|
# parameter description string, the parameter type, and the default
|
|
|
|
# value (if any). The convert() method on these objects is used to
|
|
|
|
# force whatever value is assigned to the parameter to the appropriate
|
|
|
|
# type.
|
|
|
|
#
|
|
|
|
# Note that the default values are loaded into the class's attribute
|
|
|
|
# space when the parameter dictionary is initialized (in
|
|
|
|
# MetaSimObject._new_param()); after that point they aren't used.
|
|
|
|
#
|
|
|
|
#####################################################################
|
|
|
|
|
2007-01-03 19:12:55 +01:00
|
|
|
import copy
|
|
|
|
import datetime
|
2007-07-24 06:51:38 +02:00
|
|
|
import re
|
2007-01-03 19:12:55 +01:00
|
|
|
import sys
|
|
|
|
import time
|
2010-08-17 14:11:00 +02:00
|
|
|
import math
|
2007-01-03 19:12:55 +01:00
|
|
|
|
2007-04-12 17:37:55 +02:00
|
|
|
import proxy
|
2007-03-06 20:13:43 +01:00
|
|
|
import ticks
|
2006-09-05 02:14:07 +02:00
|
|
|
from util import *
|
2006-09-04 19:52:26 +02:00
|
|
|
|
2007-07-24 06:51:38 +02:00
|
|
|
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)
|
|
|
|
|
2007-08-30 21:16:58 +02:00
|
|
|
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
|
|
|
|
|
|
|
|
|
2006-09-04 19:52:26 +02:00
|
|
|
# Dummy base class to identify types that are legitimate for SimObject
|
|
|
|
# parameters.
|
|
|
|
class ParamValue(object):
|
2007-08-30 21:16:58 +02:00
|
|
|
__metaclass__ = MetaParamValue
|
2014-08-10 11:39:13 +02:00
|
|
|
cmd_line_settable = False
|
2011-10-20 22:08:49 +02:00
|
|
|
|
|
|
|
# Generate the code needed as a prerequisite for declaring a C++
|
|
|
|
# object of this type. Typically generates one or more #include
|
|
|
|
# statements. Used when declaring parameters of this type.
|
2010-09-09 23:15:41 +02:00
|
|
|
@classmethod
|
|
|
|
def cxx_predecls(cls, code):
|
|
|
|
pass
|
|
|
|
|
2011-10-20 22:08:49 +02:00
|
|
|
# Generate the code needed as a prerequisite for including a
|
|
|
|
# reference to a C++ object of this type in a SWIG .i file.
|
|
|
|
# Typically generates one or more %import or %include statements.
|
2010-09-09 23:15:41 +02:00
|
|
|
@classmethod
|
|
|
|
def swig_predecls(cls, code):
|
|
|
|
pass
|
2006-09-04 19:52:26 +02:00
|
|
|
|
|
|
|
# default for printing to .ini file is regular string conversion.
|
|
|
|
# will be overridden in some cases
|
|
|
|
def ini_str(self):
|
|
|
|
return str(self)
|
|
|
|
|
|
|
|
# allows us to blithely call unproxy() on things without checking
|
|
|
|
# if they're really proxies or not
|
|
|
|
def unproxy(self, base):
|
|
|
|
return self
|
|
|
|
|
2014-08-10 11:39:13 +02:00
|
|
|
# Produce a human readable version of the stored value
|
|
|
|
def pretty_print(self, value):
|
|
|
|
return str(value)
|
|
|
|
|
2006-09-04 19:52:26 +02:00
|
|
|
# Regular parameter description.
|
|
|
|
class ParamDesc(object):
|
|
|
|
def __init__(self, ptype_str, ptype, *args, **kwargs):
|
|
|
|
self.ptype_str = ptype_str
|
|
|
|
# remember ptype only if it is provided
|
|
|
|
if ptype != None:
|
|
|
|
self.ptype = ptype
|
|
|
|
|
|
|
|
if args:
|
|
|
|
if len(args) == 1:
|
|
|
|
self.desc = args[0]
|
|
|
|
elif len(args) == 2:
|
|
|
|
self.default = args[0]
|
|
|
|
self.desc = args[1]
|
|
|
|
else:
|
|
|
|
raise TypeError, 'too many arguments'
|
|
|
|
|
|
|
|
if kwargs.has_key('desc'):
|
|
|
|
assert(not hasattr(self, 'desc'))
|
|
|
|
self.desc = kwargs['desc']
|
|
|
|
del kwargs['desc']
|
|
|
|
|
|
|
|
if kwargs.has_key('default'):
|
|
|
|
assert(not hasattr(self, 'default'))
|
|
|
|
self.default = kwargs['default']
|
|
|
|
del kwargs['default']
|
|
|
|
|
|
|
|
if kwargs:
|
|
|
|
raise TypeError, 'extra unknown kwargs %s' % kwargs
|
|
|
|
|
|
|
|
if not hasattr(self, 'desc'):
|
|
|
|
raise TypeError, 'desc attribute missing'
|
|
|
|
|
|
|
|
def __getattr__(self, attr):
|
|
|
|
if attr == 'ptype':
|
2007-08-30 21:16:58 +02:00
|
|
|
ptype = SimObject.allClasses[self.ptype_str]
|
2009-09-23 00:24:16 +02:00
|
|
|
assert isSimObjectClass(ptype)
|
2007-08-30 21:16:58 +02:00
|
|
|
self.ptype = ptype
|
|
|
|
return ptype
|
|
|
|
|
2006-09-04 19:52:26 +02:00
|
|
|
raise AttributeError, "'%s' object has no attribute '%s'" % \
|
|
|
|
(type(self).__name__, attr)
|
|
|
|
|
2014-08-10 11:39:13 +02:00
|
|
|
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
|
|
|
|
|
2006-09-04 19:52:26 +02:00
|
|
|
def convert(self, value):
|
|
|
|
if isinstance(value, proxy.BaseProxy):
|
|
|
|
value.set_param_desc(self)
|
|
|
|
return value
|
|
|
|
if not hasattr(self, 'ptype') and isNullPointer(value):
|
|
|
|
# deferred evaluation of SimObject; continue to defer if
|
|
|
|
# we're just assigning a null pointer
|
|
|
|
return value
|
|
|
|
if isinstance(value, self.ptype):
|
|
|
|
return value
|
2006-09-05 02:14:07 +02:00
|
|
|
if isNullPointer(value) and isSimObjectClass(self.ptype):
|
2006-09-04 19:52:26 +02:00
|
|
|
return value
|
|
|
|
return self.ptype(value)
|
|
|
|
|
2014-08-10 11:39:13 +02:00
|
|
|
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)
|
|
|
|
|
2010-09-09 23:15:41 +02:00
|
|
|
def cxx_predecls(self, code):
|
2011-10-31 09:09:44 +01:00
|
|
|
code('#include <cstddef>')
|
2010-09-09 23:15:41 +02:00
|
|
|
self.ptype.cxx_predecls(code)
|
2006-09-04 19:52:26 +02:00
|
|
|
|
2010-09-09 23:15:41 +02:00
|
|
|
def swig_predecls(self, code):
|
|
|
|
self.ptype.swig_predecls(code)
|
2006-09-04 19:52:26 +02:00
|
|
|
|
2010-09-09 23:15:41 +02:00
|
|
|
def cxx_decl(self, code):
|
|
|
|
code('${{self.ptype.cxx_type}} ${{self.name}};')
|
2006-09-04 19:52:26 +02:00
|
|
|
|
|
|
|
# Vector-valued parameter description. Just like ParamDesc, except
|
|
|
|
# that the value is a vector (list) of the specified type instead of a
|
|
|
|
# single value.
|
|
|
|
|
|
|
|
class VectorParamValue(list):
|
2007-08-30 21:16:58 +02:00
|
|
|
__metaclass__ = MetaParamValue
|
2008-06-16 06:26:33 +02:00
|
|
|
def __setattr__(self, attr, value):
|
|
|
|
raise AttributeError, \
|
|
|
|
"Not allowed to set %s on '%s'" % (attr, type(self).__name__)
|
|
|
|
|
2006-09-04 19:52:26 +02:00
|
|
|
def ini_str(self):
|
|
|
|
return ' '.join([v.ini_str() for v in self])
|
|
|
|
|
2007-07-24 06:51:38 +02:00
|
|
|
def getValue(self):
|
|
|
|
return [ v.getValue() for v in self ]
|
|
|
|
|
2006-09-04 19:52:26 +02:00
|
|
|
def unproxy(self, base):
|
2011-07-10 19:56:08 +02:00
|
|
|
if len(self) == 1 and isinstance(self[0], proxy.AllProxy):
|
2011-07-10 19:56:08 +02:00
|
|
|
return self[0].unproxy(base)
|
|
|
|
else:
|
|
|
|
return [v.unproxy(base) for v in self]
|
2006-09-04 19:52:26 +02:00
|
|
|
|
2010-08-17 14:11:00 +02:00
|
|
|
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))
|
|
|
|
|
2011-05-23 23:29:08 +02:00
|
|
|
def has_parent(self):
|
|
|
|
return reduce(lambda x,y: x and y, [v.has_parent() for v in self])
|
2010-08-17 14:11:00 +02:00
|
|
|
|
|
|
|
# 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):
|
2006-09-04 19:52:26 +02:00
|
|
|
for v in self:
|
2010-08-17 14:11:00 +02:00
|
|
|
for obj in v.descendants():
|
|
|
|
yield obj
|
2006-09-04 19:52:26 +02:00
|
|
|
|
2012-01-10 01:08:20 +01:00
|
|
|
def get_config_as_dict(self):
|
|
|
|
a = []
|
|
|
|
for v in self:
|
|
|
|
a.append(v.get_config_as_dict())
|
|
|
|
return a
|
|
|
|
|
2013-10-31 19:41:13 +01:00
|
|
|
# If we are replacing an item in the vector, make sure to set the
|
|
|
|
# parent reference of the new SimObject to be the same as the parent
|
|
|
|
# of the SimObject being replaced. Useful to have if we created
|
|
|
|
# a SimObjectVector of temporary objects that will be modified later in
|
|
|
|
# configuration scripts.
|
|
|
|
def __setitem__(self, key, value):
|
|
|
|
val = self[key]
|
|
|
|
if value.has_parent():
|
|
|
|
warn("SimObject %s already has a parent" % value.get_name() +\
|
|
|
|
" that is being overwritten by a SimObjectVector")
|
|
|
|
value.set_parent(val.get_parent(), val._name)
|
|
|
|
super(SimObjectVector, self).__setitem__(key, value)
|
|
|
|
|
2014-08-10 11:39:13 +02:00
|
|
|
# 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
|
|
|
|
|
2006-09-04 19:52:26 +02:00
|
|
|
class VectorParamDesc(ParamDesc):
|
|
|
|
# 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 ]
|
|
|
|
else:
|
2007-07-24 06:51:38 +02:00
|
|
|
# singleton: coerce to a single-element list
|
|
|
|
tmp_list = [ ParamDesc.convert(self, value) ]
|
2006-09-04 19:52:26 +02:00
|
|
|
|
2007-07-24 06:51:38 +02:00
|
|
|
if isSimObjectSequence(tmp_list):
|
2010-08-17 14:11:00 +02:00
|
|
|
return SimObjectVector(tmp_list)
|
2007-07-24 06:51:38 +02:00
|
|
|
else:
|
|
|
|
return VectorParamValue(tmp_list)
|
2006-09-04 19:52:26 +02:00
|
|
|
|
2014-08-10 11:39:13 +02:00
|
|
|
# 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)
|
|
|
|
|
2011-10-20 22:08:49 +02:00
|
|
|
def swig_module_name(self):
|
|
|
|
return "%s_vector" % self.ptype_str
|
|
|
|
|
2010-09-09 23:15:41 +02:00
|
|
|
def swig_predecls(self, code):
|
2011-10-20 22:08:49 +02:00
|
|
|
code('%import "${{self.swig_module_name()}}.i"')
|
2007-07-24 06:51:38 +02:00
|
|
|
|
2010-09-09 23:15:41 +02:00
|
|
|
def swig_decl(self, code):
|
2011-10-20 22:08:49 +02:00
|
|
|
code('%module(package="m5.internal") ${{self.swig_module_name()}}')
|
2010-09-09 23:26:29 +02:00
|
|
|
code('%{')
|
|
|
|
self.ptype.cxx_predecls(code)
|
|
|
|
code('%}')
|
|
|
|
code()
|
2012-01-10 01:08:20 +01:00
|
|
|
# Make sure the SWIGPY_SLICE_ARG is defined through this inclusion
|
|
|
|
code('%include "std_container.i"')
|
|
|
|
code()
|
2010-09-09 23:15:41 +02:00
|
|
|
self.ptype.swig_predecls(code)
|
2010-09-09 23:26:29 +02:00
|
|
|
code()
|
|
|
|
code('%include "std_vector.i"')
|
|
|
|
code()
|
|
|
|
|
|
|
|
ptype = self.ptype_str
|
|
|
|
cxx_type = self.ptype.cxx_type
|
|
|
|
|
|
|
|
code('%template(vector_$ptype) std::vector< $cxx_type >;')
|
|
|
|
|
2010-09-09 23:15:41 +02:00
|
|
|
def cxx_predecls(self, code):
|
|
|
|
code('#include <vector>')
|
|
|
|
self.ptype.cxx_predecls(code)
|
2006-09-04 19:52:26 +02:00
|
|
|
|
2010-09-09 23:15:41 +02:00
|
|
|
def cxx_decl(self, code):
|
|
|
|
code('std::vector< ${{self.ptype.cxx_type}} > ${{self.name}};')
|
2006-09-04 19:52:26 +02:00
|
|
|
|
|
|
|
class ParamFactory(object):
|
|
|
|
def __init__(self, param_desc_class, ptype_str = None):
|
|
|
|
self.param_desc_class = param_desc_class
|
|
|
|
self.ptype_str = ptype_str
|
|
|
|
|
|
|
|
def __getattr__(self, attr):
|
|
|
|
if self.ptype_str:
|
|
|
|
attr = self.ptype_str + '.' + attr
|
|
|
|
return ParamFactory(self.param_desc_class, attr)
|
|
|
|
|
|
|
|
# E.g., Param.Int(5, "number of widgets")
|
|
|
|
def __call__(self, *args, **kwargs):
|
|
|
|
ptype = None
|
|
|
|
try:
|
2007-08-30 21:16:58 +02:00
|
|
|
ptype = allParams[self.ptype_str]
|
|
|
|
except KeyError:
|
2006-09-04 19:52:26 +02:00
|
|
|
# if name isn't defined yet, assume it's a SimObject, and
|
|
|
|
# try to resolve it later
|
|
|
|
pass
|
|
|
|
return self.param_desc_class(self.ptype_str, ptype, *args, **kwargs)
|
|
|
|
|
|
|
|
Param = ParamFactory(ParamDesc)
|
|
|
|
VectorParam = ParamFactory(VectorParamDesc)
|
|
|
|
|
|
|
|
#####################################################################
|
|
|
|
#
|
|
|
|
# Parameter Types
|
|
|
|
#
|
|
|
|
# Though native Python types could be used to specify parameter types
|
|
|
|
# (the 'ptype' field of the Param and VectorParam classes), it's more
|
|
|
|
# flexible to define our own set of types. This gives us more control
|
|
|
|
# over how Python expressions are converted to values (via the
|
|
|
|
# __init__() constructor) and how these values are printed out (via
|
|
|
|
# the __str__() conversion method).
|
|
|
|
#
|
|
|
|
#####################################################################
|
|
|
|
|
|
|
|
# String-valued parameter. Just mixin the ParamValue class with the
|
|
|
|
# built-in str class.
|
|
|
|
class String(ParamValue,str):
|
|
|
|
cxx_type = 'std::string'
|
2014-08-10 11:39:13 +02:00
|
|
|
cmd_line_settable = True
|
2010-09-09 23:15:41 +02:00
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def cxx_predecls(self, code):
|
|
|
|
code('#include <string>')
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def swig_predecls(cls, code):
|
|
|
|
code('%include "std_string.i"')
|
2007-07-24 06:51:38 +02:00
|
|
|
|
2014-08-10 11:39:13 +02:00
|
|
|
def __call__(self, value):
|
|
|
|
self = value
|
|
|
|
return value
|
|
|
|
|
2007-07-24 06:51:38 +02:00
|
|
|
def getValue(self):
|
|
|
|
return self
|
2006-09-04 19:52:26 +02:00
|
|
|
|
|
|
|
# superclass for "numeric" parameter values, to emulate math
|
|
|
|
# operations in a type-safe way. e.g., a Latency times an int returns
|
|
|
|
# a new Latency object.
|
|
|
|
class NumericParamValue(ParamValue):
|
|
|
|
def __str__(self):
|
|
|
|
return str(self.value)
|
|
|
|
|
|
|
|
def __float__(self):
|
|
|
|
return float(self.value)
|
|
|
|
|
2006-12-03 07:24:52 +01:00
|
|
|
def __long__(self):
|
|
|
|
return long(self.value)
|
|
|
|
|
|
|
|
def __int__(self):
|
|
|
|
return int(self.value)
|
|
|
|
|
2006-09-04 19:52:26 +02:00
|
|
|
# hook for bounds checking
|
|
|
|
def _check(self):
|
|
|
|
return
|
|
|
|
|
|
|
|
def __mul__(self, other):
|
|
|
|
newobj = self.__class__(self)
|
|
|
|
newobj.value *= other
|
|
|
|
newobj._check()
|
|
|
|
return newobj
|
|
|
|
|
|
|
|
__rmul__ = __mul__
|
|
|
|
|
|
|
|
def __div__(self, other):
|
|
|
|
newobj = self.__class__(self)
|
|
|
|
newobj.value /= other
|
|
|
|
newobj._check()
|
|
|
|
return newobj
|
|
|
|
|
|
|
|
def __sub__(self, other):
|
|
|
|
newobj = self.__class__(self)
|
|
|
|
newobj.value -= other
|
|
|
|
newobj._check()
|
|
|
|
return newobj
|
|
|
|
|
|
|
|
# Metaclass for bounds-checked integer parameters. See CheckedInt.
|
2007-08-30 21:16:58 +02:00
|
|
|
class CheckedIntType(MetaParamValue):
|
2006-09-04 19:52:26 +02:00
|
|
|
def __init__(cls, name, bases, dict):
|
|
|
|
super(CheckedIntType, cls).__init__(name, bases, dict)
|
|
|
|
|
|
|
|
# CheckedInt is an abstract base class, so we actually don't
|
|
|
|
# want to do any processing on it... the rest of this code is
|
|
|
|
# just for classes that derive from CheckedInt.
|
|
|
|
if name == 'CheckedInt':
|
|
|
|
return
|
|
|
|
|
|
|
|
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" \
|
2009-01-31 02:04:15 +01:00
|
|
|
" 'min' and 'max' or 'size' and 'unsigned'\n",
|
|
|
|
name);
|
2006-09-04 19:52:26 +02:00
|
|
|
if cls.unsigned:
|
|
|
|
cls.min = 0
|
|
|
|
cls.max = 2 ** cls.size - 1
|
|
|
|
else:
|
|
|
|
cls.min = -(2 ** (cls.size - 1))
|
|
|
|
cls.max = (2 ** (cls.size - 1)) - 1
|
|
|
|
|
|
|
|
# Abstract superclass for bounds-checked integer parameters. This
|
|
|
|
# class is subclassed to generate parameter classes with specific
|
|
|
|
# bounds. Initialization of the min and max bounds is done in the
|
|
|
|
# metaclass CheckedIntType.__init__.
|
|
|
|
class CheckedInt(NumericParamValue):
|
|
|
|
__metaclass__ = CheckedIntType
|
2014-08-10 11:39:13 +02:00
|
|
|
cmd_line_settable = True
|
2006-09-04 19:52:26 +02:00
|
|
|
|
|
|
|
def _check(self):
|
|
|
|
if not self.min <= self.value <= self.max:
|
|
|
|
raise TypeError, 'Integer param out of bounds %d < %d < %d' % \
|
|
|
|
(self.min, self.value, self.max)
|
|
|
|
|
|
|
|
def __init__(self, value):
|
|
|
|
if isinstance(value, str):
|
2006-09-05 02:14:07 +02:00
|
|
|
self.value = convert.toInteger(value)
|
2006-12-03 07:24:52 +01:00
|
|
|
elif isinstance(value, (int, long, float, NumericParamValue)):
|
2006-09-04 19:52:26 +02:00
|
|
|
self.value = long(value)
|
2006-12-03 07:24:52 +01:00
|
|
|
else:
|
|
|
|
raise TypeError, "Can't convert object of type %s to CheckedInt" \
|
|
|
|
% type(value).__name__
|
2006-09-04 19:52:26 +02:00
|
|
|
self._check()
|
|
|
|
|
2014-08-10 11:39:13 +02:00
|
|
|
def __call__(self, value):
|
|
|
|
self.__init__(value)
|
|
|
|
return value
|
|
|
|
|
2010-09-09 23:15:41 +02:00
|
|
|
@classmethod
|
|
|
|
def cxx_predecls(cls, code):
|
|
|
|
# most derived types require this, so we just do it here once
|
|
|
|
code('#include "base/types.hh"')
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def swig_predecls(cls, code):
|
|
|
|
# most derived types require this, so we just do it here once
|
|
|
|
code('%import "stdint.i"')
|
|
|
|
code('%import "base/types.hh"')
|
|
|
|
|
2007-07-24 06:51:38 +02:00
|
|
|
def getValue(self):
|
|
|
|
return long(self.value)
|
|
|
|
|
2006-09-04 19:52:26 +02:00
|
|
|
class Int(CheckedInt): cxx_type = 'int'; size = 32; unsigned = False
|
|
|
|
class Unsigned(CheckedInt): cxx_type = 'unsigned'; size = 32; unsigned = True
|
|
|
|
|
|
|
|
class Int8(CheckedInt): cxx_type = 'int8_t'; size = 8; unsigned = False
|
|
|
|
class UInt8(CheckedInt): cxx_type = 'uint8_t'; size = 8; unsigned = True
|
|
|
|
class Int16(CheckedInt): cxx_type = 'int16_t'; size = 16; unsigned = False
|
|
|
|
class UInt16(CheckedInt): cxx_type = 'uint16_t'; size = 16; unsigned = True
|
|
|
|
class Int32(CheckedInt): cxx_type = 'int32_t'; size = 32; unsigned = False
|
|
|
|
class UInt32(CheckedInt): cxx_type = 'uint32_t'; size = 32; unsigned = True
|
|
|
|
class Int64(CheckedInt): cxx_type = 'int64_t'; size = 64; unsigned = False
|
|
|
|
class UInt64(CheckedInt): cxx_type = 'uint64_t'; size = 64; unsigned = True
|
|
|
|
|
|
|
|
class Counter(CheckedInt): cxx_type = 'Counter'; size = 64; unsigned = True
|
|
|
|
class Tick(CheckedInt): cxx_type = 'Tick'; size = 64; unsigned = True
|
|
|
|
class TcpPort(CheckedInt): cxx_type = 'uint16_t'; size = 16; unsigned = True
|
|
|
|
class UdpPort(CheckedInt): cxx_type = 'uint16_t'; size = 16; unsigned = True
|
|
|
|
|
|
|
|
class Percent(CheckedInt): cxx_type = 'int'; min = 0; max = 100
|
|
|
|
|
2012-09-07 18:34:38 +02:00
|
|
|
class Cycles(CheckedInt):
|
|
|
|
cxx_type = 'Cycles'
|
|
|
|
size = 64
|
|
|
|
unsigned = True
|
|
|
|
|
|
|
|
def getValue(self):
|
|
|
|
from m5.internal.core import Cycles
|
|
|
|
return Cycles(self.value)
|
|
|
|
|
2006-09-04 19:52:26 +02:00
|
|
|
class Float(ParamValue, float):
|
2007-05-11 20:48:58 +02:00
|
|
|
cxx_type = 'double'
|
2014-08-10 11:39:13 +02:00
|
|
|
cmdLineSettable = True
|
2006-09-04 19:52:26 +02:00
|
|
|
|
2008-06-15 05:39:31 +02:00
|
|
|
def __init__(self, value):
|
2014-08-10 11:39:13 +02:00
|
|
|
if isinstance(value, (int, long, float, NumericParamValue, Float, str)):
|
2008-06-15 05:39:31 +02:00
|
|
|
self.value = float(value)
|
|
|
|
else:
|
|
|
|
raise TypeError, "Can't convert object of type %s to Float" \
|
|
|
|
% type(value).__name__
|
|
|
|
|
2014-08-10 11:39:13 +02:00
|
|
|
def __call__(self, value):
|
|
|
|
self.__init__(value)
|
|
|
|
return value
|
|
|
|
|
2007-07-24 06:51:38 +02:00
|
|
|
def getValue(self):
|
|
|
|
return float(self.value)
|
|
|
|
|
2006-09-04 19:52:26 +02:00
|
|
|
class MemorySize(CheckedInt):
|
|
|
|
cxx_type = 'uint64_t'
|
2014-08-10 11:39:13 +02:00
|
|
|
ex_str = '512MB'
|
2006-09-04 19:52:26 +02:00
|
|
|
size = 64
|
|
|
|
unsigned = True
|
|
|
|
def __init__(self, value):
|
|
|
|
if isinstance(value, MemorySize):
|
|
|
|
self.value = value.value
|
|
|
|
else:
|
2006-09-05 02:14:07 +02:00
|
|
|
self.value = convert.toMemorySize(value)
|
2006-09-04 19:52:26 +02:00
|
|
|
self._check()
|
|
|
|
|
|
|
|
class MemorySize32(CheckedInt):
|
2007-03-06 20:16:15 +01:00
|
|
|
cxx_type = 'uint32_t'
|
2014-08-10 11:39:13 +02:00
|
|
|
ex_str = '512MB'
|
2006-09-04 19:52:26 +02:00
|
|
|
size = 32
|
|
|
|
unsigned = True
|
|
|
|
def __init__(self, value):
|
|
|
|
if isinstance(value, MemorySize):
|
|
|
|
self.value = value.value
|
|
|
|
else:
|
2006-09-05 02:14:07 +02:00
|
|
|
self.value = convert.toMemorySize(value)
|
2006-09-04 19:52:26 +02:00
|
|
|
self._check()
|
|
|
|
|
|
|
|
class Addr(CheckedInt):
|
|
|
|
cxx_type = 'Addr'
|
|
|
|
size = 64
|
|
|
|
unsigned = True
|
|
|
|
def __init__(self, value):
|
|
|
|
if isinstance(value, Addr):
|
|
|
|
self.value = value.value
|
|
|
|
else:
|
|
|
|
try:
|
2014-09-03 13:42:20 +02:00
|
|
|
# Often addresses are referred to with sizes. Ex: A device
|
|
|
|
# base address is at "512MB". Use toMemorySize() to convert
|
|
|
|
# these into addresses. If the address is not specified with a
|
|
|
|
# "size", an exception will occur and numeric translation will
|
|
|
|
# proceed below.
|
2006-09-05 02:14:07 +02:00
|
|
|
self.value = convert.toMemorySize(value)
|
2014-09-03 13:42:20 +02:00
|
|
|
except (TypeError, ValueError):
|
|
|
|
# Convert number to string and use long() to do automatic
|
|
|
|
# base conversion (requires base=0 for auto-conversion)
|
|
|
|
self.value = long(str(value), base=0)
|
|
|
|
|
2006-09-04 19:52:26 +02:00
|
|
|
self._check()
|
2006-11-10 00:22:46 +01:00
|
|
|
def __add__(self, other):
|
|
|
|
if isinstance(other, Addr):
|
|
|
|
return self.value + other.value
|
|
|
|
else:
|
|
|
|
return self.value + other
|
2014-08-10 11:39:13 +02:00
|
|
|
def pretty_print(self, value):
|
|
|
|
try:
|
|
|
|
val = convert.toMemorySize(value)
|
|
|
|
except TypeError:
|
|
|
|
val = long(value)
|
|
|
|
return "0x%x" % long(val)
|
2006-09-04 19:52:26 +02:00
|
|
|
|
2012-09-19 12:15:41 +02:00
|
|
|
class AddrRange(ParamValue):
|
2012-09-19 12:15:44 +02:00
|
|
|
cxx_type = 'AddrRange'
|
2006-09-04 19:52:26 +02:00
|
|
|
|
|
|
|
def __init__(self, *args, **kwargs):
|
2013-01-07 19:05:38 +01:00
|
|
|
# Disable interleaving by default
|
|
|
|
self.intlvHighBit = 0
|
|
|
|
self.intlvBits = 0
|
|
|
|
self.intlvMatch = 0
|
|
|
|
|
2006-09-04 19:52:26 +02:00
|
|
|
def handle_kwargs(self, kwargs):
|
2013-01-07 19:05:38 +01:00
|
|
|
# An address range needs to have an upper limit, specified
|
|
|
|
# either explicitly with an end, or as an offset using the
|
|
|
|
# size keyword.
|
2006-09-04 19:52:26 +02:00
|
|
|
if 'end' in kwargs:
|
2012-09-19 12:15:41 +02:00
|
|
|
self.end = Addr(kwargs.pop('end'))
|
2006-09-04 19:52:26 +02:00
|
|
|
elif 'size' in kwargs:
|
2012-09-19 12:15:41 +02:00
|
|
|
self.end = self.start + Addr(kwargs.pop('size')) - 1
|
2006-09-04 19:52:26 +02:00
|
|
|
else:
|
|
|
|
raise TypeError, "Either end or size must be specified"
|
|
|
|
|
2013-01-07 19:05:38 +01:00
|
|
|
# Now on to the optional bit
|
|
|
|
if 'intlvHighBit' in kwargs:
|
|
|
|
self.intlvHighBit = int(kwargs.pop('intlvHighBit'))
|
|
|
|
if 'intlvBits' in kwargs:
|
|
|
|
self.intlvBits = int(kwargs.pop('intlvBits'))
|
|
|
|
if 'intlvMatch' in kwargs:
|
|
|
|
self.intlvMatch = int(kwargs.pop('intlvMatch'))
|
|
|
|
|
2006-09-04 19:52:26 +02:00
|
|
|
if len(args) == 0:
|
2012-09-19 12:15:41 +02:00
|
|
|
self.start = Addr(kwargs.pop('start'))
|
2006-09-04 19:52:26 +02:00
|
|
|
handle_kwargs(self, kwargs)
|
|
|
|
|
|
|
|
elif len(args) == 1:
|
|
|
|
if kwargs:
|
2012-09-19 12:15:41 +02:00
|
|
|
self.start = Addr(args[0])
|
2006-09-04 19:52:26 +02:00
|
|
|
handle_kwargs(self, kwargs)
|
2007-11-08 16:46:41 +01:00
|
|
|
elif isinstance(args[0], (list, tuple)):
|
2012-09-19 12:15:41 +02:00
|
|
|
self.start = Addr(args[0][0])
|
|
|
|
self.end = Addr(args[0][1])
|
2006-09-04 19:52:26 +02:00
|
|
|
else:
|
2012-09-19 12:15:41 +02:00
|
|
|
self.start = Addr(0)
|
|
|
|
self.end = Addr(args[0]) - 1
|
2006-09-04 19:52:26 +02:00
|
|
|
|
|
|
|
elif len(args) == 2:
|
2012-09-19 12:15:41 +02:00
|
|
|
self.start = Addr(args[0])
|
|
|
|
self.end = Addr(args[1])
|
2006-09-04 19:52:26 +02:00
|
|
|
else:
|
|
|
|
raise TypeError, "Too many arguments specified"
|
|
|
|
|
|
|
|
if kwargs:
|
2012-09-19 12:15:41 +02:00
|
|
|
raise TypeError, "Too many keywords: %s" % kwargs.keys()
|
2006-09-04 19:52:26 +02:00
|
|
|
|
|
|
|
def __str__(self):
|
2012-09-19 12:15:41 +02:00
|
|
|
return '%s:%s' % (self.start, self.end)
|
|
|
|
|
|
|
|
def size(self):
|
2013-01-07 19:05:38 +01:00
|
|
|
# Divide the size by the size of the interleaving slice
|
|
|
|
return (long(self.end) - long(self.start) + 1) >> self.intlvBits
|
2006-09-04 19:52:26 +02:00
|
|
|
|
2010-09-09 23:15:41 +02:00
|
|
|
@classmethod
|
|
|
|
def cxx_predecls(cls, code):
|
2012-09-19 12:15:41 +02:00
|
|
|
Addr.cxx_predecls(code)
|
2012-09-19 12:15:44 +02:00
|
|
|
code('#include "base/addr_range.hh"')
|
2010-09-09 23:15:41 +02:00
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def swig_predecls(cls, code):
|
2012-09-19 12:15:41 +02:00
|
|
|
Addr.swig_predecls(code)
|
2010-09-09 23:26:29 +02:00
|
|
|
|
2007-07-24 06:51:38 +02:00
|
|
|
def getValue(self):
|
2012-09-19 12:15:44 +02:00
|
|
|
# Go from the Python class to the wrapped C++ class generated
|
|
|
|
# by swig
|
2010-09-09 23:26:29 +02:00
|
|
|
from m5.internal.range import AddrRange
|
2007-07-24 06:51:38 +02:00
|
|
|
|
2013-01-07 19:05:38 +01:00
|
|
|
return AddrRange(long(self.start), long(self.end),
|
|
|
|
int(self.intlvHighBit), int(self.intlvBits),
|
|
|
|
int(self.intlvMatch))
|
2006-09-04 19:52:26 +02:00
|
|
|
|
|
|
|
# Boolean parameter type. Python doesn't let you subclass bool, since
|
|
|
|
# it doesn't want to let you create multiple instances of True and
|
|
|
|
# False. Thus this is a little more complicated than String.
|
|
|
|
class Bool(ParamValue):
|
|
|
|
cxx_type = 'bool'
|
2014-08-10 11:39:13 +02:00
|
|
|
cmd_line_settable = True
|
|
|
|
|
2006-09-04 19:52:26 +02:00
|
|
|
def __init__(self, value):
|
|
|
|
try:
|
2006-09-05 02:14:07 +02:00
|
|
|
self.value = convert.toBool(value)
|
2006-09-04 19:52:26 +02:00
|
|
|
except TypeError:
|
|
|
|
self.value = bool(value)
|
|
|
|
|
2014-08-10 11:39:13 +02:00
|
|
|
def __call__(self, value):
|
|
|
|
self.__init__(value)
|
|
|
|
return value
|
|
|
|
|
2007-07-24 06:51:38 +02:00
|
|
|
def getValue(self):
|
|
|
|
return bool(self.value)
|
|
|
|
|
2006-09-04 19:52:26 +02:00
|
|
|
def __str__(self):
|
|
|
|
return str(self.value)
|
|
|
|
|
2012-04-06 22:47:07 +02:00
|
|
|
# implement truth value testing for Bool parameters so that these params
|
|
|
|
# evaluate correctly during the python configuration phase
|
|
|
|
def __nonzero__(self):
|
|
|
|
return bool(self.value)
|
|
|
|
|
2006-09-04 19:52:26 +02:00
|
|
|
def ini_str(self):
|
|
|
|
if self.value:
|
|
|
|
return 'true'
|
|
|
|
return 'false'
|
|
|
|
|
|
|
|
def IncEthernetAddr(addr, val = 1):
|
|
|
|
bytes = map(lambda x: int(x, 16), addr.split(':'))
|
|
|
|
bytes[5] += val
|
|
|
|
for i in (5, 4, 3, 2, 1):
|
|
|
|
val,rem = divmod(bytes[i], 256)
|
|
|
|
bytes[i] = rem
|
|
|
|
if val == 0:
|
|
|
|
break
|
|
|
|
bytes[i - 1] += val
|
|
|
|
assert(bytes[0] <= 255)
|
|
|
|
return ':'.join(map(lambda x: '%02x' % x, bytes))
|
|
|
|
|
2007-04-12 17:37:55 +02:00
|
|
|
_NextEthernetAddr = "00:90:00:00:00:01"
|
|
|
|
def NextEthernetAddr():
|
|
|
|
global _NextEthernetAddr
|
2006-09-04 19:52:26 +02:00
|
|
|
|
2007-04-12 17:37:55 +02:00
|
|
|
value = _NextEthernetAddr
|
|
|
|
_NextEthernetAddr = IncEthernetAddr(_NextEthernetAddr, 1)
|
|
|
|
return value
|
2006-09-04 19:52:26 +02:00
|
|
|
|
|
|
|
class EthernetAddr(ParamValue):
|
|
|
|
cxx_type = 'Net::EthAddr'
|
2014-08-10 11:39:13 +02:00
|
|
|
ex_str = "00:90:00:00:00:01"
|
|
|
|
cmd_line_settable = True
|
2010-09-09 23:15:41 +02:00
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def cxx_predecls(cls, code):
|
|
|
|
code('#include "base/inet.hh"')
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def swig_predecls(cls, code):
|
|
|
|
code('%include "python/swig/inet.i"')
|
|
|
|
|
2006-09-04 19:52:26 +02:00
|
|
|
def __init__(self, value):
|
|
|
|
if value == NextEthernetAddr:
|
|
|
|
self.value = value
|
|
|
|
return
|
|
|
|
|
|
|
|
if not isinstance(value, str):
|
|
|
|
raise TypeError, "expected an ethernet address and didn't get one"
|
|
|
|
|
|
|
|
bytes = value.split(':')
|
|
|
|
if len(bytes) != 6:
|
|
|
|
raise TypeError, 'invalid ethernet address %s' % value
|
|
|
|
|
|
|
|
for byte in bytes:
|
2013-10-17 17:20:45 +02:00
|
|
|
if not 0 <= int(byte, base=16) <= 0xff:
|
2006-09-04 19:52:26 +02:00
|
|
|
raise TypeError, 'invalid ethernet address %s' % value
|
|
|
|
|
|
|
|
self.value = value
|
|
|
|
|
2014-08-10 11:39:13 +02:00
|
|
|
def __call__(self, value):
|
|
|
|
self.__init__(value)
|
|
|
|
return value
|
|
|
|
|
2006-09-04 19:52:26 +02:00
|
|
|
def unproxy(self, base):
|
|
|
|
if self.value == NextEthernetAddr:
|
2007-04-12 17:37:55 +02:00
|
|
|
return EthernetAddr(self.value())
|
2006-09-04 19:52:26 +02:00
|
|
|
return self
|
|
|
|
|
2007-07-24 06:51:38 +02:00
|
|
|
def getValue(self):
|
2010-09-13 00:41:34 +02:00
|
|
|
from m5.internal.params import EthAddr
|
2007-07-24 06:51:38 +02:00
|
|
|
return EthAddr(self.value)
|
|
|
|
|
2007-04-12 17:37:55 +02:00
|
|
|
def ini_str(self):
|
|
|
|
return self.value
|
2006-09-04 19:52:26 +02:00
|
|
|
|
2010-11-23 21:54:43 +01:00
|
|
|
# When initializing an IpAddress, pass in an existing IpAddress, a string of
|
|
|
|
# the form "a.b.c.d", or an integer representing an IP.
|
|
|
|
class IpAddress(ParamValue):
|
|
|
|
cxx_type = 'Net::IpAddress'
|
2014-08-10 11:39:13 +02:00
|
|
|
ex_str = "127.0.0.1"
|
|
|
|
cmd_line_settable = True
|
2010-11-23 21:54:43 +01:00
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def cxx_predecls(cls, code):
|
|
|
|
code('#include "base/inet.hh"')
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def swig_predecls(cls, code):
|
|
|
|
code('%include "python/swig/inet.i"')
|
|
|
|
|
|
|
|
def __init__(self, value):
|
|
|
|
if isinstance(value, IpAddress):
|
|
|
|
self.ip = value.ip
|
|
|
|
else:
|
|
|
|
try:
|
|
|
|
self.ip = convert.toIpAddress(value)
|
|
|
|
except TypeError:
|
|
|
|
self.ip = long(value)
|
|
|
|
self.verifyIp()
|
|
|
|
|
2014-08-10 11:39:13 +02:00
|
|
|
def __call__(self, value):
|
|
|
|
self.__init__(value)
|
|
|
|
return value
|
|
|
|
|
2011-09-23 03:58:14 +02:00
|
|
|
def __str__(self):
|
|
|
|
tup = [(self.ip >> i) & 0xff for i in (24, 16, 8, 0)]
|
|
|
|
return '%d.%d.%d.%d' % tuple(tup)
|
|
|
|
|
|
|
|
def __eq__(self, other):
|
|
|
|
if isinstance(other, IpAddress):
|
|
|
|
return self.ip == other.ip
|
|
|
|
elif isinstance(other, str):
|
|
|
|
try:
|
|
|
|
return self.ip == convert.toIpAddress(other)
|
|
|
|
except:
|
|
|
|
return False
|
|
|
|
else:
|
|
|
|
return self.ip == other
|
|
|
|
|
|
|
|
def __ne__(self, other):
|
|
|
|
return not (self == other)
|
|
|
|
|
2010-11-23 21:54:43 +01:00
|
|
|
def verifyIp(self):
|
|
|
|
if self.ip < 0 or self.ip >= (1 << 32):
|
2010-12-20 10:20:58 +01:00
|
|
|
raise TypeError, "invalid ip address %#08x" % self.ip
|
2010-11-23 21:54:43 +01:00
|
|
|
|
|
|
|
def getValue(self):
|
|
|
|
from m5.internal.params import IpAddress
|
|
|
|
return IpAddress(self.ip)
|
|
|
|
|
|
|
|
# When initializing an IpNetmask, pass in an existing IpNetmask, a string of
|
|
|
|
# the form "a.b.c.d/n" or "a.b.c.d/e.f.g.h", or an ip and netmask as
|
|
|
|
# positional or keyword arguments.
|
|
|
|
class IpNetmask(IpAddress):
|
|
|
|
cxx_type = 'Net::IpNetmask'
|
2014-08-10 11:39:13 +02:00
|
|
|
ex_str = "127.0.0.0/24"
|
|
|
|
cmd_line_settable = True
|
2010-11-23 21:54:43 +01:00
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def cxx_predecls(cls, code):
|
|
|
|
code('#include "base/inet.hh"')
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def swig_predecls(cls, code):
|
|
|
|
code('%include "python/swig/inet.i"')
|
|
|
|
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
|
|
def handle_kwarg(self, kwargs, key, elseVal = None):
|
|
|
|
if key in kwargs:
|
|
|
|
setattr(self, key, kwargs.pop(key))
|
|
|
|
elif elseVal:
|
|
|
|
setattr(self, key, elseVal)
|
|
|
|
else:
|
|
|
|
raise TypeError, "No value set for %s" % key
|
|
|
|
|
|
|
|
if len(args) == 0:
|
|
|
|
handle_kwarg(self, kwargs, 'ip')
|
|
|
|
handle_kwarg(self, kwargs, 'netmask')
|
|
|
|
|
|
|
|
elif len(args) == 1:
|
|
|
|
if kwargs:
|
|
|
|
if not 'ip' in kwargs and not 'netmask' in kwargs:
|
|
|
|
raise TypeError, "Invalid arguments"
|
|
|
|
handle_kwarg(self, kwargs, 'ip', args[0])
|
|
|
|
handle_kwarg(self, kwargs, 'netmask', args[0])
|
|
|
|
elif isinstance(args[0], IpNetmask):
|
|
|
|
self.ip = args[0].ip
|
|
|
|
self.netmask = args[0].netmask
|
|
|
|
else:
|
|
|
|
(self.ip, self.netmask) = convert.toIpNetmask(args[0])
|
|
|
|
|
|
|
|
elif len(args) == 2:
|
|
|
|
self.ip = args[0]
|
|
|
|
self.netmask = args[1]
|
|
|
|
else:
|
|
|
|
raise TypeError, "Too many arguments specified"
|
|
|
|
|
|
|
|
if kwargs:
|
|
|
|
raise TypeError, "Too many keywords: %s" % kwargs.keys()
|
|
|
|
|
|
|
|
self.verify()
|
|
|
|
|
2014-08-10 11:39:13 +02:00
|
|
|
def __call__(self, value):
|
|
|
|
self.__init__(value)
|
|
|
|
return value
|
|
|
|
|
2011-09-23 03:58:14 +02:00
|
|
|
def __str__(self):
|
|
|
|
return "%s/%d" % (super(IpNetmask, self).__str__(), self.netmask)
|
|
|
|
|
|
|
|
def __eq__(self, other):
|
|
|
|
if isinstance(other, IpNetmask):
|
|
|
|
return self.ip == other.ip and self.netmask == other.netmask
|
|
|
|
elif isinstance(other, str):
|
|
|
|
try:
|
|
|
|
return (self.ip, self.netmask) == convert.toIpNetmask(other)
|
|
|
|
except:
|
|
|
|
return False
|
|
|
|
else:
|
|
|
|
return False
|
|
|
|
|
2010-11-23 21:54:43 +01:00
|
|
|
def verify(self):
|
|
|
|
self.verifyIp()
|
|
|
|
if self.netmask < 0 or self.netmask > 32:
|
|
|
|
raise TypeError, "invalid netmask %d" % netmask
|
|
|
|
|
|
|
|
def getValue(self):
|
|
|
|
from m5.internal.params import IpNetmask
|
|
|
|
return IpNetmask(self.ip, self.netmask)
|
|
|
|
|
|
|
|
# When initializing an IpWithPort, pass in an existing IpWithPort, a string of
|
|
|
|
# the form "a.b.c.d:p", or an ip and port as positional or keyword arguments.
|
|
|
|
class IpWithPort(IpAddress):
|
|
|
|
cxx_type = 'Net::IpWithPort'
|
2014-08-10 11:39:13 +02:00
|
|
|
ex_str = "127.0.0.1:80"
|
|
|
|
cmd_line_settable = True
|
2010-11-23 21:54:43 +01:00
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def cxx_predecls(cls, code):
|
|
|
|
code('#include "base/inet.hh"')
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def swig_predecls(cls, code):
|
|
|
|
code('%include "python/swig/inet.i"')
|
|
|
|
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
|
|
def handle_kwarg(self, kwargs, key, elseVal = None):
|
|
|
|
if key in kwargs:
|
|
|
|
setattr(self, key, kwargs.pop(key))
|
|
|
|
elif elseVal:
|
|
|
|
setattr(self, key, elseVal)
|
|
|
|
else:
|
|
|
|
raise TypeError, "No value set for %s" % key
|
|
|
|
|
|
|
|
if len(args) == 0:
|
|
|
|
handle_kwarg(self, kwargs, 'ip')
|
|
|
|
handle_kwarg(self, kwargs, 'port')
|
|
|
|
|
|
|
|
elif len(args) == 1:
|
|
|
|
if kwargs:
|
|
|
|
if not 'ip' in kwargs and not 'port' in kwargs:
|
|
|
|
raise TypeError, "Invalid arguments"
|
|
|
|
handle_kwarg(self, kwargs, 'ip', args[0])
|
|
|
|
handle_kwarg(self, kwargs, 'port', args[0])
|
|
|
|
elif isinstance(args[0], IpWithPort):
|
|
|
|
self.ip = args[0].ip
|
|
|
|
self.port = args[0].port
|
|
|
|
else:
|
|
|
|
(self.ip, self.port) = convert.toIpWithPort(args[0])
|
|
|
|
|
|
|
|
elif len(args) == 2:
|
|
|
|
self.ip = args[0]
|
|
|
|
self.port = args[1]
|
|
|
|
else:
|
|
|
|
raise TypeError, "Too many arguments specified"
|
|
|
|
|
|
|
|
if kwargs:
|
|
|
|
raise TypeError, "Too many keywords: %s" % kwargs.keys()
|
|
|
|
|
|
|
|
self.verify()
|
|
|
|
|
2014-08-10 11:39:13 +02:00
|
|
|
def __call__(self, value):
|
|
|
|
self.__init__(value)
|
|
|
|
return value
|
|
|
|
|
2011-09-23 03:58:14 +02:00
|
|
|
def __str__(self):
|
|
|
|
return "%s:%d" % (super(IpWithPort, self).__str__(), self.port)
|
|
|
|
|
|
|
|
def __eq__(self, other):
|
|
|
|
if isinstance(other, IpWithPort):
|
|
|
|
return self.ip == other.ip and self.port == other.port
|
|
|
|
elif isinstance(other, str):
|
|
|
|
try:
|
|
|
|
return (self.ip, self.port) == convert.toIpWithPort(other)
|
|
|
|
except:
|
|
|
|
return False
|
|
|
|
else:
|
|
|
|
return False
|
|
|
|
|
2010-11-23 21:54:43 +01:00
|
|
|
def verify(self):
|
|
|
|
self.verifyIp()
|
|
|
|
if self.port < 0 or self.port > 0xffff:
|
|
|
|
raise TypeError, "invalid port %d" % self.port
|
|
|
|
|
|
|
|
def getValue(self):
|
|
|
|
from m5.internal.params import IpWithPort
|
|
|
|
return IpWithPort(self.ip, self.port)
|
|
|
|
|
2007-01-25 20:59:41 +01:00
|
|
|
time_formats = [ "%a %b %d %H:%M:%S %Z %Y",
|
|
|
|
"%a %b %d %H:%M:%S %Z %Y",
|
|
|
|
"%Y/%m/%d %H:%M:%S",
|
|
|
|
"%Y/%m/%d %H:%M",
|
|
|
|
"%Y/%m/%d",
|
|
|
|
"%m/%d/%Y %H:%M:%S",
|
|
|
|
"%m/%d/%Y %H:%M",
|
|
|
|
"%m/%d/%Y",
|
|
|
|
"%m/%d/%y %H:%M:%S",
|
|
|
|
"%m/%d/%y %H:%M",
|
|
|
|
"%m/%d/%y"]
|
|
|
|
|
|
|
|
|
2007-01-03 19:12:55 +01:00
|
|
|
def parse_time(value):
|
2007-01-25 20:59:41 +01:00
|
|
|
from time import gmtime, strptime, struct_time, time
|
|
|
|
from datetime import datetime, date
|
|
|
|
|
|
|
|
if isinstance(value, struct_time):
|
|
|
|
return value
|
|
|
|
|
|
|
|
if isinstance(value, (int, long)):
|
|
|
|
return gmtime(value)
|
|
|
|
|
|
|
|
if isinstance(value, (datetime, date)):
|
|
|
|
return value.timetuple()
|
|
|
|
|
|
|
|
if isinstance(value, str):
|
|
|
|
if value in ('Now', 'Today'):
|
|
|
|
return time.gmtime(time.time())
|
|
|
|
|
|
|
|
for format in time_formats:
|
|
|
|
try:
|
|
|
|
return strptime(value, format)
|
|
|
|
except ValueError:
|
|
|
|
pass
|
2007-01-03 19:12:55 +01:00
|
|
|
|
|
|
|
raise ValueError, "Could not parse '%s' as a time" % value
|
|
|
|
|
|
|
|
class Time(ParamValue):
|
2007-07-24 06:51:38 +02:00
|
|
|
cxx_type = 'tm'
|
2010-09-09 23:15:41 +02:00
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def cxx_predecls(cls, code):
|
|
|
|
code('#include <time.h>')
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def swig_predecls(cls, code):
|
|
|
|
code('%include "python/swig/time.i"')
|
|
|
|
|
2007-01-03 19:12:55 +01:00
|
|
|
def __init__(self, value):
|
2007-01-25 20:59:41 +01:00
|
|
|
self.value = parse_time(value)
|
2007-01-03 19:12:55 +01:00
|
|
|
|
2014-08-10 11:39:13 +02:00
|
|
|
def __call__(self, value):
|
|
|
|
self.__init__(value)
|
|
|
|
return value
|
|
|
|
|
2007-07-24 06:51:38 +02:00
|
|
|
def getValue(self):
|
2010-09-13 00:41:34 +02:00
|
|
|
from m5.internal.params import tm
|
2007-07-24 06:51:38 +02:00
|
|
|
|
|
|
|
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
|
|
|
|
|
2007-01-03 19:12:55 +01:00
|
|
|
def __str__(self):
|
2007-07-24 06:51:38 +02:00
|
|
|
return time.asctime(self.value)
|
2007-01-03 19:12:55 +01:00
|
|
|
|
|
|
|
def ini_str(self):
|
2007-01-25 20:59:41 +01:00
|
|
|
return str(self)
|
2007-01-03 19:12:55 +01:00
|
|
|
|
2012-01-10 01:08:20 +01:00
|
|
|
def get_config_as_dict(self):
|
|
|
|
return str(self)
|
|
|
|
|
2006-09-04 19:52:26 +02:00
|
|
|
# Enumerated types are a little more complex. The user specifies the
|
|
|
|
# type as Enum(foo) where foo is either a list or dictionary of
|
|
|
|
# alternatives (typically strings, but not necessarily so). (In the
|
|
|
|
# long run, the integer value of the parameter will be the list index
|
|
|
|
# or the corresponding dictionary value. For now, since we only check
|
|
|
|
# that the alternative is valid and then spit it into a .ini file,
|
|
|
|
# there's not much point in using the dictionary.)
|
|
|
|
|
|
|
|
# What Enum() must do is generate a new type encapsulating the
|
|
|
|
# provided list/dictionary so that specific values of the parameter
|
|
|
|
# can be instances of that type. We define two hidden internal
|
|
|
|
# classes (_ListEnum and _DictEnum) to serve as base classes, then
|
|
|
|
# derive the new type from the appropriate base class on the fly.
|
|
|
|
|
2007-07-24 06:51:38 +02:00
|
|
|
allEnums = {}
|
2006-09-04 19:52:26 +02:00
|
|
|
# Metaclass for Enum types
|
2007-08-30 21:16:58 +02:00
|
|
|
class MetaEnum(MetaParamValue):
|
2007-07-24 06:51:38 +02:00
|
|
|
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
|
|
|
|
|
2006-09-04 19:52:26 +02:00
|
|
|
def __init__(cls, name, bases, init_dict):
|
|
|
|
if init_dict.has_key('map'):
|
|
|
|
if not isinstance(cls.map, dict):
|
|
|
|
raise TypeError, "Enum-derived class attribute 'map' " \
|
|
|
|
"must be of type dict"
|
|
|
|
# build list of value strings from map
|
|
|
|
cls.vals = cls.map.keys()
|
|
|
|
cls.vals.sort()
|
|
|
|
elif init_dict.has_key('vals'):
|
|
|
|
if not isinstance(cls.vals, list):
|
|
|
|
raise TypeError, "Enum-derived class attribute 'vals' " \
|
|
|
|
"must be of type list"
|
|
|
|
# build string->value map from vals sequence
|
|
|
|
cls.map = {}
|
|
|
|
for idx,val in enumerate(cls.vals):
|
|
|
|
cls.map[val] = idx
|
|
|
|
else:
|
|
|
|
raise TypeError, "Enum-derived class must define "\
|
|
|
|
"attribute 'map' or 'vals'"
|
|
|
|
|
2007-07-24 06:51:38 +02:00
|
|
|
cls.cxx_type = 'Enums::%s' % name
|
2006-09-04 19:52:26 +02:00
|
|
|
|
|
|
|
super(MetaEnum, cls).__init__(name, bases, init_dict)
|
|
|
|
|
|
|
|
# Generate C++ class declaration for this enum type.
|
|
|
|
# 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.
|
2010-09-09 23:15:41 +02:00
|
|
|
def cxx_decl(cls, code):
|
2014-05-10 00:58:47 +02:00
|
|
|
wrapper_name = cls.wrapper_name
|
|
|
|
wrapper = 'struct' if cls.wrapper_is_struct else 'namespace'
|
|
|
|
name = cls.__name__ if cls.enum_name is None else cls.enum_name
|
|
|
|
idem_macro = '__ENUM__%s__%s__' % (wrapper_name, name)
|
|
|
|
|
2010-09-09 23:15:41 +02:00
|
|
|
code('''\
|
2014-05-10 00:58:47 +02:00
|
|
|
#ifndef $idem_macro
|
|
|
|
#define $idem_macro
|
2010-09-09 23:15:41 +02:00
|
|
|
|
2014-05-10 00:58:47 +02:00
|
|
|
$wrapper $wrapper_name {
|
2010-09-09 23:15:41 +02:00
|
|
|
enum $name {
|
|
|
|
''')
|
|
|
|
code.indent(2)
|
2007-07-24 06:51:38 +02:00
|
|
|
for val in cls.vals:
|
2010-09-09 23:15:41 +02:00
|
|
|
code('$val = ${{cls.map[val]}},')
|
2012-03-19 11:36:09 +01:00
|
|
|
code('Num_$name = ${{len(cls.vals)}}')
|
2010-09-09 23:15:41 +02:00
|
|
|
code.dedent(2)
|
2014-05-10 00:58:47 +02:00
|
|
|
code(' };')
|
2010-09-09 23:15:41 +02:00
|
|
|
|
2014-05-10 00:58:47 +02:00
|
|
|
if cls.wrapper_is_struct:
|
|
|
|
code(' static const char *${name}Strings[Num_${name}];')
|
|
|
|
code('};')
|
|
|
|
else:
|
|
|
|
code('extern const char *${name}Strings[Num_${name}];')
|
|
|
|
code('}')
|
|
|
|
|
|
|
|
code()
|
|
|
|
code('#endif // $idem_macro')
|
2010-09-09 23:15:41 +02:00
|
|
|
|
|
|
|
def cxx_def(cls, code):
|
2014-05-10 00:58:47 +02:00
|
|
|
wrapper_name = cls.wrapper_name
|
|
|
|
file_name = cls.__name__
|
|
|
|
name = cls.__name__ if cls.enum_name is None else cls.enum_name
|
|
|
|
|
|
|
|
code('#include "enums/$file_name.hh"')
|
|
|
|
if cls.wrapper_is_struct:
|
|
|
|
code('const char *${wrapper_name}::${name}Strings'
|
|
|
|
'[Num_${name}] =')
|
|
|
|
else:
|
|
|
|
code('namespace Enums {')
|
|
|
|
code.indent(1)
|
|
|
|
code(' const char *${name}Strings[Num_${name}] =')
|
|
|
|
|
|
|
|
code('{')
|
|
|
|
code.indent(1)
|
2007-07-24 06:51:38 +02:00
|
|
|
for val in cls.vals:
|
2010-09-09 23:15:41 +02:00
|
|
|
code('"$val",')
|
2014-05-10 00:58:47 +02:00
|
|
|
code.dedent(1)
|
|
|
|
code('};')
|
|
|
|
|
|
|
|
if not cls.wrapper_is_struct:
|
|
|
|
code('} // namespace $wrapper_name')
|
|
|
|
code.dedent(1)
|
2006-09-04 19:52:26 +02:00
|
|
|
|
2011-10-20 22:08:49 +02:00
|
|
|
def swig_decl(cls, code):
|
|
|
|
name = cls.__name__
|
|
|
|
code('''\
|
|
|
|
%module(package="m5.internal") enum_$name
|
|
|
|
|
|
|
|
%{
|
|
|
|
#include "enums/$name.hh"
|
|
|
|
%}
|
|
|
|
|
|
|
|
%include "enums/$name.hh"
|
|
|
|
''')
|
|
|
|
|
|
|
|
|
2006-09-04 19:52:26 +02:00
|
|
|
# Base class for enum types.
|
|
|
|
class Enum(ParamValue):
|
|
|
|
__metaclass__ = MetaEnum
|
|
|
|
vals = []
|
2014-08-10 11:39:13 +02:00
|
|
|
cmd_line_settable = True
|
2006-09-04 19:52:26 +02:00
|
|
|
|
2014-05-10 00:58:47 +02:00
|
|
|
# The name of the wrapping namespace or struct
|
|
|
|
wrapper_name = 'Enums'
|
|
|
|
|
|
|
|
# If true, the enum is wrapped in a struct rather than a namespace
|
|
|
|
wrapper_is_struct = False
|
|
|
|
|
|
|
|
# If not None, use this as the enum name rather than this class name
|
|
|
|
enum_name = None
|
|
|
|
|
2006-09-04 19:52:26 +02:00
|
|
|
def __init__(self, value):
|
|
|
|
if value not in self.map:
|
|
|
|
raise TypeError, "Enum param got bad value '%s' (not in %s)" \
|
|
|
|
% (value, self.vals)
|
|
|
|
self.value = value
|
|
|
|
|
2014-08-10 11:39:13 +02:00
|
|
|
def __call__(self, value):
|
|
|
|
self.__init__(value)
|
|
|
|
return value
|
|
|
|
|
2010-09-09 23:26:29 +02:00
|
|
|
@classmethod
|
|
|
|
def cxx_predecls(cls, code):
|
|
|
|
code('#include "enums/$0.hh"', cls.__name__)
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def swig_predecls(cls, code):
|
2010-09-13 00:41:34 +02:00
|
|
|
code('%import "python/m5/internal/enum_$0.i"', cls.__name__)
|
2010-09-09 23:26:29 +02:00
|
|
|
|
2007-07-24 06:51:38 +02:00
|
|
|
def getValue(self):
|
|
|
|
return int(self.map[self.value])
|
|
|
|
|
2006-09-04 19:52:26 +02:00
|
|
|
def __str__(self):
|
|
|
|
return self.value
|
|
|
|
|
|
|
|
# how big does a rounding error need to be before we warn about it?
|
|
|
|
frequency_tolerance = 0.001 # 0.1%
|
|
|
|
|
2007-03-06 20:13:43 +01:00
|
|
|
class TickParamValue(NumericParamValue):
|
2006-09-04 19:52:26 +02:00
|
|
|
cxx_type = 'Tick'
|
2014-08-10 11:39:13 +02:00
|
|
|
ex_str = "1MHz"
|
|
|
|
cmd_line_settable = True
|
2010-09-09 23:15:41 +02:00
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def cxx_predecls(cls, code):
|
|
|
|
code('#include "base/types.hh"')
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def swig_predecls(cls, code):
|
|
|
|
code('%import "stdint.i"')
|
|
|
|
code('%import "base/types.hh"')
|
2007-03-06 20:13:43 +01:00
|
|
|
|
2014-08-10 11:39:13 +02:00
|
|
|
def __call__(self, value):
|
|
|
|
self.__init__(value)
|
|
|
|
return value
|
|
|
|
|
2007-07-24 06:51:38 +02:00
|
|
|
def getValue(self):
|
|
|
|
return long(self.value)
|
|
|
|
|
2007-03-06 20:13:43 +01:00
|
|
|
class Latency(TickParamValue):
|
2014-08-10 11:39:13 +02:00
|
|
|
ex_str = "100ns"
|
|
|
|
|
2006-09-04 19:52:26 +02:00
|
|
|
def __init__(self, value):
|
2007-03-06 20:13:43 +01:00
|
|
|
if isinstance(value, (Latency, Clock)):
|
|
|
|
self.ticks = value.ticks
|
|
|
|
self.value = value.value
|
|
|
|
elif isinstance(value, Frequency):
|
|
|
|
self.ticks = value.ticks
|
|
|
|
self.value = 1.0 / value.value
|
|
|
|
elif value.endswith('t'):
|
|
|
|
self.ticks = True
|
|
|
|
self.value = int(value[:-1])
|
|
|
|
else:
|
|
|
|
self.ticks = False
|
|
|
|
self.value = convert.toLatency(value)
|
2006-09-04 19:52:26 +02:00
|
|
|
|
2014-08-10 11:39:13 +02:00
|
|
|
def __call__(self, value):
|
|
|
|
self.__init__(value)
|
|
|
|
return value
|
|
|
|
|
2006-09-04 19:52:26 +02:00
|
|
|
def __getattr__(self, attr):
|
|
|
|
if attr in ('latency', 'period'):
|
|
|
|
return self
|
|
|
|
if attr == 'frequency':
|
|
|
|
return Frequency(self)
|
|
|
|
raise AttributeError, "Latency object has no attribute '%s'" % attr
|
|
|
|
|
2007-07-24 06:51:38 +02:00
|
|
|
def getValue(self):
|
2007-03-06 20:13:43 +01:00
|
|
|
if self.ticks or self.value == 0:
|
2007-07-24 06:51:38 +02:00
|
|
|
value = self.value
|
2007-03-06 20:13:43 +01:00
|
|
|
else:
|
2007-07-24 06:51:38 +02:00
|
|
|
value = ticks.fromSeconds(self.value)
|
|
|
|
return long(value)
|
|
|
|
|
|
|
|
# convert latency to ticks
|
|
|
|
def ini_str(self):
|
|
|
|
return '%d' % self.getValue()
|
2006-09-04 19:52:26 +02:00
|
|
|
|
2007-03-06 20:13:43 +01:00
|
|
|
class Frequency(TickParamValue):
|
2014-08-10 11:39:13 +02:00
|
|
|
ex_str = "1GHz"
|
|
|
|
|
2006-09-04 19:52:26 +02:00
|
|
|
def __init__(self, value):
|
2007-03-06 20:13:43 +01:00
|
|
|
if isinstance(value, (Latency, Clock)):
|
|
|
|
if value.value == 0:
|
|
|
|
self.value = 0
|
|
|
|
else:
|
|
|
|
self.value = 1.0 / value.value
|
|
|
|
self.ticks = value.ticks
|
|
|
|
elif isinstance(value, Frequency):
|
|
|
|
self.value = value.value
|
|
|
|
self.ticks = value.ticks
|
|
|
|
else:
|
|
|
|
self.ticks = False
|
|
|
|
self.value = convert.toFrequency(value)
|
2006-09-04 19:52:26 +02:00
|
|
|
|
2014-08-10 11:39:13 +02:00
|
|
|
def __call__(self, value):
|
|
|
|
self.__init__(value)
|
|
|
|
return value
|
|
|
|
|
2006-09-04 19:52:26 +02:00
|
|
|
def __getattr__(self, attr):
|
|
|
|
if attr == 'frequency':
|
|
|
|
return self
|
|
|
|
if attr in ('latency', 'period'):
|
|
|
|
return Latency(self)
|
|
|
|
raise AttributeError, "Frequency object has no attribute '%s'" % attr
|
|
|
|
|
2007-03-06 20:13:43 +01:00
|
|
|
# convert latency to ticks
|
2007-07-24 06:51:38 +02:00
|
|
|
def getValue(self):
|
2007-03-06 20:13:43 +01:00
|
|
|
if self.ticks or self.value == 0:
|
2007-07-24 06:51:38 +02:00
|
|
|
value = self.value
|
2007-03-06 20:13:43 +01:00
|
|
|
else:
|
2007-07-24 06:51:38 +02:00
|
|
|
value = ticks.fromSeconds(1.0 / self.value)
|
|
|
|
return long(value)
|
|
|
|
|
|
|
|
def ini_str(self):
|
|
|
|
return '%d' % self.getValue()
|
2006-09-04 19:52:26 +02:00
|
|
|
|
2014-01-24 22:29:29 +01:00
|
|
|
# A generic Frequency and/or Latency value. Value is stored as a
|
|
|
|
# latency, just like Latency and Frequency.
|
|
|
|
class Clock(TickParamValue):
|
2006-09-04 19:52:26 +02:00
|
|
|
def __init__(self, value):
|
2007-03-06 20:13:43 +01:00
|
|
|
if isinstance(value, (Latency, Clock)):
|
|
|
|
self.ticks = value.ticks
|
|
|
|
self.value = value.value
|
|
|
|
elif isinstance(value, Frequency):
|
|
|
|
self.ticks = value.ticks
|
|
|
|
self.value = 1.0 / value.value
|
|
|
|
elif value.endswith('t'):
|
|
|
|
self.ticks = True
|
|
|
|
self.value = int(value[:-1])
|
|
|
|
else:
|
|
|
|
self.ticks = False
|
|
|
|
self.value = convert.anyToLatency(value)
|
2006-09-04 19:52:26 +02:00
|
|
|
|
2014-08-10 11:39:13 +02:00
|
|
|
def __call__(self, value):
|
|
|
|
self.__init__(value)
|
|
|
|
return value
|
|
|
|
|
|
|
|
def __str__(self):
|
|
|
|
return "%s" % Latency(self)
|
|
|
|
|
2006-09-04 19:52:26 +02:00
|
|
|
def __getattr__(self, attr):
|
|
|
|
if attr == 'frequency':
|
|
|
|
return Frequency(self)
|
|
|
|
if attr in ('latency', 'period'):
|
|
|
|
return Latency(self)
|
|
|
|
raise AttributeError, "Frequency object has no attribute '%s'" % attr
|
|
|
|
|
2007-07-24 06:51:38 +02:00
|
|
|
def getValue(self):
|
|
|
|
return self.period.getValue()
|
|
|
|
|
2006-09-04 19:52:26 +02:00
|
|
|
def ini_str(self):
|
|
|
|
return self.period.ini_str()
|
|
|
|
|
2013-08-19 09:52:28 +02:00
|
|
|
class Voltage(float,ParamValue):
|
|
|
|
cxx_type = 'double'
|
2014-08-10 11:39:13 +02:00
|
|
|
ex_str = "1V"
|
|
|
|
cmd_line_settable = False
|
|
|
|
|
2013-08-19 09:52:28 +02:00
|
|
|
def __new__(cls, value):
|
|
|
|
# convert to voltage
|
|
|
|
val = convert.toVoltage(value)
|
|
|
|
return super(cls, Voltage).__new__(cls, val)
|
|
|
|
|
2014-08-10 11:39:13 +02:00
|
|
|
def __call__(self, value):
|
|
|
|
val = convert.toVoltage(value)
|
|
|
|
self.__init__(val)
|
|
|
|
return value
|
|
|
|
|
2013-08-19 09:52:28 +02:00
|
|
|
def __str__(self):
|
2014-08-10 11:39:13 +02:00
|
|
|
return str(self.getValue())
|
2013-08-19 09:52:28 +02:00
|
|
|
|
|
|
|
def getValue(self):
|
|
|
|
value = float(self)
|
|
|
|
return value
|
|
|
|
|
|
|
|
def ini_str(self):
|
|
|
|
return '%f' % self.getValue()
|
|
|
|
|
2006-09-04 19:52:26 +02:00
|
|
|
class NetworkBandwidth(float,ParamValue):
|
|
|
|
cxx_type = 'float'
|
2014-08-10 11:39:13 +02:00
|
|
|
ex_str = "1Gbps"
|
|
|
|
cmd_line_settable = True
|
|
|
|
|
2006-09-04 19:52:26 +02:00
|
|
|
def __new__(cls, value):
|
2007-03-06 20:13:43 +01:00
|
|
|
# convert to bits per second
|
|
|
|
val = convert.toNetworkBandwidth(value)
|
2006-09-04 19:52:26 +02:00
|
|
|
return super(cls, NetworkBandwidth).__new__(cls, val)
|
|
|
|
|
|
|
|
def __str__(self):
|
|
|
|
return str(self.val)
|
|
|
|
|
2014-08-10 11:39:13 +02:00
|
|
|
def __call__(self, value):
|
|
|
|
val = convert.toNetworkBandwidth(value)
|
|
|
|
self.__init__(val)
|
|
|
|
return value
|
|
|
|
|
2007-07-24 06:51:38 +02:00
|
|
|
def getValue(self):
|
2007-03-06 20:13:43 +01:00
|
|
|
# convert to seconds per byte
|
|
|
|
value = 8.0 / float(self)
|
|
|
|
# convert to ticks per byte
|
2007-07-24 06:51:38 +02:00
|
|
|
value = ticks.fromSeconds(value)
|
|
|
|
return float(value)
|
|
|
|
|
|
|
|
def ini_str(self):
|
|
|
|
return '%f' % self.getValue()
|
2006-09-04 19:52:26 +02:00
|
|
|
|
|
|
|
class MemoryBandwidth(float,ParamValue):
|
|
|
|
cxx_type = 'float'
|
2014-08-10 11:39:13 +02:00
|
|
|
ex_str = "1GB/s"
|
|
|
|
cmd_line_settable = True
|
|
|
|
|
2008-06-15 05:42:45 +02:00
|
|
|
def __new__(cls, value):
|
2010-11-11 20:58:09 +01:00
|
|
|
# convert to bytes per second
|
2006-09-05 02:14:07 +02:00
|
|
|
val = convert.toMemoryBandwidth(value)
|
2006-09-04 19:52:26 +02:00
|
|
|
return super(cls, MemoryBandwidth).__new__(cls, val)
|
|
|
|
|
2014-08-10 11:39:13 +02:00
|
|
|
def __call__(self, value):
|
|
|
|
val = convert.toMemoryBandwidth(value)
|
|
|
|
self.__init__(val)
|
|
|
|
return value
|
2006-09-04 19:52:26 +02:00
|
|
|
|
2007-07-24 06:51:38 +02:00
|
|
|
def getValue(self):
|
2007-03-06 20:13:43 +01:00
|
|
|
# convert to seconds per byte
|
2008-06-15 05:39:31 +02:00
|
|
|
value = float(self)
|
|
|
|
if value:
|
|
|
|
value = 1.0 / float(self)
|
2007-03-06 20:13:43 +01:00
|
|
|
# convert to ticks per byte
|
2007-07-24 06:51:38 +02:00
|
|
|
value = ticks.fromSeconds(value)
|
|
|
|
return float(value)
|
|
|
|
|
|
|
|
def ini_str(self):
|
|
|
|
return '%f' % self.getValue()
|
2006-09-04 19:52:26 +02:00
|
|
|
|
|
|
|
#
|
|
|
|
# "Constants"... handy aliases for various values.
|
|
|
|
#
|
|
|
|
|
2006-09-05 02:14:07 +02:00
|
|
|
# Special class for NULL pointers. Note the special check in
|
|
|
|
# make_param_value() above that lets these be assigned where a
|
|
|
|
# SimObject is required.
|
|
|
|
# only one copy of a particular node
|
|
|
|
class NullSimObject(object):
|
|
|
|
__metaclass__ = Singleton
|
|
|
|
|
|
|
|
def __call__(cls):
|
|
|
|
return cls
|
|
|
|
|
|
|
|
def _instantiate(self, parent = None, path = ''):
|
|
|
|
pass
|
|
|
|
|
|
|
|
def ini_str(self):
|
|
|
|
return 'Null'
|
|
|
|
|
|
|
|
def unproxy(self, base):
|
|
|
|
return self
|
|
|
|
|
|
|
|
def set_path(self, parent, name):
|
|
|
|
pass
|
2007-07-24 06:51:38 +02:00
|
|
|
|
2006-09-05 02:14:07 +02:00
|
|
|
def __str__(self):
|
|
|
|
return 'Null'
|
|
|
|
|
2007-07-24 06:51:38 +02:00
|
|
|
def getValue(self):
|
|
|
|
return None
|
|
|
|
|
2006-09-05 02:14:07 +02:00
|
|
|
# The only instance you'll ever need...
|
|
|
|
NULL = NullSimObject()
|
|
|
|
|
|
|
|
def isNullPointer(value):
|
|
|
|
return isinstance(value, NullSimObject)
|
|
|
|
|
2006-09-04 19:52:26 +02:00
|
|
|
# Some memory range specifications use this as a default upper bound.
|
|
|
|
MaxAddr = Addr.max
|
|
|
|
MaxTick = Tick.max
|
|
|
|
AllMemory = AddrRange(0, MaxAddr)
|
|
|
|
|
|
|
|
|
|
|
|
#####################################################################
|
|
|
|
#
|
|
|
|
# Port objects
|
|
|
|
#
|
|
|
|
# Ports are used to interconnect objects in the memory system.
|
|
|
|
#
|
|
|
|
#####################################################################
|
|
|
|
|
|
|
|
# Port reference: encapsulates a reference to a particular port on a
|
|
|
|
# particular SimObject.
|
|
|
|
class PortRef(object):
|
2012-02-13 12:43:09 +01:00
|
|
|
def __init__(self, simobj, name, role):
|
2006-09-06 07:04:34 +02:00
|
|
|
assert(isSimObject(simobj) or isSimObjectClass(simobj))
|
2006-09-04 19:52:26 +02:00
|
|
|
self.simobj = simobj
|
|
|
|
self.name = name
|
2012-02-13 12:43:09 +01:00
|
|
|
self.role = role
|
2006-09-04 19:52:26 +02:00
|
|
|
self.peer = None # not associated with another port yet
|
|
|
|
self.ccConnected = False # C++ port connection done?
|
2006-09-06 07:04:34 +02:00
|
|
|
self.index = -1 # always -1 for non-vector ports
|
2006-09-04 19:52:26 +02:00
|
|
|
|
2006-09-05 21:22:47 +02:00
|
|
|
def __str__(self):
|
2006-09-06 07:04:34 +02:00
|
|
|
return '%s.%s' % (self.simobj, self.name)
|
|
|
|
|
2012-02-13 12:45:11 +01:00
|
|
|
def __len__(self):
|
|
|
|
# Return the number of connected ports, i.e. 0 is we have no
|
|
|
|
# peer and 1 if we do.
|
|
|
|
return int(self.peer != None)
|
|
|
|
|
2006-09-06 07:04:34 +02:00
|
|
|
# for config.ini, print peer's name (not ours)
|
|
|
|
def ini_str(self):
|
|
|
|
return str(self.peer)
|
|
|
|
|
2012-05-23 15:16:39 +02:00
|
|
|
# for config.json
|
|
|
|
def get_config_as_dict(self):
|
|
|
|
return {'role' : self.role, 'peer' : str(self.peer)}
|
|
|
|
|
2006-09-06 07:04:34 +02:00
|
|
|
def __getattr__(self, attr):
|
|
|
|
if attr == 'peerObj':
|
|
|
|
# shorthand for proxies
|
|
|
|
return self.peer.simobj
|
|
|
|
raise AttributeError, "'%s' object has no attribute '%s'" % \
|
|
|
|
(self.__class__.__name__, attr)
|
|
|
|
|
|
|
|
# Full connection is symmetric (both ways). Called via
|
|
|
|
# SimObject.__setattr__ as a result of a port assignment, e.g.,
|
2006-09-09 01:10:11 +02:00
|
|
|
# "obj1.portA = obj2.portB", or via VectorPortElementRef.__setitem__,
|
2006-09-06 07:04:34 +02:00
|
|
|
# e.g., "obj1.portA[3] = obj2.portB".
|
|
|
|
def connect(self, other):
|
|
|
|
if isinstance(other, VectorPortRef):
|
|
|
|
# reference to plain VectorPort is implicit append
|
|
|
|
other = other._get_next()
|
|
|
|
if self.peer and not proxy.isproxy(self.peer):
|
2012-05-23 15:01:56 +02:00
|
|
|
fatal("Port %s is already connected to %s, cannot connect %s\n",
|
|
|
|
self, self.peer, other);
|
2006-09-04 19:52:26 +02:00
|
|
|
self.peer = other
|
2006-09-09 01:10:11 +02:00
|
|
|
if proxy.isproxy(other):
|
|
|
|
other.set_param_desc(PortParamDesc())
|
|
|
|
elif isinstance(other, PortRef):
|
|
|
|
if other.peer is not self:
|
|
|
|
other.connect(self)
|
|
|
|
else:
|
|
|
|
raise TypeError, \
|
|
|
|
"assigning non-port reference '%s' to port '%s'" \
|
|
|
|
% (other, self)
|
2006-09-04 19:52:26 +02:00
|
|
|
|
2014-09-03 13:43:03 +02:00
|
|
|
# Allow a master/slave port pair to be spliced between
|
|
|
|
# a port and its connected peer. Useful operation for connecting
|
|
|
|
# instrumentation structures into a system when it is necessary
|
|
|
|
# to connect the instrumentation after the full system has been
|
|
|
|
# constructed.
|
|
|
|
def splice(self, new_master_peer, new_slave_peer):
|
|
|
|
if self.peer and not proxy.isproxy(self.peer):
|
|
|
|
if isinstance(new_master_peer, PortRef) and \
|
|
|
|
isinstance(new_slave_peer, PortRef):
|
|
|
|
old_peer = self.peer
|
|
|
|
if self.role == 'SLAVE':
|
|
|
|
self.peer = new_master_peer
|
|
|
|
old_peer.peer = new_slave_peer
|
|
|
|
new_master_peer.connect(self)
|
|
|
|
new_slave_peer.connect(old_peer)
|
|
|
|
elif self.role == 'MASTER':
|
|
|
|
self.peer = new_slave_peer
|
|
|
|
old_peer.peer = new_master_peer
|
|
|
|
new_slave_peer.connect(self)
|
|
|
|
new_master_peer.connect(old_peer)
|
|
|
|
else:
|
|
|
|
panic("Port %s has unknown role, "+\
|
|
|
|
"cannot splice in new peers\n", self)
|
|
|
|
else:
|
|
|
|
raise TypeError, \
|
|
|
|
"Splicing non-port references '%s','%s' to port '%s'"\
|
|
|
|
% (new_peer, peers_new_peer, self)
|
|
|
|
else:
|
|
|
|
fatal("Port %s not connected, cannot splice in new peers\n", self)
|
|
|
|
|
2006-09-06 07:04:34 +02:00
|
|
|
def clone(self, simobj, memo):
|
|
|
|
if memo.has_key(self):
|
|
|
|
return memo[self]
|
2006-09-04 19:52:26 +02:00
|
|
|
newRef = copy.copy(self)
|
2006-09-06 07:04:34 +02:00
|
|
|
memo[self] = newRef
|
|
|
|
newRef.simobj = simobj
|
2006-09-04 19:52:26 +02:00
|
|
|
assert(isSimObject(newRef.simobj))
|
2006-09-06 07:04:34 +02:00
|
|
|
if self.peer and not proxy.isproxy(self.peer):
|
2006-10-09 03:26:59 +02:00
|
|
|
peerObj = self.peer.simobj(_memo=memo)
|
2006-09-06 07:04:34 +02:00
|
|
|
newRef.peer = self.peer.clone(peerObj, memo)
|
|
|
|
assert(not isinstance(newRef.peer, VectorPortRef))
|
2006-09-04 19:52:26 +02:00
|
|
|
return newRef
|
|
|
|
|
2006-09-06 07:04:34 +02:00
|
|
|
def unproxy(self, simobj):
|
|
|
|
assert(simobj is self.simobj)
|
|
|
|
if proxy.isproxy(self.peer):
|
|
|
|
try:
|
|
|
|
realPeer = self.peer.unproxy(self.simobj)
|
|
|
|
except:
|
|
|
|
print "Error in unproxying port '%s' of %s" % \
|
|
|
|
(self.name, self.simobj.path())
|
|
|
|
raise
|
|
|
|
self.connect(realPeer)
|
|
|
|
|
2006-09-04 19:52:26 +02:00
|
|
|
# Call C++ to create corresponding port connection between C++ objects
|
|
|
|
def ccConnect(self):
|
2011-10-20 22:09:10 +02:00
|
|
|
from m5.internal.pyobject import connectPorts
|
2007-07-24 06:51:38 +02:00
|
|
|
|
2012-02-13 12:43:09 +01:00
|
|
|
if self.role == 'SLAVE':
|
|
|
|
# do nothing and let the master take care of it
|
|
|
|
return
|
|
|
|
|
2006-09-04 19:52:26 +02:00
|
|
|
if self.ccConnected: # already done this
|
|
|
|
return
|
|
|
|
peer = self.peer
|
2008-09-30 08:30:14 +02:00
|
|
|
if not self.peer: # nothing to connect to
|
|
|
|
return
|
2012-02-13 12:43:09 +01:00
|
|
|
|
|
|
|
# check that we connect a master to a slave
|
|
|
|
if self.role == peer.role:
|
|
|
|
raise TypeError, \
|
|
|
|
"cannot connect '%s' and '%s' due to identical role '%s'" \
|
|
|
|
% (peer, self, self.role)
|
|
|
|
|
2010-08-17 14:06:22 +02:00
|
|
|
try:
|
2012-02-13 12:43:09 +01:00
|
|
|
# self is always the master and peer the slave
|
2010-08-17 14:06:22 +02:00
|
|
|
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
|
2006-09-04 19:52:26 +02:00
|
|
|
self.ccConnected = True
|
|
|
|
peer.ccConnected = True
|
|
|
|
|
2006-09-06 07:04:34 +02:00
|
|
|
# A reference to an individual element of a VectorPort... much like a
|
|
|
|
# PortRef, but has an index.
|
|
|
|
class VectorPortElementRef(PortRef):
|
2012-02-13 12:43:09 +01:00
|
|
|
def __init__(self, simobj, name, role, index):
|
|
|
|
PortRef.__init__(self, simobj, name, role)
|
2006-09-06 07:04:34 +02:00
|
|
|
self.index = index
|
|
|
|
|
|
|
|
def __str__(self):
|
|
|
|
return '%s.%s[%d]' % (self.simobj, self.name, self.index)
|
|
|
|
|
|
|
|
# A reference to a complete vector-valued port (not just a single element).
|
|
|
|
# Can be indexed to retrieve individual VectorPortElementRef instances.
|
|
|
|
class VectorPortRef(object):
|
2012-02-13 12:43:09 +01:00
|
|
|
def __init__(self, simobj, name, role):
|
2006-09-06 07:04:34 +02:00
|
|
|
assert(isSimObject(simobj) or isSimObjectClass(simobj))
|
|
|
|
self.simobj = simobj
|
|
|
|
self.name = name
|
2012-02-13 12:43:09 +01:00
|
|
|
self.role = role
|
2006-09-06 07:04:34 +02:00
|
|
|
self.elements = []
|
|
|
|
|
2006-09-09 01:10:11 +02:00
|
|
|
def __str__(self):
|
|
|
|
return '%s.%s[:]' % (self.simobj, self.name)
|
|
|
|
|
2012-02-13 12:45:11 +01:00
|
|
|
def __len__(self):
|
|
|
|
# Return the number of connected peers, corresponding the the
|
|
|
|
# length of the elements.
|
|
|
|
return len(self.elements)
|
|
|
|
|
2006-09-06 07:04:34 +02:00
|
|
|
# for config.ini, print peer's name (not ours)
|
|
|
|
def ini_str(self):
|
|
|
|
return ' '.join([el.ini_str() for el in self.elements])
|
|
|
|
|
2012-05-23 15:16:39 +02:00
|
|
|
# for config.json
|
|
|
|
def get_config_as_dict(self):
|
|
|
|
return {'role' : self.role,
|
|
|
|
'peer' : [el.ini_str() for el in self.elements]}
|
|
|
|
|
2006-09-06 07:04:34 +02:00
|
|
|
def __getitem__(self, key):
|
|
|
|
if not isinstance(key, int):
|
|
|
|
raise TypeError, "VectorPort index must be integer"
|
|
|
|
if key >= len(self.elements):
|
|
|
|
# need to extend list
|
2012-02-13 12:43:09 +01:00
|
|
|
ext = [VectorPortElementRef(self.simobj, self.name, self.role, i)
|
2006-09-06 07:04:34 +02:00
|
|
|
for i in range(len(self.elements), key+1)]
|
|
|
|
self.elements.extend(ext)
|
|
|
|
return self.elements[key]
|
|
|
|
|
|
|
|
def _get_next(self):
|
|
|
|
return self[len(self.elements)]
|
|
|
|
|
|
|
|
def __setitem__(self, key, value):
|
|
|
|
if not isinstance(key, int):
|
|
|
|
raise TypeError, "VectorPort index must be integer"
|
|
|
|
self[key].connect(value)
|
|
|
|
|
|
|
|
def connect(self, other):
|
2006-09-09 01:10:11 +02:00
|
|
|
if isinstance(other, (list, tuple)):
|
|
|
|
# Assign list of port refs to vector port.
|
|
|
|
# For now, append them... not sure if that's the right semantics
|
|
|
|
# or if it should replace the current vector.
|
|
|
|
for ref in other:
|
|
|
|
self._get_next().connect(ref)
|
|
|
|
else:
|
|
|
|
# scalar assignment to plain VectorPort is implicit append
|
|
|
|
self._get_next().connect(other)
|
|
|
|
|
|
|
|
def clone(self, simobj, memo):
|
|
|
|
if memo.has_key(self):
|
|
|
|
return memo[self]
|
|
|
|
newRef = copy.copy(self)
|
|
|
|
memo[self] = newRef
|
|
|
|
newRef.simobj = simobj
|
|
|
|
assert(isSimObject(newRef.simobj))
|
|
|
|
newRef.elements = [el.clone(simobj, memo) for el in self.elements]
|
|
|
|
return newRef
|
2006-09-06 07:04:34 +02:00
|
|
|
|
|
|
|
def unproxy(self, simobj):
|
|
|
|
[el.unproxy(simobj) for el in self.elements]
|
|
|
|
|
|
|
|
def ccConnect(self):
|
|
|
|
[el.ccConnect() for el in self.elements]
|
|
|
|
|
2006-09-04 19:52:26 +02:00
|
|
|
# Port description object. Like a ParamDesc object, this represents a
|
|
|
|
# logical port in the SimObject class, not a particular port on a
|
|
|
|
# SimObject instance. The latter are represented by PortRef objects.
|
|
|
|
class Port(object):
|
|
|
|
# Generate a PortRef for this port on the given SimObject with the
|
|
|
|
# given name
|
2006-09-06 07:04:34 +02:00
|
|
|
def makeRef(self, simobj):
|
2012-02-13 12:43:09 +01:00
|
|
|
return PortRef(simobj, self.name, self.role)
|
2006-09-04 19:52:26 +02:00
|
|
|
|
|
|
|
# Connect an instance of this port (on the given SimObject with
|
|
|
|
# the given name) with the port described by the supplied PortRef
|
2006-09-06 07:04:34 +02:00
|
|
|
def connect(self, simobj, ref):
|
|
|
|
self.makeRef(simobj).connect(ref)
|
2006-09-04 19:52:26 +02:00
|
|
|
|
2012-02-13 12:45:11 +01:00
|
|
|
# No need for any pre-declarations at the moment as we merely rely
|
|
|
|
# on an unsigned int.
|
|
|
|
def cxx_predecls(self, code):
|
|
|
|
pass
|
|
|
|
|
|
|
|
# Declare an unsigned int with the same name as the port, that
|
|
|
|
# will eventually hold the number of connected ports (and thus the
|
|
|
|
# number of elements for a VectorPort).
|
|
|
|
def cxx_decl(self, code):
|
|
|
|
code('unsigned int port_${{self.name}}_connection_count;')
|
|
|
|
|
2012-02-13 12:43:09 +01:00
|
|
|
class MasterPort(Port):
|
|
|
|
# MasterPort("description")
|
|
|
|
def __init__(self, *args):
|
|
|
|
if len(args) == 1:
|
|
|
|
self.desc = args[0]
|
|
|
|
self.role = 'MASTER'
|
|
|
|
else:
|
|
|
|
raise TypeError, 'wrong number of arguments'
|
|
|
|
|
|
|
|
class SlavePort(Port):
|
|
|
|
# SlavePort("description")
|
|
|
|
def __init__(self, *args):
|
|
|
|
if len(args) == 1:
|
|
|
|
self.desc = args[0]
|
|
|
|
self.role = 'SLAVE'
|
|
|
|
else:
|
|
|
|
raise TypeError, 'wrong number of arguments'
|
|
|
|
|
2006-09-04 19:52:26 +02:00
|
|
|
# VectorPort description object. Like Port, but represents a vector
|
|
|
|
# of connections (e.g., as on a Bus).
|
|
|
|
class VectorPort(Port):
|
2006-09-06 07:04:34 +02:00
|
|
|
def __init__(self, *args):
|
2006-09-04 19:52:26 +02:00
|
|
|
self.isVec = True
|
|
|
|
|
2006-09-06 07:04:34 +02:00
|
|
|
def makeRef(self, simobj):
|
2012-02-13 12:43:09 +01:00
|
|
|
return VectorPortRef(simobj, self.name, self.role)
|
|
|
|
|
|
|
|
class VectorMasterPort(VectorPort):
|
|
|
|
# VectorMasterPort("description")
|
|
|
|
def __init__(self, *args):
|
|
|
|
if len(args) == 1:
|
|
|
|
self.desc = args[0]
|
|
|
|
self.role = 'MASTER'
|
|
|
|
VectorPort.__init__(self, *args)
|
|
|
|
else:
|
|
|
|
raise TypeError, 'wrong number of arguments'
|
|
|
|
|
|
|
|
class VectorSlavePort(VectorPort):
|
|
|
|
# VectorSlavePort("description")
|
|
|
|
def __init__(self, *args):
|
|
|
|
if len(args) == 1:
|
|
|
|
self.desc = args[0]
|
|
|
|
self.role = 'SLAVE'
|
|
|
|
VectorPort.__init__(self, *args)
|
|
|
|
else:
|
|
|
|
raise TypeError, 'wrong number of arguments'
|
2006-09-06 07:04:34 +02:00
|
|
|
|
2006-09-09 01:10:11 +02:00
|
|
|
# 'Fake' ParamDesc for Port references to assign to the _pdesc slot of
|
|
|
|
# proxy objects (via set_param_desc()) so that proxy error messages
|
|
|
|
# make sense.
|
|
|
|
class PortParamDesc(object):
|
|
|
|
__metaclass__ = Singleton
|
|
|
|
|
|
|
|
ptype_str = 'Port'
|
|
|
|
ptype = Port
|
2006-09-06 07:04:34 +02:00
|
|
|
|
2009-09-23 00:24:16 +02:00
|
|
|
baseEnums = allEnums.copy()
|
|
|
|
baseParams = allParams.copy()
|
|
|
|
|
|
|
|
def clear():
|
|
|
|
global allEnums, allParams
|
|
|
|
|
|
|
|
allEnums = baseEnums.copy()
|
|
|
|
allParams = baseParams.copy()
|
|
|
|
|
2006-09-04 19:52:26 +02:00
|
|
|
__all__ = ['Param', 'VectorParam',
|
|
|
|
'Enum', 'Bool', 'String', 'Float',
|
|
|
|
'Int', 'Unsigned', 'Int8', 'UInt8', 'Int16', 'UInt16',
|
|
|
|
'Int32', 'UInt32', 'Int64', 'UInt64',
|
|
|
|
'Counter', 'Addr', 'Tick', 'Percent',
|
|
|
|
'TcpPort', 'UdpPort', 'EthernetAddr',
|
2010-11-23 21:54:43 +01:00
|
|
|
'IpAddress', 'IpNetmask', 'IpWithPort',
|
2006-09-04 19:52:26 +02:00
|
|
|
'MemorySize', 'MemorySize32',
|
2013-08-19 09:52:28 +02:00
|
|
|
'Latency', 'Frequency', 'Clock', 'Voltage',
|
2006-09-04 19:52:26 +02:00
|
|
|
'NetworkBandwidth', 'MemoryBandwidth',
|
2012-09-19 12:15:41 +02:00
|
|
|
'AddrRange',
|
2006-09-04 19:52:26 +02:00
|
|
|
'MaxAddr', 'MaxTick', 'AllMemory',
|
2007-01-03 19:12:55 +01:00
|
|
|
'Time',
|
2006-09-05 02:14:07 +02:00
|
|
|
'NextEthernetAddr', 'NULL',
|
2012-02-13 12:43:09 +01:00
|
|
|
'MasterPort', 'SlavePort',
|
|
|
|
'VectorMasterPort', 'VectorSlavePort']
|
2009-09-23 00:24:16 +02:00
|
|
|
|
|
|
|
import SimObject
|