params.py revision 5468:786868ff3058
111988Sandreas.sandberg@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 10511988Sandreas.sandberg@arm.com if args: 10611988Sandreas.sandberg@arm.com if len(args) == 1: 10711988Sandreas.sandberg@arm.com self.desc = args[0] 10811988Sandreas.sandberg@arm.com elif len(args) == 2: 1093101Sstever@eecs.umich.edu self.default = args[0] 1103101Sstever@eecs.umich.edu self.desc = args[1] 1113101Sstever@eecs.umich.edu else: 1123101Sstever@eecs.umich.edu raise TypeError, 'too many arguments' 1133101Sstever@eecs.umich.edu 11410380SAndrew.Bardsley@arm.com if kwargs.has_key('desc'): 11510380SAndrew.Bardsley@arm.com assert(not hasattr(self, 'desc')) 11610380SAndrew.Bardsley@arm.com self.desc = kwargs['desc'] 11710380SAndrew.Bardsley@arm.com del kwargs['desc'] 11810380SAndrew.Bardsley@arm.com 11910380SAndrew.Bardsley@arm.com if kwargs.has_key('default'): 12010458Sandreas.hansson@arm.com assert(not hasattr(self, 'default')) 12110458Sandreas.hansson@arm.com self.default = kwargs['default'] 12210458Sandreas.hansson@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': 1323101Sstever@eecs.umich.edu ptype = SimObject.allClasses[self.ptype_str] 1333101Sstever@eecs.umich.edu assert issubclass(ptype, SimObject.SimObject) 1343101Sstever@eecs.umich.edu self.ptype = ptype 1353101Sstever@eecs.umich.edu return ptype 1363101Sstever@eecs.umich.edu 13710267SGeoffrey.Blake@arm.com raise AttributeError, "'%s' object has no attribute '%s'" % \ 13810267SGeoffrey.Blake@arm.com (type(self).__name__, attr) 13910267SGeoffrey.Blake@arm.com 14010267SGeoffrey.Blake@arm.com def convert(self, value): 1413101Sstever@eecs.umich.edu if isinstance(value, proxy.BaseProxy): 1423101Sstever@eecs.umich.edu value.set_param_desc(self) 1433101Sstever@eecs.umich.edu 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): 1765033Smilesck@eecs.umich.edu return [v.unproxy(base) for v in self] 1776656Snate@binkert.org 1785033Smilesck@eecs.umich.educlass SimObjVector(VectorParamValue): 1795033Smilesck@eecs.umich.edu def print_ini(self, ini_file): 1805033Smilesck@eecs.umich.edu for v in self: 1813101Sstever@eecs.umich.edu v.print_ini(ini_file) 1823101Sstever@eecs.umich.edu 1833101Sstever@eecs.umich.educlass VectorParamDesc(ParamDesc): 18410267SGeoffrey.Blake@arm.com # Convert assigned value to appropriate type. If the RHS is not a 18510267SGeoffrey.Blake@arm.com # list or tuple, it generates a single-element list. 18610267SGeoffrey.Blake@arm.com 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: 1973101Sstever@eecs.umich.edu return VectorParamValue(tmp_list) 1983101Sstever@eecs.umich.edu 1993101Sstever@eecs.umich.edu 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] 2073102Sstever@eecs.umich.edu 2083101Sstever@eecs.umich.edu def cxx_predecls(self): 2093101Sstever@eecs.umich.edu return ['#include <vector>'] + self.ptype.cxx_predecls 2103101Sstever@eecs.umich.edu 21110267SGeoffrey.Blake@arm.com def cxx_decl(self): 21210267SGeoffrey.Blake@arm.com return 'std::vector< %s > %s;' % (self.ptype.cxx_type, self.name) 21310267SGeoffrey.Blake@arm.com 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 2187673Snate@binkert.org 2198607Sgblack@eecs.umich.edu def __getattr__(self, attr): 2207673Snate@binkert.org if self.ptype_str: 2213101Sstever@eecs.umich.edu attr = self.ptype_str + '.' + attr 22211988Sandreas.sandberg@arm.com return ParamFactory(self.param_desc_class, attr) 22311988Sandreas.sandberg@arm.com 22411988Sandreas.sandberg@arm.com # 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: 2283101Sstever@eecs.umich.edu ptype = allParams[self.ptype_str] 2293101Sstever@eecs.umich.edu 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 2335033Smilesck@eecs.umich.edu return self.param_desc_class(self.ptype_str, ptype, *args, **kwargs) 2345475Snate@binkert.org 2355475Snate@binkert.orgParam = ParamFactory(ParamDesc) 2365475Snate@binkert.orgVectorParam = ParamFactory(VectorParamDesc) 2375475Snate@binkert.org 23810380SAndrew.Bardsley@arm.com##################################################################### 23910380SAndrew.Bardsley@arm.com# 24010380SAndrew.Bardsley@arm.com# Parameter Types 2413101Sstever@eecs.umich.edu# 2423101Sstever@eecs.umich.edu# Though native Python types could be used to specify parameter types 2433101Sstever@eecs.umich.edu# (the 'ptype' field of the Param and VectorParam classes), it's more 2444762Snate@binkert.org# flexible to define our own set of types. This gives us more control 2454762Snate@binkert.org# over how Python expressions are converted to values (via the 2464762Snate@binkert.org# __init__() constructor) and how these values are printed out (via 2473101Sstever@eecs.umich.edu# the __str__() conversion method). 2488460SAli.Saidi@ARM.com# 2498459SAli.Saidi@ARM.com##################################################################### 2508459SAli.Saidi@ARM.com 2518459SAli.Saidi@ARM.com# String-valued parameter. Just mixin the ParamValue class with the 2523101Sstever@eecs.umich.edu# built-in str class. 2537528Ssteve.reinhardt@amd.comclass String(ParamValue,str): 2547528Ssteve.reinhardt@amd.com cxx_type = 'std::string' 2557528Ssteve.reinhardt@amd.com 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"' ] 2593101Sstever@eecs.umich.edu 2607528Ssteve.reinhardt@amd.com def getValue(self): 2617528Ssteve.reinhardt@amd.com return self 2627528Ssteve.reinhardt@amd.com 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 2708321Ssteve.reinhardt@amd.com def __float__(self): 2718321Ssteve.reinhardt@amd.com return float(self.value) 2727528Ssteve.reinhardt@amd.com 2737528Ssteve.reinhardt@amd.com def __long__(self): 2747528Ssteve.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) 2853101Sstever@eecs.umich.edu newobj.value *= other 2868664SAli.Saidi@ARM.com newobj._check() 2878664SAli.Saidi@ARM.com return newobj 2888664SAli.Saidi@ARM.com 2898664SAli.Saidi@ARM.com __rmul__ = __mul__ 2908664SAli.Saidi@ARM.com 2918664SAli.Saidi@ARM.com def __div__(self, other): 2929953Sgeoffrey.blake@arm.com newobj = self.__class__(self) 2939953Sgeoffrey.blake@arm.com newobj.value /= other 2949953Sgeoffrey.blake@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): 30510267SGeoffrey.Blake@arm.com def __init__(cls, name, bases, dict): 30610267SGeoffrey.Blake@arm.com super(CheckedIntType, cls).__init__(name, bases, dict) 30710267SGeoffrey.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')): 3253101Sstever@eecs.umich.edu panic("CheckedInt subclass %s must define either\n" \ 3263101Sstever@eecs.umich.edu " 'min' and 'max' or 'size' and 'unsigned'\n" \ 3273101Sstever@eecs.umich.edu % 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: 33210364SGeoffrey.Blake@arm.com cls.min = -(2 ** (cls.size - 1)) 33310364SGeoffrey.Blake@arm.com cls.max = (2 ** (cls.size - 1)) - 1 33410364SGeoffrey.Blake@arm.com 33510364SGeoffrey.Blake@arm.com# Abstract superclass for bounds-checked integer parameters. This 3363101Sstever@eecs.umich.edu# class is subclassed to generate parameter classes with specific 3374762Snate@binkert.org# bounds. Initialization of the min and max bounds is done in the 3384762Snate@binkert.org# metaclass CheckedIntType.__init__. 3394762Snate@binkert.orgclass CheckedInt(NumericParamValue): 3404762Snate@binkert.org __metaclass__ = CheckedIntType 3417528Ssteve.reinhardt@amd.com 3424762Snate@binkert.org def _check(self): 3434762Snate@binkert.org if not self.min <= self.value <= self.max: 3444762Snate@binkert.org raise TypeError, 'Integer param out of bounds %d < %d < %d' % \ 34510267SGeoffrey.Blake@arm.com (self.min, self.value, self.max) 34610267SGeoffrey.Blake@arm.com 34710267SGeoffrey.Blake@arm.com 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 37110364SGeoffrey.Blake@arm.com 37210364SGeoffrey.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 37410267SGeoffrey.Blake@arm.comclass TcpPort(CheckedInt): cxx_type = 'uint16_t'; size = 16; unsigned = True 37510267SGeoffrey.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 3797673Snate@binkert.orgclass Float(ParamValue, float): 3807673Snate@binkert.org cxx_type = 'double' 3817673Snate@binkert.org 3823101Sstever@eecs.umich.edu def __init__(self, value): 38311988Sandreas.sandberg@arm.com if isinstance(value, (int, long, float, NumericParamValue, Float)): 38411988Sandreas.sandberg@arm.com self.value = float(value) 38511988Sandreas.sandberg@arm.com else: 38611988Sandreas.sandberg@arm.com raise TypeError, "Can't convert object of type %s to Float" \ 3877673Snate@binkert.org % type(value).__name__ 3887673Snate@binkert.org 3893101Sstever@eecs.umich.edu def getValue(self): 3903101Sstever@eecs.umich.edu return float(self.value) 3913101Sstever@eecs.umich.edu 3923101Sstever@eecs.umich.educlass MemorySize(CheckedInt): 3933101Sstever@eecs.umich.edu cxx_type = 'uint64_t' 3943101Sstever@eecs.umich.edu size = 64 3953101Sstever@eecs.umich.edu unsigned = True 3963101Sstever@eecs.umich.edu def __init__(self, value): 3973101Sstever@eecs.umich.edu if isinstance(value, MemorySize): 3983101Sstever@eecs.umich.edu self.value = value.value 3993101Sstever@eecs.umich.edu else: 4003101Sstever@eecs.umich.edu self.value = convert.toMemorySize(value) 4013101Sstever@eecs.umich.edu self._check() 4023101Sstever@eecs.umich.edu 4033101Sstever@eecs.umich.educlass MemorySize32(CheckedInt): 4045033Smilesck@eecs.umich.edu cxx_type = 'uint32_t' 4055033Smilesck@eecs.umich.edu size = 32 4063101Sstever@eecs.umich.edu unsigned = True 4073101Sstever@eecs.umich.edu def __init__(self, value): 4083101Sstever@eecs.umich.edu if isinstance(value, MemorySize): 4093101Sstever@eecs.umich.edu self.value = value.value 4103101Sstever@eecs.umich.edu else: 4113101Sstever@eecs.umich.edu self.value = convert.toMemorySize(value) 4123101Sstever@eecs.umich.edu 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): 4283101Sstever@eecs.umich.edu if isinstance(other, Addr): 4293101Sstever@eecs.umich.edu return self.value + other.value 4303101Sstever@eecs.umich.edu else: 43110267SGeoffrey.Blake@arm.com return self.value + other 4327673Snate@binkert.org 4337673Snate@binkert.org 4347673Snate@binkert.orgclass MetaRange(MetaParamValue): 4357673Snate@binkert.org def __init__(cls, name, bases, dict): 4367673Snate@binkert.org super(MetaRange, cls).__init__(name, bases, dict) 43710267SGeoffrey.Blake@arm.com if name == 'Range': 43810267SGeoffrey.Blake@arm.com return 43910267SGeoffrey.Blake@arm.com cls.cxx_type = 'Range< %s >' % cls.type.cxx_type 44010267SGeoffrey.Blake@arm.com cls.cxx_predecls = \ 44110458Sandreas.hansson@arm.com ['#include "base/range.hh"'] + cls.type.cxx_predecls 44210458Sandreas.hansson@arm.com 44310458Sandreas.hansson@arm.comclass Range(ParamValue): 44410458Sandreas.hansson@arm.com __metaclass__ = MetaRange 44510458Sandreas.hansson@arm.com type = Int # default; can be overridden in subclasses 4464762Snate@binkert.org def __init__(self, *args, **kwargs): 4474762Snate@binkert.org 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 4553101Sstever@eecs.umich.edu if len(args) == 0: 4563101Sstever@eecs.umich.edu self.first = self.type(kwargs.pop('start')) 4573101Sstever@eecs.umich.edu handle_kwargs(self, kwargs) 4583101Sstever@eecs.umich.edu 4593714Sstever@eecs.umich.edu elif len(args) == 1: 4603714Sstever@eecs.umich.edu if kwargs: 4613714Sstever@eecs.umich.edu self.first = self.type(args[0]) 4623714Sstever@eecs.umich.edu handle_kwargs(self, kwargs) 4633714Sstever@eecs.umich.edu elif isinstance(args[0], Range): 4643714Sstever@eecs.umich.edu self.first = self.type(args[0].first) 4653101Sstever@eecs.umich.edu self.second = self.type(args[0].second) 4663101Sstever@eecs.umich.edu elif isinstance(args[0], (list, tuple)): 4673101Sstever@eecs.umich.edu self.first = self.type(args[0][0]) 4683101Sstever@eecs.umich.edu self.second = self.type(args[0][1]) 4693101Sstever@eecs.umich.edu else: 4703101Sstever@eecs.umich.edu self.first = self.type(0) 4713101Sstever@eecs.umich.edu self.second = self.type(args[0]) - 1 4723101Sstever@eecs.umich.edu 4733101Sstever@eecs.umich.edu elif len(args) == 2: 4743101Sstever@eecs.umich.edu self.first = self.type(args[0]) 4753101Sstever@eecs.umich.edu 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 4873101Sstever@eecs.umich.edu swig_predecls = ['%include "python/swig/range.i"'] 4883101Sstever@eecs.umich.edu 48910380SAndrew.Bardsley@arm.com def getValue(self): 49010380SAndrew.Bardsley@arm.com from m5.objects.params import AddrRange 49110380SAndrew.Bardsley@arm.com 49210458Sandreas.hansson@arm.com value = AddrRange() 49310458Sandreas.hansson@arm.com value.start = long(self.first) 49410458Sandreas.hansson@arm.com value.end = long(self.second) 49510458Sandreas.hansson@arm.com return value 49610458Sandreas.hansson@arm.com 49710458Sandreas.hansson@arm.comclass TickRange(Range): 49810458Sandreas.hansson@arm.com type = Tick 49910458Sandreas.hansson@arm.com swig_predecls = ['%include "python/swig/range.i"'] 50010458Sandreas.hansson@arm.com 50110458Sandreas.hansson@arm.com def getValue(self): 50210458Sandreas.hansson@arm.com from m5.objects.params import TickRange 50310458Sandreas.hansson@arm.com 50410458Sandreas.hansson@arm.com value = TickRange() 5053101Sstever@eecs.umich.edu value.start = long(self.first) 5065033Smilesck@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) 5173101Sstever@eecs.umich.edu except TypeError: 5183101Sstever@eecs.umich.edu self.value = bool(value) 5195822Ssaidi@eecs.umich.edu 5205822Ssaidi@eecs.umich.edu def getValue(self): 5213101Sstever@eecs.umich.edu return bool(self.value) 5223101Sstever@eecs.umich.edu 5233101Sstever@eecs.umich.edu def __str__(self): 5243101Sstever@eecs.umich.edu return str(self.value) 5253101Sstever@eecs.umich.edu 5263101Sstever@eecs.umich.edu def ini_str(self): 5273101Sstever@eecs.umich.edu if self.value: 5283101Sstever@eecs.umich.edu return 'true' 5293101Sstever@eecs.umich.edu return 'false' 5303101Sstever@eecs.umich.edu 5313101Sstever@eecs.umich.edudef IncEthernetAddr(addr, val = 1): 5323101Sstever@eecs.umich.edu bytes = map(lambda x: int(x, 16), addr.split(':')) 5333101Sstever@eecs.umich.edu bytes[5] += val 53410267SGeoffrey.Blake@arm.com 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 5433102Sstever@eecs.umich.edu_NextEthernetAddr = "00:90:00:00:00:01" 5443714Sstever@eecs.umich.edudef NextEthernetAddr(): 5453101Sstever@eecs.umich.edu global _NextEthernetAddr 5463714Sstever@eecs.umich.edu 5473714Sstever@eecs.umich.edu value = _NextEthernetAddr 5483714Sstever@eecs.umich.edu _NextEthernetAddr = IncEthernetAddr(_NextEthernetAddr, 1) 5493101Sstever@eecs.umich.edu return value 5503101Sstever@eecs.umich.edu 55110267SGeoffrey.Blake@arm.comclass EthernetAddr(ParamValue): 55210267SGeoffrey.Blake@arm.com cxx_type = 'Net::EthAddr' 55310267SGeoffrey.Blake@arm.com cxx_predecls = ['#include "base/inet.hh"'] 55410267SGeoffrey.Blake@arm.com swig_predecls = ['%include "python/swig/inet.i"'] 5557673Snate@binkert.org def __init__(self, value): 5567673Snate@binkert.org if value == NextEthernetAddr: 5577673Snate@binkert.org self.value = value 5587673Snate@binkert.org return 5597673Snate@binkert.org 5604762Snate@binkert.org if not isinstance(value, str): 5614762Snate@binkert.org raise TypeError, "expected an ethernet address and didn't get one" 5624762Snate@binkert.org 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 5713101Sstever@eecs.umich.edu self.value = value 5723101Sstever@eecs.umich.edu 5733101Sstever@eecs.umich.edu def unproxy(self, base): 5743101Sstever@eecs.umich.edu if self.value == NextEthernetAddr: 5753101Sstever@eecs.umich.edu return EthernetAddr(self.value()) 5763101Sstever@eecs.umich.edu return self 5773101Sstever@eecs.umich.edu 5783101Sstever@eecs.umich.edu def getValue(self): 5793101Sstever@eecs.umich.edu from m5.objects.params import EthAddr 5803101Sstever@eecs.umich.edu return EthAddr(self.value) 5813101Sstever@eecs.umich.edu 5829184Sandreas.hansson@arm.com def ini_str(self): 5839184Sandreas.hansson@arm.com return self.value 5849184Sandreas.hansson@arm.com 5859184Sandreas.hansson@arm.comtime_formats = [ "%a %b %d %H:%M:%S %Z %Y", 5869184Sandreas.hansson@arm.com "%a %b %d %H:%M:%S %Z %Y", 5879184Sandreas.hansson@arm.com "%Y/%m/%d %H:%M:%S", 58811802Sandreas.sandberg@arm.com "%Y/%m/%d %H:%M", 5899184Sandreas.hansson@arm.com "%Y/%m/%d", 5909184Sandreas.hansson@arm.com "%m/%d/%Y %H:%M:%S", 59110458Sandreas.hansson@arm.com "%m/%d/%Y %H:%M", 59210458Sandreas.hansson@arm.com "%m/%d/%Y", 59310458Sandreas.hansson@arm.com "%m/%d/%y %H:%M:%S", 59410458Sandreas.hansson@arm.com "%m/%d/%y %H:%M", 59510458Sandreas.hansson@arm.com "%m/%d/%y"] 59610458Sandreas.hansson@arm.com 59710458Sandreas.hansson@arm.com 59810458Sandreas.hansson@arm.comdef parse_time(value): 59910458Sandreas.hansson@arm.com from time import gmtime, strptime, struct_time, time 60010458Sandreas.hansson@arm.com from datetime import datetime, date 60110458Sandreas.hansson@arm.com 60210458Sandreas.hansson@arm.com if isinstance(value, struct_time): 60310458Sandreas.hansson@arm.com return value 60410458Sandreas.hansson@arm.com 6053101Sstever@eecs.umich.edu if isinstance(value, (int, long)): 6064446Sbinkertn@umich.edu return gmtime(value) 60710668SGeoffrey.Blake@arm.com 6083101Sstever@eecs.umich.edu if isinstance(value, (datetime, date)): 6095468Snate@binkert.org return value.timetuple() 61010267SGeoffrey.Blake@arm.com 6115468Snate@binkert.org if isinstance(value, str): 6125468Snate@binkert.org if value in ('Now', 'Today'): 6135468Snate@binkert.org return time.gmtime(time.time()) 6145468Snate@binkert.org 6155468Snate@binkert.org for format in time_formats: 61610267SGeoffrey.Blake@arm.com try: 61710267SGeoffrey.Blake@arm.com return strptime(value, format) 61810267SGeoffrey.Blake@arm.com except ValueError: 61910267SGeoffrey.Blake@arm.com pass 6204762Snate@binkert.org 6214762Snate@binkert.org raise ValueError, "Could not parse '%s' as a time" % value 6224762Snate@binkert.org 62310380SAndrew.Bardsley@arm.comclass Time(ParamValue): 62410380SAndrew.Bardsley@arm.com cxx_type = 'tm' 62510380SAndrew.Bardsley@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() 6343101Sstever@eecs.umich.edu py_time = self.value 6353101Sstever@eecs.umich.edu 63610267SGeoffrey.Blake@arm.com # UNIX is years since 1900 6373101Sstever@eecs.umich.edu c_time.tm_year = py_time.tm_year - 1900; 6383101Sstever@eecs.umich.edu 6393101Sstever@eecs.umich.edu # Python starts at 1, UNIX starts at 0 6403101Sstever@eecs.umich.edu c_time.tm_mon = py_time.tm_mon - 1; 6413101Sstever@eecs.umich.edu c_time.tm_mday = py_time.tm_mday; 6423101Sstever@eecs.umich.edu c_time.tm_hour = py_time.tm_hour; 6433102Sstever@eecs.umich.edu c_time.tm_min = py_time.tm_min; 6443101Sstever@eecs.umich.edu c_time.tm_sec = py_time.tm_sec; 6453101Sstever@eecs.umich.edu 6463101Sstever@eecs.umich.edu # Python has 0 as Monday, UNIX is 0 as sunday 6474168Sbinkertn@umich.edu c_time.tm_wday = py_time.tm_wday + 1 64810267SGeoffrey.Blake@arm.com if c_time.tm_wday > 6: 6493101Sstever@eecs.umich.edu c_time.tm_wday -= 7; 6503101Sstever@eecs.umich.edu 6513101Sstever@eecs.umich.edu # Python starts at 1, Unix starts at 0 6523101Sstever@eecs.umich.edu c_time.tm_yday = py_time.tm_yday - 1; 6533101Sstever@eecs.umich.edu 6543101Sstever@eecs.umich.edu return c_time 6553102Sstever@eecs.umich.edu 6563101Sstever@eecs.umich.edu def __str__(self): 6573101Sstever@eecs.umich.edu return time.asctime(self.value) 6583101Sstever@eecs.umich.edu 6593101Sstever@eecs.umich.edu def ini_str(self): 6603101Sstever@eecs.umich.edu return str(self) 6613101Sstever@eecs.umich.edu 6623101Sstever@eecs.umich.edu# Enumerated types are a little more complex. The user specifies the 6633101Sstever@eecs.umich.edu# type as Enum(foo) where foo is either a list or dictionary of 6643101Sstever@eecs.umich.edu# alternatives (typically strings, but not necessarily so). (In the 6653101Sstever@eecs.umich.edu# long run, the integer value of the parameter will be the list index 6663101Sstever@eecs.umich.edu# or the corresponding dictionary value. For now, since we only check 66710317Smitch.hayenga@arm.com# that the alternative is valid and then spit it into a .ini file, 66810317Smitch.hayenga@arm.com# there's not much point in using the dictionary.) 66910317Smitch.hayenga@arm.com 67010317Smitch.hayenga@arm.com# What Enum() must do is generate a new type encapsulating the 67110317Smitch.hayenga@arm.com# provided list/dictionary so that specific values of the parameter 6723102Sstever@eecs.umich.edu# can be instances of that type. We define two hidden internal 67310317Smitch.hayenga@arm.com# classes (_ListEnum and _DictEnum) to serve as base classes, then 67410317Smitch.hayenga@arm.com# derive the new type from the appropriate base class on the fly. 67510317Smitch.hayenga@arm.com 67610317Smitch.hayenga@arm.comallEnums = {} 67710317Smitch.hayenga@arm.com# Metaclass for Enum types 6783101Sstever@eecs.umich.educlass MetaEnum(MetaParamValue): 6793584Ssaidi@eecs.umich.edu def __new__(mcls, name, bases, dict): 6803584Ssaidi@eecs.umich.edu assert name not in allEnums 6813584Ssaidi@eecs.umich.edu 6823584Ssaidi@eecs.umich.edu cls = super(MetaEnum, mcls).__new__(mcls, name, bases, dict) 6833584Ssaidi@eecs.umich.edu allEnums[name] = cls 68410267SGeoffrey.Blake@arm.com return cls 68510267SGeoffrey.Blake@arm.com 68610267SGeoffrey.Blake@arm.com def __init__(cls, name, bases, init_dict): 68710267SGeoffrey.Blake@arm.com if init_dict.has_key('map'): 68810267SGeoffrey.Blake@arm.com if not isinstance(cls.map, dict): 68910267SGeoffrey.Blake@arm.com raise TypeError, "Enum-derived class attribute 'map' " \ 6903101Sstever@eecs.umich.edu "must be of type dict" 6919232Sandreas.hansson@arm.com # build list of value strings from map 6929235Sandreas.hansson@arm.com cls.vals = cls.map.keys() 6933101Sstever@eecs.umich.edu cls.vals.sort() 6943101Sstever@eecs.umich.edu elif init_dict.has_key('vals'): 69510676Sandreas.hansson@arm.com if not isinstance(cls.vals, list): 6969411Sandreas.hansson@arm.com raise TypeError, "Enum-derived class attribute 'vals' " \ 69710676Sandreas.hansson@arm.com "must be of type list" 6989411Sandreas.hansson@arm.com # build string->value map from vals sequence 6999411Sandreas.hansson@arm.com cls.map = {} 7009411Sandreas.hansson@arm.com for idx,val in enumerate(cls.vals): 7013101Sstever@eecs.umich.edu cls.map[val] = idx 7029411Sandreas.hansson@arm.com else: 7039411Sandreas.hansson@arm.com raise TypeError, "Enum-derived class must define "\ 7049411Sandreas.hansson@arm.com "attribute 'map' or 'vals'" 7053101Sstever@eecs.umich.edu 7069232Sandreas.hansson@arm.com cls.cxx_type = 'Enums::%s' % name 7073101Sstever@eecs.umich.edu 7089232Sandreas.hansson@arm.com super(MetaEnum, cls).__init__(name, bases, init_dict) 7093101Sstever@eecs.umich.edu 7103101Sstever@eecs.umich.edu def __str__(cls): 7113101Sstever@eecs.umich.edu return cls.__name__ 7129411Sandreas.hansson@arm.com 7139411Sandreas.hansson@arm.com # Generate C++ class declaration for this enum type. 7149411Sandreas.hansson@arm.com # Note that we wrap the enum in a class/struct to act as a namespace, 71510676Sandreas.hansson@arm.com # so that the enum strings can be brief w/o worrying about collisions. 71610676Sandreas.hansson@arm.com def cxx_decl(cls): 7179411Sandreas.hansson@arm.com code = "#ifndef __ENUM__%s\n" % cls 7189411Sandreas.hansson@arm.com code += '#define __ENUM__%s\n' % cls 7199411Sandreas.hansson@arm.com code += '\n' 7209411Sandreas.hansson@arm.com code += 'namespace Enums {\n' 7219411Sandreas.hansson@arm.com code += ' enum %s {\n' % cls 7223101Sstever@eecs.umich.edu for val in cls.vals: 7239232Sandreas.hansson@arm.com code += ' %s = %d,\n' % (val, cls.map[val]) 7243101Sstever@eecs.umich.edu code += ' Num_%s = %d,\n' % (cls, len(cls.vals)) 7253101Sstever@eecs.umich.edu code += ' };\n' 7263101Sstever@eecs.umich.edu code += ' extern const char *%sStrings[Num_%s];\n' % (cls, cls) 7273101Sstever@eecs.umich.edu code += '}\n' 7289232Sandreas.hansson@arm.com code += '\n' 7293101Sstever@eecs.umich.edu code += '#endif\n' 7305219Ssaidi@eecs.umich.edu return code 7319232Sandreas.hansson@arm.com 7329232Sandreas.hansson@arm.com def cxx_def(cls): 7333101Sstever@eecs.umich.edu code = '#include "enums/%s.hh"\n' % cls 7349232Sandreas.hansson@arm.com code += 'namespace Enums {\n' 7359232Sandreas.hansson@arm.com code += ' const char *%sStrings[Num_%s] =\n' % (cls, cls) 7363101Sstever@eecs.umich.edu code += ' {\n' 7373101Sstever@eecs.umich.edu for val in cls.vals: 7389232Sandreas.hansson@arm.com code += ' "%s",\n' % val 7399232Sandreas.hansson@arm.com code += ' };\n' 7403101Sstever@eecs.umich.edu code += '}\n' 7413101Sstever@eecs.umich.edu return code 7423101Sstever@eecs.umich.edu 7433101Sstever@eecs.umich.edu# Base class for enum types. 7449232Sandreas.hansson@arm.comclass Enum(ParamValue): 7453101Sstever@eecs.umich.edu __metaclass__ = MetaEnum 7463101Sstever@eecs.umich.edu vals = [] 74711620SMatthew.Poremba@amd.com 74811620SMatthew.Poremba@amd.com def __init__(self, value): 74911620SMatthew.Poremba@amd.com if value not in self.map: 7509232Sandreas.hansson@arm.com raise TypeError, "Enum param got bad value '%s' (not in %s)" \ 7519232Sandreas.hansson@arm.com % (value, self.vals) 7529411Sandreas.hansson@arm.com self.value = value 7539411Sandreas.hansson@arm.com 7543101Sstever@eecs.umich.edu def getValue(self): 7557673Snate@binkert.org return int(self.map[self.value]) 7567673Snate@binkert.org 7579232Sandreas.hansson@arm.com def __str__(self): 7589235Sandreas.hansson@arm.com return self.value 7597675Snate@binkert.org 7607675Snate@binkert.org# how big does a rounding error need to be before we warn about it? 76111988Sandreas.sandberg@arm.comfrequency_tolerance = 0.001 # 0.1% 76211988Sandreas.sandberg@arm.com 76311988Sandreas.sandberg@arm.comclass TickParamValue(NumericParamValue): 76411988Sandreas.sandberg@arm.com cxx_type = 'Tick' 76511988Sandreas.sandberg@arm.com cxx_predecls = ['#include "sim/host.hh"'] 76610458Sandreas.hansson@arm.com swig_predecls = ['%import "stdint.i"\n' + 76710458Sandreas.hansson@arm.com '%import "sim/host.hh"'] 76810458Sandreas.hansson@arm.com 76910458Sandreas.hansson@arm.com def getValue(self): 77010458Sandreas.hansson@arm.com return long(self.value) 77111620SMatthew.Poremba@amd.com 77211620SMatthew.Poremba@amd.comclass Latency(TickParamValue): 77310458Sandreas.hansson@arm.com def __init__(self, value): 77410458Sandreas.hansson@arm.com if isinstance(value, (Latency, Clock)): 77510458Sandreas.hansson@arm.com self.ticks = value.ticks 77610458Sandreas.hansson@arm.com self.value = value.value 77710458Sandreas.hansson@arm.com elif isinstance(value, Frequency): 77811620SMatthew.Poremba@amd.com self.ticks = value.ticks 77911620SMatthew.Poremba@amd.com self.value = 1.0 / value.value 78011620SMatthew.Poremba@amd.com elif value.endswith('t'): 78111620SMatthew.Poremba@amd.com self.ticks = True 78211620SMatthew.Poremba@amd.com self.value = int(value[:-1]) 78311620SMatthew.Poremba@amd.com else: 78411620SMatthew.Poremba@amd.com self.ticks = False 78511620SMatthew.Poremba@amd.com self.value = convert.toLatency(value) 78611620SMatthew.Poremba@amd.com 78711620SMatthew.Poremba@amd.com def __getattr__(self, attr): 78810458Sandreas.hansson@arm.com if attr in ('latency', 'period'): 78910458Sandreas.hansson@arm.com return self 79010458Sandreas.hansson@arm.com if attr == 'frequency': 79111620SMatthew.Poremba@amd.com return Frequency(self) 79211620SMatthew.Poremba@amd.com raise AttributeError, "Latency object has no attribute '%s'" % attr 79310458Sandreas.hansson@arm.com 79410458Sandreas.hansson@arm.com def getValue(self): 7954762Snate@binkert.org if self.ticks or self.value == 0: 79611991Sandreas.sandberg@arm.com value = self.value 79711802Sandreas.sandberg@arm.com else: 7984762Snate@binkert.org value = ticks.fromSeconds(self.value) 7999411Sandreas.hansson@arm.com return long(value) 80010676Sandreas.hansson@arm.com 80110676Sandreas.hansson@arm.com # convert latency to ticks 8023101Sstever@eecs.umich.edu def ini_str(self): 8033101Sstever@eecs.umich.edu return '%d' % self.getValue() 8043101Sstever@eecs.umich.edu 8053101Sstever@eecs.umich.educlass Frequency(TickParamValue): 8063101Sstever@eecs.umich.edu def __init__(self, value): 8073101Sstever@eecs.umich.edu if isinstance(value, (Latency, Clock)): 80810267SGeoffrey.Blake@arm.com if value.value == 0: 80910267SGeoffrey.Blake@arm.com self.value = 0 8103101Sstever@eecs.umich.edu else: 8113101Sstever@eecs.umich.edu self.value = 1.0 / value.value 8123102Sstever@eecs.umich.edu self.ticks = value.ticks 8133101Sstever@eecs.umich.edu elif isinstance(value, Frequency): 8143101Sstever@eecs.umich.edu self.value = value.value 8153101Sstever@eecs.umich.edu self.ticks = value.ticks 81610267SGeoffrey.Blake@arm.com else: 81710267SGeoffrey.Blake@arm.com self.ticks = False 81810267SGeoffrey.Blake@arm.com self.value = convert.toFrequency(value) 81910267SGeoffrey.Blake@arm.com 8204762Snate@binkert.org def __getattr__(self, attr): 8214762Snate@binkert.org if attr == 'frequency': 8224762Snate@binkert.org return self 8233101Sstever@eecs.umich.edu if attr in ('latency', 'period'): 8243101Sstever@eecs.umich.edu return Latency(self) 8253101Sstever@eecs.umich.edu raise AttributeError, "Frequency object has no attribute '%s'" % attr 8268934SBrad.Beckmann@amd.com 8278934SBrad.Beckmann@amd.com # convert latency to ticks 8288934SBrad.Beckmann@amd.com def getValue(self): 8298934SBrad.Beckmann@amd.com if self.ticks or self.value == 0: 8308934SBrad.Beckmann@amd.com value = self.value 8313101Sstever@eecs.umich.edu else: 8323101Sstever@eecs.umich.edu value = ticks.fromSeconds(1.0 / self.value) 8333101Sstever@eecs.umich.edu return long(value) 8343101Sstever@eecs.umich.edu 8353101Sstever@eecs.umich.edu def ini_str(self): 83610380SAndrew.Bardsley@arm.com return '%d' % self.getValue() 83710380SAndrew.Bardsley@arm.com 83810380SAndrew.Bardsley@arm.com# A generic frequency and/or Latency value. Value is stored as a latency, 83910458Sandreas.hansson@arm.com# but to avoid ambiguity this object does not support numeric ops (* or /). 84010458Sandreas.hansson@arm.com# An explicit conversion to a Latency or Frequency must be made first. 84110458Sandreas.hansson@arm.comclass Clock(ParamValue): 84210458Sandreas.hansson@arm.com cxx_type = 'Tick' 84310458Sandreas.hansson@arm.com cxx_predecls = ['#include "sim/host.hh"'] 84410458Sandreas.hansson@arm.com swig_predecls = ['%import "stdint.i"\n' + 84510458Sandreas.hansson@arm.com '%import "sim/host.hh"'] 84610458Sandreas.hansson@arm.com def __init__(self, value): 84710458Sandreas.hansson@arm.com if isinstance(value, (Latency, Clock)): 84810458Sandreas.hansson@arm.com 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 8533101Sstever@eecs.umich.edu elif value.endswith('t'): 8543101Sstever@eecs.umich.edu self.ticks = True 8553101Sstever@eecs.umich.edu self.value = int(value[:-1]) 8563101Sstever@eecs.umich.edu else: 8573101Sstever@eecs.umich.edu self.ticks = False 8583101Sstever@eecs.umich.edu self.value = convert.anyToLatency(value) 8593101Sstever@eecs.umich.edu 8603101Sstever@eecs.umich.edu def __getattr__(self, attr): 8614380Sbinkertn@umich.edu if attr == 'frequency': 8624380Sbinkertn@umich.edu return Frequency(self) 8634380Sbinkertn@umich.edu if attr in ('latency', 'period'): 8643101Sstever@eecs.umich.edu return Latency(self) 8654380Sbinkertn@umich.edu raise AttributeError, "Frequency object has no attribute '%s'" % attr 8664380Sbinkertn@umich.edu 8674380Sbinkertn@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): 87110267SGeoffrey.Blake@arm.com return self.period.ini_str() 87210267SGeoffrey.Blake@arm.com 8737673Snate@binkert.orgclass NetworkBandwidth(float,ParamValue): 8747673Snate@binkert.org cxx_type = 'float' 8757673Snate@binkert.org def __new__(cls, value): 8767673Snate@binkert.org # convert to bits per second 8777673Snate@binkert.org val = convert.toNetworkBandwidth(value) 8783101Sstever@eecs.umich.edu return super(cls, NetworkBandwidth).__new__(cls, val) 8793101Sstever@eecs.umich.edu 8803101Sstever@eecs.umich.edu def __str__(self): 8813101Sstever@eecs.umich.edu return str(self.val) 8823101Sstever@eecs.umich.edu 8833101Sstever@eecs.umich.edu def getValue(self): 8843101Sstever@eecs.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) 8883101Sstever@eecs.umich.edu return float(value) 8893101Sstever@eecs.umich.edu 8903101Sstever@eecs.umich.edu def ini_str(self): 8919941SGeoffrey.Blake@arm.com return '%f' % self.getValue() 8923101Sstever@eecs.umich.edu 8933101Sstever@eecs.umich.educlass MemoryBandwidth(float,ParamValue): 8943101Sstever@eecs.umich.edu cxx_type = 'float' 8953101Sstever@eecs.umich.edu def __new__(self, value): 89610267SGeoffrey.Blake@arm.com # we want the number of ticks per byte of data 89710267SGeoffrey.Blake@arm.com val = convert.toMemoryBandwidth(value) 89810267SGeoffrey.Blake@arm.com return super(cls, MemoryBandwidth).__new__(cls, val) 89910267SGeoffrey.Blake@arm.com 9003101Sstever@eecs.umich.edu def __str__(self): 9013101Sstever@eecs.umich.edu return str(self.val) 9024380Sbinkertn@umich.edu 9033101Sstever@eecs.umich.edu def getValue(self): 9043101Sstever@eecs.umich.edu # convert to seconds per byte 9054762Snate@binkert.org value = float(self) 90611988Sandreas.sandberg@arm.com if value: 9074762Snate@binkert.org value = 1.0 / float(self) 9084762Snate@binkert.org # convert to ticks per byte 90911228SAndrew.Bardsley@arm.com value = ticks.fromSeconds(value) 91011228SAndrew.Bardsley@arm.com return float(value) 91111228SAndrew.Bardsley@arm.com 9124380Sbinkertn@umich.edu def ini_str(self): 9134380Sbinkertn@umich.edu return '%f' % self.getValue() 9143101Sstever@eecs.umich.edu 91510458Sandreas.hansson@arm.com# 91610458Sandreas.hansson@arm.com# "Constants"... handy aliases for various values. 91710458Sandreas.hansson@arm.com# 91810458Sandreas.hansson@arm.com 91910458Sandreas.hansson@arm.com# Special class for NULL pointers. Note the special check in 9207777Sgblack@eecs.umich.edu# make_param_value() above that lets these be assigned where a 9217777Sgblack@eecs.umich.edu# SimObject is required. 9227777Sgblack@eecs.umich.edu# only one copy of a particular node 9237777Sgblack@eecs.umich.educlass NullSimObject(object): 92410267SGeoffrey.Blake@arm.com __metaclass__ = Singleton 92510267SGeoffrey.Blake@arm.com 9267777Sgblack@eecs.umich.edu def __call__(cls): 9277777Sgblack@eecs.umich.edu return cls 9287777Sgblack@eecs.umich.edu 9297777Sgblack@eecs.umich.edu def _instantiate(self, parent = None, path = ''): 9307777Sgblack@eecs.umich.edu pass 9317777Sgblack@eecs.umich.edu 9327777Sgblack@eecs.umich.edu def ini_str(self): 9337777Sgblack@eecs.umich.edu return 'Null' 9347777Sgblack@eecs.umich.edu 9357777Sgblack@eecs.umich.edu def unproxy(self, base): 9367777Sgblack@eecs.umich.edu return self 9377777Sgblack@eecs.umich.edu 9387777Sgblack@eecs.umich.edu def set_path(self, parent, name): 9397777Sgblack@eecs.umich.edu pass 9407777Sgblack@eecs.umich.edu 94110267SGeoffrey.Blake@arm.com def __str__(self): 94210267SGeoffrey.Blake@arm.com return 'Null' 94310267SGeoffrey.Blake@arm.com 94410267SGeoffrey.Blake@arm.com def getValue(self): 9458579Ssteve.reinhardt@amd.com return None 9468579Ssteve.reinhardt@amd.com 9478579Ssteve.reinhardt@amd.com# The only instance you'll ever need... 9488579Ssteve.reinhardt@amd.comNULL = NullSimObject() 9498579Ssteve.reinhardt@amd.com 9508579Ssteve.reinhardt@amd.comdef isNullPointer(value): 9518579Ssteve.reinhardt@amd.com return isinstance(value, NullSimObject) 9528579Ssteve.reinhardt@amd.com 9538579Ssteve.reinhardt@amd.com# Some memory range specifications use this as a default upper bound. 9548579Ssteve.reinhardt@amd.comMaxAddr = Addr.max 9558579Ssteve.reinhardt@amd.comMaxTick = Tick.max 9568579Ssteve.reinhardt@amd.comAllMemory = AddrRange(0, MaxAddr) 9578579Ssteve.reinhardt@amd.com 9588579Ssteve.reinhardt@amd.com 9598579Ssteve.reinhardt@amd.com##################################################################### 9608579Ssteve.reinhardt@amd.com# 9618579Ssteve.reinhardt@amd.com# Port objects 9628579Ssteve.reinhardt@amd.com# 9637777Sgblack@eecs.umich.edu# Ports are used to interconnect objects in the memory system. 9647777Sgblack@eecs.umich.edu# 9657798Sgblack@eecs.umich.edu##################################################################### 9667777Sgblack@eecs.umich.edu 9677777Sgblack@eecs.umich.edu# Port reference: encapsulates a reference to a particular port on a 96811988Sandreas.sandberg@arm.com# particular SimObject. 9697777Sgblack@eecs.umich.educlass PortRef(object): 9707777Sgblack@eecs.umich.edu def __init__(self, simobj, name): 9717777Sgblack@eecs.umich.edu assert(isSimObject(simobj) or isSimObjectClass(simobj)) 9727777Sgblack@eecs.umich.edu self.simobj = simobj 9737777Sgblack@eecs.umich.edu self.name = name 9747777Sgblack@eecs.umich.edu self.peer = None # not associated with another port yet 9757777Sgblack@eecs.umich.edu self.ccConnected = False # C++ port connection done? 97610267SGeoffrey.Blake@arm.com self.index = -1 # always -1 for non-vector ports 97710267SGeoffrey.Blake@arm.com 9787777Sgblack@eecs.umich.edu def __str__(self): 9797777Sgblack@eecs.umich.edu return '%s.%s' % (self.simobj, self.name) 9807777Sgblack@eecs.umich.edu 9817777Sgblack@eecs.umich.edu # for config.ini, print peer's name (not ours) 9827777Sgblack@eecs.umich.edu def ini_str(self): 9837777Sgblack@eecs.umich.edu return str(self.peer) 9847777Sgblack@eecs.umich.edu 9857777Sgblack@eecs.umich.edu def __getattr__(self, attr): 9867777Sgblack@eecs.umich.edu if attr == 'peerObj': 9877777Sgblack@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): 9987777Sgblack@eecs.umich.edu # reference to plain VectorPort is implicit append 9997777Sgblack@eecs.umich.edu 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 101910267SGeoffrey.Blake@arm.com newRef.simobj = simobj 102010267SGeoffrey.Blake@arm.com assert(isSimObject(newRef.simobj)) 102110267SGeoffrey.Blake@arm.com if self.peer and not proxy.isproxy(self.peer): 102210267SGeoffrey.Blake@arm.com peerObj = self.peer.simobj(_memo=memo) 10238579Ssteve.reinhardt@amd.com newRef.peer = self.peer.clone(peerObj, memo) 10248579Ssteve.reinhardt@amd.com assert(not isinstance(newRef.peer, VectorPortRef)) 10258579Ssteve.reinhardt@amd.com return newRef 10268579Ssteve.reinhardt@amd.com 10278579Ssteve.reinhardt@amd.com def unproxy(self, simobj): 10288579Ssteve.reinhardt@amd.com assert(simobj is self.simobj) 10298579Ssteve.reinhardt@amd.com if proxy.isproxy(self.peer): 10308579Ssteve.reinhardt@amd.com try: 10318579Ssteve.reinhardt@amd.com realPeer = self.peer.unproxy(self.simobj) 10328579Ssteve.reinhardt@amd.com except: 10338579Ssteve.reinhardt@amd.com print "Error in unproxying port '%s' of %s" % \ 10348579Ssteve.reinhardt@amd.com (self.name, self.simobj.path()) 10358579Ssteve.reinhardt@amd.com raise 10368579Ssteve.reinhardt@amd.com 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 104311988Sandreas.sandberg@arm.com return 10447777Sgblack@eecs.umich.edu peer = self.peer 10457777Sgblack@eecs.umich.edu connectPorts(self.simobj.getCCObject(), self.name, self.index, 10467777Sgblack@eecs.umich.edu peer.simobj.getCCObject(), peer.name, peer.index) 10477777Sgblack@eecs.umich.edu self.ccConnected = True 10487777Sgblack@eecs.umich.edu peer.ccConnected = True 10497777Sgblack@eecs.umich.edu 105010267SGeoffrey.Blake@arm.com# A reference to an individual element of a VectorPort... much like a 105110267SGeoffrey.Blake@arm.com# PortRef, but has an index. 10527777Sgblack@eecs.umich.educlass VectorPortElementRef(PortRef): 10537777Sgblack@eecs.umich.edu def __init__(self, simobj, name, index): 10547777Sgblack@eecs.umich.edu PortRef.__init__(self, simobj, name) 10557777Sgblack@eecs.umich.edu self.index = index 10567777Sgblack@eecs.umich.edu 10577777Sgblack@eecs.umich.edu def __str__(self): 10587777Sgblack@eecs.umich.edu return '%s.%s[%d]' % (self.simobj, self.name, self.index) 10597777Sgblack@eecs.umich.edu 10607777Sgblack@eecs.umich.edu# A reference to a complete vector-valued port (not just a single element). 10617777Sgblack@eecs.umich.edu# Can be indexed to retrieve individual VectorPortElementRef instances. 10627777Sgblack@eecs.umich.educlass 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 10767777Sgblack@eecs.umich.edu def __getitem__(self, key): 10777777Sgblack@eecs.umich.edu 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) 109310267SGeoffrey.Blake@arm.com 109410267SGeoffrey.Blake@arm.com def connect(self, other): 109510267SGeoffrey.Blake@arm.com if isinstance(other, (list, tuple)): 109610267SGeoffrey.Blake@arm.com # Assign list of port refs to vector port. 10978579Ssteve.reinhardt@amd.com # For now, append them... not sure if that's the right semantics 10988579Ssteve.reinhardt@amd.com # or if it should replace the current vector. 10998579Ssteve.reinhardt@amd.com for ref in other: 11008579Ssteve.reinhardt@amd.com self._get_next().connect(ref) 11018579Ssteve.reinhardt@amd.com else: 11028579Ssteve.reinhardt@amd.com # scalar assignment to plain VectorPort is implicit append 11038579Ssteve.reinhardt@amd.com self._get_next().connect(other) 11048579Ssteve.reinhardt@amd.com 11058579Ssteve.reinhardt@amd.com def clone(self, simobj, memo): 11068579Ssteve.reinhardt@amd.com if memo.has_key(self): 11078579Ssteve.reinhardt@amd.com return memo[self] 11088579Ssteve.reinhardt@amd.com newRef = copy.copy(self) 11098579Ssteve.reinhardt@amd.com memo[self] = newRef 11108579Ssteve.reinhardt@amd.com 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] 111711988Sandreas.sandberg@arm.com 11187777Sgblack@eecs.umich.edu def ccConnect(self): 11197777Sgblack@eecs.umich.edu [el.ccConnect() for el in self.elements] 11203932Sbinkertn@umich.edu 112110380SAndrew.Bardsley@arm.com# Port description object. Like a ParamDesc object, this represents a 11223932Sbinkertn@umich.edu# logical port in the SimObject class, not a particular port on a 11233932Sbinkertn@umich.edu# SimObject instance. The latter are represented by PortRef objects. 11243932Sbinkertn@umich.educlass Port(object): 11253932Sbinkertn@umich.edu # Port("description") or Port(default, "description") 11263932Sbinkertn@umich.edu def __init__(self, *args): 11273932Sbinkertn@umich.edu if len(args) == 1: 11283932Sbinkertn@umich.edu self.desc = args[0] 11293932Sbinkertn@umich.edu elif len(args) == 2: 11303932Sbinkertn@umich.edu self.default = args[0] 11313932Sbinkertn@umich.edu self.desc = args[1] 11323932Sbinkertn@umich.edu else: 11333885Sbinkertn@umich.edu raise TypeError, 'wrong number of arguments' 11343932Sbinkertn@umich.edu # self.name is set by SimObject class on assignment 11353932Sbinkertn@umich.edu # e.g., pio_port = Port("blah") sets self.name to 'pio_port' 11363885Sbinkertn@umich.edu 11373932Sbinkertn@umich.edu # Generate a PortRef for this port on the given SimObject with the 11383932Sbinkertn@umich.edu # given name 11393932Sbinkertn@umich.edu def makeRef(self, simobj): 11403932Sbinkertn@umich.edu return PortRef(simobj, self.name) 11413932Sbinkertn@umich.edu 11423932Sbinkertn@umich.edu # Connect an instance of this port (on the given SimObject with 11433932Sbinkertn@umich.edu # the given name) with the port described by the supplied PortRef 11443932Sbinkertn@umich.edu def connect(self, simobj, ref): 11453932Sbinkertn@umich.edu self.makeRef(simobj).connect(ref) 11463932Sbinkertn@umich.edu 11473932Sbinkertn@umich.edu# VectorPort description object. Like Port, but represents a vector 11483932Sbinkertn@umich.edu# of connections (e.g., as on a Bus). 11493932Sbinkertn@umich.educlass VectorPort(Port): 11503932Sbinkertn@umich.edu def __init__(self, *args): 11513932Sbinkertn@umich.edu Port.__init__(self, *args) 11523932Sbinkertn@umich.edu self.isVec = True 11533932Sbinkertn@umich.edu 11543932Sbinkertn@umich.edu def makeRef(self, simobj): 11553885Sbinkertn@umich.edu return VectorPortRef(simobj, self.name) 11563885Sbinkertn@umich.edu 11573885Sbinkertn@umich.edu# 'Fake' ParamDesc for Port references to assign to the _pdesc slot of 11583885Sbinkertn@umich.edu# proxy objects (via set_param_desc()) so that proxy error messages 11594762Snate@binkert.org# make sense. 11607673Snate@binkert.orgclass PortParamDesc(object): 11617673Snate@binkert.org __metaclass__ = Singleton 11627673Snate@binkert.org 11637673Snate@binkert.org ptype_str = 'Port' 11647673Snate@binkert.org ptype = Port 11653885Sbinkertn@umich.edu 11663932Sbinkertn@umich.edu__all__ = ['Param', 'VectorParam', 11673885Sbinkertn@umich.edu 'Enum', 'Bool', 'String', 'Float', 116810267SGeoffrey.Blake@arm.com 'Int', 'Unsigned', 'Int8', 'UInt8', 'Int16', 'UInt16', 116910267SGeoffrey.Blake@arm.com 'Int32', 'UInt32', 'Int64', 'UInt64', 117010267SGeoffrey.Blake@arm.com 'Counter', 'Addr', 'Tick', 'Percent', 117110267SGeoffrey.Blake@arm.com 'TcpPort', 'UdpPort', 'EthernetAddr', 11724762Snate@binkert.org 'MemorySize', 'MemorySize32', 117311988Sandreas.sandberg@arm.com 'Latency', 'Frequency', 'Clock', 117411988Sandreas.sandberg@arm.com 'NetworkBandwidth', 'MemoryBandwidth', 11754762Snate@binkert.org 'Range', 'AddrRange', 'TickRange', 117611988Sandreas.sandberg@arm.com 'MaxAddr', 'MaxTick', 'AllMemory', 11774762Snate@binkert.org 'Time', 11783885Sbinkertn@umich.edu 'NextEthernetAddr', 'NULL', 11794762Snate@binkert.org 'Port', 'VectorPort'] 11803885Sbinkertn@umich.edu