params.py revision 5037:f7af52292c45
110355SGeoffrey.Blake@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 re 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.eduimport SimObject 593101Sstever@eecs.umich.edu 603101Sstever@eecs.umich.edudef isSimObject(*args, **kwargs): 613101Sstever@eecs.umich.edu return SimObject.isSimObject(*args, **kwargs) 623885Sbinkertn@umich.edu 633885Sbinkertn@umich.edudef isSimObjectSequence(*args, **kwargs): 644762Snate@binkert.org return SimObject.isSimObjectSequence(*args, **kwargs) 653885Sbinkertn@umich.edu 663885Sbinkertn@umich.edudef isSimObjectClass(*args, **kwargs): 677528Ssteve.reinhardt@amd.com return SimObject.isSimObjectClass(*args, **kwargs) 683885Sbinkertn@umich.edu 694380Sbinkertn@umich.eduallParams = {} 704167Sbinkertn@umich.edu 713102Sstever@eecs.umich.educlass MetaParamValue(type): 723101Sstever@eecs.umich.edu def __new__(mcls, name, bases, dct): 734762Snate@binkert.org cls = super(MetaParamValue, mcls).__new__(mcls, name, bases, dct) 744762Snate@binkert.org assert name not in allParams 754762Snate@binkert.org allParams[name] = cls 764762Snate@binkert.org return cls 774762Snate@binkert.org 784762Snate@binkert.org 794762Snate@binkert.org# Dummy base class to identify types that are legitimate for SimObject 804762Snate@binkert.org# parameters. 814762Snate@binkert.orgclass ParamValue(object): 825033Smilesck@eecs.umich.edu __metaclass__ = MetaParamValue 835033Smilesck@eecs.umich.edu 845033Smilesck@eecs.umich.edu cxx_predecls = [] 855033Smilesck@eecs.umich.edu swig_predecls = [] 865033Smilesck@eecs.umich.edu 875033Smilesck@eecs.umich.edu # default for printing to .ini file is regular string conversion. 885033Smilesck@eecs.umich.edu # will be overridden in some cases 895033Smilesck@eecs.umich.edu def ini_str(self): 905033Smilesck@eecs.umich.edu return str(self) 915033Smilesck@eecs.umich.edu 923101Sstever@eecs.umich.edu # allows us to blithely call unproxy() on things without checking 933101Sstever@eecs.umich.edu # if they're really proxies or not 943101Sstever@eecs.umich.edu def unproxy(self, base): 955033Smilesck@eecs.umich.edu return self 9610267SGeoffrey.Blake@arm.com 978596Ssteve.reinhardt@amd.com# Regular parameter description. 988596Ssteve.reinhardt@amd.comclass ParamDesc(object): 998596Ssteve.reinhardt@amd.com def __init__(self, ptype_str, ptype, *args, **kwargs): 1008596Ssteve.reinhardt@amd.com self.ptype_str = ptype_str 1017673Snate@binkert.org # remember ptype only if it is provided 1027673Snate@binkert.org if ptype != None: 1037673Snate@binkert.org self.ptype = ptype 1047673Snate@binkert.org 1058596Ssteve.reinhardt@amd.com if args: 1068596Ssteve.reinhardt@amd.com if len(args) == 1: 1078596Ssteve.reinhardt@amd.com self.desc = args[0] 1087673Snate@binkert.org elif len(args) == 2: 1097673Snate@binkert.org self.default = args[0] 1107673Snate@binkert.org self.desc = args[1] 1113101Sstever@eecs.umich.edu else: 1123101Sstever@eecs.umich.edu raise TypeError, 'too many arguments' 1133101Sstever@eecs.umich.edu 1143101Sstever@eecs.umich.edu if kwargs.has_key('desc'): 1153101Sstever@eecs.umich.edu assert(not hasattr(self, 'desc')) 1163101Sstever@eecs.umich.edu self.desc = kwargs['desc'] 11710380SAndrew.Bardsley@arm.com del kwargs['desc'] 11810380SAndrew.Bardsley@arm.com 11910380SAndrew.Bardsley@arm.com if kwargs.has_key('default'): 12010380SAndrew.Bardsley@arm.com assert(not hasattr(self, 'default')) 12110380SAndrew.Bardsley@arm.com self.default = kwargs['default'] 12210380SAndrew.Bardsley@arm.com del kwargs['default'] 12310458Sandreas.hansson@arm.com 12410458Sandreas.hansson@arm.com if kwargs: 12510458Sandreas.hansson@arm.com raise TypeError, 'extra unknown kwargs %s' % kwargs 12610458Sandreas.hansson@arm.com 12710458Sandreas.hansson@arm.com if not hasattr(self, 'desc'): 12810458Sandreas.hansson@arm.com raise TypeError, 'desc attribute missing' 12910458Sandreas.hansson@arm.com 13010458Sandreas.hansson@arm.com def __getattr__(self, attr): 13110458Sandreas.hansson@arm.com if attr == 'ptype': 13210458Sandreas.hansson@arm.com ptype = SimObject.allClasses[self.ptype_str] 13310458Sandreas.hansson@arm.com assert issubclass(ptype, SimObject.SimObject) 13410458Sandreas.hansson@arm.com self.ptype = ptype 1353101Sstever@eecs.umich.edu return ptype 1363101Sstever@eecs.umich.edu 1373101Sstever@eecs.umich.edu raise AttributeError, "'%s' object has no attribute '%s'" % \ 1383101Sstever@eecs.umich.edu (type(self).__name__, attr) 1393101Sstever@eecs.umich.edu 14010267SGeoffrey.Blake@arm.com def convert(self, value): 14110267SGeoffrey.Blake@arm.com if isinstance(value, proxy.BaseProxy): 14210267SGeoffrey.Blake@arm.com value.set_param_desc(self) 14310267SGeoffrey.Blake@arm.com return value 1443101Sstever@eecs.umich.edu if not hasattr(self, 'ptype') and isNullPointer(value): 1453101Sstever@eecs.umich.edu # deferred evaluation of SimObject; continue to defer if 1463101Sstever@eecs.umich.edu # we're just assigning a null pointer 1473101Sstever@eecs.umich.edu return value 1483101Sstever@eecs.umich.edu if isinstance(value, self.ptype): 1493101Sstever@eecs.umich.edu return value 1503101Sstever@eecs.umich.edu if isNullPointer(value) and isSimObjectClass(self.ptype): 1513101Sstever@eecs.umich.edu return value 1523101Sstever@eecs.umich.edu return self.ptype(value) 1533101Sstever@eecs.umich.edu 1543101Sstever@eecs.umich.edu def cxx_predecls(self): 1553101Sstever@eecs.umich.edu return self.ptype.cxx_predecls 1563101Sstever@eecs.umich.edu 1573101Sstever@eecs.umich.edu def swig_predecls(self): 1583101Sstever@eecs.umich.edu return self.ptype.swig_predecls 1593101Sstever@eecs.umich.edu 1603101Sstever@eecs.umich.edu def cxx_decl(self): 1613101Sstever@eecs.umich.edu return '%s %s;' % (self.ptype.cxx_type, self.name) 1623101Sstever@eecs.umich.edu 1633101Sstever@eecs.umich.edu# Vector-valued parameter description. Just like ParamDesc, except 1643101Sstever@eecs.umich.edu# that the value is a vector (list) of the specified type instead of a 1653101Sstever@eecs.umich.edu# single value. 1663101Sstever@eecs.umich.edu 1673101Sstever@eecs.umich.educlass VectorParamValue(list): 1683101Sstever@eecs.umich.edu __metaclass__ = MetaParamValue 1693101Sstever@eecs.umich.edu def ini_str(self): 1703101Sstever@eecs.umich.edu return ' '.join([v.ini_str() for v in self]) 1713101Sstever@eecs.umich.edu 1723101Sstever@eecs.umich.edu def getValue(self): 1733101Sstever@eecs.umich.edu return [ v.getValue() for v in self ] 1743101Sstever@eecs.umich.edu 1753101Sstever@eecs.umich.edu def unproxy(self, base): 1763101Sstever@eecs.umich.edu return [v.unproxy(base) for v in self] 1773101Sstever@eecs.umich.edu 1783101Sstever@eecs.umich.educlass SimObjVector(VectorParamValue): 1795033Smilesck@eecs.umich.edu def print_ini(self, ini_file): 1806656Snate@binkert.org for v in self: 1815033Smilesck@eecs.umich.edu v.print_ini(ini_file) 1825033Smilesck@eecs.umich.edu 1835033Smilesck@eecs.umich.educlass VectorParamDesc(ParamDesc): 1843101Sstever@eecs.umich.edu # Convert assigned value to appropriate type. If the RHS is not a 1853101Sstever@eecs.umich.edu # list or tuple, it generates a single-element list. 1863101Sstever@eecs.umich.edu def convert(self, value): 18710267SGeoffrey.Blake@arm.com if isinstance(value, (list, tuple)): 18810267SGeoffrey.Blake@arm.com # list: coerce each element into new list 18910267SGeoffrey.Blake@arm.com tmp_list = [ ParamDesc.convert(self, v) for v in value ] 19010267SGeoffrey.Blake@arm.com else: 19110267SGeoffrey.Blake@arm.com # singleton: coerce to a single-element list 19210267SGeoffrey.Blake@arm.com tmp_list = [ ParamDesc.convert(self, value) ] 19310267SGeoffrey.Blake@arm.com 19410267SGeoffrey.Blake@arm.com if isSimObjectSequence(tmp_list): 19510267SGeoffrey.Blake@arm.com return SimObjVector(tmp_list) 19610267SGeoffrey.Blake@arm.com else: 19710267SGeoffrey.Blake@arm.com return VectorParamValue(tmp_list) 19810267SGeoffrey.Blake@arm.com 19910267SGeoffrey.Blake@arm.com def swig_predecls(self): 2003101Sstever@eecs.umich.edu return ['%%include "%s_vptype.i"' % self.ptype_str] 2013101Sstever@eecs.umich.edu 2023101Sstever@eecs.umich.edu def swig_decl(self): 2033101Sstever@eecs.umich.edu cxx_type = re.sub('std::', '', self.ptype.cxx_type) 2043101Sstever@eecs.umich.edu vdecl = 'namespace std { %%template(vector_%s) vector< %s >; }' % \ 2053101Sstever@eecs.umich.edu (self.ptype_str, cxx_type) 2063101Sstever@eecs.umich.edu return ['%include "std_vector.i"'] + self.ptype.swig_predecls + [vdecl] 2073101Sstever@eecs.umich.edu 2083101Sstever@eecs.umich.edu def cxx_predecls(self): 2093101Sstever@eecs.umich.edu return ['#include <vector>'] + self.ptype.cxx_predecls 2103102Sstever@eecs.umich.edu 2113101Sstever@eecs.umich.edu def cxx_decl(self): 2123101Sstever@eecs.umich.edu return 'std::vector< %s > %s;' % (self.ptype.cxx_type, self.name) 2133101Sstever@eecs.umich.edu 21410267SGeoffrey.Blake@arm.comclass ParamFactory(object): 21510267SGeoffrey.Blake@arm.com def __init__(self, param_desc_class, ptype_str = None): 21610267SGeoffrey.Blake@arm.com self.param_desc_class = param_desc_class 21710267SGeoffrey.Blake@arm.com self.ptype_str = ptype_str 21810267SGeoffrey.Blake@arm.com 21910267SGeoffrey.Blake@arm.com def __getattr__(self, attr): 22010267SGeoffrey.Blake@arm.com if self.ptype_str: 2217673Snate@binkert.org attr = self.ptype_str + '.' + attr 2228607Sgblack@eecs.umich.edu return ParamFactory(self.param_desc_class, attr) 2237673Snate@binkert.org 2243101Sstever@eecs.umich.edu # E.g., Param.Int(5, "number of widgets") 2257673Snate@binkert.org def __call__(self, *args, **kwargs): 2267673Snate@binkert.org ptype = None 2273101Sstever@eecs.umich.edu try: 2287673Snate@binkert.org ptype = allParams[self.ptype_str] 2297673Snate@binkert.org except KeyError: 2303101Sstever@eecs.umich.edu # if name isn't defined yet, assume it's a SimObject, and 2313101Sstever@eecs.umich.edu # try to resolve it later 2323101Sstever@eecs.umich.edu pass 2333101Sstever@eecs.umich.edu return self.param_desc_class(self.ptype_str, ptype, *args, **kwargs) 2343101Sstever@eecs.umich.edu 2353101Sstever@eecs.umich.eduParam = ParamFactory(ParamDesc) 2365033Smilesck@eecs.umich.eduVectorParam = ParamFactory(VectorParamDesc) 2375475Snate@binkert.org 2385475Snate@binkert.org##################################################################### 2395475Snate@binkert.org# 2405475Snate@binkert.org# Parameter Types 24110380SAndrew.Bardsley@arm.com# 24210380SAndrew.Bardsley@arm.com# Though native Python types could be used to specify parameter types 24310380SAndrew.Bardsley@arm.com# (the 'ptype' field of the Param and VectorParam classes), it's more 2443101Sstever@eecs.umich.edu# flexible to define our own set of types. This gives us more control 2453101Sstever@eecs.umich.edu# over how Python expressions are converted to values (via the 2463101Sstever@eecs.umich.edu# __init__() constructor) and how these values are printed out (via 2474762Snate@binkert.org# the __str__() conversion method). 2484762Snate@binkert.org# 2494762Snate@binkert.org##################################################################### 2503101Sstever@eecs.umich.edu 2518460SAli.Saidi@ARM.com# String-valued parameter. Just mixin the ParamValue class with the 2528459SAli.Saidi@ARM.com# built-in str class. 2538459SAli.Saidi@ARM.comclass String(ParamValue,str): 2548459SAli.Saidi@ARM.com cxx_type = 'std::string' 2553101Sstever@eecs.umich.edu cxx_predecls = ['#include <string>'] 2567528Ssteve.reinhardt@amd.com swig_predecls = ['%include "std_string.i"\n' + 2577528Ssteve.reinhardt@amd.com '%apply const std::string& {std::string *};'] 2587528Ssteve.reinhardt@amd.com swig_predecls = ['%include "std_string.i"' ] 2597528Ssteve.reinhardt@amd.com 2607528Ssteve.reinhardt@amd.com def getValue(self): 2617528Ssteve.reinhardt@amd.com return self 2623101Sstever@eecs.umich.edu 2637528Ssteve.reinhardt@amd.com# superclass for "numeric" parameter values, to emulate math 2647528Ssteve.reinhardt@amd.com# operations in a type-safe way. e.g., a Latency times an int returns 2657528Ssteve.reinhardt@amd.com# a new Latency object. 2667528Ssteve.reinhardt@amd.comclass NumericParamValue(ParamValue): 2677528Ssteve.reinhardt@amd.com def __str__(self): 2687528Ssteve.reinhardt@amd.com return str(self.value) 2697528Ssteve.reinhardt@amd.com 2707528Ssteve.reinhardt@amd.com def __float__(self): 2717528Ssteve.reinhardt@amd.com return float(self.value) 2727528Ssteve.reinhardt@amd.com 2738321Ssteve.reinhardt@amd.com def __long__(self): 2748321Ssteve.reinhardt@amd.com return long(self.value) 2757528Ssteve.reinhardt@amd.com 2767528Ssteve.reinhardt@amd.com def __int__(self): 2777528Ssteve.reinhardt@amd.com return int(self.value) 2787528Ssteve.reinhardt@amd.com 2797528Ssteve.reinhardt@amd.com # hook for bounds checking 2807528Ssteve.reinhardt@amd.com def _check(self): 2817528Ssteve.reinhardt@amd.com return 2827528Ssteve.reinhardt@amd.com 2837528Ssteve.reinhardt@amd.com def __mul__(self, other): 2847528Ssteve.reinhardt@amd.com newobj = self.__class__(self) 2857528Ssteve.reinhardt@amd.com newobj.value *= other 2867528Ssteve.reinhardt@amd.com newobj._check() 2877528Ssteve.reinhardt@amd.com return newobj 2883101Sstever@eecs.umich.edu 2898664SAli.Saidi@ARM.com __rmul__ = __mul__ 2908664SAli.Saidi@ARM.com 2918664SAli.Saidi@ARM.com def __div__(self, other): 2928664SAli.Saidi@ARM.com newobj = self.__class__(self) 2938664SAli.Saidi@ARM.com newobj.value /= other 2948664SAli.Saidi@ARM.com newobj._check() 2959953Sgeoffrey.blake@arm.com return newobj 2969953Sgeoffrey.blake@arm.com 2979953Sgeoffrey.blake@arm.com def __sub__(self, other): 2989953Sgeoffrey.blake@arm.com newobj = self.__class__(self) 2999953Sgeoffrey.blake@arm.com newobj.value -= other 3009953Sgeoffrey.blake@arm.com newobj._check() 3019953Sgeoffrey.blake@arm.com return newobj 3029953Sgeoffrey.blake@arm.com 3039953Sgeoffrey.blake@arm.com# Metaclass for bounds-checked integer parameters. See CheckedInt. 3049953Sgeoffrey.blake@arm.comclass CheckedIntType(MetaParamValue): 3059953Sgeoffrey.blake@arm.com def __init__(cls, name, bases, dict): 3069953Sgeoffrey.blake@arm.com super(CheckedIntType, cls).__init__(name, bases, dict) 3079953Sgeoffrey.blake@arm.com 30810267SGeoffrey.Blake@arm.com # CheckedInt is an abstract base class, so we actually don't 30910267SGeoffrey.Blake@arm.com # want to do any processing on it... the rest of this code is 31010267SGeoffrey.Blake@arm.com # just for classes that derive from CheckedInt. 31110267SGeoffrey.Blake@arm.com if name == 'CheckedInt': 31210267SGeoffrey.Blake@arm.com return 31310267SGeoffrey.Blake@arm.com 31410267SGeoffrey.Blake@arm.com if not cls.cxx_predecls: 31510267SGeoffrey.Blake@arm.com # most derived types require this, so we just do it here once 31610267SGeoffrey.Blake@arm.com cls.cxx_predecls = ['#include "sim/host.hh"'] 31710267SGeoffrey.Blake@arm.com 31810267SGeoffrey.Blake@arm.com if not cls.swig_predecls: 31910267SGeoffrey.Blake@arm.com # most derived types require this, so we just do it here once 32010267SGeoffrey.Blake@arm.com cls.swig_predecls = ['%import "stdint.i"\n' + 32110267SGeoffrey.Blake@arm.com '%import "sim/host.hh"'] 32210267SGeoffrey.Blake@arm.com 32310267SGeoffrey.Blake@arm.com if not (hasattr(cls, 'min') and hasattr(cls, 'max')): 32410267SGeoffrey.Blake@arm.com if not (hasattr(cls, 'size') and hasattr(cls, 'unsigned')): 32510267SGeoffrey.Blake@arm.com panic("CheckedInt subclass %s must define either\n" \ 32610267SGeoffrey.Blake@arm.com " 'min' and 'max' or 'size' and 'unsigned'\n" \ 32710267SGeoffrey.Blake@arm.com % name); 3283101Sstever@eecs.umich.edu if cls.unsigned: 3293101Sstever@eecs.umich.edu cls.min = 0 3303101Sstever@eecs.umich.edu cls.max = 2 ** cls.size - 1 3313101Sstever@eecs.umich.edu else: 3323101Sstever@eecs.umich.edu cls.min = -(2 ** (cls.size - 1)) 3333101Sstever@eecs.umich.edu cls.max = (2 ** (cls.size - 1)) - 1 3343101Sstever@eecs.umich.edu 33510364SGeoffrey.Blake@arm.com# Abstract superclass for bounds-checked integer parameters. This 33610364SGeoffrey.Blake@arm.com# class is subclassed to generate parameter classes with specific 33710364SGeoffrey.Blake@arm.com# bounds. Initialization of the min and max bounds is done in the 33810364SGeoffrey.Blake@arm.com# metaclass CheckedIntType.__init__. 3393101Sstever@eecs.umich.educlass CheckedInt(NumericParamValue): 3404762Snate@binkert.org __metaclass__ = CheckedIntType 3414762Snate@binkert.org 3424762Snate@binkert.org def _check(self): 3434762Snate@binkert.org if not self.min <= self.value <= self.max: 3447528Ssteve.reinhardt@amd.com raise TypeError, 'Integer param out of bounds %d < %d < %d' % \ 3454762Snate@binkert.org (self.min, self.value, self.max) 3464762Snate@binkert.org 3474762Snate@binkert.org def __init__(self, value): 34810267SGeoffrey.Blake@arm.com if isinstance(value, str): 34910267SGeoffrey.Blake@arm.com self.value = convert.toInteger(value) 35010267SGeoffrey.Blake@arm.com elif isinstance(value, (int, long, float, NumericParamValue)): 35110267SGeoffrey.Blake@arm.com self.value = long(value) 35210267SGeoffrey.Blake@arm.com else: 35310267SGeoffrey.Blake@arm.com raise TypeError, "Can't convert object of type %s to CheckedInt" \ 35410267SGeoffrey.Blake@arm.com % type(value).__name__ 35510267SGeoffrey.Blake@arm.com self._check() 35610267SGeoffrey.Blake@arm.com 35710267SGeoffrey.Blake@arm.com def getValue(self): 35810267SGeoffrey.Blake@arm.com return long(self.value) 35910267SGeoffrey.Blake@arm.com 36010267SGeoffrey.Blake@arm.comclass Int(CheckedInt): cxx_type = 'int'; size = 32; unsigned = False 36110267SGeoffrey.Blake@arm.comclass Unsigned(CheckedInt): cxx_type = 'unsigned'; size = 32; unsigned = True 36210267SGeoffrey.Blake@arm.com 36310267SGeoffrey.Blake@arm.comclass Int8(CheckedInt): cxx_type = 'int8_t'; size = 8; unsigned = False 36410267SGeoffrey.Blake@arm.comclass UInt8(CheckedInt): cxx_type = 'uint8_t'; size = 8; unsigned = True 36510267SGeoffrey.Blake@arm.comclass Int16(CheckedInt): cxx_type = 'int16_t'; size = 16; unsigned = False 36610267SGeoffrey.Blake@arm.comclass UInt16(CheckedInt): cxx_type = 'uint16_t'; size = 16; unsigned = True 36710267SGeoffrey.Blake@arm.comclass Int32(CheckedInt): cxx_type = 'int32_t'; size = 32; unsigned = False 36810267SGeoffrey.Blake@arm.comclass UInt32(CheckedInt): cxx_type = 'uint32_t'; size = 32; unsigned = True 36910267SGeoffrey.Blake@arm.comclass Int64(CheckedInt): cxx_type = 'int64_t'; size = 64; unsigned = False 37010267SGeoffrey.Blake@arm.comclass UInt64(CheckedInt): cxx_type = 'uint64_t'; size = 64; unsigned = True 37110267SGeoffrey.Blake@arm.com 37210267SGeoffrey.Blake@arm.comclass Counter(CheckedInt): cxx_type = 'Counter'; size = 64; unsigned = True 37310267SGeoffrey.Blake@arm.comclass Tick(CheckedInt): cxx_type = 'Tick'; size = 64; unsigned = True 37410364SGeoffrey.Blake@arm.comclass TcpPort(CheckedInt): cxx_type = 'uint16_t'; size = 16; unsigned = True 37510364SGeoffrey.Blake@arm.comclass UdpPort(CheckedInt): cxx_type = 'uint16_t'; size = 16; unsigned = True 37610267SGeoffrey.Blake@arm.com 37710267SGeoffrey.Blake@arm.comclass Percent(CheckedInt): cxx_type = 'int'; min = 0; max = 100 37810267SGeoffrey.Blake@arm.com 37910267SGeoffrey.Blake@arm.comclass Float(ParamValue, float): 38010267SGeoffrey.Blake@arm.com cxx_type = 'double' 38110267SGeoffrey.Blake@arm.com 3828596Ssteve.reinhardt@amd.com def getValue(self): 3838596Ssteve.reinhardt@amd.com return float(self.value) 3848596Ssteve.reinhardt@amd.com 3857673Snate@binkert.orgclass MemorySize(CheckedInt): 3868596Ssteve.reinhardt@amd.com cxx_type = 'uint64_t' 3874762Snate@binkert.org size = 64 3887673Snate@binkert.org unsigned = True 3898596Ssteve.reinhardt@amd.com def __init__(self, value): 3907675Snate@binkert.org if isinstance(value, MemorySize): 3917675Snate@binkert.org self.value = value.value 3927675Snate@binkert.org else: 3937675Snate@binkert.org self.value = convert.toMemorySize(value) 3948656Sandreas.hansson@arm.com self._check() 3958656Sandreas.hansson@arm.com 3968656Sandreas.hansson@arm.comclass MemorySize32(CheckedInt): 3977675Snate@binkert.org cxx_type = 'uint32_t' 3987675Snate@binkert.org size = 32 3997673Snate@binkert.org unsigned = True 4007675Snate@binkert.org def __init__(self, value): 4017675Snate@binkert.org if isinstance(value, MemorySize): 4027675Snate@binkert.org self.value = value.value 4037675Snate@binkert.org else: 4047675Snate@binkert.org self.value = convert.toMemorySize(value) 4057675Snate@binkert.org self._check() 4067675Snate@binkert.org 4077673Snate@binkert.orgclass Addr(CheckedInt): 4087673Snate@binkert.org cxx_type = 'Addr' 4097673Snate@binkert.org cxx_predecls = ['#include "arch/isa_traits.hh"'] 4103101Sstever@eecs.umich.edu size = 64 4117673Snate@binkert.org unsigned = True 4127673Snate@binkert.org def __init__(self, value): 4133101Sstever@eecs.umich.edu if isinstance(value, Addr): 4143101Sstever@eecs.umich.edu self.value = value.value 4153101Sstever@eecs.umich.edu else: 4163101Sstever@eecs.umich.edu try: 4173101Sstever@eecs.umich.edu self.value = convert.toMemorySize(value) 4183101Sstever@eecs.umich.edu except TypeError: 4193101Sstever@eecs.umich.edu self.value = long(value) 4203101Sstever@eecs.umich.edu self._check() 4213101Sstever@eecs.umich.edu def __add__(self, other): 4223101Sstever@eecs.umich.edu if isinstance(other, Addr): 4233101Sstever@eecs.umich.edu return self.value + other.value 4243101Sstever@eecs.umich.edu else: 4253101Sstever@eecs.umich.edu return self.value + other 4263101Sstever@eecs.umich.edu 4273101Sstever@eecs.umich.edu 4285033Smilesck@eecs.umich.educlass MetaRange(MetaParamValue): 4295033Smilesck@eecs.umich.edu def __init__(cls, name, bases, dict): 4303101Sstever@eecs.umich.edu super(MetaRange, cls).__init__(name, bases, dict) 4313101Sstever@eecs.umich.edu if name == 'Range': 4323101Sstever@eecs.umich.edu return 4333101Sstever@eecs.umich.edu cls.cxx_type = 'Range< %s >' % cls.type.cxx_type 4343101Sstever@eecs.umich.edu cls.cxx_predecls = \ 4353101Sstever@eecs.umich.edu ['#include "base/range.hh"'] + cls.type.cxx_predecls 4363101Sstever@eecs.umich.edu 4373101Sstever@eecs.umich.educlass Range(ParamValue): 4383101Sstever@eecs.umich.edu __metaclass__ = MetaRange 4393101Sstever@eecs.umich.edu type = Int # default; can be overridden in subclasses 4403101Sstever@eecs.umich.edu def __init__(self, *args, **kwargs): 4413101Sstever@eecs.umich.edu def handle_kwargs(self, kwargs): 4423101Sstever@eecs.umich.edu if 'end' in kwargs: 4433101Sstever@eecs.umich.edu self.second = self.type(kwargs.pop('end')) 4443101Sstever@eecs.umich.edu elif 'size' in kwargs: 4453101Sstever@eecs.umich.edu self.second = self.first + self.type(kwargs.pop('size')) - 1 4463101Sstever@eecs.umich.edu else: 4473101Sstever@eecs.umich.edu raise TypeError, "Either end or size must be specified" 4483101Sstever@eecs.umich.edu 4493101Sstever@eecs.umich.edu if len(args) == 0: 4503101Sstever@eecs.umich.edu self.first = self.type(kwargs.pop('start')) 4513101Sstever@eecs.umich.edu handle_kwargs(self, kwargs) 4523101Sstever@eecs.umich.edu 4533101Sstever@eecs.umich.edu elif len(args) == 1: 4543101Sstever@eecs.umich.edu if kwargs: 45510267SGeoffrey.Blake@arm.com self.first = self.type(args[0]) 4567673Snate@binkert.org handle_kwargs(self, kwargs) 4577673Snate@binkert.org elif isinstance(args[0], Range): 4587673Snate@binkert.org self.first = self.type(args[0].first) 4597673Snate@binkert.org self.second = self.type(args[0].second) 4607673Snate@binkert.org else: 4617673Snate@binkert.org self.first = self.type(0) 4627673Snate@binkert.org self.second = self.type(args[0]) - 1 4637673Snate@binkert.org 4644762Snate@binkert.org elif len(args) == 2: 46510267SGeoffrey.Blake@arm.com self.first = self.type(args[0]) 46610267SGeoffrey.Blake@arm.com self.second = self.type(args[1]) 46710267SGeoffrey.Blake@arm.com else: 46810267SGeoffrey.Blake@arm.com raise TypeError, "Too many arguments specified" 46910458Sandreas.hansson@arm.com 47010458Sandreas.hansson@arm.com if kwargs: 47110458Sandreas.hansson@arm.com raise TypeError, "too many keywords: %s" % kwargs.keys() 47210458Sandreas.hansson@arm.com 47310458Sandreas.hansson@arm.com def __str__(self): 4744762Snate@binkert.org return '%s:%s' % (self.first, self.second) 4754762Snate@binkert.org 4763101Sstever@eecs.umich.educlass AddrRange(Range): 4773101Sstever@eecs.umich.edu type = Addr 4783101Sstever@eecs.umich.edu swig_predecls = ['%include "python/swig/range.i"'] 4793101Sstever@eecs.umich.edu 4803101Sstever@eecs.umich.edu def getValue(self): 4813101Sstever@eecs.umich.edu from m5.objects.params import AddrRange 4823101Sstever@eecs.umich.edu 4833101Sstever@eecs.umich.edu value = AddrRange() 4843101Sstever@eecs.umich.edu value.start = long(self.first) 4853101Sstever@eecs.umich.edu value.end = long(self.second) 4863101Sstever@eecs.umich.edu return value 4873714Sstever@eecs.umich.edu 4883714Sstever@eecs.umich.educlass TickRange(Range): 4893714Sstever@eecs.umich.edu type = Tick 4903714Sstever@eecs.umich.edu swig_predecls = ['%include "python/swig/range.i"'] 4913714Sstever@eecs.umich.edu 4923714Sstever@eecs.umich.edu def getValue(self): 4933101Sstever@eecs.umich.edu from m5.objects.params import TickRange 4943101Sstever@eecs.umich.edu 4953101Sstever@eecs.umich.edu value = TickRange() 4963101Sstever@eecs.umich.edu value.start = long(self.first) 4973101Sstever@eecs.umich.edu value.end = long(self.second) 4983101Sstever@eecs.umich.edu return value 4993101Sstever@eecs.umich.edu 5003101Sstever@eecs.umich.edu# Boolean parameter type. Python doesn't let you subclass bool, since 5013101Sstever@eecs.umich.edu# it doesn't want to let you create multiple instances of True and 5023101Sstever@eecs.umich.edu# False. Thus this is a little more complicated than String. 5033101Sstever@eecs.umich.educlass Bool(ParamValue): 5043101Sstever@eecs.umich.edu cxx_type = 'bool' 5053101Sstever@eecs.umich.edu def __init__(self, value): 5063101Sstever@eecs.umich.edu try: 5073101Sstever@eecs.umich.edu self.value = convert.toBool(value) 5083101Sstever@eecs.umich.edu except TypeError: 5093101Sstever@eecs.umich.edu self.value = bool(value) 5103101Sstever@eecs.umich.edu 5113101Sstever@eecs.umich.edu def getValue(self): 5123101Sstever@eecs.umich.edu return bool(self.value) 5133101Sstever@eecs.umich.edu 5143101Sstever@eecs.umich.edu def __str__(self): 5153101Sstever@eecs.umich.edu return str(self.value) 5163101Sstever@eecs.umich.edu 51710380SAndrew.Bardsley@arm.com def ini_str(self): 51810380SAndrew.Bardsley@arm.com if self.value: 51910380SAndrew.Bardsley@arm.com return 'true' 52010458Sandreas.hansson@arm.com return 'false' 52110458Sandreas.hansson@arm.com 52210458Sandreas.hansson@arm.comdef IncEthernetAddr(addr, val = 1): 52310458Sandreas.hansson@arm.com bytes = map(lambda x: int(x, 16), addr.split(':')) 52410458Sandreas.hansson@arm.com bytes[5] += val 52510458Sandreas.hansson@arm.com for i in (5, 4, 3, 2, 1): 52610458Sandreas.hansson@arm.com val,rem = divmod(bytes[i], 256) 52710458Sandreas.hansson@arm.com bytes[i] = rem 52810458Sandreas.hansson@arm.com if val == 0: 52910458Sandreas.hansson@arm.com break 53010458Sandreas.hansson@arm.com bytes[i - 1] += val 53110458Sandreas.hansson@arm.com assert(bytes[0] <= 255) 53210458Sandreas.hansson@arm.com return ':'.join(map(lambda x: '%02x' % x, bytes)) 5333101Sstever@eecs.umich.edu 5345033Smilesck@eecs.umich.edu_NextEthernetAddr = "00:90:00:00:00:01" 5353101Sstever@eecs.umich.edudef NextEthernetAddr(): 5363101Sstever@eecs.umich.edu global _NextEthernetAddr 5373101Sstever@eecs.umich.edu 5383101Sstever@eecs.umich.edu value = _NextEthernetAddr 5393101Sstever@eecs.umich.edu _NextEthernetAddr = IncEthernetAddr(_NextEthernetAddr, 1) 5403101Sstever@eecs.umich.edu return value 5413101Sstever@eecs.umich.edu 5423101Sstever@eecs.umich.educlass EthernetAddr(ParamValue): 5433101Sstever@eecs.umich.edu cxx_type = 'Net::EthAddr' 5443101Sstever@eecs.umich.edu cxx_predecls = ['#include "base/inet.hh"'] 5453101Sstever@eecs.umich.edu swig_predecls = ['%include "python/swig/inet.i"'] 5463101Sstever@eecs.umich.edu def __init__(self, value): 5475822Ssaidi@eecs.umich.edu if value == NextEthernetAddr: 5485822Ssaidi@eecs.umich.edu self.value = value 5493101Sstever@eecs.umich.edu return 5503101Sstever@eecs.umich.edu 5513101Sstever@eecs.umich.edu if not isinstance(value, str): 5523101Sstever@eecs.umich.edu raise TypeError, "expected an ethernet address and didn't get one" 5533101Sstever@eecs.umich.edu 5543101Sstever@eecs.umich.edu bytes = value.split(':') 5553101Sstever@eecs.umich.edu if len(bytes) != 6: 5563101Sstever@eecs.umich.edu raise TypeError, 'invalid ethernet address %s' % value 5573101Sstever@eecs.umich.edu 5583101Sstever@eecs.umich.edu for byte in bytes: 5593101Sstever@eecs.umich.edu if not 0 <= int(byte) <= 256: 5603101Sstever@eecs.umich.edu raise TypeError, 'invalid ethernet address %s' % value 5613101Sstever@eecs.umich.edu 56210267SGeoffrey.Blake@arm.com self.value = value 5633101Sstever@eecs.umich.edu 5643101Sstever@eecs.umich.edu def unproxy(self, base): 5653101Sstever@eecs.umich.edu if self.value == NextEthernetAddr: 5663101Sstever@eecs.umich.edu return EthernetAddr(self.value()) 5673101Sstever@eecs.umich.edu return self 5683101Sstever@eecs.umich.edu 5693101Sstever@eecs.umich.edu def getValue(self): 5703101Sstever@eecs.umich.edu from m5.objects.params import EthAddr 5713102Sstever@eecs.umich.edu return EthAddr(self.value) 5723714Sstever@eecs.umich.edu 5733101Sstever@eecs.umich.edu def ini_str(self): 5743714Sstever@eecs.umich.edu return self.value 5753714Sstever@eecs.umich.edu 5763714Sstever@eecs.umich.edutime_formats = [ "%a %b %d %H:%M:%S %Z %Y", 5773101Sstever@eecs.umich.edu "%a %b %d %H:%M:%S %Z %Y", 5783101Sstever@eecs.umich.edu "%Y/%m/%d %H:%M:%S", 57910267SGeoffrey.Blake@arm.com "%Y/%m/%d %H:%M", 58010267SGeoffrey.Blake@arm.com "%Y/%m/%d", 58110267SGeoffrey.Blake@arm.com "%m/%d/%Y %H:%M:%S", 58210267SGeoffrey.Blake@arm.com "%m/%d/%Y %H:%M", 5837673Snate@binkert.org "%m/%d/%Y", 5847673Snate@binkert.org "%m/%d/%y %H:%M:%S", 5857673Snate@binkert.org "%m/%d/%y %H:%M", 5867673Snate@binkert.org "%m/%d/%y"] 5877673Snate@binkert.org 5887673Snate@binkert.org 5897673Snate@binkert.orgdef parse_time(value): 5907673Snate@binkert.org from time import gmtime, strptime, struct_time, time 5917673Snate@binkert.org from datetime import datetime, date 5927673Snate@binkert.org 5937673Snate@binkert.org if isinstance(value, struct_time): 5944762Snate@binkert.org return value 5954762Snate@binkert.org 5964762Snate@binkert.org if isinstance(value, (int, long)): 5973101Sstever@eecs.umich.edu return gmtime(value) 5983101Sstever@eecs.umich.edu 5993101Sstever@eecs.umich.edu if isinstance(value, (datetime, date)): 6003101Sstever@eecs.umich.edu return value.timetuple() 6013101Sstever@eecs.umich.edu 6023101Sstever@eecs.umich.edu if isinstance(value, str): 6033101Sstever@eecs.umich.edu if value in ('Now', 'Today'): 6043101Sstever@eecs.umich.edu return time.gmtime(time.time()) 6053101Sstever@eecs.umich.edu 6063101Sstever@eecs.umich.edu for format in time_formats: 6073101Sstever@eecs.umich.edu try: 6083101Sstever@eecs.umich.edu return strptime(value, format) 6093101Sstever@eecs.umich.edu except ValueError: 6103101Sstever@eecs.umich.edu pass 6113101Sstever@eecs.umich.edu 6123101Sstever@eecs.umich.edu raise ValueError, "Could not parse '%s' as a time" % value 6133101Sstever@eecs.umich.edu 6143101Sstever@eecs.umich.educlass Time(ParamValue): 6153101Sstever@eecs.umich.edu cxx_type = 'tm' 6169184Sandreas.hansson@arm.com cxx_predecls = [ '#include <time.h>' ] 6179184Sandreas.hansson@arm.com swig_predecls = [ '%include "python/swig/time.i"' ] 6189184Sandreas.hansson@arm.com def __init__(self, value): 6199184Sandreas.hansson@arm.com self.value = parse_time(value) 6209184Sandreas.hansson@arm.com 6219184Sandreas.hansson@arm.com def getValue(self): 6229184Sandreas.hansson@arm.com from m5.objects.params import tm 6239184Sandreas.hansson@arm.com 6249184Sandreas.hansson@arm.com c_time = tm() 62510458Sandreas.hansson@arm.com py_time = self.value 62610458Sandreas.hansson@arm.com 62710458Sandreas.hansson@arm.com # UNIX is years since 1900 62810458Sandreas.hansson@arm.com c_time.tm_year = py_time.tm_year - 1900; 62910458Sandreas.hansson@arm.com 63010458Sandreas.hansson@arm.com # Python starts at 1, UNIX starts at 0 63110458Sandreas.hansson@arm.com c_time.tm_mon = py_time.tm_mon - 1; 63210458Sandreas.hansson@arm.com c_time.tm_mday = py_time.tm_mday; 63310458Sandreas.hansson@arm.com c_time.tm_hour = py_time.tm_hour; 63410458Sandreas.hansson@arm.com c_time.tm_min = py_time.tm_min; 63510458Sandreas.hansson@arm.com c_time.tm_sec = py_time.tm_sec; 63610458Sandreas.hansson@arm.com 63710458Sandreas.hansson@arm.com # Python has 0 as Monday, UNIX is 0 as sunday 63810458Sandreas.hansson@arm.com c_time.tm_wday = py_time.tm_wday + 1 6393101Sstever@eecs.umich.edu if c_time.tm_wday > 6: 6404446Sbinkertn@umich.edu c_time.tm_wday -= 7; 64110668SGeoffrey.Blake@arm.com 6423101Sstever@eecs.umich.edu # Python starts at 1, Unix starts at 0 6435468Snate@binkert.org c_time.tm_yday = py_time.tm_yday - 1; 64410267SGeoffrey.Blake@arm.com 6455468Snate@binkert.org return c_time 6465468Snate@binkert.org 6475468Snate@binkert.org def __str__(self): 6485468Snate@binkert.org return time.asctime(self.value) 6495468Snate@binkert.org 65010267SGeoffrey.Blake@arm.com def ini_str(self): 65110267SGeoffrey.Blake@arm.com return str(self) 65210267SGeoffrey.Blake@arm.com 65310267SGeoffrey.Blake@arm.com# Enumerated types are a little more complex. The user specifies the 6544762Snate@binkert.org# type as Enum(foo) where foo is either a list or dictionary of 6554762Snate@binkert.org# alternatives (typically strings, but not necessarily so). (In the 6564762Snate@binkert.org# long run, the integer value of the parameter will be the list index 65710380SAndrew.Bardsley@arm.com# or the corresponding dictionary value. For now, since we only check 65810380SAndrew.Bardsley@arm.com# that the alternative is valid and then spit it into a .ini file, 65910380SAndrew.Bardsley@arm.com# there's not much point in using the dictionary.) 66010458Sandreas.hansson@arm.com 66110458Sandreas.hansson@arm.com# What Enum() must do is generate a new type encapsulating the 66210458Sandreas.hansson@arm.com# provided list/dictionary so that specific values of the parameter 66310458Sandreas.hansson@arm.com# can be instances of that type. We define two hidden internal 66410458Sandreas.hansson@arm.com# classes (_ListEnum and _DictEnum) to serve as base classes, then 66510458Sandreas.hansson@arm.com# derive the new type from the appropriate base class on the fly. 66610458Sandreas.hansson@arm.com 66710458Sandreas.hansson@arm.comallEnums = {} 6683101Sstever@eecs.umich.edu# Metaclass for Enum types 6693101Sstever@eecs.umich.educlass MetaEnum(MetaParamValue): 67010267SGeoffrey.Blake@arm.com def __new__(mcls, name, bases, dict): 6713101Sstever@eecs.umich.edu assert name not in allEnums 6723101Sstever@eecs.umich.edu 6733101Sstever@eecs.umich.edu cls = super(MetaEnum, mcls).__new__(mcls, name, bases, dict) 6743101Sstever@eecs.umich.edu allEnums[name] = cls 6753101Sstever@eecs.umich.edu return cls 6763101Sstever@eecs.umich.edu 6773102Sstever@eecs.umich.edu def __init__(cls, name, bases, init_dict): 6783101Sstever@eecs.umich.edu if init_dict.has_key('map'): 6793101Sstever@eecs.umich.edu if not isinstance(cls.map, dict): 6803101Sstever@eecs.umich.edu raise TypeError, "Enum-derived class attribute 'map' " \ 6814168Sbinkertn@umich.edu "must be of type dict" 68210267SGeoffrey.Blake@arm.com # build list of value strings from map 6833101Sstever@eecs.umich.edu cls.vals = cls.map.keys() 6843101Sstever@eecs.umich.edu cls.vals.sort() 6853101Sstever@eecs.umich.edu elif init_dict.has_key('vals'): 6863101Sstever@eecs.umich.edu if not isinstance(cls.vals, list): 6873101Sstever@eecs.umich.edu raise TypeError, "Enum-derived class attribute 'vals' " \ 6883101Sstever@eecs.umich.edu "must be of type list" 6893102Sstever@eecs.umich.edu # build string->value map from vals sequence 6903101Sstever@eecs.umich.edu cls.map = {} 6913101Sstever@eecs.umich.edu for idx,val in enumerate(cls.vals): 6923101Sstever@eecs.umich.edu cls.map[val] = idx 6933101Sstever@eecs.umich.edu else: 6943101Sstever@eecs.umich.edu raise TypeError, "Enum-derived class must define "\ 6953101Sstever@eecs.umich.edu "attribute 'map' or 'vals'" 6963101Sstever@eecs.umich.edu 6973101Sstever@eecs.umich.edu cls.cxx_type = 'Enums::%s' % name 6983101Sstever@eecs.umich.edu 6993101Sstever@eecs.umich.edu super(MetaEnum, cls).__init__(name, bases, init_dict) 7003101Sstever@eecs.umich.edu 70110317Smitch.hayenga@arm.com def __str__(cls): 70210317Smitch.hayenga@arm.com return cls.__name__ 70310317Smitch.hayenga@arm.com 70410317Smitch.hayenga@arm.com # Generate C++ class declaration for this enum type. 70510317Smitch.hayenga@arm.com # Note that we wrap the enum in a class/struct to act as a namespace, 7063102Sstever@eecs.umich.edu # so that the enum strings can be brief w/o worrying about collisions. 70710317Smitch.hayenga@arm.com def cxx_decl(cls): 70810317Smitch.hayenga@arm.com code = "#ifndef __ENUM__%s\n" % cls 70910317Smitch.hayenga@arm.com code += '#define __ENUM__%s\n' % cls 71010317Smitch.hayenga@arm.com code += '\n' 71110317Smitch.hayenga@arm.com code += 'namespace Enums {\n' 7123101Sstever@eecs.umich.edu code += ' enum %s {\n' % cls 7133584Ssaidi@eecs.umich.edu for val in cls.vals: 7143584Ssaidi@eecs.umich.edu code += ' %s = %d,\n' % (val, cls.map[val]) 7153584Ssaidi@eecs.umich.edu code += ' Num_%s = %d,\n' % (cls, len(cls.vals)) 7163584Ssaidi@eecs.umich.edu code += ' };\n' 7173584Ssaidi@eecs.umich.edu code += ' extern const char *%sStrings[Num_%s];\n' % (cls, cls) 71810267SGeoffrey.Blake@arm.com code += '}\n' 71910267SGeoffrey.Blake@arm.com code += '\n' 72010267SGeoffrey.Blake@arm.com code += '#endif\n' 72110267SGeoffrey.Blake@arm.com return code 72210267SGeoffrey.Blake@arm.com 72310267SGeoffrey.Blake@arm.com def cxx_def(cls): 7243101Sstever@eecs.umich.edu code = '#include "enums/%s.hh"\n' % cls 7259232Sandreas.hansson@arm.com code += 'namespace Enums {\n' 7269235Sandreas.hansson@arm.com code += ' const char *%sStrings[Num_%s] =\n' % (cls, cls) 7273101Sstever@eecs.umich.edu code += ' {\n' 7283101Sstever@eecs.umich.edu for val in cls.vals: 72910676Sandreas.hansson@arm.com code += ' "%s",\n' % val 7309411Sandreas.hansson@arm.com code += ' };\n' 73110676Sandreas.hansson@arm.com code += '}\n' 7329411Sandreas.hansson@arm.com return code 7339411Sandreas.hansson@arm.com 7349411Sandreas.hansson@arm.com# Base class for enum types. 7353101Sstever@eecs.umich.educlass Enum(ParamValue): 7369411Sandreas.hansson@arm.com __metaclass__ = MetaEnum 7379411Sandreas.hansson@arm.com vals = [] 7389411Sandreas.hansson@arm.com 7393101Sstever@eecs.umich.edu def __init__(self, value): 7409232Sandreas.hansson@arm.com if value not in self.map: 7413101Sstever@eecs.umich.edu raise TypeError, "Enum param got bad value '%s' (not in %s)" \ 7429232Sandreas.hansson@arm.com % (value, self.vals) 7433101Sstever@eecs.umich.edu self.value = value 7443101Sstever@eecs.umich.edu 7453101Sstever@eecs.umich.edu def getValue(self): 7469411Sandreas.hansson@arm.com return int(self.map[self.value]) 7479411Sandreas.hansson@arm.com 7489411Sandreas.hansson@arm.com def __str__(self): 74910676Sandreas.hansson@arm.com return self.value 75010676Sandreas.hansson@arm.com 7519411Sandreas.hansson@arm.com# how big does a rounding error need to be before we warn about it? 7529411Sandreas.hansson@arm.comfrequency_tolerance = 0.001 # 0.1% 7539411Sandreas.hansson@arm.com 7549411Sandreas.hansson@arm.comclass TickParamValue(NumericParamValue): 7559411Sandreas.hansson@arm.com cxx_type = 'Tick' 7563101Sstever@eecs.umich.edu cxx_predecls = ['#include "sim/host.hh"'] 7579232Sandreas.hansson@arm.com swig_predecls = ['%import "stdint.i"\n' + 7583101Sstever@eecs.umich.edu '%import "sim/host.hh"'] 7593101Sstever@eecs.umich.edu 7603101Sstever@eecs.umich.edu def getValue(self): 7613101Sstever@eecs.umich.edu return long(self.value) 7629232Sandreas.hansson@arm.com 7633101Sstever@eecs.umich.educlass Latency(TickParamValue): 7645219Ssaidi@eecs.umich.edu def __init__(self, value): 7659232Sandreas.hansson@arm.com if isinstance(value, (Latency, Clock)): 7669232Sandreas.hansson@arm.com self.ticks = value.ticks 7673101Sstever@eecs.umich.edu self.value = value.value 7689232Sandreas.hansson@arm.com elif isinstance(value, Frequency): 7699232Sandreas.hansson@arm.com self.ticks = value.ticks 7703101Sstever@eecs.umich.edu self.value = 1.0 / value.value 7713101Sstever@eecs.umich.edu elif value.endswith('t'): 7729232Sandreas.hansson@arm.com self.ticks = True 7739232Sandreas.hansson@arm.com self.value = int(value[:-1]) 7743101Sstever@eecs.umich.edu else: 7753101Sstever@eecs.umich.edu self.ticks = False 7763101Sstever@eecs.umich.edu self.value = convert.toLatency(value) 7773101Sstever@eecs.umich.edu 7789232Sandreas.hansson@arm.com def __getattr__(self, attr): 7793101Sstever@eecs.umich.edu if attr in ('latency', 'period'): 7803101Sstever@eecs.umich.edu return self 78111620SMatthew.Poremba@amd.com if attr == 'frequency': 78211620SMatthew.Poremba@amd.com return Frequency(self) 78311620SMatthew.Poremba@amd.com raise AttributeError, "Latency object has no attribute '%s'" % attr 7849232Sandreas.hansson@arm.com 7859232Sandreas.hansson@arm.com def getValue(self): 7869411Sandreas.hansson@arm.com if self.ticks or self.value == 0: 7879411Sandreas.hansson@arm.com value = self.value 7883101Sstever@eecs.umich.edu else: 7897673Snate@binkert.org value = ticks.fromSeconds(self.value) 7907673Snate@binkert.org return long(value) 7919232Sandreas.hansson@arm.com 7929235Sandreas.hansson@arm.com # convert latency to ticks 7937675Snate@binkert.org def ini_str(self): 7947675Snate@binkert.org return '%d' % self.getValue() 7957675Snate@binkert.org 7969232Sandreas.hansson@arm.comclass Frequency(TickParamValue): 7977673Snate@binkert.org def __init__(self, value): 79810458Sandreas.hansson@arm.com if isinstance(value, (Latency, Clock)): 79910458Sandreas.hansson@arm.com if value.value == 0: 80010458Sandreas.hansson@arm.com self.value = 0 80110458Sandreas.hansson@arm.com else: 80210458Sandreas.hansson@arm.com self.value = 1.0 / value.value 80310458Sandreas.hansson@arm.com self.ticks = value.ticks 80411620SMatthew.Poremba@amd.com elif isinstance(value, Frequency): 80511620SMatthew.Poremba@amd.com self.value = value.value 80610458Sandreas.hansson@arm.com self.ticks = value.ticks 80710458Sandreas.hansson@arm.com else: 80810458Sandreas.hansson@arm.com self.ticks = False 80910458Sandreas.hansson@arm.com self.value = convert.toFrequency(value) 81010458Sandreas.hansson@arm.com 81111620SMatthew.Poremba@amd.com def __getattr__(self, attr): 81211620SMatthew.Poremba@amd.com if attr == 'frequency': 81311620SMatthew.Poremba@amd.com return self 81411620SMatthew.Poremba@amd.com if attr in ('latency', 'period'): 81511620SMatthew.Poremba@amd.com return Latency(self) 81611620SMatthew.Poremba@amd.com raise AttributeError, "Frequency object has no attribute '%s'" % attr 81711620SMatthew.Poremba@amd.com 81811620SMatthew.Poremba@amd.com # convert latency to ticks 81911620SMatthew.Poremba@amd.com def getValue(self): 82011620SMatthew.Poremba@amd.com if self.ticks or self.value == 0: 82110458Sandreas.hansson@arm.com value = self.value 82210458Sandreas.hansson@arm.com else: 82310458Sandreas.hansson@arm.com value = ticks.fromSeconds(1.0 / self.value) 82411620SMatthew.Poremba@amd.com return long(value) 82511620SMatthew.Poremba@amd.com 82610458Sandreas.hansson@arm.com def ini_str(self): 82710458Sandreas.hansson@arm.com return '%d' % self.getValue() 8284762Snate@binkert.org 8299235Sandreas.hansson@arm.com# A generic frequency and/or Latency value. Value is stored as a latency, 8309235Sandreas.hansson@arm.com# but to avoid ambiguity this object does not support numeric ops (* or /). 8317675Snate@binkert.org# An explicit conversion to a Latency or Frequency must be made first. 8324762Snate@binkert.orgclass Clock(ParamValue): 8339411Sandreas.hansson@arm.com cxx_type = 'Tick' 83410676Sandreas.hansson@arm.com cxx_predecls = ['#include "sim/host.hh"'] 83510676Sandreas.hansson@arm.com swig_predecls = ['%import "stdint.i"\n' + 8363101Sstever@eecs.umich.edu '%import "sim/host.hh"'] 8373101Sstever@eecs.umich.edu def __init__(self, value): 8383101Sstever@eecs.umich.edu if isinstance(value, (Latency, Clock)): 8393101Sstever@eecs.umich.edu self.ticks = value.ticks 8403101Sstever@eecs.umich.edu self.value = value.value 8413101Sstever@eecs.umich.edu elif isinstance(value, Frequency): 84210267SGeoffrey.Blake@arm.com self.ticks = value.ticks 84310267SGeoffrey.Blake@arm.com self.value = 1.0 / value.value 8443101Sstever@eecs.umich.edu elif value.endswith('t'): 8453101Sstever@eecs.umich.edu self.ticks = True 8463102Sstever@eecs.umich.edu self.value = int(value[:-1]) 8473101Sstever@eecs.umich.edu else: 8483101Sstever@eecs.umich.edu self.ticks = False 8493101Sstever@eecs.umich.edu self.value = convert.anyToLatency(value) 85010267SGeoffrey.Blake@arm.com 85110267SGeoffrey.Blake@arm.com def __getattr__(self, attr): 85210267SGeoffrey.Blake@arm.com if attr == 'frequency': 85310267SGeoffrey.Blake@arm.com return Frequency(self) 8544762Snate@binkert.org if attr in ('latency', 'period'): 8554762Snate@binkert.org return Latency(self) 8564762Snate@binkert.org raise AttributeError, "Frequency object has no attribute '%s'" % attr 8573101Sstever@eecs.umich.edu 8583101Sstever@eecs.umich.edu def getValue(self): 8593101Sstever@eecs.umich.edu return self.period.getValue() 8608934SBrad.Beckmann@amd.com 8618934SBrad.Beckmann@amd.com def ini_str(self): 8628934SBrad.Beckmann@amd.com return self.period.ini_str() 8638934SBrad.Beckmann@amd.com 8648934SBrad.Beckmann@amd.comclass NetworkBandwidth(float,ParamValue): 8653101Sstever@eecs.umich.edu cxx_type = 'float' 8663101Sstever@eecs.umich.edu def __new__(cls, value): 8673101Sstever@eecs.umich.edu # convert to bits per second 8683101Sstever@eecs.umich.edu val = convert.toNetworkBandwidth(value) 8693101Sstever@eecs.umich.edu return super(cls, NetworkBandwidth).__new__(cls, val) 87010380SAndrew.Bardsley@arm.com 87110380SAndrew.Bardsley@arm.com def __str__(self): 87210380SAndrew.Bardsley@arm.com return str(self.val) 87310458Sandreas.hansson@arm.com 87410458Sandreas.hansson@arm.com def getValue(self): 87510458Sandreas.hansson@arm.com # convert to seconds per byte 87610458Sandreas.hansson@arm.com value = 8.0 / float(self) 87710458Sandreas.hansson@arm.com # convert to ticks per byte 87810458Sandreas.hansson@arm.com value = ticks.fromSeconds(value) 87910458Sandreas.hansson@arm.com return float(value) 88010458Sandreas.hansson@arm.com 88110458Sandreas.hansson@arm.com def ini_str(self): 88210458Sandreas.hansson@arm.com return '%f' % self.getValue() 8833101Sstever@eecs.umich.edu 8843101Sstever@eecs.umich.educlass MemoryBandwidth(float,ParamValue): 8853101Sstever@eecs.umich.edu cxx_type = 'float' 8863101Sstever@eecs.umich.edu def __new__(self, value): 8873101Sstever@eecs.umich.edu # we want the number of ticks per byte of data 8883101Sstever@eecs.umich.edu val = convert.toMemoryBandwidth(value) 8893101Sstever@eecs.umich.edu return super(cls, MemoryBandwidth).__new__(cls, val) 8903101Sstever@eecs.umich.edu 8913101Sstever@eecs.umich.edu def __str__(self): 8923101Sstever@eecs.umich.edu return str(self.val) 8933101Sstever@eecs.umich.edu 8943101Sstever@eecs.umich.edu def getValue(self): 8954380Sbinkertn@umich.edu # convert to seconds per byte 8964380Sbinkertn@umich.edu value = 1.0 / float(self) 8974380Sbinkertn@umich.edu # convert to ticks per byte 8983101Sstever@eecs.umich.edu value = ticks.fromSeconds(value) 8994380Sbinkertn@umich.edu return float(value) 9004380Sbinkertn@umich.edu 9014380Sbinkertn@umich.edu def ini_str(self): 9023101Sstever@eecs.umich.edu return '%f' % self.getValue() 9033101Sstever@eecs.umich.edu 9043101Sstever@eecs.umich.edu# 90510267SGeoffrey.Blake@arm.com# "Constants"... handy aliases for various values. 90610267SGeoffrey.Blake@arm.com# 9077673Snate@binkert.org 9087673Snate@binkert.org# Special class for NULL pointers. Note the special check in 9097673Snate@binkert.org# make_param_value() above that lets these be assigned where a 9107673Snate@binkert.org# SimObject is required. 9117673Snate@binkert.org# only one copy of a particular node 9127673Snate@binkert.orgclass NullSimObject(object): 9137673Snate@binkert.org __metaclass__ = Singleton 9147673Snate@binkert.org 9157673Snate@binkert.org def __call__(cls): 9163101Sstever@eecs.umich.edu return cls 9173101Sstever@eecs.umich.edu 9183101Sstever@eecs.umich.edu def _instantiate(self, parent = None, path = ''): 9193101Sstever@eecs.umich.edu pass 9203101Sstever@eecs.umich.edu 9213101Sstever@eecs.umich.edu def ini_str(self): 9223101Sstever@eecs.umich.edu return 'Null' 9233101Sstever@eecs.umich.edu 9243101Sstever@eecs.umich.edu def unproxy(self, base): 9253101Sstever@eecs.umich.edu return self 9263101Sstever@eecs.umich.edu 9273101Sstever@eecs.umich.edu def set_path(self, parent, name): 9283101Sstever@eecs.umich.edu pass 9299941SGeoffrey.Blake@arm.com 9303101Sstever@eecs.umich.edu def __str__(self): 9313101Sstever@eecs.umich.edu return 'Null' 9323101Sstever@eecs.umich.edu 9333101Sstever@eecs.umich.edu def getValue(self): 93410267SGeoffrey.Blake@arm.com return None 93510267SGeoffrey.Blake@arm.com 93610267SGeoffrey.Blake@arm.com# The only instance you'll ever need... 93710267SGeoffrey.Blake@arm.comNULL = NullSimObject() 9383101Sstever@eecs.umich.edu 9393101Sstever@eecs.umich.edudef isNullPointer(value): 9404380Sbinkertn@umich.edu return isinstance(value, NullSimObject) 9413101Sstever@eecs.umich.edu 9423101Sstever@eecs.umich.edu# Some memory range specifications use this as a default upper bound. 9434762Snate@binkert.orgMaxAddr = Addr.max 9447677Snate@binkert.orgMaxTick = Tick.max 9454762Snate@binkert.orgAllMemory = AddrRange(0, MaxAddr) 9464762Snate@binkert.org 94711228SAndrew.Bardsley@arm.com 94811228SAndrew.Bardsley@arm.com##################################################################### 94911228SAndrew.Bardsley@arm.com# 9504380Sbinkertn@umich.edu# Port objects 9514380Sbinkertn@umich.edu# 9523101Sstever@eecs.umich.edu# Ports are used to interconnect objects in the memory system. 95310458Sandreas.hansson@arm.com# 95410458Sandreas.hansson@arm.com##################################################################### 95510458Sandreas.hansson@arm.com 95610458Sandreas.hansson@arm.com# Port reference: encapsulates a reference to a particular port on a 95710458Sandreas.hansson@arm.com# particular SimObject. 9587777Sgblack@eecs.umich.educlass PortRef(object): 9597777Sgblack@eecs.umich.edu def __init__(self, simobj, name): 9607777Sgblack@eecs.umich.edu assert(isSimObject(simobj) or isSimObjectClass(simobj)) 9617777Sgblack@eecs.umich.edu self.simobj = simobj 96210267SGeoffrey.Blake@arm.com self.name = name 96310267SGeoffrey.Blake@arm.com self.peer = None # not associated with another port yet 9647777Sgblack@eecs.umich.edu self.ccConnected = False # C++ port connection done? 9657777Sgblack@eecs.umich.edu self.index = -1 # always -1 for non-vector ports 9667777Sgblack@eecs.umich.edu 9677777Sgblack@eecs.umich.edu def __str__(self): 9687777Sgblack@eecs.umich.edu return '%s.%s' % (self.simobj, self.name) 9697777Sgblack@eecs.umich.edu 9707777Sgblack@eecs.umich.edu # for config.ini, print peer's name (not ours) 9717777Sgblack@eecs.umich.edu def ini_str(self): 9727777Sgblack@eecs.umich.edu return str(self.peer) 9737777Sgblack@eecs.umich.edu 9747777Sgblack@eecs.umich.edu def __getattr__(self, attr): 9757777Sgblack@eecs.umich.edu if attr == 'peerObj': 9767777Sgblack@eecs.umich.edu # shorthand for proxies 9777777Sgblack@eecs.umich.edu return self.peer.simobj 9787777Sgblack@eecs.umich.edu raise AttributeError, "'%s' object has no attribute '%s'" % \ 9797777Sgblack@eecs.umich.edu (self.__class__.__name__, attr) 9807777Sgblack@eecs.umich.edu 9817777Sgblack@eecs.umich.edu # Full connection is symmetric (both ways). Called via 9827777Sgblack@eecs.umich.edu # SimObject.__setattr__ as a result of a port assignment, e.g., 98310267SGeoffrey.Blake@arm.com # "obj1.portA = obj2.portB", or via VectorPortElementRef.__setitem__, 98410267SGeoffrey.Blake@arm.com # e.g., "obj1.portA[3] = obj2.portB". 98510267SGeoffrey.Blake@arm.com def connect(self, other): 98610267SGeoffrey.Blake@arm.com if isinstance(other, VectorPortRef): 9878579Ssteve.reinhardt@amd.com # reference to plain VectorPort is implicit append 9888579Ssteve.reinhardt@amd.com other = other._get_next() 9898579Ssteve.reinhardt@amd.com if self.peer and not proxy.isproxy(self.peer): 9908579Ssteve.reinhardt@amd.com print "warning: overwriting port", self, \ 9918579Ssteve.reinhardt@amd.com "value", self.peer, "with", other 9928579Ssteve.reinhardt@amd.com self.peer = other 9938579Ssteve.reinhardt@amd.com if proxy.isproxy(other): 9948579Ssteve.reinhardt@amd.com other.set_param_desc(PortParamDesc()) 9958579Ssteve.reinhardt@amd.com elif isinstance(other, PortRef): 9968579Ssteve.reinhardt@amd.com if other.peer is not self: 9978579Ssteve.reinhardt@amd.com other.connect(self) 9988579Ssteve.reinhardt@amd.com else: 9998579Ssteve.reinhardt@amd.com raise TypeError, \ 10008579Ssteve.reinhardt@amd.com "assigning non-port reference '%s' to port '%s'" \ 10018579Ssteve.reinhardt@amd.com % (other, self) 10028579Ssteve.reinhardt@amd.com 10038579Ssteve.reinhardt@amd.com def clone(self, simobj, memo): 10048579Ssteve.reinhardt@amd.com if memo.has_key(self): 10057777Sgblack@eecs.umich.edu return memo[self] 10067777Sgblack@eecs.umich.edu newRef = copy.copy(self) 10077798Sgblack@eecs.umich.edu memo[self] = newRef 10087777Sgblack@eecs.umich.edu newRef.simobj = simobj 10097777Sgblack@eecs.umich.edu assert(isSimObject(newRef.simobj)) 10107777Sgblack@eecs.umich.edu if self.peer and not proxy.isproxy(self.peer): 10117777Sgblack@eecs.umich.edu peerObj = self.peer.simobj(_memo=memo) 10127777Sgblack@eecs.umich.edu newRef.peer = self.peer.clone(peerObj, memo) 10137777Sgblack@eecs.umich.edu assert(not isinstance(newRef.peer, VectorPortRef)) 10147777Sgblack@eecs.umich.edu return newRef 10157777Sgblack@eecs.umich.edu 10167777Sgblack@eecs.umich.edu def unproxy(self, simobj): 10177777Sgblack@eecs.umich.edu assert(simobj is self.simobj) 101810267SGeoffrey.Blake@arm.com if proxy.isproxy(self.peer): 101910267SGeoffrey.Blake@arm.com try: 10207777Sgblack@eecs.umich.edu realPeer = self.peer.unproxy(self.simobj) 10217777Sgblack@eecs.umich.edu except: 10227777Sgblack@eecs.umich.edu print "Error in unproxying port '%s' of %s" % \ 10237777Sgblack@eecs.umich.edu (self.name, self.simobj.path()) 10247777Sgblack@eecs.umich.edu raise 10257777Sgblack@eecs.umich.edu self.connect(realPeer) 10267777Sgblack@eecs.umich.edu 10277777Sgblack@eecs.umich.edu # Call C++ to create corresponding port connection between C++ objects 10287777Sgblack@eecs.umich.edu def ccConnect(self): 10297777Sgblack@eecs.umich.edu from m5.objects.params import connectPorts 10307777Sgblack@eecs.umich.edu 10317777Sgblack@eecs.umich.edu if self.ccConnected: # already done this 10327777Sgblack@eecs.umich.edu return 10337777Sgblack@eecs.umich.edu peer = self.peer 10347777Sgblack@eecs.umich.edu connectPorts(self.simobj.getCCObject(), self.name, self.index, 10357777Sgblack@eecs.umich.edu peer.simobj.getCCObject(), peer.name, peer.index) 10367777Sgblack@eecs.umich.edu self.ccConnected = True 10377777Sgblack@eecs.umich.edu peer.ccConnected = True 10387777Sgblack@eecs.umich.edu 10397777Sgblack@eecs.umich.edu# A reference to an individual element of a VectorPort... much like a 10407777Sgblack@eecs.umich.edu# PortRef, but has an index. 10417777Sgblack@eecs.umich.educlass VectorPortElementRef(PortRef): 10427777Sgblack@eecs.umich.edu def __init__(self, simobj, name, index): 10437777Sgblack@eecs.umich.edu PortRef.__init__(self, simobj, name) 10447777Sgblack@eecs.umich.edu self.index = index 10457777Sgblack@eecs.umich.edu 10467777Sgblack@eecs.umich.edu def __str__(self): 10477777Sgblack@eecs.umich.edu return '%s.%s[%d]' % (self.simobj, self.name, self.index) 10487777Sgblack@eecs.umich.edu 10497777Sgblack@eecs.umich.edu# A reference to a complete vector-valued port (not just a single element). 10507777Sgblack@eecs.umich.edu# Can be indexed to retrieve individual VectorPortElementRef instances. 10517777Sgblack@eecs.umich.educlass VectorPortRef(object): 10527777Sgblack@eecs.umich.edu def __init__(self, simobj, name): 10537777Sgblack@eecs.umich.edu assert(isSimObject(simobj) or isSimObjectClass(simobj)) 10547777Sgblack@eecs.umich.edu self.simobj = simobj 10557777Sgblack@eecs.umich.edu self.name = name 10567777Sgblack@eecs.umich.edu self.elements = [] 10577777Sgblack@eecs.umich.edu 10587777Sgblack@eecs.umich.edu def __str__(self): 10597777Sgblack@eecs.umich.edu return '%s.%s[:]' % (self.simobj, self.name) 10607777Sgblack@eecs.umich.edu 10617777Sgblack@eecs.umich.edu # for config.ini, print peer's name (not ours) 10627777Sgblack@eecs.umich.edu def ini_str(self): 10637777Sgblack@eecs.umich.edu return ' '.join([el.ini_str() for el in self.elements]) 10647777Sgblack@eecs.umich.edu 106510267SGeoffrey.Blake@arm.com def __getitem__(self, key): 106610267SGeoffrey.Blake@arm.com if not isinstance(key, int): 106710267SGeoffrey.Blake@arm.com raise TypeError, "VectorPort index must be integer" 106810267SGeoffrey.Blake@arm.com if key >= len(self.elements): 10698579Ssteve.reinhardt@amd.com # need to extend list 10708579Ssteve.reinhardt@amd.com ext = [VectorPortElementRef(self.simobj, self.name, i) 10718579Ssteve.reinhardt@amd.com for i in range(len(self.elements), key+1)] 10728579Ssteve.reinhardt@amd.com self.elements.extend(ext) 10738579Ssteve.reinhardt@amd.com return self.elements[key] 10748579Ssteve.reinhardt@amd.com 10758579Ssteve.reinhardt@amd.com def _get_next(self): 10768579Ssteve.reinhardt@amd.com return self[len(self.elements)] 10778579Ssteve.reinhardt@amd.com 10788579Ssteve.reinhardt@amd.com def __setitem__(self, key, value): 10798579Ssteve.reinhardt@amd.com if not isinstance(key, int): 10808579Ssteve.reinhardt@amd.com raise TypeError, "VectorPort index must be integer" 10818579Ssteve.reinhardt@amd.com self[key].connect(value) 10828579Ssteve.reinhardt@amd.com 10837777Sgblack@eecs.umich.edu def connect(self, other): 10847777Sgblack@eecs.umich.edu if isinstance(other, (list, tuple)): 10857777Sgblack@eecs.umich.edu # Assign list of port refs to vector port. 10867777Sgblack@eecs.umich.edu # For now, append them... not sure if that's the right semantics 10877777Sgblack@eecs.umich.edu # or if it should replace the current vector. 10887777Sgblack@eecs.umich.edu for ref in other: 10897777Sgblack@eecs.umich.edu self._get_next().connect(ref) 10907777Sgblack@eecs.umich.edu else: 10917777Sgblack@eecs.umich.edu # scalar assignment to plain VectorPort is implicit append 10927777Sgblack@eecs.umich.edu self._get_next().connect(other) 10937777Sgblack@eecs.umich.edu 10947777Sgblack@eecs.umich.edu def clone(self, simobj, memo): 10957777Sgblack@eecs.umich.edu if memo.has_key(self): 109610267SGeoffrey.Blake@arm.com return memo[self] 109710267SGeoffrey.Blake@arm.com newRef = copy.copy(self) 10987777Sgblack@eecs.umich.edu memo[self] = newRef 10997777Sgblack@eecs.umich.edu newRef.simobj = simobj 11007777Sgblack@eecs.umich.edu assert(isSimObject(newRef.simobj)) 11017777Sgblack@eecs.umich.edu newRef.elements = [el.clone(simobj, memo) for el in self.elements] 11027777Sgblack@eecs.umich.edu return newRef 11037777Sgblack@eecs.umich.edu 11047777Sgblack@eecs.umich.edu def unproxy(self, simobj): 11057777Sgblack@eecs.umich.edu [el.unproxy(simobj) for el in self.elements] 11067777Sgblack@eecs.umich.edu 11077777Sgblack@eecs.umich.edu def ccConnect(self): 11087777Sgblack@eecs.umich.edu [el.ccConnect() for el in self.elements] 11097777Sgblack@eecs.umich.edu 11107777Sgblack@eecs.umich.edu# Port description object. Like a ParamDesc object, this represents a 11117777Sgblack@eecs.umich.edu# logical port in the SimObject class, not a particular port on a 11127777Sgblack@eecs.umich.edu# SimObject instance. The latter are represented by PortRef objects. 11137777Sgblack@eecs.umich.educlass Port(object): 11147777Sgblack@eecs.umich.edu # Port("description") or Port(default, "description") 11157777Sgblack@eecs.umich.edu def __init__(self, *args): 11167777Sgblack@eecs.umich.edu if len(args) == 1: 11177777Sgblack@eecs.umich.edu self.desc = args[0] 11187777Sgblack@eecs.umich.edu elif len(args) == 2: 11197777Sgblack@eecs.umich.edu self.default = args[0] 11207777Sgblack@eecs.umich.edu self.desc = args[1] 11217777Sgblack@eecs.umich.edu else: 11227777Sgblack@eecs.umich.edu raise TypeError, 'wrong number of arguments' 11237777Sgblack@eecs.umich.edu # self.name is set by SimObject class on assignment 11247777Sgblack@eecs.umich.edu # e.g., pio_port = Port("blah") sets self.name to 'pio_port' 11257777Sgblack@eecs.umich.edu 11267777Sgblack@eecs.umich.edu # Generate a PortRef for this port on the given SimObject with the 11277777Sgblack@eecs.umich.edu # given name 11287777Sgblack@eecs.umich.edu def makeRef(self, simobj): 11297777Sgblack@eecs.umich.edu return PortRef(simobj, self.name) 11307777Sgblack@eecs.umich.edu 11317777Sgblack@eecs.umich.edu # Connect an instance of this port (on the given SimObject with 11327777Sgblack@eecs.umich.edu # the given name) with the port described by the supplied PortRef 11337777Sgblack@eecs.umich.edu def connect(self, simobj, ref): 11347777Sgblack@eecs.umich.edu self.makeRef(simobj).connect(ref) 11357777Sgblack@eecs.umich.edu 11367777Sgblack@eecs.umich.edu# VectorPort description object. Like Port, but represents a vector 11377777Sgblack@eecs.umich.edu# of connections (e.g., as on a Bus). 11387777Sgblack@eecs.umich.educlass VectorPort(Port): 11397777Sgblack@eecs.umich.edu def __init__(self, *args): 11407777Sgblack@eecs.umich.edu Port.__init__(self, *args) 11417777Sgblack@eecs.umich.edu self.isVec = True 11427777Sgblack@eecs.umich.edu 114310267SGeoffrey.Blake@arm.com def makeRef(self, simobj): 114410267SGeoffrey.Blake@arm.com return VectorPortRef(simobj, self.name) 114510267SGeoffrey.Blake@arm.com 114610267SGeoffrey.Blake@arm.com# 'Fake' ParamDesc for Port references to assign to the _pdesc slot of 11478579Ssteve.reinhardt@amd.com# proxy objects (via set_param_desc()) so that proxy error messages 11488579Ssteve.reinhardt@amd.com# make sense. 11498579Ssteve.reinhardt@amd.comclass PortParamDesc(object): 11508579Ssteve.reinhardt@amd.com __metaclass__ = Singleton 11518579Ssteve.reinhardt@amd.com 11528579Ssteve.reinhardt@amd.com ptype_str = 'Port' 11538579Ssteve.reinhardt@amd.com ptype = Port 11548579Ssteve.reinhardt@amd.com 11558579Ssteve.reinhardt@amd.com__all__ = ['Param', 'VectorParam', 11568579Ssteve.reinhardt@amd.com 'Enum', 'Bool', 'String', 'Float', 11578579Ssteve.reinhardt@amd.com 'Int', 'Unsigned', 'Int8', 'UInt8', 'Int16', 'UInt16', 11588579Ssteve.reinhardt@amd.com 'Int32', 'UInt32', 'Int64', 'UInt64', 11598579Ssteve.reinhardt@amd.com 'Counter', 'Addr', 'Tick', 'Percent', 11608579Ssteve.reinhardt@amd.com 'TcpPort', 'UdpPort', 'EthernetAddr', 11617777Sgblack@eecs.umich.edu 'MemorySize', 'MemorySize32', 11627777Sgblack@eecs.umich.edu 'Latency', 'Frequency', 'Clock', 11637777Sgblack@eecs.umich.edu 'NetworkBandwidth', 'MemoryBandwidth', 11647777Sgblack@eecs.umich.edu 'Range', 'AddrRange', 'TickRange', 11657777Sgblack@eecs.umich.edu 'MaxAddr', 'MaxTick', 'AllMemory', 11667777Sgblack@eecs.umich.edu 'Time', 11677777Sgblack@eecs.umich.edu 'NextEthernetAddr', 'NULL', 11687777Sgblack@eecs.umich.edu 'Port', 'VectorPort'] 11697777Sgblack@eecs.umich.edu