params.py revision 4380
113558Snikos.nikoleris@arm.com# Copyright (c) 2004-2006 The Regents of The University of Michigan 28839Sandreas.hansson@arm.com# All rights reserved. 38839Sandreas.hansson@arm.com# 48839Sandreas.hansson@arm.com# Redistribution and use in source and binary forms, with or without 58839Sandreas.hansson@arm.com# modification, are permitted provided that the following conditions are 68839Sandreas.hansson@arm.com# met: redistributions of source code must retain the above copyright 78839Sandreas.hansson@arm.com# notice, this list of conditions and the following disclaimer; 88839Sandreas.hansson@arm.com# redistributions in binary form must reproduce the above copyright 98839Sandreas.hansson@arm.com# notice, this list of conditions and the following disclaimer in the 108839Sandreas.hansson@arm.com# documentation and/or other materials provided with the distribution; 118839Sandreas.hansson@arm.com# neither the name of the copyright holders nor the names of its 128839Sandreas.hansson@arm.com# contributors may be used to endorse or promote products derived from 133101Sstever@eecs.umich.edu# this software without specific prior written permission. 148579Ssteve.reinhardt@amd.com# 153101Sstever@eecs.umich.edu# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 163101Sstever@eecs.umich.edu# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 173101Sstever@eecs.umich.edu# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 183101Sstever@eecs.umich.edu# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 193101Sstever@eecs.umich.edu# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 203101Sstever@eecs.umich.edu# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 213101Sstever@eecs.umich.edu# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 223101Sstever@eecs.umich.edu# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 233101Sstever@eecs.umich.edu# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 243101Sstever@eecs.umich.edu# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 253101Sstever@eecs.umich.edu# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 263101Sstever@eecs.umich.edu# 273101Sstever@eecs.umich.edu# Authors: Steve Reinhardt 283101Sstever@eecs.umich.edu# Nathan Binkert 293101Sstever@eecs.umich.edu 303101Sstever@eecs.umich.edu##################################################################### 313101Sstever@eecs.umich.edu# 323101Sstever@eecs.umich.edu# Parameter description classes 333101Sstever@eecs.umich.edu# 343101Sstever@eecs.umich.edu# The _params dictionary in each class maps parameter names to either 353101Sstever@eecs.umich.edu# a Param or a VectorParam object. These objects contain the 363101Sstever@eecs.umich.edu# parameter description string, the parameter type, and the default 373101Sstever@eecs.umich.edu# value (if any). The convert() method on these objects is used to 383101Sstever@eecs.umich.edu# force whatever value is assigned to the parameter to the appropriate 393101Sstever@eecs.umich.edu# type. 403101Sstever@eecs.umich.edu# 413101Sstever@eecs.umich.edu# Note that the default values are loaded into the class's attribute 427778Sgblack@eecs.umich.edu# space when the parameter dictionary is initialized (in 438839Sandreas.hansson@arm.com# MetaSimObject._new_param()); after that point they aren't used. 443101Sstever@eecs.umich.edu# 453101Sstever@eecs.umich.edu##################################################################### 463101Sstever@eecs.umich.edu 473101Sstever@eecs.umich.eduimport copy 483101Sstever@eecs.umich.eduimport datetime 493101Sstever@eecs.umich.eduimport inspect 503101Sstever@eecs.umich.eduimport sys 513101Sstever@eecs.umich.eduimport time 523101Sstever@eecs.umich.edu 533101Sstever@eecs.umich.eduimport convert 543101Sstever@eecs.umich.eduimport proxy 553101Sstever@eecs.umich.eduimport ticks 563101Sstever@eecs.umich.edufrom util import * 573101Sstever@eecs.umich.edu 583101Sstever@eecs.umich.edu# Dummy base class to identify types that are legitimate for SimObject 593101Sstever@eecs.umich.edu# parameters. 603101Sstever@eecs.umich.educlass ParamValue(object): 613101Sstever@eecs.umich.edu 6212563Sgabeblack@google.com cxx_predecls = [] 6312563Sgabeblack@google.com swig_predecls = [] 643885Sbinkertn@umich.edu 653885Sbinkertn@umich.edu # default for printing to .ini file is regular string conversion. 664762Snate@binkert.org # will be overridden in some cases 673885Sbinkertn@umich.edu def ini_str(self): 683885Sbinkertn@umich.edu return str(self) 697528Ssteve.reinhardt@amd.com 703885Sbinkertn@umich.edu # allows us to blithely call unproxy() on things without checking 714380Sbinkertn@umich.edu # if they're really proxies or not 724167Sbinkertn@umich.edu def unproxy(self, base): 733102Sstever@eecs.umich.edu return self 743101Sstever@eecs.umich.edu 754762Snate@binkert.org# Regular parameter description. 764762Snate@binkert.orgclass ParamDesc(object): 774762Snate@binkert.org def __init__(self, ptype_str, ptype, *args, **kwargs): 784762Snate@binkert.org self.ptype_str = ptype_str 794762Snate@binkert.org # remember ptype only if it is provided 804762Snate@binkert.org if ptype != None: 814762Snate@binkert.org self.ptype = ptype 824762Snate@binkert.org 834762Snate@binkert.org if args: 845033Smilesck@eecs.umich.edu if len(args) == 1: 855033Smilesck@eecs.umich.edu self.desc = args[0] 865033Smilesck@eecs.umich.edu elif len(args) == 2: 875033Smilesck@eecs.umich.edu self.default = args[0] 885033Smilesck@eecs.umich.edu self.desc = args[1] 895033Smilesck@eecs.umich.edu else: 905033Smilesck@eecs.umich.edu raise TypeError, 'too many arguments' 915033Smilesck@eecs.umich.edu 925033Smilesck@eecs.umich.edu if kwargs.has_key('desc'): 935033Smilesck@eecs.umich.edu assert(not hasattr(self, 'desc')) 943101Sstever@eecs.umich.edu self.desc = kwargs['desc'] 953101Sstever@eecs.umich.edu del kwargs['desc'] 963101Sstever@eecs.umich.edu 975033Smilesck@eecs.umich.edu if kwargs.has_key('default'): 9810267SGeoffrey.Blake@arm.com assert(not hasattr(self, 'default')) 998596Ssteve.reinhardt@amd.com self.default = kwargs['default'] 1008596Ssteve.reinhardt@amd.com del kwargs['default'] 1018596Ssteve.reinhardt@amd.com 1028596Ssteve.reinhardt@amd.com if kwargs: 1037673Snate@binkert.org raise TypeError, 'extra unknown kwargs %s' % kwargs 1047673Snate@binkert.org 1057673Snate@binkert.org if not hasattr(self, 'desc'): 1067673Snate@binkert.org raise TypeError, 'desc attribute missing' 10711988Sandreas.sandberg@arm.com 10811988Sandreas.sandberg@arm.com def __getattr__(self, attr): 10911988Sandreas.sandberg@arm.com if attr == 'ptype': 11011988Sandreas.sandberg@arm.com try: 1113101Sstever@eecs.umich.edu ptype = eval(self.ptype_str, objects.__dict__) 1123101Sstever@eecs.umich.edu if not isinstance(ptype, type): 1133101Sstever@eecs.umich.edu raise NameError 1143101Sstever@eecs.umich.edu self.ptype = ptype 1153101Sstever@eecs.umich.edu return ptype 11610380SAndrew.Bardsley@arm.com except NameError: 11710380SAndrew.Bardsley@arm.com raise TypeError, \ 11810380SAndrew.Bardsley@arm.com "Param qualifier '%s' is not a type" % self.ptype_str 11910380SAndrew.Bardsley@arm.com raise AttributeError, "'%s' object has no attribute '%s'" % \ 12010380SAndrew.Bardsley@arm.com (type(self).__name__, attr) 12110380SAndrew.Bardsley@arm.com 12210458Sandreas.hansson@arm.com def convert(self, value): 12310458Sandreas.hansson@arm.com if isinstance(value, proxy.BaseProxy): 12410458Sandreas.hansson@arm.com value.set_param_desc(self) 12510458Sandreas.hansson@arm.com return value 12610458Sandreas.hansson@arm.com if not hasattr(self, 'ptype') and isNullPointer(value): 12710458Sandreas.hansson@arm.com # deferred evaluation of SimObject; continue to defer if 12810458Sandreas.hansson@arm.com # we're just assigning a null pointer 12910458Sandreas.hansson@arm.com return value 13010458Sandreas.hansson@arm.com if isinstance(value, self.ptype): 13110458Sandreas.hansson@arm.com return value 13210458Sandreas.hansson@arm.com if isNullPointer(value) and isSimObjectClass(self.ptype): 13310458Sandreas.hansson@arm.com return value 1343101Sstever@eecs.umich.edu return self.ptype(value) 1353101Sstever@eecs.umich.edu 1363101Sstever@eecs.umich.edu def cxx_predecls(self): 1373101Sstever@eecs.umich.edu return self.ptype.cxx_predecls 1383101Sstever@eecs.umich.edu 13910267SGeoffrey.Blake@arm.com def swig_predecls(self): 14010267SGeoffrey.Blake@arm.com return self.ptype.swig_predecls 14110267SGeoffrey.Blake@arm.com 14210267SGeoffrey.Blake@arm.com def cxx_decl(self): 1433101Sstever@eecs.umich.edu return '%s %s;' % (self.ptype.cxx_type, self.name) 1443101Sstever@eecs.umich.edu 1453101Sstever@eecs.umich.edu# Vector-valued parameter description. Just like ParamDesc, except 1463101Sstever@eecs.umich.edu# that the value is a vector (list) of the specified type instead of a 1473101Sstever@eecs.umich.edu# single value. 1483101Sstever@eecs.umich.edu 1493101Sstever@eecs.umich.educlass VectorParamValue(list): 1503101Sstever@eecs.umich.edu def ini_str(self): 1513101Sstever@eecs.umich.edu return ' '.join([v.ini_str() for v in self]) 1523101Sstever@eecs.umich.edu 1533101Sstever@eecs.umich.edu def unproxy(self, base): 1543101Sstever@eecs.umich.edu return [v.unproxy(base) for v in self] 1553101Sstever@eecs.umich.edu 1563101Sstever@eecs.umich.educlass SimObjVector(VectorParamValue): 1573101Sstever@eecs.umich.edu def print_ini(self): 15813663Sandreas.sandberg@arm.com for v in self: 1593101Sstever@eecs.umich.edu v.print_ini() 16013675Sandreas.sandberg@arm.com 1613101Sstever@eecs.umich.educlass VectorParamDesc(ParamDesc): 1623101Sstever@eecs.umich.edu # Convert assigned value to appropriate type. If the RHS is not a 1633101Sstever@eecs.umich.edu # list or tuple, it generates a single-element list. 1643101Sstever@eecs.umich.edu def convert(self, value): 16513675Sandreas.sandberg@arm.com if isinstance(value, (list, tuple)): 1663101Sstever@eecs.umich.edu # list: coerce each element into new list 1673101Sstever@eecs.umich.edu tmp_list = [ ParamDesc.convert(self, v) for v in value ] 1683101Sstever@eecs.umich.edu if isSimObjectSequence(tmp_list): 1693101Sstever@eecs.umich.edu return SimObjVector(tmp_list) 1703101Sstever@eecs.umich.edu else: 17113663Sandreas.sandberg@arm.com return VectorParamValue(tmp_list) 1723101Sstever@eecs.umich.edu else: 1733101Sstever@eecs.umich.edu # singleton: leave it be (could coerce to a single-element 17413663Sandreas.sandberg@arm.com # list here, but for some historical reason we don't... 1753101Sstever@eecs.umich.edu return ParamDesc.convert(self, value) 1763101Sstever@eecs.umich.edu 1773101Sstever@eecs.umich.edu def cxx_predecls(self): 1785033Smilesck@eecs.umich.edu return ['#include <vector>'] + self.ptype.cxx_predecls 1796656Snate@binkert.org 1805033Smilesck@eecs.umich.edu def swig_predecls(self): 1815033Smilesck@eecs.umich.edu return ['%include "std_vector.i"'] + self.ptype.swig_predecls 1825033Smilesck@eecs.umich.edu 18313663Sandreas.sandberg@arm.com def cxx_decl(self): 18413663Sandreas.sandberg@arm.com return 'std::vector< %s > %s;' % (self.ptype.cxx_type, self.name) 1853101Sstever@eecs.umich.edu 18610267SGeoffrey.Blake@arm.comclass ParamFactory(object): 18710267SGeoffrey.Blake@arm.com def __init__(self, param_desc_class, ptype_str = None): 18810267SGeoffrey.Blake@arm.com self.param_desc_class = param_desc_class 18910267SGeoffrey.Blake@arm.com self.ptype_str = ptype_str 19010267SGeoffrey.Blake@arm.com 19110267SGeoffrey.Blake@arm.com def __getattr__(self, attr): 19210267SGeoffrey.Blake@arm.com if self.ptype_str: 19310267SGeoffrey.Blake@arm.com attr = self.ptype_str + '.' + attr 19410267SGeoffrey.Blake@arm.com return ParamFactory(self.param_desc_class, attr) 19510267SGeoffrey.Blake@arm.com 19610267SGeoffrey.Blake@arm.com # E.g., Param.Int(5, "number of widgets") 19710267SGeoffrey.Blake@arm.com def __call__(self, *args, **kwargs): 19810267SGeoffrey.Blake@arm.com caller_frame = inspect.currentframe().f_back 1993101Sstever@eecs.umich.edu ptype = None 2003101Sstever@eecs.umich.edu try: 2013101Sstever@eecs.umich.edu ptype = eval(self.ptype_str, 2023101Sstever@eecs.umich.edu caller_frame.f_globals, caller_frame.f_locals) 20313699Sandreas.sandberg@arm.com if not isinstance(ptype, type): 2043101Sstever@eecs.umich.edu raise TypeError, \ 2053101Sstever@eecs.umich.edu "Param qualifier is not a type: %s" % ptype 2063101Sstever@eecs.umich.edu except NameError: 2073101Sstever@eecs.umich.edu # if name isn't defined yet, assume it's a SimObject, and 2083101Sstever@eecs.umich.edu # try to resolve it later 2093102Sstever@eecs.umich.edu pass 2103101Sstever@eecs.umich.edu return self.param_desc_class(self.ptype_str, ptype, *args, **kwargs) 2113101Sstever@eecs.umich.edu 2123101Sstever@eecs.umich.eduParam = ParamFactory(ParamDesc) 21310267SGeoffrey.Blake@arm.comVectorParam = ParamFactory(VectorParamDesc) 21410267SGeoffrey.Blake@arm.com 21510267SGeoffrey.Blake@arm.com##################################################################### 21610267SGeoffrey.Blake@arm.com# 21710267SGeoffrey.Blake@arm.com# Parameter Types 21810267SGeoffrey.Blake@arm.com# 21910267SGeoffrey.Blake@arm.com# Though native Python types could be used to specify parameter types 2207673Snate@binkert.org# (the 'ptype' field of the Param and VectorParam classes), it's more 2218607Sgblack@eecs.umich.edu# flexible to define our own set of types. This gives us more control 2227673Snate@binkert.org# over how Python expressions are converted to values (via the 2233101Sstever@eecs.umich.edu# __init__() constructor) and how these values are printed out (via 22411988Sandreas.sandberg@arm.com# the __str__() conversion method). 22511988Sandreas.sandberg@arm.com# 22611988Sandreas.sandberg@arm.com##################################################################### 2277673Snate@binkert.org 2287673Snate@binkert.org# String-valued parameter. Just mixin the ParamValue class with the 2293101Sstever@eecs.umich.edu# built-in str class. 2303101Sstever@eecs.umich.educlass String(ParamValue,str): 2313101Sstever@eecs.umich.edu cxx_type = 'std::string' 2323101Sstever@eecs.umich.edu cxx_predecls = ['#include <string>'] 2333101Sstever@eecs.umich.edu swig_predecls = ['%include "std_string.i"\n' + 2343101Sstever@eecs.umich.edu '%apply const std::string& {std::string *};'] 2355033Smilesck@eecs.umich.edu pass 2365475Snate@binkert.org 23713663Sandreas.sandberg@arm.com# superclass for "numeric" parameter values, to emulate math 23813663Sandreas.sandberg@arm.com# operations in a type-safe way. e.g., a Latency times an int returns 2395475Snate@binkert.org# a new Latency object. 24010380SAndrew.Bardsley@arm.comclass NumericParamValue(ParamValue): 24110380SAndrew.Bardsley@arm.com def __str__(self): 24210380SAndrew.Bardsley@arm.com return str(self.value) 2433101Sstever@eecs.umich.edu 2443101Sstever@eecs.umich.edu def __float__(self): 2453101Sstever@eecs.umich.edu return float(self.value) 2464762Snate@binkert.org 2474762Snate@binkert.org def __long__(self): 2484762Snate@binkert.org return long(self.value) 2493101Sstever@eecs.umich.edu 25012050Snikos.nikoleris@arm.com def __int__(self): 25112050Snikos.nikoleris@arm.com return int(self.value) 25212050Snikos.nikoleris@arm.com 2538459SAli.Saidi@ARM.com # hook for bounds checking 2548459SAli.Saidi@ARM.com def _check(self): 25512050Snikos.nikoleris@arm.com return 2563101Sstever@eecs.umich.edu 2577528Ssteve.reinhardt@amd.com def __mul__(self, other): 2587528Ssteve.reinhardt@amd.com newobj = self.__class__(self) 2597528Ssteve.reinhardt@amd.com newobj.value *= other 2607528Ssteve.reinhardt@amd.com newobj._check() 2617528Ssteve.reinhardt@amd.com return newobj 2627528Ssteve.reinhardt@amd.com 2633101Sstever@eecs.umich.edu __rmul__ = __mul__ 2647528Ssteve.reinhardt@amd.com 2657528Ssteve.reinhardt@amd.com def __div__(self, other): 2667528Ssteve.reinhardt@amd.com newobj = self.__class__(self) 2677528Ssteve.reinhardt@amd.com newobj.value /= other 2687528Ssteve.reinhardt@amd.com newobj._check() 2697528Ssteve.reinhardt@amd.com return newobj 2707528Ssteve.reinhardt@amd.com 2717528Ssteve.reinhardt@amd.com def __sub__(self, other): 2727528Ssteve.reinhardt@amd.com newobj = self.__class__(self) 2737528Ssteve.reinhardt@amd.com newobj.value -= other 2748321Ssteve.reinhardt@amd.com newobj._check() 27512194Sgabeblack@google.com return newobj 2767528Ssteve.reinhardt@amd.com 2777528Ssteve.reinhardt@amd.com# Metaclass for bounds-checked integer parameters. See CheckedInt. 2787528Ssteve.reinhardt@amd.comclass CheckedIntType(type): 2797528Ssteve.reinhardt@amd.com def __init__(cls, name, bases, dict): 2807528Ssteve.reinhardt@amd.com super(CheckedIntType, cls).__init__(name, bases, dict) 2817528Ssteve.reinhardt@amd.com 2827528Ssteve.reinhardt@amd.com # CheckedInt is an abstract base class, so we actually don't 2837528Ssteve.reinhardt@amd.com # want to do any processing on it... the rest of this code is 2847528Ssteve.reinhardt@amd.com # just for classes that derive from CheckedInt. 2857528Ssteve.reinhardt@amd.com if name == 'CheckedInt': 2867528Ssteve.reinhardt@amd.com return 2877528Ssteve.reinhardt@amd.com 2887528Ssteve.reinhardt@amd.com if not cls.cxx_predecls: 2893101Sstever@eecs.umich.edu # most derived types require this, so we just do it here once 2908664SAli.Saidi@ARM.com cls.cxx_predecls = ['#include "sim/host.hh"'] 2918664SAli.Saidi@ARM.com 2928664SAli.Saidi@ARM.com if not cls.swig_predecls: 2938664SAli.Saidi@ARM.com # most derived types require this, so we just do it here once 2948664SAli.Saidi@ARM.com cls.swig_predecls = ['%import "python/m5/swig/stdint.i"\n' + 2958664SAli.Saidi@ARM.com '%import "sim/host.hh"'] 2969953Sgeoffrey.blake@arm.com 2979953Sgeoffrey.blake@arm.com if not (hasattr(cls, 'min') and hasattr(cls, 'max')): 2989953Sgeoffrey.blake@arm.com if not (hasattr(cls, 'size') and hasattr(cls, 'unsigned')): 2999953Sgeoffrey.blake@arm.com panic("CheckedInt subclass %s must define either\n" \ 3009953Sgeoffrey.blake@arm.com " 'min' and 'max' or 'size' and 'unsigned'\n" \ 3019953Sgeoffrey.blake@arm.com % name); 3029953Sgeoffrey.blake@arm.com if cls.unsigned: 3039953Sgeoffrey.blake@arm.com cls.min = 0 3049953Sgeoffrey.blake@arm.com cls.max = 2 ** cls.size - 1 3059953Sgeoffrey.blake@arm.com else: 3069953Sgeoffrey.blake@arm.com cls.min = -(2 ** (cls.size - 1)) 3079953Sgeoffrey.blake@arm.com cls.max = (2 ** (cls.size - 1)) - 1 3089953Sgeoffrey.blake@arm.com 30910267SGeoffrey.Blake@arm.com# Abstract superclass for bounds-checked integer parameters. This 31010267SGeoffrey.Blake@arm.com# class is subclassed to generate parameter classes with specific 31110267SGeoffrey.Blake@arm.com# bounds. Initialization of the min and max bounds is done in the 31210267SGeoffrey.Blake@arm.com# metaclass CheckedIntType.__init__. 31310267SGeoffrey.Blake@arm.comclass CheckedInt(NumericParamValue): 31410267SGeoffrey.Blake@arm.com __metaclass__ = CheckedIntType 31510267SGeoffrey.Blake@arm.com 31612563Sgabeblack@google.com def _check(self): 31710267SGeoffrey.Blake@arm.com if not self.min <= self.value <= self.max: 31810267SGeoffrey.Blake@arm.com raise TypeError, 'Integer param out of bounds %d < %d < %d' % \ 31910267SGeoffrey.Blake@arm.com (self.min, self.value, self.max) 32010267SGeoffrey.Blake@arm.com 32110267SGeoffrey.Blake@arm.com def __init__(self, value): 32210267SGeoffrey.Blake@arm.com if isinstance(value, str): 32310267SGeoffrey.Blake@arm.com self.value = convert.toInteger(value) 32410267SGeoffrey.Blake@arm.com elif isinstance(value, (int, long, float, NumericParamValue)): 32510267SGeoffrey.Blake@arm.com self.value = long(value) 32610267SGeoffrey.Blake@arm.com else: 32710267SGeoffrey.Blake@arm.com raise TypeError, "Can't convert object of type %s to CheckedInt" \ 32810267SGeoffrey.Blake@arm.com % type(value).__name__ 3293101Sstever@eecs.umich.edu self._check() 3303101Sstever@eecs.umich.edu 3313101Sstever@eecs.umich.educlass Int(CheckedInt): cxx_type = 'int'; size = 32; unsigned = False 3323101Sstever@eecs.umich.educlass Unsigned(CheckedInt): cxx_type = 'unsigned'; size = 32; unsigned = True 3333101Sstever@eecs.umich.edu 3343101Sstever@eecs.umich.educlass Int8(CheckedInt): cxx_type = 'int8_t'; size = 8; unsigned = False 3353101Sstever@eecs.umich.educlass UInt8(CheckedInt): cxx_type = 'uint8_t'; size = 8; unsigned = True 33610364SGeoffrey.Blake@arm.comclass Int16(CheckedInt): cxx_type = 'int16_t'; size = 16; unsigned = False 33710364SGeoffrey.Blake@arm.comclass UInt16(CheckedInt): cxx_type = 'uint16_t'; size = 16; unsigned = True 33810364SGeoffrey.Blake@arm.comclass Int32(CheckedInt): cxx_type = 'int32_t'; size = 32; unsigned = False 33910364SGeoffrey.Blake@arm.comclass UInt32(CheckedInt): cxx_type = 'uint32_t'; size = 32; unsigned = True 3403101Sstever@eecs.umich.educlass Int64(CheckedInt): cxx_type = 'int64_t'; size = 64; unsigned = False 3414762Snate@binkert.orgclass UInt64(CheckedInt): cxx_type = 'uint64_t'; size = 64; unsigned = True 3424762Snate@binkert.org 3434762Snate@binkert.orgclass Counter(CheckedInt): cxx_type = 'Counter'; size = 64; unsigned = True 3444762Snate@binkert.orgclass Tick(CheckedInt): cxx_type = 'Tick'; size = 64; unsigned = True 3457528Ssteve.reinhardt@amd.comclass TcpPort(CheckedInt): cxx_type = 'uint16_t'; size = 16; unsigned = True 3464762Snate@binkert.orgclass UdpPort(CheckedInt): cxx_type = 'uint16_t'; size = 16; unsigned = True 3474762Snate@binkert.org 3484762Snate@binkert.orgclass Percent(CheckedInt): cxx_type = 'int'; min = 0; max = 100 34910267SGeoffrey.Blake@arm.com 35010267SGeoffrey.Blake@arm.comclass Float(ParamValue, float): 35110267SGeoffrey.Blake@arm.com pass 35210267SGeoffrey.Blake@arm.com 35310267SGeoffrey.Blake@arm.comclass MemorySize(CheckedInt): 35410267SGeoffrey.Blake@arm.com cxx_type = 'uint64_t' 35510267SGeoffrey.Blake@arm.com size = 64 35610267SGeoffrey.Blake@arm.com unsigned = True 35710267SGeoffrey.Blake@arm.com def __init__(self, value): 35810267SGeoffrey.Blake@arm.com if isinstance(value, MemorySize): 35910267SGeoffrey.Blake@arm.com self.value = value.value 36010267SGeoffrey.Blake@arm.com else: 36110267SGeoffrey.Blake@arm.com self.value = convert.toMemorySize(value) 36210267SGeoffrey.Blake@arm.com self._check() 36310267SGeoffrey.Blake@arm.com 36410267SGeoffrey.Blake@arm.comclass MemorySize32(CheckedInt): 36510267SGeoffrey.Blake@arm.com cxx_type = 'uint32_t' 36610267SGeoffrey.Blake@arm.com size = 32 36710267SGeoffrey.Blake@arm.com unsigned = True 36810267SGeoffrey.Blake@arm.com def __init__(self, value): 36910267SGeoffrey.Blake@arm.com if isinstance(value, MemorySize): 37010267SGeoffrey.Blake@arm.com self.value = value.value 37110267SGeoffrey.Blake@arm.com else: 37210267SGeoffrey.Blake@arm.com self.value = convert.toMemorySize(value) 37310267SGeoffrey.Blake@arm.com self._check() 37410267SGeoffrey.Blake@arm.com 37510364SGeoffrey.Blake@arm.comclass Addr(CheckedInt): 37610364SGeoffrey.Blake@arm.com cxx_type = 'Addr' 37710267SGeoffrey.Blake@arm.com cxx_predecls = ['#include "targetarch/isa_traits.hh"'] 37810267SGeoffrey.Blake@arm.com size = 64 37910267SGeoffrey.Blake@arm.com unsigned = True 38010267SGeoffrey.Blake@arm.com def __init__(self, value): 38110267SGeoffrey.Blake@arm.com if isinstance(value, Addr): 38210267SGeoffrey.Blake@arm.com self.value = value.value 3837673Snate@binkert.org else: 3847673Snate@binkert.org try: 3857673Snate@binkert.org self.value = convert.toMemorySize(value) 3863101Sstever@eecs.umich.edu except TypeError: 38711988Sandreas.sandberg@arm.com self.value = long(value) 38811988Sandreas.sandberg@arm.com self._check() 38911988Sandreas.sandberg@arm.com def __add__(self, other): 39011988Sandreas.sandberg@arm.com if isinstance(other, Addr): 3917673Snate@binkert.org return self.value + other.value 3927673Snate@binkert.org else: 3933101Sstever@eecs.umich.edu return self.value + other 3943101Sstever@eecs.umich.edu 3953101Sstever@eecs.umich.edu 3963101Sstever@eecs.umich.educlass MetaRange(type): 3973101Sstever@eecs.umich.edu def __init__(cls, name, bases, dict): 3983101Sstever@eecs.umich.edu super(MetaRange, cls).__init__(name, bases, dict) 3993101Sstever@eecs.umich.edu if name == 'Range': 4003101Sstever@eecs.umich.edu return 4013101Sstever@eecs.umich.edu cls.cxx_type = 'Range< %s >' % cls.type.cxx_type 4023101Sstever@eecs.umich.edu cls.cxx_predecls = \ 4033101Sstever@eecs.umich.edu ['#include "base/range.hh"'] + cls.type.cxx_predecls 4043101Sstever@eecs.umich.edu 4053101Sstever@eecs.umich.educlass Range(ParamValue): 4063101Sstever@eecs.umich.edu __metaclass__ = MetaRange 4073101Sstever@eecs.umich.edu type = Int # default; can be overridden in subclasses 4085033Smilesck@eecs.umich.edu def __init__(self, *args, **kwargs): 4095033Smilesck@eecs.umich.edu def handle_kwargs(self, kwargs): 4103101Sstever@eecs.umich.edu if 'end' in kwargs: 4113101Sstever@eecs.umich.edu self.second = self.type(kwargs.pop('end')) 4123101Sstever@eecs.umich.edu elif 'size' in kwargs: 4133101Sstever@eecs.umich.edu self.second = self.first + self.type(kwargs.pop('size')) - 1 4143101Sstever@eecs.umich.edu else: 4153101Sstever@eecs.umich.edu raise TypeError, "Either end or size must be specified" 4163101Sstever@eecs.umich.edu 4173101Sstever@eecs.umich.edu if len(args) == 0: 4183101Sstever@eecs.umich.edu self.first = self.type(kwargs.pop('start')) 4193101Sstever@eecs.umich.edu handle_kwargs(self, kwargs) 4203101Sstever@eecs.umich.edu 4213101Sstever@eecs.umich.edu elif len(args) == 1: 4223101Sstever@eecs.umich.edu if kwargs: 4233101Sstever@eecs.umich.edu self.first = self.type(args[0]) 4243101Sstever@eecs.umich.edu handle_kwargs(self, kwargs) 4253101Sstever@eecs.umich.edu elif isinstance(args[0], Range): 4263101Sstever@eecs.umich.edu self.first = self.type(args[0].first) 4273101Sstever@eecs.umich.edu self.second = self.type(args[0].second) 4283101Sstever@eecs.umich.edu else: 4293101Sstever@eecs.umich.edu self.first = self.type(0) 4303101Sstever@eecs.umich.edu self.second = self.type(args[0]) - 1 4313101Sstever@eecs.umich.edu 4323101Sstever@eecs.umich.edu elif len(args) == 2: 4333101Sstever@eecs.umich.edu self.first = self.type(args[0]) 4343101Sstever@eecs.umich.edu self.second = self.type(args[1]) 43510267SGeoffrey.Blake@arm.com else: 4367673Snate@binkert.org raise TypeError, "Too many arguments specified" 4377673Snate@binkert.org 4387673Snate@binkert.org if kwargs: 4397673Snate@binkert.org raise TypeError, "too many keywords: %s" % kwargs.keys() 4407673Snate@binkert.org 44110267SGeoffrey.Blake@arm.com def __str__(self): 44210267SGeoffrey.Blake@arm.com return '%s:%s' % (self.first, self.second) 44310267SGeoffrey.Blake@arm.com 44410267SGeoffrey.Blake@arm.comclass AddrRange(Range): 44510458Sandreas.hansson@arm.com type = Addr 44610458Sandreas.hansson@arm.com 44710458Sandreas.hansson@arm.comclass TickRange(Range): 44810458Sandreas.hansson@arm.com type = Tick 44910458Sandreas.hansson@arm.com 4504762Snate@binkert.org# Boolean parameter type. Python doesn't let you subclass bool, since 4514762Snate@binkert.org# it doesn't want to let you create multiple instances of True and 4523101Sstever@eecs.umich.edu# False. Thus this is a little more complicated than String. 4533101Sstever@eecs.umich.educlass Bool(ParamValue): 4543101Sstever@eecs.umich.edu cxx_type = 'bool' 4553101Sstever@eecs.umich.edu def __init__(self, value): 4563101Sstever@eecs.umich.edu try: 4573101Sstever@eecs.umich.edu self.value = convert.toBool(value) 4583101Sstever@eecs.umich.edu except TypeError: 4593101Sstever@eecs.umich.edu self.value = bool(value) 4603101Sstever@eecs.umich.edu 4613101Sstever@eecs.umich.edu def __str__(self): 4623101Sstever@eecs.umich.edu return str(self.value) 4633714Sstever@eecs.umich.edu 4643714Sstever@eecs.umich.edu def ini_str(self): 4653714Sstever@eecs.umich.edu if self.value: 4663714Sstever@eecs.umich.edu return 'true' 4673714Sstever@eecs.umich.edu return 'false' 4683714Sstever@eecs.umich.edu 4693101Sstever@eecs.umich.edudef IncEthernetAddr(addr, val = 1): 4703101Sstever@eecs.umich.edu bytes = map(lambda x: int(x, 16), addr.split(':')) 4713101Sstever@eecs.umich.edu bytes[5] += val 4723101Sstever@eecs.umich.edu for i in (5, 4, 3, 2, 1): 4733101Sstever@eecs.umich.edu val,rem = divmod(bytes[i], 256) 4743101Sstever@eecs.umich.edu bytes[i] = rem 4753101Sstever@eecs.umich.edu if val == 0: 4763101Sstever@eecs.umich.edu break 4773101Sstever@eecs.umich.edu bytes[i - 1] += val 4783101Sstever@eecs.umich.edu assert(bytes[0] <= 255) 4793101Sstever@eecs.umich.edu return ':'.join(map(lambda x: '%02x' % x, bytes)) 4803101Sstever@eecs.umich.edu 4813101Sstever@eecs.umich.edu_NextEthernetAddr = "00:90:00:00:00:01" 4823101Sstever@eecs.umich.edudef NextEthernetAddr(): 4833101Sstever@eecs.umich.edu global _NextEthernetAddr 4843101Sstever@eecs.umich.edu 4853101Sstever@eecs.umich.edu value = _NextEthernetAddr 4863101Sstever@eecs.umich.edu _NextEthernetAddr = IncEthernetAddr(_NextEthernetAddr, 1) 4873101Sstever@eecs.umich.edu return value 4883101Sstever@eecs.umich.edu 4893101Sstever@eecs.umich.educlass EthernetAddr(ParamValue): 4903101Sstever@eecs.umich.edu cxx_type = 'Net::EthAddr' 4913101Sstever@eecs.umich.edu cxx_predecls = ['#include "base/inet.hh"'] 4923101Sstever@eecs.umich.edu swig_predecls = ['class Net::EthAddr;'] 49310380SAndrew.Bardsley@arm.com def __init__(self, value): 49410380SAndrew.Bardsley@arm.com if value == NextEthernetAddr: 49510380SAndrew.Bardsley@arm.com self.value = value 49610458Sandreas.hansson@arm.com return 49710458Sandreas.hansson@arm.com 49810458Sandreas.hansson@arm.com if not isinstance(value, str): 49910458Sandreas.hansson@arm.com raise TypeError, "expected an ethernet address and didn't get one" 50010458Sandreas.hansson@arm.com 50110458Sandreas.hansson@arm.com bytes = value.split(':') 50210458Sandreas.hansson@arm.com if len(bytes) != 6: 50310458Sandreas.hansson@arm.com raise TypeError, 'invalid ethernet address %s' % value 50410458Sandreas.hansson@arm.com 50510458Sandreas.hansson@arm.com for byte in bytes: 50610458Sandreas.hansson@arm.com if not 0 <= int(byte) <= 256: 50710458Sandreas.hansson@arm.com raise TypeError, 'invalid ethernet address %s' % value 50810458Sandreas.hansson@arm.com 5093101Sstever@eecs.umich.edu self.value = value 5105033Smilesck@eecs.umich.edu 5113101Sstever@eecs.umich.edu def unproxy(self, base): 5123101Sstever@eecs.umich.edu if self.value == NextEthernetAddr: 5133101Sstever@eecs.umich.edu return EthernetAddr(self.value()) 5143101Sstever@eecs.umich.edu return self 5153101Sstever@eecs.umich.edu 5163101Sstever@eecs.umich.edu def ini_str(self): 5173101Sstever@eecs.umich.edu return self.value 5183101Sstever@eecs.umich.edu 5193101Sstever@eecs.umich.edutime_formats = [ "%a %b %d %H:%M:%S %Z %Y", 5203101Sstever@eecs.umich.edu "%a %b %d %H:%M:%S %Z %Y", 5213101Sstever@eecs.umich.edu "%Y/%m/%d %H:%M:%S", 5223101Sstever@eecs.umich.edu "%Y/%m/%d %H:%M", 5235822Ssaidi@eecs.umich.edu "%Y/%m/%d", 5245822Ssaidi@eecs.umich.edu "%m/%d/%Y %H:%M:%S", 5253101Sstever@eecs.umich.edu "%m/%d/%Y %H:%M", 5263101Sstever@eecs.umich.edu "%m/%d/%Y", 5273101Sstever@eecs.umich.edu "%m/%d/%y %H:%M:%S", 5283101Sstever@eecs.umich.edu "%m/%d/%y %H:%M", 5293101Sstever@eecs.umich.edu "%m/%d/%y"] 5303101Sstever@eecs.umich.edu 5313101Sstever@eecs.umich.edu 5323101Sstever@eecs.umich.edudef parse_time(value): 5333101Sstever@eecs.umich.edu from time import gmtime, strptime, struct_time, time 5343101Sstever@eecs.umich.edu from datetime import datetime, date 5353101Sstever@eecs.umich.edu 5363101Sstever@eecs.umich.edu if isinstance(value, struct_time): 5373101Sstever@eecs.umich.edu return value 53810267SGeoffrey.Blake@arm.com 5393101Sstever@eecs.umich.edu if isinstance(value, (int, long)): 5403101Sstever@eecs.umich.edu return gmtime(value) 5413101Sstever@eecs.umich.edu 54213663Sandreas.sandberg@arm.com if isinstance(value, (datetime, date)): 54313663Sandreas.sandberg@arm.com return value.timetuple() 5443101Sstever@eecs.umich.edu 5453101Sstever@eecs.umich.edu if isinstance(value, str): 5463101Sstever@eecs.umich.edu if value in ('Now', 'Today'): 5473102Sstever@eecs.umich.edu return time.gmtime(time.time()) 5483714Sstever@eecs.umich.edu 5493101Sstever@eecs.umich.edu for format in time_formats: 5503714Sstever@eecs.umich.edu try: 55113663Sandreas.sandberg@arm.com return strptime(value, format) 55213663Sandreas.sandberg@arm.com except ValueError: 5533101Sstever@eecs.umich.edu pass 5543101Sstever@eecs.umich.edu 55510267SGeoffrey.Blake@arm.com raise ValueError, "Could not parse '%s' as a time" % value 55610267SGeoffrey.Blake@arm.com 55710267SGeoffrey.Blake@arm.comclass Time(ParamValue): 55810267SGeoffrey.Blake@arm.com cxx_type = 'time_t' 5597673Snate@binkert.org def __init__(self, value): 5607673Snate@binkert.org self.value = parse_time(value) 5617673Snate@binkert.org 5627673Snate@binkert.org def __str__(self): 5637673Snate@binkert.org tm = self.value 5644762Snate@binkert.org return ' '.join([ str(tm[i]) for i in xrange(8)]) 5654762Snate@binkert.org 5664762Snate@binkert.org def ini_str(self): 5673101Sstever@eecs.umich.edu return str(self) 5683101Sstever@eecs.umich.edu 5693101Sstever@eecs.umich.edu# Enumerated types are a little more complex. The user specifies the 5703101Sstever@eecs.umich.edu# type as Enum(foo) where foo is either a list or dictionary of 5713101Sstever@eecs.umich.edu# alternatives (typically strings, but not necessarily so). (In the 5723101Sstever@eecs.umich.edu# long run, the integer value of the parameter will be the list index 5733101Sstever@eecs.umich.edu# or the corresponding dictionary value. For now, since we only check 5743101Sstever@eecs.umich.edu# that the alternative is valid and then spit it into a .ini file, 5753101Sstever@eecs.umich.edu# there's not much point in using the dictionary.) 5763101Sstever@eecs.umich.edu 5773101Sstever@eecs.umich.edu# What Enum() must do is generate a new type encapsulating the 5783101Sstever@eecs.umich.edu# provided list/dictionary so that specific values of the parameter 5793101Sstever@eecs.umich.edu# can be instances of that type. We define two hidden internal 5803101Sstever@eecs.umich.edu# classes (_ListEnum and _DictEnum) to serve as base classes, then 5813101Sstever@eecs.umich.edu# derive the new type from the appropriate base class on the fly. 5823101Sstever@eecs.umich.edu 5833101Sstever@eecs.umich.edu 5843101Sstever@eecs.umich.edu# Metaclass for Enum types 5853101Sstever@eecs.umich.educlass MetaEnum(type): 5869184Sandreas.hansson@arm.com def __init__(cls, name, bases, init_dict): 5879184Sandreas.hansson@arm.com if init_dict.has_key('map'): 5889184Sandreas.hansson@arm.com if not isinstance(cls.map, dict): 5899184Sandreas.hansson@arm.com raise TypeError, "Enum-derived class attribute 'map' " \ 5909184Sandreas.hansson@arm.com "must be of type dict" 5919184Sandreas.hansson@arm.com # build list of value strings from map 59211802Sandreas.sandberg@arm.com cls.vals = cls.map.keys() 5939184Sandreas.hansson@arm.com cls.vals.sort() 5949184Sandreas.hansson@arm.com elif init_dict.has_key('vals'): 59510458Sandreas.hansson@arm.com if not isinstance(cls.vals, list): 59610458Sandreas.hansson@arm.com raise TypeError, "Enum-derived class attribute 'vals' " \ 59710458Sandreas.hansson@arm.com "must be of type list" 59810458Sandreas.hansson@arm.com # build string->value map from vals sequence 59910458Sandreas.hansson@arm.com cls.map = {} 60010458Sandreas.hansson@arm.com for idx,val in enumerate(cls.vals): 60110458Sandreas.hansson@arm.com cls.map[val] = idx 60210458Sandreas.hansson@arm.com else: 60310458Sandreas.hansson@arm.com raise TypeError, "Enum-derived class must define "\ 60410458Sandreas.hansson@arm.com "attribute 'map' or 'vals'" 60510458Sandreas.hansson@arm.com 60610458Sandreas.hansson@arm.com cls.cxx_type = name + '::Enum' 60710458Sandreas.hansson@arm.com 60810458Sandreas.hansson@arm.com super(MetaEnum, cls).__init__(name, bases, init_dict) 6093101Sstever@eecs.umich.edu 6104446Sbinkertn@umich.edu # Generate C++ class declaration for this enum type. 61110668SGeoffrey.Blake@arm.com # Note that we wrap the enum in a class/struct to act as a namespace, 6123101Sstever@eecs.umich.edu # so that the enum strings can be brief w/o worrying about collisions. 6135468Snate@binkert.org def cxx_decl(cls): 61410267SGeoffrey.Blake@arm.com s = 'struct %s {\n enum Enum {\n ' % cls.__name__ 6155468Snate@binkert.org s += ',\n '.join(['%s = %d' % (v,cls.map[v]) for v in cls.vals]) 6165468Snate@binkert.org s += '\n };\n};\n' 61713663Sandreas.sandberg@arm.com return s 61813663Sandreas.sandberg@arm.com 6195468Snate@binkert.org# Base class for enum types. 62010267SGeoffrey.Blake@arm.comclass Enum(ParamValue): 62110267SGeoffrey.Blake@arm.com __metaclass__ = MetaEnum 62210267SGeoffrey.Blake@arm.com vals = [] 62310267SGeoffrey.Blake@arm.com 6244762Snate@binkert.org def __init__(self, value): 6254762Snate@binkert.org if value not in self.map: 6264762Snate@binkert.org raise TypeError, "Enum param got bad value '%s' (not in %s)" \ 62710380SAndrew.Bardsley@arm.com % (value, self.vals) 62810380SAndrew.Bardsley@arm.com self.value = value 62910380SAndrew.Bardsley@arm.com 63010458Sandreas.hansson@arm.com def __str__(self): 63110458Sandreas.hansson@arm.com return self.value 63210458Sandreas.hansson@arm.com 63310458Sandreas.hansson@arm.com# how big does a rounding error need to be before we warn about it? 63410458Sandreas.hansson@arm.comfrequency_tolerance = 0.001 # 0.1% 63510458Sandreas.hansson@arm.com 63610458Sandreas.hansson@arm.comclass TickParamValue(NumericParamValue): 63710458Sandreas.hansson@arm.com cxx_type = 'Tick' 6383101Sstever@eecs.umich.edu cxx_predecls = ['#include "sim/host.hh"'] 6393101Sstever@eecs.umich.edu swig_predecls = ['%import "python/m5/swig/stdint.i"\n' + 64010267SGeoffrey.Blake@arm.com '%import "sim/host.hh"'] 6413101Sstever@eecs.umich.edu 6423101Sstever@eecs.umich.educlass Latency(TickParamValue): 6433101Sstever@eecs.umich.edu def __init__(self, value): 6443101Sstever@eecs.umich.edu if isinstance(value, (Latency, Clock)): 6453101Sstever@eecs.umich.edu self.ticks = value.ticks 6463101Sstever@eecs.umich.edu self.value = value.value 6473102Sstever@eecs.umich.edu elif isinstance(value, Frequency): 6483101Sstever@eecs.umich.edu self.ticks = value.ticks 6493101Sstever@eecs.umich.edu self.value = 1.0 / value.value 6503101Sstever@eecs.umich.edu elif value.endswith('t'): 6514168Sbinkertn@umich.edu self.ticks = True 65210267SGeoffrey.Blake@arm.com self.value = int(value[:-1]) 6533101Sstever@eecs.umich.edu else: 6543101Sstever@eecs.umich.edu self.ticks = False 6553101Sstever@eecs.umich.edu self.value = convert.toLatency(value) 6563101Sstever@eecs.umich.edu 6573101Sstever@eecs.umich.edu def __getattr__(self, attr): 6583101Sstever@eecs.umich.edu if attr in ('latency', 'period'): 6593102Sstever@eecs.umich.edu return self 6603101Sstever@eecs.umich.edu if attr == 'frequency': 6613101Sstever@eecs.umich.edu return Frequency(self) 6623101Sstever@eecs.umich.edu raise AttributeError, "Latency object has no attribute '%s'" % attr 6633101Sstever@eecs.umich.edu 6643101Sstever@eecs.umich.edu # convert latency to ticks 6653101Sstever@eecs.umich.edu def ini_str(self): 6663101Sstever@eecs.umich.edu if self.ticks or self.value == 0: 6673101Sstever@eecs.umich.edu return '%d' % self.value 6683101Sstever@eecs.umich.edu else: 6693101Sstever@eecs.umich.edu return '%d' % (ticks.fromSeconds(self.value)) 6703101Sstever@eecs.umich.edu 67110317Smitch.hayenga@arm.comclass Frequency(TickParamValue): 67210317Smitch.hayenga@arm.com def __init__(self, value): 67310317Smitch.hayenga@arm.com if isinstance(value, (Latency, Clock)): 67410317Smitch.hayenga@arm.com if value.value == 0: 67510317Smitch.hayenga@arm.com self.value = 0 6763102Sstever@eecs.umich.edu else: 67710317Smitch.hayenga@arm.com self.value = 1.0 / value.value 67810317Smitch.hayenga@arm.com self.ticks = value.ticks 67910317Smitch.hayenga@arm.com elif isinstance(value, Frequency): 68010317Smitch.hayenga@arm.com self.value = value.value 68110317Smitch.hayenga@arm.com self.ticks = value.ticks 6823101Sstever@eecs.umich.edu else: 6833584Ssaidi@eecs.umich.edu self.ticks = False 6843584Ssaidi@eecs.umich.edu self.value = convert.toFrequency(value) 6853584Ssaidi@eecs.umich.edu 6863584Ssaidi@eecs.umich.edu def __getattr__(self, attr): 6873584Ssaidi@eecs.umich.edu if attr == 'frequency': 68810267SGeoffrey.Blake@arm.com return self 68910267SGeoffrey.Blake@arm.com if attr in ('latency', 'period'): 69010267SGeoffrey.Blake@arm.com return Latency(self) 69110267SGeoffrey.Blake@arm.com raise AttributeError, "Frequency object has no attribute '%s'" % attr 69210267SGeoffrey.Blake@arm.com 69310267SGeoffrey.Blake@arm.com # convert latency to ticks 6943101Sstever@eecs.umich.edu def ini_str(self): 6959232Sandreas.hansson@arm.com if self.ticks or self.value == 0: 6969235Sandreas.hansson@arm.com return '%d' % self.value 6973101Sstever@eecs.umich.edu else: 6983101Sstever@eecs.umich.edu return '%d' % (ticks.fromSeconds(1.0 / self.value)) 69910676Sandreas.hansson@arm.com 7009411Sandreas.hansson@arm.com# A generic frequency and/or Latency value. Value is stored as a latency, 70110676Sandreas.hansson@arm.com# but to avoid ambiguity this object does not support numeric ops (* or /). 7029411Sandreas.hansson@arm.com# An explicit conversion to a Latency or Frequency must be made first. 7039411Sandreas.hansson@arm.comclass Clock(ParamValue): 7049411Sandreas.hansson@arm.com cxx_type = 'Tick' 7053101Sstever@eecs.umich.edu cxx_predecls = ['#include "sim/host.hh"'] 7069411Sandreas.hansson@arm.com swig_predecls = ['%import "python/m5/swig/stdint.i"\n' + 7079411Sandreas.hansson@arm.com '%import "sim/host.hh"'] 7089411Sandreas.hansson@arm.com def __init__(self, value): 7093101Sstever@eecs.umich.edu if isinstance(value, (Latency, Clock)): 7109232Sandreas.hansson@arm.com self.ticks = value.ticks 7113101Sstever@eecs.umich.edu self.value = value.value 7129232Sandreas.hansson@arm.com elif isinstance(value, Frequency): 7133101Sstever@eecs.umich.edu self.ticks = value.ticks 71413663Sandreas.sandberg@arm.com self.value = 1.0 / value.value 7153101Sstever@eecs.umich.edu elif value.endswith('t'): 7169411Sandreas.hansson@arm.com self.ticks = True 7179411Sandreas.hansson@arm.com self.value = int(value[:-1]) 7189411Sandreas.hansson@arm.com else: 71910676Sandreas.hansson@arm.com self.ticks = False 72010676Sandreas.hansson@arm.com self.value = convert.anyToLatency(value) 7219411Sandreas.hansson@arm.com 7229411Sandreas.hansson@arm.com def __getattr__(self, attr): 7239411Sandreas.hansson@arm.com if attr == 'frequency': 7249411Sandreas.hansson@arm.com return Frequency(self) 7259411Sandreas.hansson@arm.com if attr in ('latency', 'period'): 7263101Sstever@eecs.umich.edu return Latency(self) 7279232Sandreas.hansson@arm.com raise AttributeError, "Frequency object has no attribute '%s'" % attr 7283101Sstever@eecs.umich.edu 7293101Sstever@eecs.umich.edu def ini_str(self): 7303101Sstever@eecs.umich.edu return self.period.ini_str() 7313101Sstever@eecs.umich.edu 7329232Sandreas.hansson@arm.comclass NetworkBandwidth(float,ParamValue): 7333101Sstever@eecs.umich.edu cxx_type = 'float' 7345219Ssaidi@eecs.umich.edu def __new__(cls, value): 7359232Sandreas.hansson@arm.com # convert to bits per second 7369232Sandreas.hansson@arm.com val = convert.toNetworkBandwidth(value) 7373101Sstever@eecs.umich.edu return super(cls, NetworkBandwidth).__new__(cls, val) 7389232Sandreas.hansson@arm.com 7399232Sandreas.hansson@arm.com def __str__(self): 7403101Sstever@eecs.umich.edu return str(self.val) 7413101Sstever@eecs.umich.edu 7429232Sandreas.hansson@arm.com def ini_str(self): 7439232Sandreas.hansson@arm.com # convert to seconds per byte 7443101Sstever@eecs.umich.edu value = 8.0 / float(self) 74513663Sandreas.sandberg@arm.com # convert to ticks per byte 7463101Sstever@eecs.umich.edu return '%f' % (ticks.fromSeconds(value)) 7473101Sstever@eecs.umich.edu 74813663Sandreas.sandberg@arm.comclass MemoryBandwidth(float,ParamValue): 7493101Sstever@eecs.umich.edu cxx_type = 'float' 7503101Sstever@eecs.umich.edu def __new__(self, value): 75111620SMatthew.Poremba@amd.com # we want the number of ticks per byte of data 75211620SMatthew.Poremba@amd.com val = convert.toMemoryBandwidth(value) 75311620SMatthew.Poremba@amd.com return super(cls, MemoryBandwidth).__new__(cls, val) 7549232Sandreas.hansson@arm.com 7559232Sandreas.hansson@arm.com def __str__(self): 7569411Sandreas.hansson@arm.com return str(self.val) 7579411Sandreas.hansson@arm.com 7583101Sstever@eecs.umich.edu def ini_str(self): 7597673Snate@binkert.org # convert to seconds per byte 7607673Snate@binkert.org value = 1.0 / float(self) 7619232Sandreas.hansson@arm.com # convert to ticks per byte 7629235Sandreas.hansson@arm.com return '%f' % (ticks.fromSeconds(value)) 7637675Snate@binkert.org 7647675Snate@binkert.org# 76511988Sandreas.sandberg@arm.com# "Constants"... handy aliases for various values. 76611988Sandreas.sandberg@arm.com# 76711988Sandreas.sandberg@arm.com 76811988Sandreas.sandberg@arm.com# Special class for NULL pointers. Note the special check in 76911988Sandreas.sandberg@arm.com# make_param_value() above that lets these be assigned where a 77010458Sandreas.hansson@arm.com# SimObject is required. 77110458Sandreas.hansson@arm.com# only one copy of a particular node 77210458Sandreas.hansson@arm.comclass NullSimObject(object): 77310458Sandreas.hansson@arm.com __metaclass__ = Singleton 77410458Sandreas.hansson@arm.com 77511620SMatthew.Poremba@amd.com def __call__(cls): 77611620SMatthew.Poremba@amd.com return cls 77710458Sandreas.hansson@arm.com 77810458Sandreas.hansson@arm.com def _instantiate(self, parent = None, path = ''): 77910458Sandreas.hansson@arm.com pass 78010458Sandreas.hansson@arm.com 78110458Sandreas.hansson@arm.com def ini_str(self): 78211620SMatthew.Poremba@amd.com return 'Null' 78311620SMatthew.Poremba@amd.com 78411620SMatthew.Poremba@amd.com def unproxy(self, base): 78511620SMatthew.Poremba@amd.com return self 78611620SMatthew.Poremba@amd.com 78711620SMatthew.Poremba@amd.com def set_path(self, parent, name): 78811620SMatthew.Poremba@amd.com pass 78911620SMatthew.Poremba@amd.com def __str__(self): 79011620SMatthew.Poremba@amd.com return 'Null' 79111620SMatthew.Poremba@amd.com 79210458Sandreas.hansson@arm.com# The only instance you'll ever need... 79310458Sandreas.hansson@arm.comNULL = NullSimObject() 79410458Sandreas.hansson@arm.com 79511620SMatthew.Poremba@amd.comdef isNullPointer(value): 79611620SMatthew.Poremba@amd.com return isinstance(value, NullSimObject) 79710458Sandreas.hansson@arm.com 79810458Sandreas.hansson@arm.com# Some memory range specifications use this as a default upper bound. 7994762Snate@binkert.orgMaxAddr = Addr.max 80011991Sandreas.sandberg@arm.comMaxTick = Tick.max 80111802Sandreas.sandberg@arm.comAllMemory = AddrRange(0, MaxAddr) 8024762Snate@binkert.org 8039411Sandreas.hansson@arm.com 80410676Sandreas.hansson@arm.com##################################################################### 80510676Sandreas.hansson@arm.com# 8063101Sstever@eecs.umich.edu# Port objects 8073101Sstever@eecs.umich.edu# 8083101Sstever@eecs.umich.edu# Ports are used to interconnect objects in the memory system. 8093101Sstever@eecs.umich.edu# 8103101Sstever@eecs.umich.edu##################################################################### 8113101Sstever@eecs.umich.edu 81210267SGeoffrey.Blake@arm.com# Port reference: encapsulates a reference to a particular port on a 81310267SGeoffrey.Blake@arm.com# particular SimObject. 8143101Sstever@eecs.umich.educlass PortRef(object): 8153101Sstever@eecs.umich.edu def __init__(self, simobj, name): 8163102Sstever@eecs.umich.edu assert(isSimObject(simobj) or isSimObjectClass(simobj)) 8173101Sstever@eecs.umich.edu self.simobj = simobj 8183101Sstever@eecs.umich.edu self.name = name 8193101Sstever@eecs.umich.edu self.peer = None # not associated with another port yet 82010267SGeoffrey.Blake@arm.com self.ccConnected = False # C++ port connection done? 82110267SGeoffrey.Blake@arm.com self.index = -1 # always -1 for non-vector ports 82210267SGeoffrey.Blake@arm.com 82310267SGeoffrey.Blake@arm.com def __str__(self): 8244762Snate@binkert.org return '%s.%s' % (self.simobj, self.name) 8254762Snate@binkert.org 8264762Snate@binkert.org # for config.ini, print peer's name (not ours) 8273101Sstever@eecs.umich.edu def ini_str(self): 8283101Sstever@eecs.umich.edu return str(self.peer) 8293101Sstever@eecs.umich.edu 8308934SBrad.Beckmann@amd.com def __getattr__(self, attr): 8318934SBrad.Beckmann@amd.com if attr == 'peerObj': 83213697Sandreas.sandberg@arm.com # shorthand for proxies 8338934SBrad.Beckmann@amd.com return self.peer.simobj 8348934SBrad.Beckmann@amd.com raise AttributeError, "'%s' object has no attribute '%s'" % \ 83513697Sandreas.sandberg@arm.com (self.__class__.__name__, attr) 83613697Sandreas.sandberg@arm.com 83713697Sandreas.sandberg@arm.com # Full connection is symmetric (both ways). Called via 8383101Sstever@eecs.umich.edu # SimObject.__setattr__ as a result of a port assignment, e.g., 8393101Sstever@eecs.umich.edu # "obj1.portA = obj2.portB", or via VectorPortElementRef.__setitem__, 8403101Sstever@eecs.umich.edu # e.g., "obj1.portA[3] = obj2.portB". 8413101Sstever@eecs.umich.edu def connect(self, other): 8423101Sstever@eecs.umich.edu if isinstance(other, VectorPortRef): 84310380SAndrew.Bardsley@arm.com # reference to plain VectorPort is implicit append 84410380SAndrew.Bardsley@arm.com other = other._get_next() 84510380SAndrew.Bardsley@arm.com if self.peer and not proxy.isproxy(self.peer): 84610458Sandreas.hansson@arm.com print "warning: overwriting port", self, \ 84710458Sandreas.hansson@arm.com "value", self.peer, "with", other 84810458Sandreas.hansson@arm.com self.peer = other 84910458Sandreas.hansson@arm.com if proxy.isproxy(other): 85010458Sandreas.hansson@arm.com other.set_param_desc(PortParamDesc()) 85110458Sandreas.hansson@arm.com elif isinstance(other, PortRef): 85210458Sandreas.hansson@arm.com if other.peer is not self: 85310458Sandreas.hansson@arm.com other.connect(self) 85410458Sandreas.hansson@arm.com else: 85510458Sandreas.hansson@arm.com raise TypeError, \ 8563101Sstever@eecs.umich.edu "assigning non-port reference '%s' to port '%s'" \ 8573101Sstever@eecs.umich.edu % (other, self) 8583101Sstever@eecs.umich.edu 8593101Sstever@eecs.umich.edu def clone(self, simobj, memo): 8603101Sstever@eecs.umich.edu if memo.has_key(self): 8613101Sstever@eecs.umich.edu return memo[self] 8623101Sstever@eecs.umich.edu newRef = copy.copy(self) 8633101Sstever@eecs.umich.edu memo[self] = newRef 8643101Sstever@eecs.umich.edu newRef.simobj = simobj 8653101Sstever@eecs.umich.edu assert(isSimObject(newRef.simobj)) 8663101Sstever@eecs.umich.edu if self.peer and not proxy.isproxy(self.peer): 8673101Sstever@eecs.umich.edu peerObj = self.peer.simobj(_memo=memo) 8684380Sbinkertn@umich.edu newRef.peer = self.peer.clone(peerObj, memo) 8694380Sbinkertn@umich.edu assert(not isinstance(newRef.peer, VectorPortRef)) 8704380Sbinkertn@umich.edu return newRef 8713101Sstever@eecs.umich.edu 8724380Sbinkertn@umich.edu def unproxy(self, simobj): 8734380Sbinkertn@umich.edu assert(simobj is self.simobj) 8744380Sbinkertn@umich.edu if proxy.isproxy(self.peer): 8753101Sstever@eecs.umich.edu try: 8763101Sstever@eecs.umich.edu realPeer = self.peer.unproxy(self.simobj) 8773101Sstever@eecs.umich.edu except: 87810267SGeoffrey.Blake@arm.com print "Error in unproxying port '%s' of %s" % \ 87910267SGeoffrey.Blake@arm.com (self.name, self.simobj.path()) 8807673Snate@binkert.org raise 8817673Snate@binkert.org self.connect(realPeer) 8827673Snate@binkert.org 8837673Snate@binkert.org # Call C++ to create corresponding port connection between C++ objects 8847673Snate@binkert.org def ccConnect(self): 8853101Sstever@eecs.umich.edu if self.ccConnected: # already done this 8863101Sstever@eecs.umich.edu return 8873101Sstever@eecs.umich.edu peer = self.peer 8883101Sstever@eecs.umich.edu internal.sim_object.connectPorts(self.simobj.getCCObject(), self.name, 8893101Sstever@eecs.umich.edu self.index, peer.simobj.getCCObject(), peer.name, peer.index) 8903101Sstever@eecs.umich.edu self.ccConnected = True 89113663Sandreas.sandberg@arm.com peer.ccConnected = True 8923101Sstever@eecs.umich.edu 8933101Sstever@eecs.umich.edu# A reference to an individual element of a VectorPort... much like a 8943101Sstever@eecs.umich.edu# PortRef, but has an index. 89513663Sandreas.sandberg@arm.comclass VectorPortElementRef(PortRef): 8963101Sstever@eecs.umich.edu def __init__(self, simobj, name, index): 8973101Sstever@eecs.umich.edu PortRef.__init__(self, simobj, name) 8989941SGeoffrey.Blake@arm.com self.index = index 89913663Sandreas.sandberg@arm.com 9003101Sstever@eecs.umich.edu def __str__(self): 9013101Sstever@eecs.umich.edu return '%s.%s[%d]' % (self.simobj, self.name, self.index) 9023101Sstever@eecs.umich.edu 90310267SGeoffrey.Blake@arm.com# A reference to a complete vector-valued port (not just a single element). 90410267SGeoffrey.Blake@arm.com# Can be indexed to retrieve individual VectorPortElementRef instances. 90510267SGeoffrey.Blake@arm.comclass VectorPortRef(object): 90610267SGeoffrey.Blake@arm.com def __init__(self, simobj, name): 9073101Sstever@eecs.umich.edu assert(isSimObject(simobj) or isSimObjectClass(simobj)) 9083101Sstever@eecs.umich.edu self.simobj = simobj 9094380Sbinkertn@umich.edu self.name = name 9103101Sstever@eecs.umich.edu self.elements = [] 9113101Sstever@eecs.umich.edu 9124762Snate@binkert.org def __str__(self): 91311988Sandreas.sandberg@arm.com return '%s.%s[:]' % (self.simobj, self.name) 9144762Snate@binkert.org 9154762Snate@binkert.org # for config.ini, print peer's name (not ours) 91611228SAndrew.Bardsley@arm.com def ini_str(self): 91711228SAndrew.Bardsley@arm.com return ' '.join([el.ini_str() for el in self.elements]) 91811228SAndrew.Bardsley@arm.com 9194380Sbinkertn@umich.edu def __getitem__(self, key): 9204380Sbinkertn@umich.edu if not isinstance(key, int): 9213101Sstever@eecs.umich.edu raise TypeError, "VectorPort index must be integer" 92210458Sandreas.hansson@arm.com if key >= len(self.elements): 92310458Sandreas.hansson@arm.com # need to extend list 92410458Sandreas.hansson@arm.com ext = [VectorPortElementRef(self.simobj, self.name, i) 92510458Sandreas.hansson@arm.com for i in range(len(self.elements), key+1)] 92610458Sandreas.hansson@arm.com self.elements.extend(ext) 9277777Sgblack@eecs.umich.edu return self.elements[key] 9287777Sgblack@eecs.umich.edu 9297777Sgblack@eecs.umich.edu def _get_next(self): 9307777Sgblack@eecs.umich.edu return self[len(self.elements)] 93110267SGeoffrey.Blake@arm.com 93210267SGeoffrey.Blake@arm.com def __setitem__(self, key, value): 9337777Sgblack@eecs.umich.edu if not isinstance(key, int): 9347777Sgblack@eecs.umich.edu raise TypeError, "VectorPort index must be integer" 9357777Sgblack@eecs.umich.edu self[key].connect(value) 9367777Sgblack@eecs.umich.edu 9377777Sgblack@eecs.umich.edu def connect(self, other): 9387777Sgblack@eecs.umich.edu if isinstance(other, (list, tuple)): 9397777Sgblack@eecs.umich.edu # Assign list of port refs to vector port. 9407777Sgblack@eecs.umich.edu # For now, append them... not sure if that's the right semantics 9417777Sgblack@eecs.umich.edu # or if it should replace the current vector. 9427777Sgblack@eecs.umich.edu for ref in other: 9437777Sgblack@eecs.umich.edu self._get_next().connect(ref) 9447777Sgblack@eecs.umich.edu else: 9457777Sgblack@eecs.umich.edu # scalar assignment to plain VectorPort is implicit append 9467777Sgblack@eecs.umich.edu self._get_next().connect(other) 9477777Sgblack@eecs.umich.edu 94810267SGeoffrey.Blake@arm.com def clone(self, simobj, memo): 94910267SGeoffrey.Blake@arm.com if memo.has_key(self): 95010267SGeoffrey.Blake@arm.com return memo[self] 95110267SGeoffrey.Blake@arm.com newRef = copy.copy(self) 9528579Ssteve.reinhardt@amd.com memo[self] = newRef 9538579Ssteve.reinhardt@amd.com newRef.simobj = simobj 9548579Ssteve.reinhardt@amd.com assert(isSimObject(newRef.simobj)) 9558579Ssteve.reinhardt@amd.com newRef.elements = [el.clone(simobj, memo) for el in self.elements] 9568579Ssteve.reinhardt@amd.com return newRef 9578579Ssteve.reinhardt@amd.com 9588579Ssteve.reinhardt@amd.com def unproxy(self, simobj): 9598579Ssteve.reinhardt@amd.com [el.unproxy(simobj) for el in self.elements] 9608579Ssteve.reinhardt@amd.com 9618579Ssteve.reinhardt@amd.com def ccConnect(self): 9628579Ssteve.reinhardt@amd.com [el.ccConnect() for el in self.elements] 9638579Ssteve.reinhardt@amd.com 9648579Ssteve.reinhardt@amd.com# Port description object. Like a ParamDesc object, this represents a 9658579Ssteve.reinhardt@amd.com# logical port in the SimObject class, not a particular port on a 9668579Ssteve.reinhardt@amd.com# SimObject instance. The latter are represented by PortRef objects. 9678579Ssteve.reinhardt@amd.comclass Port(object): 9688579Ssteve.reinhardt@amd.com # Port("description") or Port(default, "description") 9698579Ssteve.reinhardt@amd.com def __init__(self, *args): 9707777Sgblack@eecs.umich.edu if len(args) == 1: 9717777Sgblack@eecs.umich.edu self.desc = args[0] 97213663Sandreas.sandberg@arm.com elif len(args) == 2: 9737777Sgblack@eecs.umich.edu self.default = args[0] 9747777Sgblack@eecs.umich.edu self.desc = args[1] 97511988Sandreas.sandberg@arm.com else: 9767777Sgblack@eecs.umich.edu raise TypeError, 'wrong number of arguments' 9777777Sgblack@eecs.umich.edu # self.name is set by SimObject class on assignment 9787777Sgblack@eecs.umich.edu # e.g., pio_port = Port("blah") sets self.name to 'pio_port' 9797777Sgblack@eecs.umich.edu 9807777Sgblack@eecs.umich.edu # Generate a PortRef for this port on the given SimObject with the 9817777Sgblack@eecs.umich.edu # given name 9827777Sgblack@eecs.umich.edu def makeRef(self, simobj): 98310267SGeoffrey.Blake@arm.com return PortRef(simobj, self.name) 98410267SGeoffrey.Blake@arm.com 9857777Sgblack@eecs.umich.edu # Connect an instance of this port (on the given SimObject with 9867777Sgblack@eecs.umich.edu # the given name) with the port described by the supplied PortRef 9877777Sgblack@eecs.umich.edu def connect(self, simobj, ref): 9887777Sgblack@eecs.umich.edu self.makeRef(simobj).connect(ref) 9897777Sgblack@eecs.umich.edu 9907777Sgblack@eecs.umich.edu# VectorPort description object. Like Port, but represents a vector 9917777Sgblack@eecs.umich.edu# of connections (e.g., as on a Bus). 9927777Sgblack@eecs.umich.educlass VectorPort(Port): 9937777Sgblack@eecs.umich.edu def __init__(self, *args): 9947777Sgblack@eecs.umich.edu Port.__init__(self, *args) 9957777Sgblack@eecs.umich.edu self.isVec = True 9967777Sgblack@eecs.umich.edu 99713663Sandreas.sandberg@arm.com def makeRef(self, simobj): 9987777Sgblack@eecs.umich.edu return VectorPortRef(simobj, self.name) 9997777Sgblack@eecs.umich.edu 10007777Sgblack@eecs.umich.edu# 'Fake' ParamDesc for Port references to assign to the _pdesc slot of 10017777Sgblack@eecs.umich.edu# proxy objects (via set_param_desc()) so that proxy error messages 10027777Sgblack@eecs.umich.edu# make sense. 10037777Sgblack@eecs.umich.educlass PortParamDesc(object): 10047777Sgblack@eecs.umich.edu __metaclass__ = Singleton 10057777Sgblack@eecs.umich.edu 100613663Sandreas.sandberg@arm.com ptype_str = 'Port' 10077777Sgblack@eecs.umich.edu ptype = Port 10087777Sgblack@eecs.umich.edu 10097777Sgblack@eecs.umich.edu 10107777Sgblack@eecs.umich.edu__all__ = ['Param', 'VectorParam', 10117777Sgblack@eecs.umich.edu 'Enum', 'Bool', 'String', 'Float', 10127777Sgblack@eecs.umich.edu 'Int', 'Unsigned', 'Int8', 'UInt8', 'Int16', 'UInt16', 10137777Sgblack@eecs.umich.edu 'Int32', 'UInt32', 'Int64', 'UInt64', 10147777Sgblack@eecs.umich.edu 'Counter', 'Addr', 'Tick', 'Percent', 10157777Sgblack@eecs.umich.edu 'TcpPort', 'UdpPort', 'EthernetAddr', 10167777Sgblack@eecs.umich.edu 'MemorySize', 'MemorySize32', 10177777Sgblack@eecs.umich.edu 'Latency', 'Frequency', 'Clock', 10187777Sgblack@eecs.umich.edu 'NetworkBandwidth', 'MemoryBandwidth', 101913663Sandreas.sandberg@arm.com 'Range', 'AddrRange', 'TickRange', 10207777Sgblack@eecs.umich.edu 'MaxAddr', 'MaxTick', 'AllMemory', 10217777Sgblack@eecs.umich.edu 'Time', 102213663Sandreas.sandberg@arm.com 'NextEthernetAddr', 'NULL', 10237777Sgblack@eecs.umich.edu 'Port', 'VectorPort'] 10247777Sgblack@eecs.umich.edu 10257777Sgblack@eecs.umich.edu# see comment on imports at end of __init__.py. 102610267SGeoffrey.Blake@arm.comfrom SimObject import isSimObject, isSimObjectSequence, isSimObjectClass 102710267SGeoffrey.Blake@arm.comimport objects 102810267SGeoffrey.Blake@arm.comimport internal 102910267SGeoffrey.Blake@arm.com