params.py revision 5468
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 __init__(self, value): 3838596Ssteve.reinhardt@amd.com if isinstance(value, (int, long, float, NumericParamValue, Float)): 3848596Ssteve.reinhardt@amd.com self.value = float(value) 3857673Snate@binkert.org else: 3868596Ssteve.reinhardt@amd.com raise TypeError, "Can't convert object of type %s to Float" \ 3874762Snate@binkert.org % type(value).__name__ 3887673Snate@binkert.org 3898596Ssteve.reinhardt@amd.com def getValue(self): 3907675Snate@binkert.org return float(self.value) 3917675Snate@binkert.org 3927675Snate@binkert.orgclass MemorySize(CheckedInt): 3937675Snate@binkert.org cxx_type = 'uint64_t' 3948656Sandreas.hansson@arm.com size = 64 3958656Sandreas.hansson@arm.com unsigned = True 3968656Sandreas.hansson@arm.com def __init__(self, value): 3977675Snate@binkert.org if isinstance(value, MemorySize): 3987675Snate@binkert.org self.value = value.value 3997673Snate@binkert.org else: 4007675Snate@binkert.org self.value = convert.toMemorySize(value) 4017675Snate@binkert.org self._check() 4027675Snate@binkert.org 4037675Snate@binkert.orgclass MemorySize32(CheckedInt): 4047675Snate@binkert.org cxx_type = 'uint32_t' 4057675Snate@binkert.org size = 32 4067675Snate@binkert.org unsigned = True 4077673Snate@binkert.org def __init__(self, value): 4087673Snate@binkert.org if isinstance(value, MemorySize): 4097673Snate@binkert.org self.value = value.value 4103101Sstever@eecs.umich.edu else: 4117673Snate@binkert.org self.value = convert.toMemorySize(value) 4127673Snate@binkert.org self._check() 4133101Sstever@eecs.umich.edu 4143101Sstever@eecs.umich.educlass Addr(CheckedInt): 4153101Sstever@eecs.umich.edu cxx_type = 'Addr' 4163101Sstever@eecs.umich.edu size = 64 4173101Sstever@eecs.umich.edu unsigned = True 4183101Sstever@eecs.umich.edu def __init__(self, value): 4193101Sstever@eecs.umich.edu if isinstance(value, Addr): 4203101Sstever@eecs.umich.edu self.value = value.value 4213101Sstever@eecs.umich.edu else: 4223101Sstever@eecs.umich.edu try: 4233101Sstever@eecs.umich.edu self.value = convert.toMemorySize(value) 4243101Sstever@eecs.umich.edu except TypeError: 4253101Sstever@eecs.umich.edu self.value = long(value) 4263101Sstever@eecs.umich.edu self._check() 4273101Sstever@eecs.umich.edu def __add__(self, other): 4285033Smilesck@eecs.umich.edu if isinstance(other, Addr): 4295033Smilesck@eecs.umich.edu return self.value + other.value 4303101Sstever@eecs.umich.edu else: 4313101Sstever@eecs.umich.edu return self.value + other 4323101Sstever@eecs.umich.edu 4333101Sstever@eecs.umich.edu 4343101Sstever@eecs.umich.educlass MetaRange(MetaParamValue): 4353101Sstever@eecs.umich.edu def __init__(cls, name, bases, dict): 4363101Sstever@eecs.umich.edu super(MetaRange, cls).__init__(name, bases, dict) 4373101Sstever@eecs.umich.edu if name == 'Range': 4383101Sstever@eecs.umich.edu return 4393101Sstever@eecs.umich.edu cls.cxx_type = 'Range< %s >' % cls.type.cxx_type 4403101Sstever@eecs.umich.edu cls.cxx_predecls = \ 4413101Sstever@eecs.umich.edu ['#include "base/range.hh"'] + cls.type.cxx_predecls 4423101Sstever@eecs.umich.edu 4433101Sstever@eecs.umich.educlass Range(ParamValue): 4443101Sstever@eecs.umich.edu __metaclass__ = MetaRange 4453101Sstever@eecs.umich.edu type = Int # default; can be overridden in subclasses 4463101Sstever@eecs.umich.edu def __init__(self, *args, **kwargs): 4473101Sstever@eecs.umich.edu def handle_kwargs(self, kwargs): 4483101Sstever@eecs.umich.edu if 'end' in kwargs: 4493101Sstever@eecs.umich.edu self.second = self.type(kwargs.pop('end')) 4503101Sstever@eecs.umich.edu elif 'size' in kwargs: 4513101Sstever@eecs.umich.edu self.second = self.first + self.type(kwargs.pop('size')) - 1 4523101Sstever@eecs.umich.edu else: 4533101Sstever@eecs.umich.edu raise TypeError, "Either end or size must be specified" 4543101Sstever@eecs.umich.edu 45510267SGeoffrey.Blake@arm.com if len(args) == 0: 4567673Snate@binkert.org self.first = self.type(kwargs.pop('start')) 4577673Snate@binkert.org handle_kwargs(self, kwargs) 4587673Snate@binkert.org 4597673Snate@binkert.org elif len(args) == 1: 4607673Snate@binkert.org if kwargs: 4617673Snate@binkert.org self.first = self.type(args[0]) 4627673Snate@binkert.org handle_kwargs(self, kwargs) 4637673Snate@binkert.org elif isinstance(args[0], Range): 4644762Snate@binkert.org self.first = self.type(args[0].first) 46510267SGeoffrey.Blake@arm.com self.second = self.type(args[0].second) 46610267SGeoffrey.Blake@arm.com elif isinstance(args[0], (list, tuple)): 46710267SGeoffrey.Blake@arm.com self.first = self.type(args[0][0]) 46810267SGeoffrey.Blake@arm.com self.second = self.type(args[0][1]) 46910458Sandreas.hansson@arm.com else: 47010458Sandreas.hansson@arm.com self.first = self.type(0) 47110458Sandreas.hansson@arm.com self.second = self.type(args[0]) - 1 47210458Sandreas.hansson@arm.com 47310458Sandreas.hansson@arm.com elif len(args) == 2: 4744762Snate@binkert.org self.first = self.type(args[0]) 4754762Snate@binkert.org self.second = self.type(args[1]) 4763101Sstever@eecs.umich.edu else: 4773101Sstever@eecs.umich.edu raise TypeError, "Too many arguments specified" 4783101Sstever@eecs.umich.edu 4793101Sstever@eecs.umich.edu if kwargs: 4803101Sstever@eecs.umich.edu raise TypeError, "too many keywords: %s" % kwargs.keys() 4813101Sstever@eecs.umich.edu 4823101Sstever@eecs.umich.edu def __str__(self): 4833101Sstever@eecs.umich.edu return '%s:%s' % (self.first, self.second) 4843101Sstever@eecs.umich.edu 4853101Sstever@eecs.umich.educlass AddrRange(Range): 4863101Sstever@eecs.umich.edu type = Addr 4873714Sstever@eecs.umich.edu swig_predecls = ['%include "python/swig/range.i"'] 4883714Sstever@eecs.umich.edu 4893714Sstever@eecs.umich.edu def getValue(self): 4903714Sstever@eecs.umich.edu from m5.objects.params import AddrRange 4913714Sstever@eecs.umich.edu 4923714Sstever@eecs.umich.edu value = AddrRange() 4933101Sstever@eecs.umich.edu value.start = long(self.first) 4943101Sstever@eecs.umich.edu value.end = long(self.second) 4953101Sstever@eecs.umich.edu return value 4963101Sstever@eecs.umich.edu 4973101Sstever@eecs.umich.educlass TickRange(Range): 4983101Sstever@eecs.umich.edu type = Tick 4993101Sstever@eecs.umich.edu swig_predecls = ['%include "python/swig/range.i"'] 5003101Sstever@eecs.umich.edu 5013101Sstever@eecs.umich.edu def getValue(self): 5023101Sstever@eecs.umich.edu from m5.objects.params import TickRange 5033101Sstever@eecs.umich.edu 5043101Sstever@eecs.umich.edu value = TickRange() 5053101Sstever@eecs.umich.edu value.start = long(self.first) 5063101Sstever@eecs.umich.edu value.end = long(self.second) 5073101Sstever@eecs.umich.edu return value 5083101Sstever@eecs.umich.edu 5093101Sstever@eecs.umich.edu# Boolean parameter type. Python doesn't let you subclass bool, since 5103101Sstever@eecs.umich.edu# it doesn't want to let you create multiple instances of True and 5113101Sstever@eecs.umich.edu# False. Thus this is a little more complicated than String. 5123101Sstever@eecs.umich.educlass Bool(ParamValue): 5133101Sstever@eecs.umich.edu cxx_type = 'bool' 5143101Sstever@eecs.umich.edu def __init__(self, value): 5153101Sstever@eecs.umich.edu try: 5163101Sstever@eecs.umich.edu self.value = convert.toBool(value) 51710380SAndrew.Bardsley@arm.com except TypeError: 51810380SAndrew.Bardsley@arm.com self.value = bool(value) 51910380SAndrew.Bardsley@arm.com 52010458Sandreas.hansson@arm.com def getValue(self): 52110458Sandreas.hansson@arm.com return bool(self.value) 52210458Sandreas.hansson@arm.com 52310458Sandreas.hansson@arm.com def __str__(self): 52410458Sandreas.hansson@arm.com return str(self.value) 52510458Sandreas.hansson@arm.com 52610458Sandreas.hansson@arm.com def ini_str(self): 52710458Sandreas.hansson@arm.com if self.value: 52810458Sandreas.hansson@arm.com return 'true' 52910458Sandreas.hansson@arm.com return 'false' 53010458Sandreas.hansson@arm.com 53110458Sandreas.hansson@arm.comdef IncEthernetAddr(addr, val = 1): 53210458Sandreas.hansson@arm.com bytes = map(lambda x: int(x, 16), addr.split(':')) 5333101Sstever@eecs.umich.edu bytes[5] += val 5345033Smilesck@eecs.umich.edu for i in (5, 4, 3, 2, 1): 5353101Sstever@eecs.umich.edu val,rem = divmod(bytes[i], 256) 5363101Sstever@eecs.umich.edu bytes[i] = rem 5373101Sstever@eecs.umich.edu if val == 0: 5383101Sstever@eecs.umich.edu break 5393101Sstever@eecs.umich.edu bytes[i - 1] += val 5403101Sstever@eecs.umich.edu assert(bytes[0] <= 255) 5413101Sstever@eecs.umich.edu return ':'.join(map(lambda x: '%02x' % x, bytes)) 5423101Sstever@eecs.umich.edu 5433101Sstever@eecs.umich.edu_NextEthernetAddr = "00:90:00:00:00:01" 5443101Sstever@eecs.umich.edudef NextEthernetAddr(): 5453101Sstever@eecs.umich.edu global _NextEthernetAddr 5463101Sstever@eecs.umich.edu 5475822Ssaidi@eecs.umich.edu value = _NextEthernetAddr 5485822Ssaidi@eecs.umich.edu _NextEthernetAddr = IncEthernetAddr(_NextEthernetAddr, 1) 5493101Sstever@eecs.umich.edu return value 5503101Sstever@eecs.umich.edu 5513101Sstever@eecs.umich.educlass EthernetAddr(ParamValue): 5523101Sstever@eecs.umich.edu cxx_type = 'Net::EthAddr' 5533101Sstever@eecs.umich.edu cxx_predecls = ['#include "base/inet.hh"'] 5543101Sstever@eecs.umich.edu swig_predecls = ['%include "python/swig/inet.i"'] 5553101Sstever@eecs.umich.edu def __init__(self, value): 5563101Sstever@eecs.umich.edu if value == NextEthernetAddr: 5573101Sstever@eecs.umich.edu self.value = value 5583101Sstever@eecs.umich.edu return 5593101Sstever@eecs.umich.edu 5603101Sstever@eecs.umich.edu if not isinstance(value, str): 5613101Sstever@eecs.umich.edu raise TypeError, "expected an ethernet address and didn't get one" 56210267SGeoffrey.Blake@arm.com 5633101Sstever@eecs.umich.edu bytes = value.split(':') 5643101Sstever@eecs.umich.edu if len(bytes) != 6: 5653101Sstever@eecs.umich.edu raise TypeError, 'invalid ethernet address %s' % value 5663101Sstever@eecs.umich.edu 5673101Sstever@eecs.umich.edu for byte in bytes: 5683101Sstever@eecs.umich.edu if not 0 <= int(byte) <= 256: 5693101Sstever@eecs.umich.edu raise TypeError, 'invalid ethernet address %s' % value 5703101Sstever@eecs.umich.edu 5713102Sstever@eecs.umich.edu self.value = value 5723714Sstever@eecs.umich.edu 5733101Sstever@eecs.umich.edu def unproxy(self, base): 5743714Sstever@eecs.umich.edu if self.value == NextEthernetAddr: 5753714Sstever@eecs.umich.edu return EthernetAddr(self.value()) 5763714Sstever@eecs.umich.edu return self 5773101Sstever@eecs.umich.edu 5783101Sstever@eecs.umich.edu def getValue(self): 57910267SGeoffrey.Blake@arm.com from m5.objects.params import EthAddr 58010267SGeoffrey.Blake@arm.com return EthAddr(self.value) 58110267SGeoffrey.Blake@arm.com 58210267SGeoffrey.Blake@arm.com def ini_str(self): 5837673Snate@binkert.org return self.value 5847673Snate@binkert.org 5857673Snate@binkert.orgtime_formats = [ "%a %b %d %H:%M:%S %Z %Y", 5867673Snate@binkert.org "%a %b %d %H:%M:%S %Z %Y", 5877673Snate@binkert.org "%Y/%m/%d %H:%M:%S", 5887673Snate@binkert.org "%Y/%m/%d %H:%M", 5897673Snate@binkert.org "%Y/%m/%d", 5907673Snate@binkert.org "%m/%d/%Y %H:%M:%S", 5917673Snate@binkert.org "%m/%d/%Y %H:%M", 5927673Snate@binkert.org "%m/%d/%Y", 5937673Snate@binkert.org "%m/%d/%y %H:%M:%S", 5944762Snate@binkert.org "%m/%d/%y %H:%M", 5954762Snate@binkert.org "%m/%d/%y"] 5964762Snate@binkert.org 5973101Sstever@eecs.umich.edu 5983101Sstever@eecs.umich.edudef parse_time(value): 5993101Sstever@eecs.umich.edu from time import gmtime, strptime, struct_time, time 6003101Sstever@eecs.umich.edu from datetime import datetime, date 6013101Sstever@eecs.umich.edu 6023101Sstever@eecs.umich.edu if isinstance(value, struct_time): 6033101Sstever@eecs.umich.edu return value 6043101Sstever@eecs.umich.edu 6053101Sstever@eecs.umich.edu if isinstance(value, (int, long)): 6063101Sstever@eecs.umich.edu return gmtime(value) 6073101Sstever@eecs.umich.edu 6083101Sstever@eecs.umich.edu if isinstance(value, (datetime, date)): 6093101Sstever@eecs.umich.edu return value.timetuple() 6103101Sstever@eecs.umich.edu 6113101Sstever@eecs.umich.edu if isinstance(value, str): 6123101Sstever@eecs.umich.edu if value in ('Now', 'Today'): 6133101Sstever@eecs.umich.edu return time.gmtime(time.time()) 6143101Sstever@eecs.umich.edu 6153101Sstever@eecs.umich.edu for format in time_formats: 6169184Sandreas.hansson@arm.com try: 6179184Sandreas.hansson@arm.com return strptime(value, format) 6189184Sandreas.hansson@arm.com except ValueError: 6199184Sandreas.hansson@arm.com pass 6209184Sandreas.hansson@arm.com 6219184Sandreas.hansson@arm.com raise ValueError, "Could not parse '%s' as a time" % value 6229184Sandreas.hansson@arm.com 6239184Sandreas.hansson@arm.comclass Time(ParamValue): 6249184Sandreas.hansson@arm.com cxx_type = 'tm' 62510458Sandreas.hansson@arm.com cxx_predecls = [ '#include <time.h>' ] 62610458Sandreas.hansson@arm.com swig_predecls = [ '%include "python/swig/time.i"' ] 62710458Sandreas.hansson@arm.com def __init__(self, value): 62810458Sandreas.hansson@arm.com self.value = parse_time(value) 62910458Sandreas.hansson@arm.com 63010458Sandreas.hansson@arm.com def getValue(self): 63110458Sandreas.hansson@arm.com from m5.objects.params import tm 63210458Sandreas.hansson@arm.com 63310458Sandreas.hansson@arm.com c_time = tm() 63410458Sandreas.hansson@arm.com py_time = self.value 63510458Sandreas.hansson@arm.com 63610458Sandreas.hansson@arm.com # UNIX is years since 1900 63710458Sandreas.hansson@arm.com c_time.tm_year = py_time.tm_year - 1900; 63810458Sandreas.hansson@arm.com 6393101Sstever@eecs.umich.edu # Python starts at 1, UNIX starts at 0 6404446Sbinkertn@umich.edu c_time.tm_mon = py_time.tm_mon - 1; 64110668SGeoffrey.Blake@arm.com c_time.tm_mday = py_time.tm_mday; 6423101Sstever@eecs.umich.edu c_time.tm_hour = py_time.tm_hour; 6435468Snate@binkert.org c_time.tm_min = py_time.tm_min; 64410267SGeoffrey.Blake@arm.com c_time.tm_sec = py_time.tm_sec; 6455468Snate@binkert.org 6465468Snate@binkert.org # Python has 0 as Monday, UNIX is 0 as sunday 6475468Snate@binkert.org c_time.tm_wday = py_time.tm_wday + 1 6485468Snate@binkert.org if c_time.tm_wday > 6: 6495468Snate@binkert.org c_time.tm_wday -= 7; 65010267SGeoffrey.Blake@arm.com 65110267SGeoffrey.Blake@arm.com # Python starts at 1, Unix starts at 0 65210267SGeoffrey.Blake@arm.com c_time.tm_yday = py_time.tm_yday - 1; 65310267SGeoffrey.Blake@arm.com 6544762Snate@binkert.org return c_time 6554762Snate@binkert.org 6564762Snate@binkert.org def __str__(self): 65710380SAndrew.Bardsley@arm.com return time.asctime(self.value) 65810380SAndrew.Bardsley@arm.com 65910380SAndrew.Bardsley@arm.com def ini_str(self): 66010458Sandreas.hansson@arm.com return str(self) 66110458Sandreas.hansson@arm.com 66210458Sandreas.hansson@arm.com# Enumerated types are a little more complex. The user specifies the 66310458Sandreas.hansson@arm.com# type as Enum(foo) where foo is either a list or dictionary of 66410458Sandreas.hansson@arm.com# alternatives (typically strings, but not necessarily so). (In the 66510458Sandreas.hansson@arm.com# long run, the integer value of the parameter will be the list index 66610458Sandreas.hansson@arm.com# or the corresponding dictionary value. For now, since we only check 66710458Sandreas.hansson@arm.com# that the alternative is valid and then spit it into a .ini file, 6683101Sstever@eecs.umich.edu# there's not much point in using the dictionary.) 6693101Sstever@eecs.umich.edu 67010267SGeoffrey.Blake@arm.com# What Enum() must do is generate a new type encapsulating the 6713101Sstever@eecs.umich.edu# provided list/dictionary so that specific values of the parameter 6723101Sstever@eecs.umich.edu# can be instances of that type. We define two hidden internal 6733101Sstever@eecs.umich.edu# classes (_ListEnum and _DictEnum) to serve as base classes, then 6743101Sstever@eecs.umich.edu# derive the new type from the appropriate base class on the fly. 6753101Sstever@eecs.umich.edu 6763101Sstever@eecs.umich.eduallEnums = {} 6773102Sstever@eecs.umich.edu# Metaclass for Enum types 6783101Sstever@eecs.umich.educlass MetaEnum(MetaParamValue): 6793101Sstever@eecs.umich.edu def __new__(mcls, name, bases, dict): 6803101Sstever@eecs.umich.edu assert name not in allEnums 6814168Sbinkertn@umich.edu 68210267SGeoffrey.Blake@arm.com cls = super(MetaEnum, mcls).__new__(mcls, name, bases, dict) 6833101Sstever@eecs.umich.edu allEnums[name] = cls 6843101Sstever@eecs.umich.edu return cls 6853101Sstever@eecs.umich.edu 6863101Sstever@eecs.umich.edu def __init__(cls, name, bases, init_dict): 6873101Sstever@eecs.umich.edu if init_dict.has_key('map'): 6883101Sstever@eecs.umich.edu if not isinstance(cls.map, dict): 6893102Sstever@eecs.umich.edu raise TypeError, "Enum-derived class attribute 'map' " \ 6903101Sstever@eecs.umich.edu "must be of type dict" 6913101Sstever@eecs.umich.edu # build list of value strings from map 6923101Sstever@eecs.umich.edu cls.vals = cls.map.keys() 6933101Sstever@eecs.umich.edu cls.vals.sort() 6943101Sstever@eecs.umich.edu elif init_dict.has_key('vals'): 6953101Sstever@eecs.umich.edu if not isinstance(cls.vals, list): 6963101Sstever@eecs.umich.edu raise TypeError, "Enum-derived class attribute 'vals' " \ 6973101Sstever@eecs.umich.edu "must be of type list" 6983101Sstever@eecs.umich.edu # build string->value map from vals sequence 6993101Sstever@eecs.umich.edu cls.map = {} 7003101Sstever@eecs.umich.edu for idx,val in enumerate(cls.vals): 70110317Smitch.hayenga@arm.com cls.map[val] = idx 70210317Smitch.hayenga@arm.com else: 70310317Smitch.hayenga@arm.com raise TypeError, "Enum-derived class must define "\ 70410317Smitch.hayenga@arm.com "attribute 'map' or 'vals'" 70510317Smitch.hayenga@arm.com 7063102Sstever@eecs.umich.edu cls.cxx_type = 'Enums::%s' % name 70710317Smitch.hayenga@arm.com 70810317Smitch.hayenga@arm.com super(MetaEnum, cls).__init__(name, bases, init_dict) 70910317Smitch.hayenga@arm.com 71010317Smitch.hayenga@arm.com def __str__(cls): 71110317Smitch.hayenga@arm.com return cls.__name__ 7123101Sstever@eecs.umich.edu 7133584Ssaidi@eecs.umich.edu # Generate C++ class declaration for this enum type. 7143584Ssaidi@eecs.umich.edu # Note that we wrap the enum in a class/struct to act as a namespace, 7153584Ssaidi@eecs.umich.edu # so that the enum strings can be brief w/o worrying about collisions. 7163584Ssaidi@eecs.umich.edu def cxx_decl(cls): 7173584Ssaidi@eecs.umich.edu code = "#ifndef __ENUM__%s\n" % cls 71810267SGeoffrey.Blake@arm.com code += '#define __ENUM__%s\n' % cls 71910267SGeoffrey.Blake@arm.com code += '\n' 72010267SGeoffrey.Blake@arm.com code += 'namespace Enums {\n' 72110267SGeoffrey.Blake@arm.com code += ' enum %s {\n' % cls 72210267SGeoffrey.Blake@arm.com for val in cls.vals: 72310267SGeoffrey.Blake@arm.com code += ' %s = %d,\n' % (val, cls.map[val]) 7243101Sstever@eecs.umich.edu code += ' Num_%s = %d,\n' % (cls, len(cls.vals)) 7259232Sandreas.hansson@arm.com code += ' };\n' 7269235Sandreas.hansson@arm.com code += ' extern const char *%sStrings[Num_%s];\n' % (cls, cls) 7273101Sstever@eecs.umich.edu code += '}\n' 7283101Sstever@eecs.umich.edu code += '\n' 7299411Sandreas.hansson@arm.com code += '#endif\n' 7309411Sandreas.hansson@arm.com return code 7319411Sandreas.hansson@arm.com 7329411Sandreas.hansson@arm.com def cxx_def(cls): 7339411Sandreas.hansson@arm.com code = '#include "enums/%s.hh"\n' % cls 7343101Sstever@eecs.umich.edu code += 'namespace Enums {\n' 7359411Sandreas.hansson@arm.com code += ' const char *%sStrings[Num_%s] =\n' % (cls, cls) 7369411Sandreas.hansson@arm.com code += ' {\n' 7379411Sandreas.hansson@arm.com for val in cls.vals: 7383101Sstever@eecs.umich.edu code += ' "%s",\n' % val 7399232Sandreas.hansson@arm.com code += ' };\n' 7403101Sstever@eecs.umich.edu code += '}\n' 7419232Sandreas.hansson@arm.com return code 7423101Sstever@eecs.umich.edu 7433101Sstever@eecs.umich.edu# Base class for enum types. 7443101Sstever@eecs.umich.educlass Enum(ParamValue): 7459411Sandreas.hansson@arm.com __metaclass__ = MetaEnum 7469411Sandreas.hansson@arm.com vals = [] 7479411Sandreas.hansson@arm.com 7489411Sandreas.hansson@arm.com def __init__(self, value): 7499411Sandreas.hansson@arm.com if value not in self.map: 7509411Sandreas.hansson@arm.com raise TypeError, "Enum param got bad value '%s' (not in %s)" \ 7519411Sandreas.hansson@arm.com % (value, self.vals) 7529411Sandreas.hansson@arm.com self.value = value 7533101Sstever@eecs.umich.edu 7549232Sandreas.hansson@arm.com def getValue(self): 7553101Sstever@eecs.umich.edu return int(self.map[self.value]) 7563101Sstever@eecs.umich.edu 7573101Sstever@eecs.umich.edu def __str__(self): 7583101Sstever@eecs.umich.edu return self.value 7599232Sandreas.hansson@arm.com 7603101Sstever@eecs.umich.edu# how big does a rounding error need to be before we warn about it? 7615219Ssaidi@eecs.umich.edufrequency_tolerance = 0.001 # 0.1% 7629232Sandreas.hansson@arm.com 7639232Sandreas.hansson@arm.comclass TickParamValue(NumericParamValue): 7643101Sstever@eecs.umich.edu cxx_type = 'Tick' 7659232Sandreas.hansson@arm.com cxx_predecls = ['#include "sim/host.hh"'] 7669232Sandreas.hansson@arm.com swig_predecls = ['%import "stdint.i"\n' + 7673101Sstever@eecs.umich.edu '%import "sim/host.hh"'] 7683101Sstever@eecs.umich.edu 7699232Sandreas.hansson@arm.com def getValue(self): 7709232Sandreas.hansson@arm.com return long(self.value) 7713101Sstever@eecs.umich.edu 7723101Sstever@eecs.umich.educlass Latency(TickParamValue): 7733101Sstever@eecs.umich.edu def __init__(self, value): 7743101Sstever@eecs.umich.edu if isinstance(value, (Latency, Clock)): 7759232Sandreas.hansson@arm.com self.ticks = value.ticks 7763101Sstever@eecs.umich.edu self.value = value.value 7773101Sstever@eecs.umich.edu elif isinstance(value, Frequency): 7789232Sandreas.hansson@arm.com self.ticks = value.ticks 7799232Sandreas.hansson@arm.com self.value = 1.0 / value.value 7809232Sandreas.hansson@arm.com elif value.endswith('t'): 7819411Sandreas.hansson@arm.com self.ticks = True 7829411Sandreas.hansson@arm.com self.value = int(value[:-1]) 7833101Sstever@eecs.umich.edu else: 7847673Snate@binkert.org self.ticks = False 7857673Snate@binkert.org self.value = convert.toLatency(value) 7869232Sandreas.hansson@arm.com 7879235Sandreas.hansson@arm.com def __getattr__(self, attr): 7887675Snate@binkert.org if attr in ('latency', 'period'): 7897675Snate@binkert.org return self 7907675Snate@binkert.org if attr == 'frequency': 7919232Sandreas.hansson@arm.com return Frequency(self) 7927673Snate@binkert.org raise AttributeError, "Latency object has no attribute '%s'" % attr 79310458Sandreas.hansson@arm.com 79410458Sandreas.hansson@arm.com def getValue(self): 79510458Sandreas.hansson@arm.com if self.ticks or self.value == 0: 79610458Sandreas.hansson@arm.com value = self.value 79710458Sandreas.hansson@arm.com else: 79810458Sandreas.hansson@arm.com value = ticks.fromSeconds(self.value) 79910458Sandreas.hansson@arm.com return long(value) 80010458Sandreas.hansson@arm.com 80110458Sandreas.hansson@arm.com # convert latency to ticks 80210458Sandreas.hansson@arm.com def ini_str(self): 80310458Sandreas.hansson@arm.com return '%d' % self.getValue() 80410458Sandreas.hansson@arm.com 80510458Sandreas.hansson@arm.comclass Frequency(TickParamValue): 80610458Sandreas.hansson@arm.com def __init__(self, value): 80710458Sandreas.hansson@arm.com if isinstance(value, (Latency, Clock)): 80810458Sandreas.hansson@arm.com if value.value == 0: 80910458Sandreas.hansson@arm.com self.value = 0 81010458Sandreas.hansson@arm.com else: 8114762Snate@binkert.org self.value = 1.0 / value.value 8129235Sandreas.hansson@arm.com self.ticks = value.ticks 8139235Sandreas.hansson@arm.com elif isinstance(value, Frequency): 8147675Snate@binkert.org self.value = value.value 8154762Snate@binkert.org self.ticks = value.ticks 8169411Sandreas.hansson@arm.com else: 8179411Sandreas.hansson@arm.com self.ticks = False 8189411Sandreas.hansson@arm.com self.value = convert.toFrequency(value) 8193101Sstever@eecs.umich.edu 8203101Sstever@eecs.umich.edu def __getattr__(self, attr): 8213101Sstever@eecs.umich.edu if attr == 'frequency': 8223101Sstever@eecs.umich.edu return self 8233101Sstever@eecs.umich.edu if attr in ('latency', 'period'): 8243101Sstever@eecs.umich.edu return Latency(self) 82510267SGeoffrey.Blake@arm.com raise AttributeError, "Frequency object has no attribute '%s'" % attr 82610267SGeoffrey.Blake@arm.com 8273101Sstever@eecs.umich.edu # convert latency to ticks 8283101Sstever@eecs.umich.edu def getValue(self): 8293102Sstever@eecs.umich.edu if self.ticks or self.value == 0: 8303101Sstever@eecs.umich.edu value = self.value 8313101Sstever@eecs.umich.edu else: 8323101Sstever@eecs.umich.edu value = ticks.fromSeconds(1.0 / self.value) 83310267SGeoffrey.Blake@arm.com return long(value) 83410267SGeoffrey.Blake@arm.com 83510267SGeoffrey.Blake@arm.com def ini_str(self): 83610267SGeoffrey.Blake@arm.com return '%d' % self.getValue() 8374762Snate@binkert.org 8384762Snate@binkert.org# A generic frequency and/or Latency value. Value is stored as a latency, 8394762Snate@binkert.org# but to avoid ambiguity this object does not support numeric ops (* or /). 8403101Sstever@eecs.umich.edu# An explicit conversion to a Latency or Frequency must be made first. 8413101Sstever@eecs.umich.educlass Clock(ParamValue): 8423101Sstever@eecs.umich.edu cxx_type = 'Tick' 8438934SBrad.Beckmann@amd.com cxx_predecls = ['#include "sim/host.hh"'] 8448934SBrad.Beckmann@amd.com swig_predecls = ['%import "stdint.i"\n' + 8458934SBrad.Beckmann@amd.com '%import "sim/host.hh"'] 8468934SBrad.Beckmann@amd.com def __init__(self, value): 8478934SBrad.Beckmann@amd.com if isinstance(value, (Latency, Clock)): 8483101Sstever@eecs.umich.edu self.ticks = value.ticks 8493101Sstever@eecs.umich.edu self.value = value.value 8503101Sstever@eecs.umich.edu elif isinstance(value, Frequency): 8513101Sstever@eecs.umich.edu self.ticks = value.ticks 8523101Sstever@eecs.umich.edu self.value = 1.0 / value.value 85310380SAndrew.Bardsley@arm.com elif value.endswith('t'): 85410380SAndrew.Bardsley@arm.com self.ticks = True 85510380SAndrew.Bardsley@arm.com self.value = int(value[:-1]) 85610458Sandreas.hansson@arm.com else: 85710458Sandreas.hansson@arm.com self.ticks = False 85810458Sandreas.hansson@arm.com self.value = convert.anyToLatency(value) 85910458Sandreas.hansson@arm.com 86010458Sandreas.hansson@arm.com def __getattr__(self, attr): 86110458Sandreas.hansson@arm.com if attr == 'frequency': 86210458Sandreas.hansson@arm.com return Frequency(self) 86310458Sandreas.hansson@arm.com if attr in ('latency', 'period'): 86410458Sandreas.hansson@arm.com return Latency(self) 86510458Sandreas.hansson@arm.com raise AttributeError, "Frequency object has no attribute '%s'" % attr 8663101Sstever@eecs.umich.edu 8673101Sstever@eecs.umich.edu def getValue(self): 8683101Sstever@eecs.umich.edu return self.period.getValue() 8693101Sstever@eecs.umich.edu 8703101Sstever@eecs.umich.edu def ini_str(self): 8713101Sstever@eecs.umich.edu return self.period.ini_str() 8723101Sstever@eecs.umich.edu 8733101Sstever@eecs.umich.educlass NetworkBandwidth(float,ParamValue): 8743101Sstever@eecs.umich.edu cxx_type = 'float' 8753101Sstever@eecs.umich.edu def __new__(cls, value): 8763101Sstever@eecs.umich.edu # convert to bits per second 8773101Sstever@eecs.umich.edu val = convert.toNetworkBandwidth(value) 8784380Sbinkertn@umich.edu return super(cls, NetworkBandwidth).__new__(cls, val) 8794380Sbinkertn@umich.edu 8804380Sbinkertn@umich.edu def __str__(self): 8813101Sstever@eecs.umich.edu return str(self.val) 8824380Sbinkertn@umich.edu 8834380Sbinkertn@umich.edu def getValue(self): 8844380Sbinkertn@umich.edu # convert to seconds per byte 8853101Sstever@eecs.umich.edu value = 8.0 / float(self) 8863101Sstever@eecs.umich.edu # convert to ticks per byte 8873101Sstever@eecs.umich.edu value = ticks.fromSeconds(value) 88810267SGeoffrey.Blake@arm.com return float(value) 88910267SGeoffrey.Blake@arm.com 8907673Snate@binkert.org def ini_str(self): 8917673Snate@binkert.org return '%f' % self.getValue() 8927673Snate@binkert.org 8937673Snate@binkert.orgclass MemoryBandwidth(float,ParamValue): 8947673Snate@binkert.org cxx_type = 'float' 8957673Snate@binkert.org def __new__(self, value): 8967673Snate@binkert.org # we want the number of ticks per byte of data 8977673Snate@binkert.org val = convert.toMemoryBandwidth(value) 8987673Snate@binkert.org return super(cls, MemoryBandwidth).__new__(cls, val) 8993101Sstever@eecs.umich.edu 9003101Sstever@eecs.umich.edu def __str__(self): 9013101Sstever@eecs.umich.edu return str(self.val) 9023101Sstever@eecs.umich.edu 9033101Sstever@eecs.umich.edu def getValue(self): 9043101Sstever@eecs.umich.edu # convert to seconds per byte 9053101Sstever@eecs.umich.edu value = float(self) 9063101Sstever@eecs.umich.edu if value: 9073101Sstever@eecs.umich.edu value = 1.0 / float(self) 9083101Sstever@eecs.umich.edu # convert to ticks per byte 9093101Sstever@eecs.umich.edu value = ticks.fromSeconds(value) 9103101Sstever@eecs.umich.edu return float(value) 9113101Sstever@eecs.umich.edu 9129941SGeoffrey.Blake@arm.com def ini_str(self): 9133101Sstever@eecs.umich.edu return '%f' % self.getValue() 9143101Sstever@eecs.umich.edu 9153101Sstever@eecs.umich.edu# 9163101Sstever@eecs.umich.edu# "Constants"... handy aliases for various values. 91710267SGeoffrey.Blake@arm.com# 91810267SGeoffrey.Blake@arm.com 91910267SGeoffrey.Blake@arm.com# Special class for NULL pointers. Note the special check in 92010267SGeoffrey.Blake@arm.com# make_param_value() above that lets these be assigned where a 9213101Sstever@eecs.umich.edu# SimObject is required. 9223101Sstever@eecs.umich.edu# only one copy of a particular node 9234380Sbinkertn@umich.educlass NullSimObject(object): 9243101Sstever@eecs.umich.edu __metaclass__ = Singleton 9253101Sstever@eecs.umich.edu 9264762Snate@binkert.org def __call__(cls): 9277677Snate@binkert.org return cls 9284762Snate@binkert.org 9294762Snate@binkert.org def _instantiate(self, parent = None, path = ''): 9304380Sbinkertn@umich.edu pass 9314380Sbinkertn@umich.edu 9323101Sstever@eecs.umich.edu def ini_str(self): 93310458Sandreas.hansson@arm.com return 'Null' 93410458Sandreas.hansson@arm.com 93510458Sandreas.hansson@arm.com def unproxy(self, base): 93610458Sandreas.hansson@arm.com return self 93710458Sandreas.hansson@arm.com 9387777Sgblack@eecs.umich.edu def set_path(self, parent, name): 9397777Sgblack@eecs.umich.edu pass 9407777Sgblack@eecs.umich.edu 9417777Sgblack@eecs.umich.edu def __str__(self): 94210267SGeoffrey.Blake@arm.com return 'Null' 94310267SGeoffrey.Blake@arm.com 9447777Sgblack@eecs.umich.edu def getValue(self): 9457777Sgblack@eecs.umich.edu return None 9467777Sgblack@eecs.umich.edu 9477777Sgblack@eecs.umich.edu# The only instance you'll ever need... 9487777Sgblack@eecs.umich.eduNULL = NullSimObject() 9497777Sgblack@eecs.umich.edu 9507777Sgblack@eecs.umich.edudef isNullPointer(value): 9517777Sgblack@eecs.umich.edu return isinstance(value, NullSimObject) 9527777Sgblack@eecs.umich.edu 9537777Sgblack@eecs.umich.edu# Some memory range specifications use this as a default upper bound. 9547777Sgblack@eecs.umich.eduMaxAddr = Addr.max 9557777Sgblack@eecs.umich.eduMaxTick = Tick.max 9567777Sgblack@eecs.umich.eduAllMemory = AddrRange(0, MaxAddr) 9577777Sgblack@eecs.umich.edu 9587777Sgblack@eecs.umich.edu 9597777Sgblack@eecs.umich.edu##################################################################### 9607777Sgblack@eecs.umich.edu# 9617777Sgblack@eecs.umich.edu# Port objects 9627777Sgblack@eecs.umich.edu# 96310267SGeoffrey.Blake@arm.com# Ports are used to interconnect objects in the memory system. 96410267SGeoffrey.Blake@arm.com# 96510267SGeoffrey.Blake@arm.com##################################################################### 96610267SGeoffrey.Blake@arm.com 9678579Ssteve.reinhardt@amd.com# Port reference: encapsulates a reference to a particular port on a 9688579Ssteve.reinhardt@amd.com# particular SimObject. 9698579Ssteve.reinhardt@amd.comclass PortRef(object): 9708579Ssteve.reinhardt@amd.com def __init__(self, simobj, name): 9718579Ssteve.reinhardt@amd.com assert(isSimObject(simobj) or isSimObjectClass(simobj)) 9728579Ssteve.reinhardt@amd.com self.simobj = simobj 9738579Ssteve.reinhardt@amd.com self.name = name 9748579Ssteve.reinhardt@amd.com self.peer = None # not associated with another port yet 9758579Ssteve.reinhardt@amd.com self.ccConnected = False # C++ port connection done? 9768579Ssteve.reinhardt@amd.com self.index = -1 # always -1 for non-vector ports 9778579Ssteve.reinhardt@amd.com 9788579Ssteve.reinhardt@amd.com def __str__(self): 9798579Ssteve.reinhardt@amd.com return '%s.%s' % (self.simobj, self.name) 9808579Ssteve.reinhardt@amd.com 9818579Ssteve.reinhardt@amd.com # for config.ini, print peer's name (not ours) 9828579Ssteve.reinhardt@amd.com def ini_str(self): 9838579Ssteve.reinhardt@amd.com return str(self.peer) 9848579Ssteve.reinhardt@amd.com 9857777Sgblack@eecs.umich.edu def __getattr__(self, attr): 9867777Sgblack@eecs.umich.edu if attr == 'peerObj': 9877798Sgblack@eecs.umich.edu # shorthand for proxies 9887777Sgblack@eecs.umich.edu return self.peer.simobj 9897777Sgblack@eecs.umich.edu raise AttributeError, "'%s' object has no attribute '%s'" % \ 9907777Sgblack@eecs.umich.edu (self.__class__.__name__, attr) 9917777Sgblack@eecs.umich.edu 9927777Sgblack@eecs.umich.edu # Full connection is symmetric (both ways). Called via 9937777Sgblack@eecs.umich.edu # SimObject.__setattr__ as a result of a port assignment, e.g., 9947777Sgblack@eecs.umich.edu # "obj1.portA = obj2.portB", or via VectorPortElementRef.__setitem__, 9957777Sgblack@eecs.umich.edu # e.g., "obj1.portA[3] = obj2.portB". 9967777Sgblack@eecs.umich.edu def connect(self, other): 9977777Sgblack@eecs.umich.edu if isinstance(other, VectorPortRef): 99810267SGeoffrey.Blake@arm.com # reference to plain VectorPort is implicit append 99910267SGeoffrey.Blake@arm.com other = other._get_next() 10007777Sgblack@eecs.umich.edu if self.peer and not proxy.isproxy(self.peer): 10017777Sgblack@eecs.umich.edu print "warning: overwriting port", self, \ 10027777Sgblack@eecs.umich.edu "value", self.peer, "with", other 10037777Sgblack@eecs.umich.edu self.peer = other 10047777Sgblack@eecs.umich.edu if proxy.isproxy(other): 10057777Sgblack@eecs.umich.edu other.set_param_desc(PortParamDesc()) 10067777Sgblack@eecs.umich.edu elif isinstance(other, PortRef): 10077777Sgblack@eecs.umich.edu if other.peer is not self: 10087777Sgblack@eecs.umich.edu other.connect(self) 10097777Sgblack@eecs.umich.edu else: 10107777Sgblack@eecs.umich.edu raise TypeError, \ 10117777Sgblack@eecs.umich.edu "assigning non-port reference '%s' to port '%s'" \ 10127777Sgblack@eecs.umich.edu % (other, self) 10137777Sgblack@eecs.umich.edu 10147777Sgblack@eecs.umich.edu def clone(self, simobj, memo): 10157777Sgblack@eecs.umich.edu if memo.has_key(self): 10167777Sgblack@eecs.umich.edu return memo[self] 10177777Sgblack@eecs.umich.edu newRef = copy.copy(self) 10187777Sgblack@eecs.umich.edu memo[self] = newRef 10197777Sgblack@eecs.umich.edu newRef.simobj = simobj 10207777Sgblack@eecs.umich.edu assert(isSimObject(newRef.simobj)) 10217777Sgblack@eecs.umich.edu if self.peer and not proxy.isproxy(self.peer): 10227777Sgblack@eecs.umich.edu peerObj = self.peer.simobj(_memo=memo) 10237777Sgblack@eecs.umich.edu newRef.peer = self.peer.clone(peerObj, memo) 10247777Sgblack@eecs.umich.edu assert(not isinstance(newRef.peer, VectorPortRef)) 10257777Sgblack@eecs.umich.edu return newRef 10267777Sgblack@eecs.umich.edu 10277777Sgblack@eecs.umich.edu def unproxy(self, simobj): 10287777Sgblack@eecs.umich.edu assert(simobj is self.simobj) 10297777Sgblack@eecs.umich.edu if proxy.isproxy(self.peer): 10307777Sgblack@eecs.umich.edu try: 10317777Sgblack@eecs.umich.edu realPeer = self.peer.unproxy(self.simobj) 10327777Sgblack@eecs.umich.edu except: 10337777Sgblack@eecs.umich.edu print "Error in unproxying port '%s' of %s" % \ 10347777Sgblack@eecs.umich.edu (self.name, self.simobj.path()) 10357777Sgblack@eecs.umich.edu raise 10367777Sgblack@eecs.umich.edu self.connect(realPeer) 10377777Sgblack@eecs.umich.edu 10387777Sgblack@eecs.umich.edu # Call C++ to create corresponding port connection between C++ objects 10397777Sgblack@eecs.umich.edu def ccConnect(self): 10407777Sgblack@eecs.umich.edu from m5.objects.params import connectPorts 10417777Sgblack@eecs.umich.edu 10427777Sgblack@eecs.umich.edu if self.ccConnected: # already done this 10437777Sgblack@eecs.umich.edu return 10447777Sgblack@eecs.umich.edu peer = self.peer 104510267SGeoffrey.Blake@arm.com connectPorts(self.simobj.getCCObject(), self.name, self.index, 104610267SGeoffrey.Blake@arm.com peer.simobj.getCCObject(), peer.name, peer.index) 104710267SGeoffrey.Blake@arm.com self.ccConnected = True 104810267SGeoffrey.Blake@arm.com peer.ccConnected = True 10498579Ssteve.reinhardt@amd.com 10508579Ssteve.reinhardt@amd.com# A reference to an individual element of a VectorPort... much like a 10518579Ssteve.reinhardt@amd.com# PortRef, but has an index. 10528579Ssteve.reinhardt@amd.comclass VectorPortElementRef(PortRef): 10538579Ssteve.reinhardt@amd.com def __init__(self, simobj, name, index): 10548579Ssteve.reinhardt@amd.com PortRef.__init__(self, simobj, name) 10558579Ssteve.reinhardt@amd.com self.index = index 10568579Ssteve.reinhardt@amd.com 10578579Ssteve.reinhardt@amd.com def __str__(self): 10588579Ssteve.reinhardt@amd.com return '%s.%s[%d]' % (self.simobj, self.name, self.index) 10598579Ssteve.reinhardt@amd.com 10608579Ssteve.reinhardt@amd.com# A reference to a complete vector-valued port (not just a single element). 10618579Ssteve.reinhardt@amd.com# Can be indexed to retrieve individual VectorPortElementRef instances. 10628579Ssteve.reinhardt@amd.comclass VectorPortRef(object): 10637777Sgblack@eecs.umich.edu def __init__(self, simobj, name): 10647777Sgblack@eecs.umich.edu assert(isSimObject(simobj) or isSimObjectClass(simobj)) 10657777Sgblack@eecs.umich.edu self.simobj = simobj 10667777Sgblack@eecs.umich.edu self.name = name 10677777Sgblack@eecs.umich.edu self.elements = [] 10687777Sgblack@eecs.umich.edu 10697777Sgblack@eecs.umich.edu def __str__(self): 10707777Sgblack@eecs.umich.edu return '%s.%s[:]' % (self.simobj, self.name) 10717777Sgblack@eecs.umich.edu 10727777Sgblack@eecs.umich.edu # for config.ini, print peer's name (not ours) 10737777Sgblack@eecs.umich.edu def ini_str(self): 10747777Sgblack@eecs.umich.edu return ' '.join([el.ini_str() for el in self.elements]) 10757777Sgblack@eecs.umich.edu 107610267SGeoffrey.Blake@arm.com def __getitem__(self, key): 107710267SGeoffrey.Blake@arm.com if not isinstance(key, int): 10787777Sgblack@eecs.umich.edu raise TypeError, "VectorPort index must be integer" 10797777Sgblack@eecs.umich.edu if key >= len(self.elements): 10807777Sgblack@eecs.umich.edu # need to extend list 10817777Sgblack@eecs.umich.edu ext = [VectorPortElementRef(self.simobj, self.name, i) 10827777Sgblack@eecs.umich.edu for i in range(len(self.elements), key+1)] 10837777Sgblack@eecs.umich.edu self.elements.extend(ext) 10847777Sgblack@eecs.umich.edu return self.elements[key] 10857777Sgblack@eecs.umich.edu 10867777Sgblack@eecs.umich.edu def _get_next(self): 10877777Sgblack@eecs.umich.edu return self[len(self.elements)] 10887777Sgblack@eecs.umich.edu 10897777Sgblack@eecs.umich.edu def __setitem__(self, key, value): 10907777Sgblack@eecs.umich.edu if not isinstance(key, int): 10917777Sgblack@eecs.umich.edu raise TypeError, "VectorPort index must be integer" 10927777Sgblack@eecs.umich.edu self[key].connect(value) 10937777Sgblack@eecs.umich.edu 10947777Sgblack@eecs.umich.edu def connect(self, other): 10957777Sgblack@eecs.umich.edu if isinstance(other, (list, tuple)): 10967777Sgblack@eecs.umich.edu # Assign list of port refs to vector port. 10977777Sgblack@eecs.umich.edu # For now, append them... not sure if that's the right semantics 10987777Sgblack@eecs.umich.edu # or if it should replace the current vector. 10997777Sgblack@eecs.umich.edu for ref in other: 11007777Sgblack@eecs.umich.edu self._get_next().connect(ref) 11017777Sgblack@eecs.umich.edu else: 11027777Sgblack@eecs.umich.edu # scalar assignment to plain VectorPort is implicit append 11037777Sgblack@eecs.umich.edu self._get_next().connect(other) 11047777Sgblack@eecs.umich.edu 11057777Sgblack@eecs.umich.edu def clone(self, simobj, memo): 11067777Sgblack@eecs.umich.edu if memo.has_key(self): 11077777Sgblack@eecs.umich.edu return memo[self] 11087777Sgblack@eecs.umich.edu newRef = copy.copy(self) 11097777Sgblack@eecs.umich.edu memo[self] = newRef 11107777Sgblack@eecs.umich.edu newRef.simobj = simobj 11117777Sgblack@eecs.umich.edu assert(isSimObject(newRef.simobj)) 11127777Sgblack@eecs.umich.edu newRef.elements = [el.clone(simobj, memo) for el in self.elements] 11137777Sgblack@eecs.umich.edu return newRef 11147777Sgblack@eecs.umich.edu 11157777Sgblack@eecs.umich.edu def unproxy(self, simobj): 11167777Sgblack@eecs.umich.edu [el.unproxy(simobj) for el in self.elements] 11177777Sgblack@eecs.umich.edu 11187777Sgblack@eecs.umich.edu def ccConnect(self): 11197777Sgblack@eecs.umich.edu [el.ccConnect() for el in self.elements] 11207777Sgblack@eecs.umich.edu 11217777Sgblack@eecs.umich.edu# Port description object. Like a ParamDesc object, this represents a 11227777Sgblack@eecs.umich.edu# logical port in the SimObject class, not a particular port on a 112310267SGeoffrey.Blake@arm.com# SimObject instance. The latter are represented by PortRef objects. 112410267SGeoffrey.Blake@arm.comclass Port(object): 112510267SGeoffrey.Blake@arm.com # Port("description") or Port(default, "description") 112610267SGeoffrey.Blake@arm.com def __init__(self, *args): 11278579Ssteve.reinhardt@amd.com if len(args) == 1: 11288579Ssteve.reinhardt@amd.com self.desc = args[0] 11298579Ssteve.reinhardt@amd.com elif len(args) == 2: 11308579Ssteve.reinhardt@amd.com self.default = args[0] 11318579Ssteve.reinhardt@amd.com self.desc = args[1] 11328579Ssteve.reinhardt@amd.com else: 11338579Ssteve.reinhardt@amd.com raise TypeError, 'wrong number of arguments' 11348579Ssteve.reinhardt@amd.com # self.name is set by SimObject class on assignment 11358579Ssteve.reinhardt@amd.com # e.g., pio_port = Port("blah") sets self.name to 'pio_port' 11368579Ssteve.reinhardt@amd.com 11378579Ssteve.reinhardt@amd.com # Generate a PortRef for this port on the given SimObject with the 11388579Ssteve.reinhardt@amd.com # given name 11398579Ssteve.reinhardt@amd.com def makeRef(self, simobj): 11408579Ssteve.reinhardt@amd.com return PortRef(simobj, self.name) 11417777Sgblack@eecs.umich.edu 11427777Sgblack@eecs.umich.edu # Connect an instance of this port (on the given SimObject with 11437777Sgblack@eecs.umich.edu # the given name) with the port described by the supplied PortRef 11447777Sgblack@eecs.umich.edu def connect(self, simobj, ref): 11457777Sgblack@eecs.umich.edu self.makeRef(simobj).connect(ref) 11467777Sgblack@eecs.umich.edu 11477777Sgblack@eecs.umich.edu# VectorPort description object. Like Port, but represents a vector 11487777Sgblack@eecs.umich.edu# of connections (e.g., as on a Bus). 11497777Sgblack@eecs.umich.educlass VectorPort(Port): 11503932Sbinkertn@umich.edu def __init__(self, *args): 115110380SAndrew.Bardsley@arm.com Port.__init__(self, *args) 11523932Sbinkertn@umich.edu self.isVec = True 11533932Sbinkertn@umich.edu 11543932Sbinkertn@umich.edu def makeRef(self, simobj): 11553932Sbinkertn@umich.edu return VectorPortRef(simobj, self.name) 11563932Sbinkertn@umich.edu 11573932Sbinkertn@umich.edu# 'Fake' ParamDesc for Port references to assign to the _pdesc slot of 11583932Sbinkertn@umich.edu# proxy objects (via set_param_desc()) so that proxy error messages 11593932Sbinkertn@umich.edu# make sense. 11603932Sbinkertn@umich.educlass PortParamDesc(object): 11613932Sbinkertn@umich.edu __metaclass__ = Singleton 11623932Sbinkertn@umich.edu 11633885Sbinkertn@umich.edu ptype_str = 'Port' 11643932Sbinkertn@umich.edu ptype = Port 11653932Sbinkertn@umich.edu 11663885Sbinkertn@umich.edu__all__ = ['Param', 'VectorParam', 11673932Sbinkertn@umich.edu 'Enum', 'Bool', 'String', 'Float', 11683932Sbinkertn@umich.edu 'Int', 'Unsigned', 'Int8', 'UInt8', 'Int16', 'UInt16', 11693932Sbinkertn@umich.edu 'Int32', 'UInt32', 'Int64', 'UInt64', 11703932Sbinkertn@umich.edu 'Counter', 'Addr', 'Tick', 'Percent', 11713932Sbinkertn@umich.edu 'TcpPort', 'UdpPort', 'EthernetAddr', 11723932Sbinkertn@umich.edu 'MemorySize', 'MemorySize32', 11733932Sbinkertn@umich.edu 'Latency', 'Frequency', 'Clock', 11743932Sbinkertn@umich.edu 'NetworkBandwidth', 'MemoryBandwidth', 11753932Sbinkertn@umich.edu 'Range', 'AddrRange', 'TickRange', 11763932Sbinkertn@umich.edu 'MaxAddr', 'MaxTick', 'AllMemory', 11773932Sbinkertn@umich.edu 'Time', 11783932Sbinkertn@umich.edu 'NextEthernetAddr', 'NULL', 11793932Sbinkertn@umich.edu 'Port', 'VectorPort'] 11803932Sbinkertn@umich.edu