params.py revision 7526
13101Sstever@eecs.umich.edu# Copyright (c) 2004-2006 The Regents of The University of Michigan 23101Sstever@eecs.umich.edu# All rights reserved. 33101Sstever@eecs.umich.edu# 43101Sstever@eecs.umich.edu# Redistribution and use in source and binary forms, with or without 53101Sstever@eecs.umich.edu# modification, are permitted provided that the following conditions are 63101Sstever@eecs.umich.edu# met: redistributions of source code must retain the above copyright 73101Sstever@eecs.umich.edu# notice, this list of conditions and the following disclaimer; 83101Sstever@eecs.umich.edu# redistributions in binary form must reproduce the above copyright 93101Sstever@eecs.umich.edu# notice, this list of conditions and the following disclaimer in the 103101Sstever@eecs.umich.edu# documentation and/or other materials provided with the distribution; 113101Sstever@eecs.umich.edu# neither the name of the copyright holders nor the names of its 123101Sstever@eecs.umich.edu# contributors may be used to endorse or promote products derived from 133101Sstever@eecs.umich.edu# this software without specific prior written permission. 143101Sstever@eecs.umich.edu# 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 423101Sstever@eecs.umich.edu# space when the parameter dictionary is initialized (in 433101Sstever@eecs.umich.edu# MetaSimObject._new_param()); after that point they aren't used. 443101Sstever@eecs.umich.edu# 453101Sstever@eecs.umich.edu##################################################################### 463101Sstever@eecs.umich.edu 473885Sbinkertn@umich.eduimport copy 483885Sbinkertn@umich.eduimport datetime 494762Snate@binkert.orgimport re 503885Sbinkertn@umich.eduimport sys 513885Sbinkertn@umich.eduimport time 523885Sbinkertn@umich.edu 534380Sbinkertn@umich.eduimport proxy 544167Sbinkertn@umich.eduimport ticks 553102Sstever@eecs.umich.edufrom util import * 563101Sstever@eecs.umich.edu 574762Snate@binkert.orgdef isSimObject(*args, **kwargs): 584762Snate@binkert.org return SimObject.isSimObject(*args, **kwargs) 594762Snate@binkert.org 604762Snate@binkert.orgdef isSimObjectSequence(*args, **kwargs): 614762Snate@binkert.org return SimObject.isSimObjectSequence(*args, **kwargs) 624762Snate@binkert.org 634762Snate@binkert.orgdef isSimObjectClass(*args, **kwargs): 644762Snate@binkert.org return SimObject.isSimObjectClass(*args, **kwargs) 654762Snate@binkert.org 665033Smilesck@eecs.umich.eduallParams = {} 675033Smilesck@eecs.umich.edu 685033Smilesck@eecs.umich.educlass MetaParamValue(type): 695033Smilesck@eecs.umich.edu def __new__(mcls, name, bases, dct): 705033Smilesck@eecs.umich.edu cls = super(MetaParamValue, mcls).__new__(mcls, name, bases, dct) 715033Smilesck@eecs.umich.edu assert name not in allParams 725033Smilesck@eecs.umich.edu allParams[name] = cls 735033Smilesck@eecs.umich.edu return cls 745033Smilesck@eecs.umich.edu 755033Smilesck@eecs.umich.edu 763101Sstever@eecs.umich.edu# Dummy base class to identify types that are legitimate for SimObject 773101Sstever@eecs.umich.edu# parameters. 783101Sstever@eecs.umich.educlass ParamValue(object): 795033Smilesck@eecs.umich.edu __metaclass__ = MetaParamValue 803101Sstever@eecs.umich.edu 813101Sstever@eecs.umich.edu cxx_predecls = [] 823101Sstever@eecs.umich.edu swig_predecls = [] 833101Sstever@eecs.umich.edu 843101Sstever@eecs.umich.edu # default for printing to .ini file is regular string conversion. 853101Sstever@eecs.umich.edu # will be overridden in some cases 863101Sstever@eecs.umich.edu def ini_str(self): 873101Sstever@eecs.umich.edu return str(self) 883101Sstever@eecs.umich.edu 893101Sstever@eecs.umich.edu # allows us to blithely call unproxy() on things without checking 903101Sstever@eecs.umich.edu # if they're really proxies or not 913101Sstever@eecs.umich.edu def unproxy(self, base): 923101Sstever@eecs.umich.edu return self 933101Sstever@eecs.umich.edu 943101Sstever@eecs.umich.edu# Regular parameter description. 953101Sstever@eecs.umich.educlass ParamDesc(object): 966656Snate@binkert.org file_ext = 'ptype' 976656Snate@binkert.org 983101Sstever@eecs.umich.edu def __init__(self, ptype_str, ptype, *args, **kwargs): 993101Sstever@eecs.umich.edu self.ptype_str = ptype_str 1003101Sstever@eecs.umich.edu # remember ptype only if it is provided 1013101Sstever@eecs.umich.edu if ptype != None: 1023101Sstever@eecs.umich.edu self.ptype = ptype 1033101Sstever@eecs.umich.edu 1043101Sstever@eecs.umich.edu if args: 1053101Sstever@eecs.umich.edu if len(args) == 1: 1063101Sstever@eecs.umich.edu self.desc = args[0] 1073101Sstever@eecs.umich.edu elif len(args) == 2: 1083101Sstever@eecs.umich.edu self.default = args[0] 1093101Sstever@eecs.umich.edu self.desc = args[1] 1103101Sstever@eecs.umich.edu else: 1113101Sstever@eecs.umich.edu raise TypeError, 'too many arguments' 1123101Sstever@eecs.umich.edu 1133101Sstever@eecs.umich.edu if kwargs.has_key('desc'): 1143101Sstever@eecs.umich.edu assert(not hasattr(self, 'desc')) 1153101Sstever@eecs.umich.edu self.desc = kwargs['desc'] 1163101Sstever@eecs.umich.edu del kwargs['desc'] 1173101Sstever@eecs.umich.edu 1183101Sstever@eecs.umich.edu if kwargs.has_key('default'): 1193101Sstever@eecs.umich.edu assert(not hasattr(self, 'default')) 1203101Sstever@eecs.umich.edu self.default = kwargs['default'] 1213101Sstever@eecs.umich.edu del kwargs['default'] 1223101Sstever@eecs.umich.edu 1233101Sstever@eecs.umich.edu if kwargs: 1243101Sstever@eecs.umich.edu raise TypeError, 'extra unknown kwargs %s' % kwargs 1253101Sstever@eecs.umich.edu 1263101Sstever@eecs.umich.edu if not hasattr(self, 'desc'): 1273101Sstever@eecs.umich.edu raise TypeError, 'desc attribute missing' 1283101Sstever@eecs.umich.edu 1293101Sstever@eecs.umich.edu def __getattr__(self, attr): 1303101Sstever@eecs.umich.edu if attr == 'ptype': 1315033Smilesck@eecs.umich.edu ptype = SimObject.allClasses[self.ptype_str] 1326656Snate@binkert.org assert isSimObjectClass(ptype) 1335033Smilesck@eecs.umich.edu self.ptype = ptype 1345033Smilesck@eecs.umich.edu return ptype 1355033Smilesck@eecs.umich.edu 1363101Sstever@eecs.umich.edu raise AttributeError, "'%s' object has no attribute '%s'" % \ 1373101Sstever@eecs.umich.edu (type(self).__name__, attr) 1383101Sstever@eecs.umich.edu 1393101Sstever@eecs.umich.edu def convert(self, value): 1403101Sstever@eecs.umich.edu if isinstance(value, proxy.BaseProxy): 1413101Sstever@eecs.umich.edu value.set_param_desc(self) 1423101Sstever@eecs.umich.edu return value 1433101Sstever@eecs.umich.edu if not hasattr(self, 'ptype') and isNullPointer(value): 1443101Sstever@eecs.umich.edu # deferred evaluation of SimObject; continue to defer if 1453101Sstever@eecs.umich.edu # we're just assigning a null pointer 1463101Sstever@eecs.umich.edu return value 1473101Sstever@eecs.umich.edu if isinstance(value, self.ptype): 1483101Sstever@eecs.umich.edu return value 1493102Sstever@eecs.umich.edu if isNullPointer(value) and isSimObjectClass(self.ptype): 1503101Sstever@eecs.umich.edu return value 1513101Sstever@eecs.umich.edu return self.ptype(value) 1523101Sstever@eecs.umich.edu 1533101Sstever@eecs.umich.edu def cxx_predecls(self): 1543101Sstever@eecs.umich.edu return self.ptype.cxx_predecls 1553101Sstever@eecs.umich.edu 1563101Sstever@eecs.umich.edu def swig_predecls(self): 1573101Sstever@eecs.umich.edu return self.ptype.swig_predecls 1583101Sstever@eecs.umich.edu 1593101Sstever@eecs.umich.edu def cxx_decl(self): 1603101Sstever@eecs.umich.edu return '%s %s;' % (self.ptype.cxx_type, self.name) 1613101Sstever@eecs.umich.edu 1623101Sstever@eecs.umich.edu# Vector-valued parameter description. Just like ParamDesc, except 1633101Sstever@eecs.umich.edu# that the value is a vector (list) of the specified type instead of a 1643101Sstever@eecs.umich.edu# single value. 1653101Sstever@eecs.umich.edu 1663101Sstever@eecs.umich.educlass VectorParamValue(list): 1675033Smilesck@eecs.umich.edu __metaclass__ = MetaParamValue 1685475Snate@binkert.org def __setattr__(self, attr, value): 1695475Snate@binkert.org raise AttributeError, \ 1705475Snate@binkert.org "Not allowed to set %s on '%s'" % (attr, type(self).__name__) 1715475Snate@binkert.org 1723101Sstever@eecs.umich.edu def ini_str(self): 1733101Sstever@eecs.umich.edu return ' '.join([v.ini_str() for v in self]) 1743101Sstever@eecs.umich.edu 1754762Snate@binkert.org def getValue(self): 1764762Snate@binkert.org return [ v.getValue() for v in self ] 1774762Snate@binkert.org 1783101Sstever@eecs.umich.edu def unproxy(self, base): 1793101Sstever@eecs.umich.edu return [v.unproxy(base) for v in self] 1803101Sstever@eecs.umich.edu 1813101Sstever@eecs.umich.educlass SimObjVector(VectorParamValue): 1825037Smilesck@eecs.umich.edu def print_ini(self, ini_file): 1833101Sstever@eecs.umich.edu for v in self: 1845037Smilesck@eecs.umich.edu v.print_ini(ini_file) 1853101Sstever@eecs.umich.edu 1863101Sstever@eecs.umich.educlass VectorParamDesc(ParamDesc): 1876656Snate@binkert.org file_ext = 'vptype' 1886656Snate@binkert.org 1893101Sstever@eecs.umich.edu # Convert assigned value to appropriate type. If the RHS is not a 1903101Sstever@eecs.umich.edu # list or tuple, it generates a single-element list. 1913101Sstever@eecs.umich.edu def convert(self, value): 1923101Sstever@eecs.umich.edu if isinstance(value, (list, tuple)): 1933101Sstever@eecs.umich.edu # list: coerce each element into new list 1943101Sstever@eecs.umich.edu tmp_list = [ ParamDesc.convert(self, v) for v in value ] 1953101Sstever@eecs.umich.edu else: 1964762Snate@binkert.org # singleton: coerce to a single-element list 1974762Snate@binkert.org tmp_list = [ ParamDesc.convert(self, value) ] 1984762Snate@binkert.org 1994762Snate@binkert.org if isSimObjectSequence(tmp_list): 2004762Snate@binkert.org return SimObjVector(tmp_list) 2014762Snate@binkert.org else: 2024762Snate@binkert.org return VectorParamValue(tmp_list) 2034762Snate@binkert.org 2044762Snate@binkert.org def swig_predecls(self): 2054762Snate@binkert.org return ['%%include "%s_vptype.i"' % self.ptype_str] 2064762Snate@binkert.org 2074762Snate@binkert.org def swig_decl(self): 2084762Snate@binkert.org cxx_type = re.sub('std::', '', self.ptype.cxx_type) 2094762Snate@binkert.org vdecl = 'namespace std { %%template(vector_%s) vector< %s >; }' % \ 2104762Snate@binkert.org (self.ptype_str, cxx_type) 2114762Snate@binkert.org return ['%include "std_vector.i"'] + self.ptype.swig_predecls + [vdecl] 2123101Sstever@eecs.umich.edu 2133101Sstever@eecs.umich.edu def cxx_predecls(self): 2143101Sstever@eecs.umich.edu return ['#include <vector>'] + self.ptype.cxx_predecls 2153101Sstever@eecs.umich.edu 2163101Sstever@eecs.umich.edu def cxx_decl(self): 2173101Sstever@eecs.umich.edu return 'std::vector< %s > %s;' % (self.ptype.cxx_type, self.name) 2183101Sstever@eecs.umich.edu 2193101Sstever@eecs.umich.educlass ParamFactory(object): 2203101Sstever@eecs.umich.edu def __init__(self, param_desc_class, ptype_str = None): 2213101Sstever@eecs.umich.edu self.param_desc_class = param_desc_class 2223101Sstever@eecs.umich.edu self.ptype_str = ptype_str 2233101Sstever@eecs.umich.edu 2243101Sstever@eecs.umich.edu def __getattr__(self, attr): 2253101Sstever@eecs.umich.edu if self.ptype_str: 2263101Sstever@eecs.umich.edu attr = self.ptype_str + '.' + attr 2273101Sstever@eecs.umich.edu return ParamFactory(self.param_desc_class, attr) 2283101Sstever@eecs.umich.edu 2293101Sstever@eecs.umich.edu # E.g., Param.Int(5, "number of widgets") 2303101Sstever@eecs.umich.edu def __call__(self, *args, **kwargs): 2313101Sstever@eecs.umich.edu ptype = None 2323101Sstever@eecs.umich.edu try: 2335033Smilesck@eecs.umich.edu ptype = allParams[self.ptype_str] 2345033Smilesck@eecs.umich.edu except KeyError: 2353101Sstever@eecs.umich.edu # if name isn't defined yet, assume it's a SimObject, and 2363101Sstever@eecs.umich.edu # try to resolve it later 2373101Sstever@eecs.umich.edu pass 2383101Sstever@eecs.umich.edu return self.param_desc_class(self.ptype_str, ptype, *args, **kwargs) 2393101Sstever@eecs.umich.edu 2403101Sstever@eecs.umich.eduParam = ParamFactory(ParamDesc) 2413101Sstever@eecs.umich.eduVectorParam = ParamFactory(VectorParamDesc) 2423101Sstever@eecs.umich.edu 2433101Sstever@eecs.umich.edu##################################################################### 2443101Sstever@eecs.umich.edu# 2453101Sstever@eecs.umich.edu# Parameter Types 2463101Sstever@eecs.umich.edu# 2473101Sstever@eecs.umich.edu# Though native Python types could be used to specify parameter types 2483101Sstever@eecs.umich.edu# (the 'ptype' field of the Param and VectorParam classes), it's more 2493101Sstever@eecs.umich.edu# flexible to define our own set of types. This gives us more control 2503101Sstever@eecs.umich.edu# over how Python expressions are converted to values (via the 2513101Sstever@eecs.umich.edu# __init__() constructor) and how these values are printed out (via 2523101Sstever@eecs.umich.edu# the __str__() conversion method). 2533101Sstever@eecs.umich.edu# 2543101Sstever@eecs.umich.edu##################################################################### 2553101Sstever@eecs.umich.edu 2563101Sstever@eecs.umich.edu# String-valued parameter. Just mixin the ParamValue class with the 2573101Sstever@eecs.umich.edu# built-in str class. 2583101Sstever@eecs.umich.educlass String(ParamValue,str): 2593101Sstever@eecs.umich.edu cxx_type = 'std::string' 2603101Sstever@eecs.umich.edu cxx_predecls = ['#include <string>'] 2613101Sstever@eecs.umich.edu swig_predecls = ['%include "std_string.i"\n' + 2623101Sstever@eecs.umich.edu '%apply const std::string& {std::string *};'] 2634762Snate@binkert.org swig_predecls = ['%include "std_string.i"' ] 2644762Snate@binkert.org 2654762Snate@binkert.org def getValue(self): 2664762Snate@binkert.org return self 2673101Sstever@eecs.umich.edu 2683101Sstever@eecs.umich.edu# superclass for "numeric" parameter values, to emulate math 2693101Sstever@eecs.umich.edu# operations in a type-safe way. e.g., a Latency times an int returns 2703101Sstever@eecs.umich.edu# a new Latency object. 2713101Sstever@eecs.umich.educlass NumericParamValue(ParamValue): 2723101Sstever@eecs.umich.edu def __str__(self): 2733101Sstever@eecs.umich.edu return str(self.value) 2743101Sstever@eecs.umich.edu 2753101Sstever@eecs.umich.edu def __float__(self): 2763101Sstever@eecs.umich.edu return float(self.value) 2773101Sstever@eecs.umich.edu 2783714Sstever@eecs.umich.edu def __long__(self): 2793714Sstever@eecs.umich.edu return long(self.value) 2803714Sstever@eecs.umich.edu 2813714Sstever@eecs.umich.edu def __int__(self): 2823714Sstever@eecs.umich.edu return int(self.value) 2833714Sstever@eecs.umich.edu 2843101Sstever@eecs.umich.edu # hook for bounds checking 2853101Sstever@eecs.umich.edu def _check(self): 2863101Sstever@eecs.umich.edu return 2873101Sstever@eecs.umich.edu 2883101Sstever@eecs.umich.edu def __mul__(self, other): 2893101Sstever@eecs.umich.edu newobj = self.__class__(self) 2903101Sstever@eecs.umich.edu newobj.value *= other 2913101Sstever@eecs.umich.edu newobj._check() 2923101Sstever@eecs.umich.edu return newobj 2933101Sstever@eecs.umich.edu 2943101Sstever@eecs.umich.edu __rmul__ = __mul__ 2953101Sstever@eecs.umich.edu 2963101Sstever@eecs.umich.edu def __div__(self, other): 2973101Sstever@eecs.umich.edu newobj = self.__class__(self) 2983101Sstever@eecs.umich.edu newobj.value /= other 2993101Sstever@eecs.umich.edu newobj._check() 3003101Sstever@eecs.umich.edu return newobj 3013101Sstever@eecs.umich.edu 3023101Sstever@eecs.umich.edu def __sub__(self, other): 3033101Sstever@eecs.umich.edu newobj = self.__class__(self) 3043101Sstever@eecs.umich.edu newobj.value -= other 3053101Sstever@eecs.umich.edu newobj._check() 3063101Sstever@eecs.umich.edu return newobj 3073101Sstever@eecs.umich.edu 3083101Sstever@eecs.umich.edu# Metaclass for bounds-checked integer parameters. See CheckedInt. 3095033Smilesck@eecs.umich.educlass CheckedIntType(MetaParamValue): 3103101Sstever@eecs.umich.edu def __init__(cls, name, bases, dict): 3113101Sstever@eecs.umich.edu super(CheckedIntType, cls).__init__(name, bases, dict) 3123101Sstever@eecs.umich.edu 3133101Sstever@eecs.umich.edu # CheckedInt is an abstract base class, so we actually don't 3143101Sstever@eecs.umich.edu # want to do any processing on it... the rest of this code is 3153101Sstever@eecs.umich.edu # just for classes that derive from CheckedInt. 3163101Sstever@eecs.umich.edu if name == 'CheckedInt': 3173101Sstever@eecs.umich.edu return 3183101Sstever@eecs.umich.edu 3193101Sstever@eecs.umich.edu if not cls.cxx_predecls: 3203101Sstever@eecs.umich.edu # most derived types require this, so we just do it here once 3216214Snate@binkert.org cls.cxx_predecls = ['#include "base/types.hh"'] 3223101Sstever@eecs.umich.edu 3233101Sstever@eecs.umich.edu if not cls.swig_predecls: 3243101Sstever@eecs.umich.edu # most derived types require this, so we just do it here once 3254762Snate@binkert.org cls.swig_predecls = ['%import "stdint.i"\n' + 3266214Snate@binkert.org '%import "base/types.hh"'] 3273101Sstever@eecs.umich.edu 3283101Sstever@eecs.umich.edu if not (hasattr(cls, 'min') and hasattr(cls, 'max')): 3293101Sstever@eecs.umich.edu if not (hasattr(cls, 'size') and hasattr(cls, 'unsigned')): 3303101Sstever@eecs.umich.edu panic("CheckedInt subclass %s must define either\n" \ 3315822Ssaidi@eecs.umich.edu " 'min' and 'max' or 'size' and 'unsigned'\n", 3325822Ssaidi@eecs.umich.edu name); 3333101Sstever@eecs.umich.edu if cls.unsigned: 3343101Sstever@eecs.umich.edu cls.min = 0 3353101Sstever@eecs.umich.edu cls.max = 2 ** cls.size - 1 3363101Sstever@eecs.umich.edu else: 3373101Sstever@eecs.umich.edu cls.min = -(2 ** (cls.size - 1)) 3383101Sstever@eecs.umich.edu cls.max = (2 ** (cls.size - 1)) - 1 3393101Sstever@eecs.umich.edu 3403101Sstever@eecs.umich.edu# Abstract superclass for bounds-checked integer parameters. This 3413101Sstever@eecs.umich.edu# class is subclassed to generate parameter classes with specific 3423101Sstever@eecs.umich.edu# bounds. Initialization of the min and max bounds is done in the 3433101Sstever@eecs.umich.edu# metaclass CheckedIntType.__init__. 3443101Sstever@eecs.umich.educlass CheckedInt(NumericParamValue): 3453101Sstever@eecs.umich.edu __metaclass__ = CheckedIntType 3463101Sstever@eecs.umich.edu 3473101Sstever@eecs.umich.edu def _check(self): 3483101Sstever@eecs.umich.edu if not self.min <= self.value <= self.max: 3493101Sstever@eecs.umich.edu raise TypeError, 'Integer param out of bounds %d < %d < %d' % \ 3503101Sstever@eecs.umich.edu (self.min, self.value, self.max) 3513101Sstever@eecs.umich.edu 3523101Sstever@eecs.umich.edu def __init__(self, value): 3533101Sstever@eecs.umich.edu if isinstance(value, str): 3543102Sstever@eecs.umich.edu self.value = convert.toInteger(value) 3553714Sstever@eecs.umich.edu elif isinstance(value, (int, long, float, NumericParamValue)): 3563101Sstever@eecs.umich.edu self.value = long(value) 3573714Sstever@eecs.umich.edu else: 3583714Sstever@eecs.umich.edu raise TypeError, "Can't convert object of type %s to CheckedInt" \ 3593714Sstever@eecs.umich.edu % type(value).__name__ 3603101Sstever@eecs.umich.edu self._check() 3613101Sstever@eecs.umich.edu 3624762Snate@binkert.org def getValue(self): 3634762Snate@binkert.org return long(self.value) 3644762Snate@binkert.org 3653101Sstever@eecs.umich.educlass Int(CheckedInt): cxx_type = 'int'; size = 32; unsigned = False 3663101Sstever@eecs.umich.educlass Unsigned(CheckedInt): cxx_type = 'unsigned'; size = 32; unsigned = True 3673101Sstever@eecs.umich.edu 3683101Sstever@eecs.umich.educlass Int8(CheckedInt): cxx_type = 'int8_t'; size = 8; unsigned = False 3693101Sstever@eecs.umich.educlass UInt8(CheckedInt): cxx_type = 'uint8_t'; size = 8; unsigned = True 3703101Sstever@eecs.umich.educlass Int16(CheckedInt): cxx_type = 'int16_t'; size = 16; unsigned = False 3713101Sstever@eecs.umich.educlass UInt16(CheckedInt): cxx_type = 'uint16_t'; size = 16; unsigned = True 3723101Sstever@eecs.umich.educlass Int32(CheckedInt): cxx_type = 'int32_t'; size = 32; unsigned = False 3733101Sstever@eecs.umich.educlass UInt32(CheckedInt): cxx_type = 'uint32_t'; size = 32; unsigned = True 3743101Sstever@eecs.umich.educlass Int64(CheckedInt): cxx_type = 'int64_t'; size = 64; unsigned = False 3753101Sstever@eecs.umich.educlass UInt64(CheckedInt): cxx_type = 'uint64_t'; size = 64; unsigned = True 3763101Sstever@eecs.umich.edu 3773101Sstever@eecs.umich.educlass Counter(CheckedInt): cxx_type = 'Counter'; size = 64; unsigned = True 3783101Sstever@eecs.umich.educlass Tick(CheckedInt): cxx_type = 'Tick'; size = 64; unsigned = True 3793101Sstever@eecs.umich.educlass TcpPort(CheckedInt): cxx_type = 'uint16_t'; size = 16; unsigned = True 3803101Sstever@eecs.umich.educlass UdpPort(CheckedInt): cxx_type = 'uint16_t'; size = 16; unsigned = True 3813101Sstever@eecs.umich.edu 3823101Sstever@eecs.umich.educlass Percent(CheckedInt): cxx_type = 'int'; min = 0; max = 100 3833101Sstever@eecs.umich.edu 3843101Sstever@eecs.umich.educlass Float(ParamValue, float): 3854446Sbinkertn@umich.edu cxx_type = 'double' 3863101Sstever@eecs.umich.edu 3875468Snate@binkert.org def __init__(self, value): 3885468Snate@binkert.org if isinstance(value, (int, long, float, NumericParamValue, Float)): 3895468Snate@binkert.org self.value = float(value) 3905468Snate@binkert.org else: 3915468Snate@binkert.org raise TypeError, "Can't convert object of type %s to Float" \ 3925468Snate@binkert.org % type(value).__name__ 3935468Snate@binkert.org 3944762Snate@binkert.org def getValue(self): 3954762Snate@binkert.org return float(self.value) 3964762Snate@binkert.org 3973101Sstever@eecs.umich.educlass MemorySize(CheckedInt): 3983101Sstever@eecs.umich.edu cxx_type = 'uint64_t' 3993101Sstever@eecs.umich.edu size = 64 4003101Sstever@eecs.umich.edu unsigned = True 4013101Sstever@eecs.umich.edu def __init__(self, value): 4023101Sstever@eecs.umich.edu if isinstance(value, MemorySize): 4033101Sstever@eecs.umich.edu self.value = value.value 4043101Sstever@eecs.umich.edu else: 4053102Sstever@eecs.umich.edu self.value = convert.toMemorySize(value) 4063101Sstever@eecs.umich.edu self._check() 4073101Sstever@eecs.umich.edu 4083101Sstever@eecs.umich.educlass MemorySize32(CheckedInt): 4094168Sbinkertn@umich.edu cxx_type = 'uint32_t' 4103101Sstever@eecs.umich.edu size = 32 4113101Sstever@eecs.umich.edu unsigned = True 4123101Sstever@eecs.umich.edu def __init__(self, value): 4133101Sstever@eecs.umich.edu if isinstance(value, MemorySize): 4143101Sstever@eecs.umich.edu self.value = value.value 4153101Sstever@eecs.umich.edu else: 4163102Sstever@eecs.umich.edu self.value = convert.toMemorySize(value) 4173101Sstever@eecs.umich.edu self._check() 4183101Sstever@eecs.umich.edu 4193101Sstever@eecs.umich.educlass Addr(CheckedInt): 4203101Sstever@eecs.umich.edu cxx_type = 'Addr' 4213101Sstever@eecs.umich.edu size = 64 4223101Sstever@eecs.umich.edu unsigned = True 4233101Sstever@eecs.umich.edu def __init__(self, value): 4243101Sstever@eecs.umich.edu if isinstance(value, Addr): 4253101Sstever@eecs.umich.edu self.value = value.value 4263101Sstever@eecs.umich.edu else: 4273101Sstever@eecs.umich.edu try: 4283102Sstever@eecs.umich.edu self.value = convert.toMemorySize(value) 4293101Sstever@eecs.umich.edu except TypeError: 4303101Sstever@eecs.umich.edu self.value = long(value) 4313101Sstever@eecs.umich.edu self._check() 4323584Ssaidi@eecs.umich.edu def __add__(self, other): 4333584Ssaidi@eecs.umich.edu if isinstance(other, Addr): 4343584Ssaidi@eecs.umich.edu return self.value + other.value 4353584Ssaidi@eecs.umich.edu else: 4363584Ssaidi@eecs.umich.edu return self.value + other 4373101Sstever@eecs.umich.edu 4383101Sstever@eecs.umich.edu 4395033Smilesck@eecs.umich.educlass MetaRange(MetaParamValue): 4403101Sstever@eecs.umich.edu def __init__(cls, name, bases, dict): 4413101Sstever@eecs.umich.edu super(MetaRange, cls).__init__(name, bases, dict) 4423101Sstever@eecs.umich.edu if name == 'Range': 4433101Sstever@eecs.umich.edu return 4443101Sstever@eecs.umich.edu cls.cxx_type = 'Range< %s >' % cls.type.cxx_type 4453101Sstever@eecs.umich.edu cls.cxx_predecls = \ 4463101Sstever@eecs.umich.edu ['#include "base/range.hh"'] + cls.type.cxx_predecls 4473101Sstever@eecs.umich.edu 4483101Sstever@eecs.umich.educlass Range(ParamValue): 4493101Sstever@eecs.umich.edu __metaclass__ = MetaRange 4503101Sstever@eecs.umich.edu type = Int # default; can be overridden in subclasses 4513101Sstever@eecs.umich.edu def __init__(self, *args, **kwargs): 4523101Sstever@eecs.umich.edu def handle_kwargs(self, kwargs): 4533101Sstever@eecs.umich.edu if 'end' in kwargs: 4543101Sstever@eecs.umich.edu self.second = self.type(kwargs.pop('end')) 4553101Sstever@eecs.umich.edu elif 'size' in kwargs: 4563101Sstever@eecs.umich.edu self.second = self.first + self.type(kwargs.pop('size')) - 1 4573101Sstever@eecs.umich.edu else: 4583101Sstever@eecs.umich.edu raise TypeError, "Either end or size must be specified" 4593101Sstever@eecs.umich.edu 4603101Sstever@eecs.umich.edu if len(args) == 0: 4613101Sstever@eecs.umich.edu self.first = self.type(kwargs.pop('start')) 4623101Sstever@eecs.umich.edu handle_kwargs(self, kwargs) 4633101Sstever@eecs.umich.edu 4643101Sstever@eecs.umich.edu elif len(args) == 1: 4653101Sstever@eecs.umich.edu if kwargs: 4663101Sstever@eecs.umich.edu self.first = self.type(args[0]) 4673101Sstever@eecs.umich.edu handle_kwargs(self, kwargs) 4683101Sstever@eecs.umich.edu elif isinstance(args[0], Range): 4693101Sstever@eecs.umich.edu self.first = self.type(args[0].first) 4703101Sstever@eecs.umich.edu self.second = self.type(args[0].second) 4715219Ssaidi@eecs.umich.edu elif isinstance(args[0], (list, tuple)): 4725219Ssaidi@eecs.umich.edu self.first = self.type(args[0][0]) 4735219Ssaidi@eecs.umich.edu self.second = self.type(args[0][1]) 4743101Sstever@eecs.umich.edu else: 4753101Sstever@eecs.umich.edu self.first = self.type(0) 4763101Sstever@eecs.umich.edu self.second = self.type(args[0]) - 1 4773101Sstever@eecs.umich.edu 4783101Sstever@eecs.umich.edu elif len(args) == 2: 4793101Sstever@eecs.umich.edu self.first = self.type(args[0]) 4803101Sstever@eecs.umich.edu self.second = self.type(args[1]) 4813101Sstever@eecs.umich.edu else: 4823101Sstever@eecs.umich.edu raise TypeError, "Too many arguments specified" 4833101Sstever@eecs.umich.edu 4843101Sstever@eecs.umich.edu if kwargs: 4853101Sstever@eecs.umich.edu raise TypeError, "too many keywords: %s" % kwargs.keys() 4863101Sstever@eecs.umich.edu 4873101Sstever@eecs.umich.edu def __str__(self): 4883101Sstever@eecs.umich.edu return '%s:%s' % (self.first, self.second) 4893101Sstever@eecs.umich.edu 4903101Sstever@eecs.umich.educlass AddrRange(Range): 4913101Sstever@eecs.umich.edu type = Addr 4924762Snate@binkert.org swig_predecls = ['%include "python/swig/range.i"'] 4934762Snate@binkert.org 4944762Snate@binkert.org def getValue(self): 4954762Snate@binkert.org from m5.objects.params import AddrRange 4964762Snate@binkert.org 4974762Snate@binkert.org value = AddrRange() 4984762Snate@binkert.org value.start = long(self.first) 4994762Snate@binkert.org value.end = long(self.second) 5004762Snate@binkert.org return value 5013101Sstever@eecs.umich.edu 5023101Sstever@eecs.umich.educlass TickRange(Range): 5033101Sstever@eecs.umich.edu type = Tick 5044762Snate@binkert.org swig_predecls = ['%include "python/swig/range.i"'] 5054762Snate@binkert.org 5064762Snate@binkert.org def getValue(self): 5074762Snate@binkert.org from m5.objects.params import TickRange 5084762Snate@binkert.org 5094762Snate@binkert.org value = TickRange() 5104762Snate@binkert.org value.start = long(self.first) 5114762Snate@binkert.org value.end = long(self.second) 5124762Snate@binkert.org return value 5133101Sstever@eecs.umich.edu 5143101Sstever@eecs.umich.edu# Boolean parameter type. Python doesn't let you subclass bool, since 5153101Sstever@eecs.umich.edu# it doesn't want to let you create multiple instances of True and 5163101Sstever@eecs.umich.edu# False. Thus this is a little more complicated than String. 5173101Sstever@eecs.umich.educlass Bool(ParamValue): 5183101Sstever@eecs.umich.edu cxx_type = 'bool' 5193101Sstever@eecs.umich.edu def __init__(self, value): 5203101Sstever@eecs.umich.edu try: 5213102Sstever@eecs.umich.edu self.value = convert.toBool(value) 5223101Sstever@eecs.umich.edu except TypeError: 5233101Sstever@eecs.umich.edu self.value = bool(value) 5243101Sstever@eecs.umich.edu 5254762Snate@binkert.org def getValue(self): 5264762Snate@binkert.org return bool(self.value) 5274762Snate@binkert.org 5283101Sstever@eecs.umich.edu def __str__(self): 5293101Sstever@eecs.umich.edu return str(self.value) 5303101Sstever@eecs.umich.edu 5313101Sstever@eecs.umich.edu def ini_str(self): 5323101Sstever@eecs.umich.edu if self.value: 5333101Sstever@eecs.umich.edu return 'true' 5343101Sstever@eecs.umich.edu return 'false' 5353101Sstever@eecs.umich.edu 5363101Sstever@eecs.umich.edudef IncEthernetAddr(addr, val = 1): 5373101Sstever@eecs.umich.edu bytes = map(lambda x: int(x, 16), addr.split(':')) 5383101Sstever@eecs.umich.edu bytes[5] += val 5393101Sstever@eecs.umich.edu for i in (5, 4, 3, 2, 1): 5403101Sstever@eecs.umich.edu val,rem = divmod(bytes[i], 256) 5413101Sstever@eecs.umich.edu bytes[i] = rem 5423101Sstever@eecs.umich.edu if val == 0: 5433101Sstever@eecs.umich.edu break 5443101Sstever@eecs.umich.edu bytes[i - 1] += val 5453101Sstever@eecs.umich.edu assert(bytes[0] <= 255) 5463101Sstever@eecs.umich.edu return ':'.join(map(lambda x: '%02x' % x, bytes)) 5473101Sstever@eecs.umich.edu 5484380Sbinkertn@umich.edu_NextEthernetAddr = "00:90:00:00:00:01" 5494380Sbinkertn@umich.edudef NextEthernetAddr(): 5504380Sbinkertn@umich.edu global _NextEthernetAddr 5513101Sstever@eecs.umich.edu 5524380Sbinkertn@umich.edu value = _NextEthernetAddr 5534380Sbinkertn@umich.edu _NextEthernetAddr = IncEthernetAddr(_NextEthernetAddr, 1) 5544380Sbinkertn@umich.edu return value 5553101Sstever@eecs.umich.edu 5563101Sstever@eecs.umich.educlass EthernetAddr(ParamValue): 5573101Sstever@eecs.umich.edu cxx_type = 'Net::EthAddr' 5583101Sstever@eecs.umich.edu cxx_predecls = ['#include "base/inet.hh"'] 5594762Snate@binkert.org swig_predecls = ['%include "python/swig/inet.i"'] 5603101Sstever@eecs.umich.edu def __init__(self, value): 5613101Sstever@eecs.umich.edu if value == NextEthernetAddr: 5623101Sstever@eecs.umich.edu self.value = value 5633101Sstever@eecs.umich.edu return 5643101Sstever@eecs.umich.edu 5653101Sstever@eecs.umich.edu if not isinstance(value, str): 5663101Sstever@eecs.umich.edu raise TypeError, "expected an ethernet address and didn't get one" 5673101Sstever@eecs.umich.edu 5683101Sstever@eecs.umich.edu bytes = value.split(':') 5693101Sstever@eecs.umich.edu if len(bytes) != 6: 5703101Sstever@eecs.umich.edu raise TypeError, 'invalid ethernet address %s' % value 5713101Sstever@eecs.umich.edu 5723101Sstever@eecs.umich.edu for byte in bytes: 5733101Sstever@eecs.umich.edu if not 0 <= int(byte) <= 256: 5743101Sstever@eecs.umich.edu raise TypeError, 'invalid ethernet address %s' % value 5753101Sstever@eecs.umich.edu 5763101Sstever@eecs.umich.edu self.value = value 5773101Sstever@eecs.umich.edu 5783101Sstever@eecs.umich.edu def unproxy(self, base): 5793101Sstever@eecs.umich.edu if self.value == NextEthernetAddr: 5804380Sbinkertn@umich.edu return EthernetAddr(self.value()) 5813101Sstever@eecs.umich.edu return self 5823101Sstever@eecs.umich.edu 5834762Snate@binkert.org def getValue(self): 5844762Snate@binkert.org from m5.objects.params import EthAddr 5854762Snate@binkert.org return EthAddr(self.value) 5864762Snate@binkert.org 5874380Sbinkertn@umich.edu def ini_str(self): 5884380Sbinkertn@umich.edu return self.value 5893101Sstever@eecs.umich.edu 5903932Sbinkertn@umich.edutime_formats = [ "%a %b %d %H:%M:%S %Z %Y", 5913932Sbinkertn@umich.edu "%a %b %d %H:%M:%S %Z %Y", 5923932Sbinkertn@umich.edu "%Y/%m/%d %H:%M:%S", 5933932Sbinkertn@umich.edu "%Y/%m/%d %H:%M", 5943932Sbinkertn@umich.edu "%Y/%m/%d", 5953932Sbinkertn@umich.edu "%m/%d/%Y %H:%M:%S", 5963932Sbinkertn@umich.edu "%m/%d/%Y %H:%M", 5973932Sbinkertn@umich.edu "%m/%d/%Y", 5983932Sbinkertn@umich.edu "%m/%d/%y %H:%M:%S", 5993932Sbinkertn@umich.edu "%m/%d/%y %H:%M", 6003932Sbinkertn@umich.edu "%m/%d/%y"] 6013932Sbinkertn@umich.edu 6023932Sbinkertn@umich.edu 6033885Sbinkertn@umich.edudef parse_time(value): 6043932Sbinkertn@umich.edu from time import gmtime, strptime, struct_time, time 6053932Sbinkertn@umich.edu from datetime import datetime, date 6063885Sbinkertn@umich.edu 6073932Sbinkertn@umich.edu if isinstance(value, struct_time): 6083932Sbinkertn@umich.edu return value 6093932Sbinkertn@umich.edu 6103932Sbinkertn@umich.edu if isinstance(value, (int, long)): 6113932Sbinkertn@umich.edu return gmtime(value) 6123932Sbinkertn@umich.edu 6133932Sbinkertn@umich.edu if isinstance(value, (datetime, date)): 6143932Sbinkertn@umich.edu return value.timetuple() 6153932Sbinkertn@umich.edu 6163932Sbinkertn@umich.edu if isinstance(value, str): 6173932Sbinkertn@umich.edu if value in ('Now', 'Today'): 6183932Sbinkertn@umich.edu return time.gmtime(time.time()) 6193932Sbinkertn@umich.edu 6203932Sbinkertn@umich.edu for format in time_formats: 6213932Sbinkertn@umich.edu try: 6223932Sbinkertn@umich.edu return strptime(value, format) 6233932Sbinkertn@umich.edu except ValueError: 6243932Sbinkertn@umich.edu pass 6253885Sbinkertn@umich.edu 6263885Sbinkertn@umich.edu raise ValueError, "Could not parse '%s' as a time" % value 6273885Sbinkertn@umich.edu 6283885Sbinkertn@umich.educlass Time(ParamValue): 6294762Snate@binkert.org cxx_type = 'tm' 6304762Snate@binkert.org cxx_predecls = [ '#include <time.h>' ] 6314762Snate@binkert.org swig_predecls = [ '%include "python/swig/time.i"' ] 6323885Sbinkertn@umich.edu def __init__(self, value): 6333932Sbinkertn@umich.edu self.value = parse_time(value) 6343885Sbinkertn@umich.edu 6354762Snate@binkert.org def getValue(self): 6364762Snate@binkert.org from m5.objects.params import tm 6374762Snate@binkert.org 6384762Snate@binkert.org c_time = tm() 6394762Snate@binkert.org py_time = self.value 6404762Snate@binkert.org 6414762Snate@binkert.org # UNIX is years since 1900 6424762Snate@binkert.org c_time.tm_year = py_time.tm_year - 1900; 6434762Snate@binkert.org 6444762Snate@binkert.org # Python starts at 1, UNIX starts at 0 6454762Snate@binkert.org c_time.tm_mon = py_time.tm_mon - 1; 6464762Snate@binkert.org c_time.tm_mday = py_time.tm_mday; 6474762Snate@binkert.org c_time.tm_hour = py_time.tm_hour; 6484762Snate@binkert.org c_time.tm_min = py_time.tm_min; 6494762Snate@binkert.org c_time.tm_sec = py_time.tm_sec; 6504762Snate@binkert.org 6514762Snate@binkert.org # Python has 0 as Monday, UNIX is 0 as sunday 6524762Snate@binkert.org c_time.tm_wday = py_time.tm_wday + 1 6534762Snate@binkert.org if c_time.tm_wday > 6: 6544762Snate@binkert.org c_time.tm_wday -= 7; 6554762Snate@binkert.org 6564762Snate@binkert.org # Python starts at 1, Unix starts at 0 6574762Snate@binkert.org c_time.tm_yday = py_time.tm_yday - 1; 6584762Snate@binkert.org 6594762Snate@binkert.org return c_time 6604762Snate@binkert.org 6613885Sbinkertn@umich.edu def __str__(self): 6624762Snate@binkert.org return time.asctime(self.value) 6633885Sbinkertn@umich.edu 6643885Sbinkertn@umich.edu def ini_str(self): 6653932Sbinkertn@umich.edu return str(self) 6663885Sbinkertn@umich.edu 6673101Sstever@eecs.umich.edu# Enumerated types are a little more complex. The user specifies the 6683101Sstever@eecs.umich.edu# type as Enum(foo) where foo is either a list or dictionary of 6693101Sstever@eecs.umich.edu# alternatives (typically strings, but not necessarily so). (In the 6703101Sstever@eecs.umich.edu# long run, the integer value of the parameter will be the list index 6713101Sstever@eecs.umich.edu# or the corresponding dictionary value. For now, since we only check 6723101Sstever@eecs.umich.edu# that the alternative is valid and then spit it into a .ini file, 6733101Sstever@eecs.umich.edu# there's not much point in using the dictionary.) 6743101Sstever@eecs.umich.edu 6753101Sstever@eecs.umich.edu# What Enum() must do is generate a new type encapsulating the 6763101Sstever@eecs.umich.edu# provided list/dictionary so that specific values of the parameter 6773101Sstever@eecs.umich.edu# can be instances of that type. We define two hidden internal 6783101Sstever@eecs.umich.edu# classes (_ListEnum and _DictEnum) to serve as base classes, then 6793101Sstever@eecs.umich.edu# derive the new type from the appropriate base class on the fly. 6803101Sstever@eecs.umich.edu 6814762Snate@binkert.orgallEnums = {} 6823101Sstever@eecs.umich.edu# Metaclass for Enum types 6835033Smilesck@eecs.umich.educlass MetaEnum(MetaParamValue): 6844762Snate@binkert.org def __new__(mcls, name, bases, dict): 6854762Snate@binkert.org assert name not in allEnums 6864762Snate@binkert.org 6874762Snate@binkert.org cls = super(MetaEnum, mcls).__new__(mcls, name, bases, dict) 6884762Snate@binkert.org allEnums[name] = cls 6894762Snate@binkert.org return cls 6904762Snate@binkert.org 6913101Sstever@eecs.umich.edu def __init__(cls, name, bases, init_dict): 6923101Sstever@eecs.umich.edu if init_dict.has_key('map'): 6933101Sstever@eecs.umich.edu if not isinstance(cls.map, dict): 6943101Sstever@eecs.umich.edu raise TypeError, "Enum-derived class attribute 'map' " \ 6953101Sstever@eecs.umich.edu "must be of type dict" 6963101Sstever@eecs.umich.edu # build list of value strings from map 6973101Sstever@eecs.umich.edu cls.vals = cls.map.keys() 6983101Sstever@eecs.umich.edu cls.vals.sort() 6993101Sstever@eecs.umich.edu elif init_dict.has_key('vals'): 7003101Sstever@eecs.umich.edu if not isinstance(cls.vals, list): 7013101Sstever@eecs.umich.edu raise TypeError, "Enum-derived class attribute 'vals' " \ 7023101Sstever@eecs.umich.edu "must be of type list" 7033101Sstever@eecs.umich.edu # build string->value map from vals sequence 7043101Sstever@eecs.umich.edu cls.map = {} 7053101Sstever@eecs.umich.edu for idx,val in enumerate(cls.vals): 7063101Sstever@eecs.umich.edu cls.map[val] = idx 7073101Sstever@eecs.umich.edu else: 7083101Sstever@eecs.umich.edu raise TypeError, "Enum-derived class must define "\ 7093101Sstever@eecs.umich.edu "attribute 'map' or 'vals'" 7103101Sstever@eecs.umich.edu 7114762Snate@binkert.org cls.cxx_type = 'Enums::%s' % name 7123101Sstever@eecs.umich.edu 7133101Sstever@eecs.umich.edu super(MetaEnum, cls).__init__(name, bases, init_dict) 7143101Sstever@eecs.umich.edu 7153101Sstever@eecs.umich.edu # Generate C++ class declaration for this enum type. 7163101Sstever@eecs.umich.edu # Note that we wrap the enum in a class/struct to act as a namespace, 7173101Sstever@eecs.umich.edu # so that the enum strings can be brief w/o worrying about collisions. 7183101Sstever@eecs.umich.edu def cxx_decl(cls): 7196654Snate@binkert.org name = cls.__name__ 7206654Snate@binkert.org code = "#ifndef __ENUM__%s\n" % name 7216654Snate@binkert.org code += '#define __ENUM__%s\n' % name 7224762Snate@binkert.org code += '\n' 7234762Snate@binkert.org code += 'namespace Enums {\n' 7246654Snate@binkert.org code += ' enum %s {\n' % name 7254762Snate@binkert.org for val in cls.vals: 7264762Snate@binkert.org code += ' %s = %d,\n' % (val, cls.map[val]) 7276654Snate@binkert.org code += ' Num_%s = %d,\n' % (name, len(cls.vals)) 7284762Snate@binkert.org code += ' };\n' 7296654Snate@binkert.org code += ' extern const char *%sStrings[Num_%s];\n' % (name, name) 7304762Snate@binkert.org code += '}\n' 7314762Snate@binkert.org code += '\n' 7324762Snate@binkert.org code += '#endif\n' 7334762Snate@binkert.org return code 7344762Snate@binkert.org 7354762Snate@binkert.org def cxx_def(cls): 7366654Snate@binkert.org name = cls.__name__ 7376654Snate@binkert.org code = '#include "enums/%s.hh"\n' % name 7384762Snate@binkert.org code += 'namespace Enums {\n' 7396654Snate@binkert.org code += ' const char *%sStrings[Num_%s] =\n' % (name, name) 7404762Snate@binkert.org code += ' {\n' 7414762Snate@binkert.org for val in cls.vals: 7424762Snate@binkert.org code += ' "%s",\n' % val 7434762Snate@binkert.org code += ' };\n' 7444762Snate@binkert.org code += '}\n' 7454762Snate@binkert.org return code 7463101Sstever@eecs.umich.edu 7473101Sstever@eecs.umich.edu# Base class for enum types. 7483101Sstever@eecs.umich.educlass Enum(ParamValue): 7493101Sstever@eecs.umich.edu __metaclass__ = MetaEnum 7503101Sstever@eecs.umich.edu vals = [] 7513101Sstever@eecs.umich.edu 7523101Sstever@eecs.umich.edu def __init__(self, value): 7533101Sstever@eecs.umich.edu if value not in self.map: 7543101Sstever@eecs.umich.edu raise TypeError, "Enum param got bad value '%s' (not in %s)" \ 7553101Sstever@eecs.umich.edu % (value, self.vals) 7563101Sstever@eecs.umich.edu self.value = value 7573101Sstever@eecs.umich.edu 7584762Snate@binkert.org def getValue(self): 7594762Snate@binkert.org return int(self.map[self.value]) 7604762Snate@binkert.org 7613101Sstever@eecs.umich.edu def __str__(self): 7623101Sstever@eecs.umich.edu return self.value 7633101Sstever@eecs.umich.edu 7643101Sstever@eecs.umich.edu# how big does a rounding error need to be before we warn about it? 7653101Sstever@eecs.umich.edufrequency_tolerance = 0.001 # 0.1% 7663101Sstever@eecs.umich.edu 7674167Sbinkertn@umich.educlass TickParamValue(NumericParamValue): 7683101Sstever@eecs.umich.edu cxx_type = 'Tick' 7696214Snate@binkert.org cxx_predecls = ['#include "base/types.hh"'] 7704762Snate@binkert.org swig_predecls = ['%import "stdint.i"\n' + 7716214Snate@binkert.org '%import "base/types.hh"'] 7724167Sbinkertn@umich.edu 7734762Snate@binkert.org def getValue(self): 7744762Snate@binkert.org return long(self.value) 7754762Snate@binkert.org 7764167Sbinkertn@umich.educlass Latency(TickParamValue): 7773101Sstever@eecs.umich.edu def __init__(self, value): 7784167Sbinkertn@umich.edu if isinstance(value, (Latency, Clock)): 7794167Sbinkertn@umich.edu self.ticks = value.ticks 7804167Sbinkertn@umich.edu self.value = value.value 7814167Sbinkertn@umich.edu elif isinstance(value, Frequency): 7824167Sbinkertn@umich.edu self.ticks = value.ticks 7834167Sbinkertn@umich.edu self.value = 1.0 / value.value 7844167Sbinkertn@umich.edu elif value.endswith('t'): 7854167Sbinkertn@umich.edu self.ticks = True 7864167Sbinkertn@umich.edu self.value = int(value[:-1]) 7874167Sbinkertn@umich.edu else: 7884167Sbinkertn@umich.edu self.ticks = False 7894167Sbinkertn@umich.edu self.value = convert.toLatency(value) 7903101Sstever@eecs.umich.edu 7913101Sstever@eecs.umich.edu def __getattr__(self, attr): 7923101Sstever@eecs.umich.edu if attr in ('latency', 'period'): 7933101Sstever@eecs.umich.edu return self 7943101Sstever@eecs.umich.edu if attr == 'frequency': 7953101Sstever@eecs.umich.edu return Frequency(self) 7963101Sstever@eecs.umich.edu raise AttributeError, "Latency object has no attribute '%s'" % attr 7973101Sstever@eecs.umich.edu 7984762Snate@binkert.org def getValue(self): 7994762Snate@binkert.org if self.ticks or self.value == 0: 8004762Snate@binkert.org value = self.value 8014762Snate@binkert.org else: 8024762Snate@binkert.org value = ticks.fromSeconds(self.value) 8034762Snate@binkert.org return long(value) 8044762Snate@binkert.org 8053101Sstever@eecs.umich.edu # convert latency to ticks 8063101Sstever@eecs.umich.edu def ini_str(self): 8074762Snate@binkert.org return '%d' % self.getValue() 8083101Sstever@eecs.umich.edu 8094167Sbinkertn@umich.educlass Frequency(TickParamValue): 8103101Sstever@eecs.umich.edu def __init__(self, value): 8114167Sbinkertn@umich.edu if isinstance(value, (Latency, Clock)): 8124167Sbinkertn@umich.edu if value.value == 0: 8134167Sbinkertn@umich.edu self.value = 0 8144167Sbinkertn@umich.edu else: 8154167Sbinkertn@umich.edu self.value = 1.0 / value.value 8164167Sbinkertn@umich.edu self.ticks = value.ticks 8174167Sbinkertn@umich.edu elif isinstance(value, Frequency): 8184167Sbinkertn@umich.edu self.value = value.value 8194167Sbinkertn@umich.edu self.ticks = value.ticks 8204167Sbinkertn@umich.edu else: 8214167Sbinkertn@umich.edu self.ticks = False 8224167Sbinkertn@umich.edu self.value = convert.toFrequency(value) 8233101Sstever@eecs.umich.edu 8243101Sstever@eecs.umich.edu def __getattr__(self, attr): 8253101Sstever@eecs.umich.edu if attr == 'frequency': 8263101Sstever@eecs.umich.edu return self 8273101Sstever@eecs.umich.edu if attr in ('latency', 'period'): 8283101Sstever@eecs.umich.edu return Latency(self) 8293101Sstever@eecs.umich.edu raise AttributeError, "Frequency object has no attribute '%s'" % attr 8303101Sstever@eecs.umich.edu 8314167Sbinkertn@umich.edu # convert latency to ticks 8324762Snate@binkert.org def getValue(self): 8334762Snate@binkert.org if self.ticks or self.value == 0: 8344762Snate@binkert.org value = self.value 8354762Snate@binkert.org else: 8364762Snate@binkert.org value = ticks.fromSeconds(1.0 / self.value) 8374762Snate@binkert.org return long(value) 8384762Snate@binkert.org 8393101Sstever@eecs.umich.edu def ini_str(self): 8404762Snate@binkert.org return '%d' % self.getValue() 8413101Sstever@eecs.umich.edu 8423101Sstever@eecs.umich.edu# A generic frequency and/or Latency value. Value is stored as a latency, 8433101Sstever@eecs.umich.edu# but to avoid ambiguity this object does not support numeric ops (* or /). 8443101Sstever@eecs.umich.edu# An explicit conversion to a Latency or Frequency must be made first. 8453101Sstever@eecs.umich.educlass Clock(ParamValue): 8463101Sstever@eecs.umich.edu cxx_type = 'Tick' 8476214Snate@binkert.org cxx_predecls = ['#include "base/types.hh"'] 8484762Snate@binkert.org swig_predecls = ['%import "stdint.i"\n' + 8496214Snate@binkert.org '%import "base/types.hh"'] 8503101Sstever@eecs.umich.edu def __init__(self, value): 8514167Sbinkertn@umich.edu if isinstance(value, (Latency, Clock)): 8524167Sbinkertn@umich.edu self.ticks = value.ticks 8534167Sbinkertn@umich.edu self.value = value.value 8544167Sbinkertn@umich.edu elif isinstance(value, Frequency): 8554167Sbinkertn@umich.edu self.ticks = value.ticks 8564167Sbinkertn@umich.edu self.value = 1.0 / value.value 8574167Sbinkertn@umich.edu elif value.endswith('t'): 8584167Sbinkertn@umich.edu self.ticks = True 8594167Sbinkertn@umich.edu self.value = int(value[:-1]) 8604167Sbinkertn@umich.edu else: 8614167Sbinkertn@umich.edu self.ticks = False 8624167Sbinkertn@umich.edu self.value = convert.anyToLatency(value) 8633101Sstever@eecs.umich.edu 8643101Sstever@eecs.umich.edu def __getattr__(self, attr): 8653101Sstever@eecs.umich.edu if attr == 'frequency': 8663101Sstever@eecs.umich.edu return Frequency(self) 8673101Sstever@eecs.umich.edu if attr in ('latency', 'period'): 8683101Sstever@eecs.umich.edu return Latency(self) 8693101Sstever@eecs.umich.edu raise AttributeError, "Frequency object has no attribute '%s'" % attr 8703101Sstever@eecs.umich.edu 8714762Snate@binkert.org def getValue(self): 8724762Snate@binkert.org return self.period.getValue() 8734762Snate@binkert.org 8743101Sstever@eecs.umich.edu def ini_str(self): 8753101Sstever@eecs.umich.edu return self.period.ini_str() 8763101Sstever@eecs.umich.edu 8773101Sstever@eecs.umich.educlass NetworkBandwidth(float,ParamValue): 8783101Sstever@eecs.umich.edu cxx_type = 'float' 8793101Sstever@eecs.umich.edu def __new__(cls, value): 8804167Sbinkertn@umich.edu # convert to bits per second 8814167Sbinkertn@umich.edu val = convert.toNetworkBandwidth(value) 8823101Sstever@eecs.umich.edu return super(cls, NetworkBandwidth).__new__(cls, val) 8833101Sstever@eecs.umich.edu 8843101Sstever@eecs.umich.edu def __str__(self): 8853101Sstever@eecs.umich.edu return str(self.val) 8863101Sstever@eecs.umich.edu 8874762Snate@binkert.org def getValue(self): 8884167Sbinkertn@umich.edu # convert to seconds per byte 8894167Sbinkertn@umich.edu value = 8.0 / float(self) 8904167Sbinkertn@umich.edu # convert to ticks per byte 8914762Snate@binkert.org value = ticks.fromSeconds(value) 8924762Snate@binkert.org return float(value) 8934762Snate@binkert.org 8944762Snate@binkert.org def ini_str(self): 8954762Snate@binkert.org return '%f' % self.getValue() 8963101Sstever@eecs.umich.edu 8973101Sstever@eecs.umich.educlass MemoryBandwidth(float,ParamValue): 8983101Sstever@eecs.umich.edu cxx_type = 'float' 8995469Snate@binkert.org def __new__(cls, value): 9004167Sbinkertn@umich.edu # we want the number of ticks per byte of data 9013102Sstever@eecs.umich.edu val = convert.toMemoryBandwidth(value) 9023101Sstever@eecs.umich.edu return super(cls, MemoryBandwidth).__new__(cls, val) 9033101Sstever@eecs.umich.edu 9043101Sstever@eecs.umich.edu def __str__(self): 9053101Sstever@eecs.umich.edu return str(self.val) 9063101Sstever@eecs.umich.edu 9074762Snate@binkert.org def getValue(self): 9084167Sbinkertn@umich.edu # convert to seconds per byte 9095468Snate@binkert.org value = float(self) 9105468Snate@binkert.org if value: 9115468Snate@binkert.org value = 1.0 / float(self) 9124167Sbinkertn@umich.edu # convert to ticks per byte 9134762Snate@binkert.org value = ticks.fromSeconds(value) 9144762Snate@binkert.org return float(value) 9154762Snate@binkert.org 9164762Snate@binkert.org def ini_str(self): 9174762Snate@binkert.org return '%f' % self.getValue() 9183101Sstever@eecs.umich.edu 9193101Sstever@eecs.umich.edu# 9203101Sstever@eecs.umich.edu# "Constants"... handy aliases for various values. 9213101Sstever@eecs.umich.edu# 9223101Sstever@eecs.umich.edu 9233102Sstever@eecs.umich.edu# Special class for NULL pointers. Note the special check in 9243102Sstever@eecs.umich.edu# make_param_value() above that lets these be assigned where a 9253102Sstever@eecs.umich.edu# SimObject is required. 9263102Sstever@eecs.umich.edu# only one copy of a particular node 9273102Sstever@eecs.umich.educlass NullSimObject(object): 9283102Sstever@eecs.umich.edu __metaclass__ = Singleton 9293102Sstever@eecs.umich.edu 9303102Sstever@eecs.umich.edu def __call__(cls): 9313102Sstever@eecs.umich.edu return cls 9323102Sstever@eecs.umich.edu 9333102Sstever@eecs.umich.edu def _instantiate(self, parent = None, path = ''): 9343102Sstever@eecs.umich.edu pass 9353102Sstever@eecs.umich.edu 9363102Sstever@eecs.umich.edu def ini_str(self): 9373102Sstever@eecs.umich.edu return 'Null' 9383102Sstever@eecs.umich.edu 9393102Sstever@eecs.umich.edu def unproxy(self, base): 9403102Sstever@eecs.umich.edu return self 9413102Sstever@eecs.umich.edu 9423102Sstever@eecs.umich.edu def set_path(self, parent, name): 9433102Sstever@eecs.umich.edu pass 9444762Snate@binkert.org 9453102Sstever@eecs.umich.edu def __str__(self): 9463102Sstever@eecs.umich.edu return 'Null' 9473102Sstever@eecs.umich.edu 9484762Snate@binkert.org def getValue(self): 9494762Snate@binkert.org return None 9504762Snate@binkert.org 9513102Sstever@eecs.umich.edu# The only instance you'll ever need... 9523102Sstever@eecs.umich.eduNULL = NullSimObject() 9533102Sstever@eecs.umich.edu 9543102Sstever@eecs.umich.edudef isNullPointer(value): 9553102Sstever@eecs.umich.edu return isinstance(value, NullSimObject) 9563102Sstever@eecs.umich.edu 9573101Sstever@eecs.umich.edu# Some memory range specifications use this as a default upper bound. 9583101Sstever@eecs.umich.eduMaxAddr = Addr.max 9593101Sstever@eecs.umich.eduMaxTick = Tick.max 9603101Sstever@eecs.umich.eduAllMemory = AddrRange(0, MaxAddr) 9613101Sstever@eecs.umich.edu 9623101Sstever@eecs.umich.edu 9633101Sstever@eecs.umich.edu##################################################################### 9643101Sstever@eecs.umich.edu# 9653101Sstever@eecs.umich.edu# Port objects 9663101Sstever@eecs.umich.edu# 9673101Sstever@eecs.umich.edu# Ports are used to interconnect objects in the memory system. 9683101Sstever@eecs.umich.edu# 9693101Sstever@eecs.umich.edu##################################################################### 9703101Sstever@eecs.umich.edu 9713101Sstever@eecs.umich.edu# Port reference: encapsulates a reference to a particular port on a 9723101Sstever@eecs.umich.edu# particular SimObject. 9733101Sstever@eecs.umich.educlass PortRef(object): 9743105Sstever@eecs.umich.edu def __init__(self, simobj, name): 9753105Sstever@eecs.umich.edu assert(isSimObject(simobj) or isSimObjectClass(simobj)) 9763101Sstever@eecs.umich.edu self.simobj = simobj 9773101Sstever@eecs.umich.edu self.name = name 9783101Sstever@eecs.umich.edu self.peer = None # not associated with another port yet 9793101Sstever@eecs.umich.edu self.ccConnected = False # C++ port connection done? 9803105Sstever@eecs.umich.edu self.index = -1 # always -1 for non-vector ports 9813101Sstever@eecs.umich.edu 9823103Sstever@eecs.umich.edu def __str__(self): 9833105Sstever@eecs.umich.edu return '%s.%s' % (self.simobj, self.name) 9843103Sstever@eecs.umich.edu 9853105Sstever@eecs.umich.edu # for config.ini, print peer's name (not ours) 9863105Sstever@eecs.umich.edu def ini_str(self): 9873105Sstever@eecs.umich.edu return str(self.peer) 9883105Sstever@eecs.umich.edu 9893105Sstever@eecs.umich.edu def __getattr__(self, attr): 9903105Sstever@eecs.umich.edu if attr == 'peerObj': 9913105Sstever@eecs.umich.edu # shorthand for proxies 9923105Sstever@eecs.umich.edu return self.peer.simobj 9933105Sstever@eecs.umich.edu raise AttributeError, "'%s' object has no attribute '%s'" % \ 9943105Sstever@eecs.umich.edu (self.__class__.__name__, attr) 9953105Sstever@eecs.umich.edu 9963105Sstever@eecs.umich.edu # Full connection is symmetric (both ways). Called via 9973105Sstever@eecs.umich.edu # SimObject.__setattr__ as a result of a port assignment, e.g., 9983109Sstever@eecs.umich.edu # "obj1.portA = obj2.portB", or via VectorPortElementRef.__setitem__, 9993105Sstever@eecs.umich.edu # e.g., "obj1.portA[3] = obj2.portB". 10003105Sstever@eecs.umich.edu def connect(self, other): 10013105Sstever@eecs.umich.edu if isinstance(other, VectorPortRef): 10023105Sstever@eecs.umich.edu # reference to plain VectorPort is implicit append 10033105Sstever@eecs.umich.edu other = other._get_next() 10043105Sstever@eecs.umich.edu if self.peer and not proxy.isproxy(self.peer): 10053105Sstever@eecs.umich.edu print "warning: overwriting port", self, \ 10063105Sstever@eecs.umich.edu "value", self.peer, "with", other 10075578SSteve.Reinhardt@amd.com self.peer.peer = None 10083101Sstever@eecs.umich.edu self.peer = other 10093109Sstever@eecs.umich.edu if proxy.isproxy(other): 10103109Sstever@eecs.umich.edu other.set_param_desc(PortParamDesc()) 10113109Sstever@eecs.umich.edu elif isinstance(other, PortRef): 10123109Sstever@eecs.umich.edu if other.peer is not self: 10133109Sstever@eecs.umich.edu other.connect(self) 10143109Sstever@eecs.umich.edu else: 10153109Sstever@eecs.umich.edu raise TypeError, \ 10163109Sstever@eecs.umich.edu "assigning non-port reference '%s' to port '%s'" \ 10173109Sstever@eecs.umich.edu % (other, self) 10183101Sstever@eecs.umich.edu 10193105Sstever@eecs.umich.edu def clone(self, simobj, memo): 10203105Sstever@eecs.umich.edu if memo.has_key(self): 10213105Sstever@eecs.umich.edu return memo[self] 10223101Sstever@eecs.umich.edu newRef = copy.copy(self) 10233105Sstever@eecs.umich.edu memo[self] = newRef 10243105Sstever@eecs.umich.edu newRef.simobj = simobj 10253101Sstever@eecs.umich.edu assert(isSimObject(newRef.simobj)) 10263105Sstever@eecs.umich.edu if self.peer and not proxy.isproxy(self.peer): 10273179Sstever@eecs.umich.edu peerObj = self.peer.simobj(_memo=memo) 10283105Sstever@eecs.umich.edu newRef.peer = self.peer.clone(peerObj, memo) 10293105Sstever@eecs.umich.edu assert(not isinstance(newRef.peer, VectorPortRef)) 10303101Sstever@eecs.umich.edu return newRef 10313101Sstever@eecs.umich.edu 10323105Sstever@eecs.umich.edu def unproxy(self, simobj): 10333105Sstever@eecs.umich.edu assert(simobj is self.simobj) 10343105Sstever@eecs.umich.edu if proxy.isproxy(self.peer): 10353105Sstever@eecs.umich.edu try: 10363105Sstever@eecs.umich.edu realPeer = self.peer.unproxy(self.simobj) 10373105Sstever@eecs.umich.edu except: 10383105Sstever@eecs.umich.edu print "Error in unproxying port '%s' of %s" % \ 10393105Sstever@eecs.umich.edu (self.name, self.simobj.path()) 10403105Sstever@eecs.umich.edu raise 10413105Sstever@eecs.umich.edu self.connect(realPeer) 10423105Sstever@eecs.umich.edu 10433101Sstever@eecs.umich.edu # Call C++ to create corresponding port connection between C++ objects 10443101Sstever@eecs.umich.edu def ccConnect(self): 10454859Snate@binkert.org from m5.objects.params import connectPorts 10464762Snate@binkert.org 10473101Sstever@eecs.umich.edu if self.ccConnected: # already done this 10483101Sstever@eecs.umich.edu return 10493101Sstever@eecs.umich.edu peer = self.peer 10505578SSteve.Reinhardt@amd.com if not self.peer: # nothing to connect to 10515578SSteve.Reinhardt@amd.com return 10527526Ssteve.reinhardt@amd.com try: 10537526Ssteve.reinhardt@amd.com connectPorts(self.simobj.getCCObject(), self.name, self.index, 10547526Ssteve.reinhardt@amd.com peer.simobj.getCCObject(), peer.name, peer.index) 10557526Ssteve.reinhardt@amd.com except: 10567526Ssteve.reinhardt@amd.com print "Error connecting port %s.%s to %s.%s" % \ 10577526Ssteve.reinhardt@amd.com (self.simobj.path(), self.name, 10587526Ssteve.reinhardt@amd.com peer.simobj.path(), peer.name) 10597526Ssteve.reinhardt@amd.com raise 10603101Sstever@eecs.umich.edu self.ccConnected = True 10613101Sstever@eecs.umich.edu peer.ccConnected = True 10623101Sstever@eecs.umich.edu 10633105Sstever@eecs.umich.edu# A reference to an individual element of a VectorPort... much like a 10643105Sstever@eecs.umich.edu# PortRef, but has an index. 10653105Sstever@eecs.umich.educlass VectorPortElementRef(PortRef): 10663105Sstever@eecs.umich.edu def __init__(self, simobj, name, index): 10673105Sstever@eecs.umich.edu PortRef.__init__(self, simobj, name) 10683105Sstever@eecs.umich.edu self.index = index 10693105Sstever@eecs.umich.edu 10703105Sstever@eecs.umich.edu def __str__(self): 10713105Sstever@eecs.umich.edu return '%s.%s[%d]' % (self.simobj, self.name, self.index) 10723105Sstever@eecs.umich.edu 10733105Sstever@eecs.umich.edu# A reference to a complete vector-valued port (not just a single element). 10743105Sstever@eecs.umich.edu# Can be indexed to retrieve individual VectorPortElementRef instances. 10753105Sstever@eecs.umich.educlass VectorPortRef(object): 10763105Sstever@eecs.umich.edu def __init__(self, simobj, name): 10773105Sstever@eecs.umich.edu assert(isSimObject(simobj) or isSimObjectClass(simobj)) 10783105Sstever@eecs.umich.edu self.simobj = simobj 10793105Sstever@eecs.umich.edu self.name = name 10803105Sstever@eecs.umich.edu self.elements = [] 10813105Sstever@eecs.umich.edu 10823109Sstever@eecs.umich.edu def __str__(self): 10833109Sstever@eecs.umich.edu return '%s.%s[:]' % (self.simobj, self.name) 10843109Sstever@eecs.umich.edu 10853105Sstever@eecs.umich.edu # for config.ini, print peer's name (not ours) 10863105Sstever@eecs.umich.edu def ini_str(self): 10873105Sstever@eecs.umich.edu return ' '.join([el.ini_str() for el in self.elements]) 10883105Sstever@eecs.umich.edu 10893105Sstever@eecs.umich.edu def __getitem__(self, key): 10903105Sstever@eecs.umich.edu if not isinstance(key, int): 10913105Sstever@eecs.umich.edu raise TypeError, "VectorPort index must be integer" 10923105Sstever@eecs.umich.edu if key >= len(self.elements): 10933105Sstever@eecs.umich.edu # need to extend list 10943105Sstever@eecs.umich.edu ext = [VectorPortElementRef(self.simobj, self.name, i) 10953105Sstever@eecs.umich.edu for i in range(len(self.elements), key+1)] 10963105Sstever@eecs.umich.edu self.elements.extend(ext) 10973105Sstever@eecs.umich.edu return self.elements[key] 10983105Sstever@eecs.umich.edu 10993105Sstever@eecs.umich.edu def _get_next(self): 11003105Sstever@eecs.umich.edu return self[len(self.elements)] 11013105Sstever@eecs.umich.edu 11023105Sstever@eecs.umich.edu def __setitem__(self, key, value): 11033105Sstever@eecs.umich.edu if not isinstance(key, int): 11043105Sstever@eecs.umich.edu raise TypeError, "VectorPort index must be integer" 11053105Sstever@eecs.umich.edu self[key].connect(value) 11063105Sstever@eecs.umich.edu 11073105Sstever@eecs.umich.edu def connect(self, other): 11083109Sstever@eecs.umich.edu if isinstance(other, (list, tuple)): 11093109Sstever@eecs.umich.edu # Assign list of port refs to vector port. 11103109Sstever@eecs.umich.edu # For now, append them... not sure if that's the right semantics 11113109Sstever@eecs.umich.edu # or if it should replace the current vector. 11123109Sstever@eecs.umich.edu for ref in other: 11133109Sstever@eecs.umich.edu self._get_next().connect(ref) 11143109Sstever@eecs.umich.edu else: 11153109Sstever@eecs.umich.edu # scalar assignment to plain VectorPort is implicit append 11163109Sstever@eecs.umich.edu self._get_next().connect(other) 11173109Sstever@eecs.umich.edu 11183109Sstever@eecs.umich.edu def clone(self, simobj, memo): 11193109Sstever@eecs.umich.edu if memo.has_key(self): 11203109Sstever@eecs.umich.edu return memo[self] 11213109Sstever@eecs.umich.edu newRef = copy.copy(self) 11223109Sstever@eecs.umich.edu memo[self] = newRef 11233109Sstever@eecs.umich.edu newRef.simobj = simobj 11243109Sstever@eecs.umich.edu assert(isSimObject(newRef.simobj)) 11253109Sstever@eecs.umich.edu newRef.elements = [el.clone(simobj, memo) for el in self.elements] 11263109Sstever@eecs.umich.edu return newRef 11273105Sstever@eecs.umich.edu 11283105Sstever@eecs.umich.edu def unproxy(self, simobj): 11293105Sstever@eecs.umich.edu [el.unproxy(simobj) for el in self.elements] 11303105Sstever@eecs.umich.edu 11313105Sstever@eecs.umich.edu def ccConnect(self): 11323105Sstever@eecs.umich.edu [el.ccConnect() for el in self.elements] 11333105Sstever@eecs.umich.edu 11343101Sstever@eecs.umich.edu# Port description object. Like a ParamDesc object, this represents a 11353101Sstever@eecs.umich.edu# logical port in the SimObject class, not a particular port on a 11363101Sstever@eecs.umich.edu# SimObject instance. The latter are represented by PortRef objects. 11373101Sstever@eecs.umich.educlass Port(object): 11383105Sstever@eecs.umich.edu # Port("description") or Port(default, "description") 11393105Sstever@eecs.umich.edu def __init__(self, *args): 11403105Sstever@eecs.umich.edu if len(args) == 1: 11413105Sstever@eecs.umich.edu self.desc = args[0] 11423105Sstever@eecs.umich.edu elif len(args) == 2: 11433105Sstever@eecs.umich.edu self.default = args[0] 11443105Sstever@eecs.umich.edu self.desc = args[1] 11453105Sstever@eecs.umich.edu else: 11463105Sstever@eecs.umich.edu raise TypeError, 'wrong number of arguments' 11473105Sstever@eecs.umich.edu # self.name is set by SimObject class on assignment 11483105Sstever@eecs.umich.edu # e.g., pio_port = Port("blah") sets self.name to 'pio_port' 11493101Sstever@eecs.umich.edu 11503101Sstever@eecs.umich.edu # Generate a PortRef for this port on the given SimObject with the 11513101Sstever@eecs.umich.edu # given name 11523105Sstever@eecs.umich.edu def makeRef(self, simobj): 11533105Sstever@eecs.umich.edu return PortRef(simobj, self.name) 11543101Sstever@eecs.umich.edu 11553101Sstever@eecs.umich.edu # Connect an instance of this port (on the given SimObject with 11563101Sstever@eecs.umich.edu # the given name) with the port described by the supplied PortRef 11573105Sstever@eecs.umich.edu def connect(self, simobj, ref): 11583105Sstever@eecs.umich.edu self.makeRef(simobj).connect(ref) 11593101Sstever@eecs.umich.edu 11603101Sstever@eecs.umich.edu# VectorPort description object. Like Port, but represents a vector 11613101Sstever@eecs.umich.edu# of connections (e.g., as on a Bus). 11623101Sstever@eecs.umich.educlass VectorPort(Port): 11633105Sstever@eecs.umich.edu def __init__(self, *args): 11643105Sstever@eecs.umich.edu Port.__init__(self, *args) 11653101Sstever@eecs.umich.edu self.isVec = True 11663101Sstever@eecs.umich.edu 11673105Sstever@eecs.umich.edu def makeRef(self, simobj): 11683105Sstever@eecs.umich.edu return VectorPortRef(simobj, self.name) 11693105Sstever@eecs.umich.edu 11703109Sstever@eecs.umich.edu# 'Fake' ParamDesc for Port references to assign to the _pdesc slot of 11713109Sstever@eecs.umich.edu# proxy objects (via set_param_desc()) so that proxy error messages 11723109Sstever@eecs.umich.edu# make sense. 11733109Sstever@eecs.umich.educlass PortParamDesc(object): 11743109Sstever@eecs.umich.edu __metaclass__ = Singleton 11753109Sstever@eecs.umich.edu 11763109Sstever@eecs.umich.edu ptype_str = 'Port' 11773109Sstever@eecs.umich.edu ptype = Port 11783105Sstever@eecs.umich.edu 11796654Snate@binkert.orgbaseEnums = allEnums.copy() 11806654Snate@binkert.orgbaseParams = allParams.copy() 11816654Snate@binkert.org 11826654Snate@binkert.orgdef clear(): 11836654Snate@binkert.org global allEnums, allParams 11846654Snate@binkert.org 11856654Snate@binkert.org allEnums = baseEnums.copy() 11866654Snate@binkert.org allParams = baseParams.copy() 11876654Snate@binkert.org 11883101Sstever@eecs.umich.edu__all__ = ['Param', 'VectorParam', 11893101Sstever@eecs.umich.edu 'Enum', 'Bool', 'String', 'Float', 11903101Sstever@eecs.umich.edu 'Int', 'Unsigned', 'Int8', 'UInt8', 'Int16', 'UInt16', 11913101Sstever@eecs.umich.edu 'Int32', 'UInt32', 'Int64', 'UInt64', 11923101Sstever@eecs.umich.edu 'Counter', 'Addr', 'Tick', 'Percent', 11933101Sstever@eecs.umich.edu 'TcpPort', 'UdpPort', 'EthernetAddr', 11943101Sstever@eecs.umich.edu 'MemorySize', 'MemorySize32', 11954167Sbinkertn@umich.edu 'Latency', 'Frequency', 'Clock', 11963101Sstever@eecs.umich.edu 'NetworkBandwidth', 'MemoryBandwidth', 11973101Sstever@eecs.umich.edu 'Range', 'AddrRange', 'TickRange', 11983101Sstever@eecs.umich.edu 'MaxAddr', 'MaxTick', 'AllMemory', 11993885Sbinkertn@umich.edu 'Time', 12003102Sstever@eecs.umich.edu 'NextEthernetAddr', 'NULL', 12013101Sstever@eecs.umich.edu 'Port', 'VectorPort'] 12026654Snate@binkert.org 12036654Snate@binkert.orgimport SimObject 1204