params.py revision 3102
15331Sgblack@eecs.umich.edu# Copyright (c) 2004-2006 The Regents of The University of Michigan 25331Sgblack@eecs.umich.edu# All rights reserved. 35331Sgblack@eecs.umich.edu# 45331Sgblack@eecs.umich.edu# Redistribution and use in source and binary forms, with or without 55331Sgblack@eecs.umich.edu# modification, are permitted provided that the following conditions are 65331Sgblack@eecs.umich.edu# met: redistributions of source code must retain the above copyright 75331Sgblack@eecs.umich.edu# notice, this list of conditions and the following disclaimer; 85331Sgblack@eecs.umich.edu# redistributions in binary form must reproduce the above copyright 95331Sgblack@eecs.umich.edu# notice, this list of conditions and the following disclaimer in the 105331Sgblack@eecs.umich.edu# documentation and/or other materials provided with the distribution; 115331Sgblack@eecs.umich.edu# neither the name of the copyright holders nor the names of its 125331Sgblack@eecs.umich.edu# contributors may be used to endorse or promote products derived from 135331Sgblack@eecs.umich.edu# this software without specific prior written permission. 145331Sgblack@eecs.umich.edu# 155331Sgblack@eecs.umich.edu# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 165331Sgblack@eecs.umich.edu# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 175331Sgblack@eecs.umich.edu# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 185331Sgblack@eecs.umich.edu# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 195331Sgblack@eecs.umich.edu# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 205331Sgblack@eecs.umich.edu# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 215331Sgblack@eecs.umich.edu# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 225331Sgblack@eecs.umich.edu# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 235331Sgblack@eecs.umich.edu# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 245331Sgblack@eecs.umich.edu# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 255331Sgblack@eecs.umich.edu# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 265331Sgblack@eecs.umich.edu# 275331Sgblack@eecs.umich.edu# Authors: Steve Reinhardt 285331Sgblack@eecs.umich.edu# Nathan Binkert 295331Sgblack@eecs.umich.edu 304276Sgblack@eecs.umich.edu##################################################################### 314276Sgblack@eecs.umich.edu# 324276Sgblack@eecs.umich.edu# Parameter description classes 334276Sgblack@eecs.umich.edu# 344276Sgblack@eecs.umich.edu# The _params dictionary in each class maps parameter names to either 354276Sgblack@eecs.umich.edu# a Param or a VectorParam object. These objects contain the 364276Sgblack@eecs.umich.edu# parameter description string, the parameter type, and the default 374276Sgblack@eecs.umich.edu# value (if any). The convert() method on these objects is used to 384276Sgblack@eecs.umich.edu# force whatever value is assigned to the parameter to the appropriate 394276Sgblack@eecs.umich.edu# type. 404276Sgblack@eecs.umich.edu# 414276Sgblack@eecs.umich.edu# Note that the default values are loaded into the class's attribute 424276Sgblack@eecs.umich.edu# space when the parameter dictionary is initialized (in 434276Sgblack@eecs.umich.edu# MetaSimObject._new_param()); after that point they aren't used. 444276Sgblack@eecs.umich.edu# 454276Sgblack@eecs.umich.edu##################################################################### 464276Sgblack@eecs.umich.edu 474276Sgblack@eecs.umich.eduimport sys, inspect, copy 484276Sgblack@eecs.umich.eduimport convert 494276Sgblack@eecs.umich.edufrom util import * 504276Sgblack@eecs.umich.edu 514276Sgblack@eecs.umich.edu# Dummy base class to identify types that are legitimate for SimObject 524276Sgblack@eecs.umich.edu# parameters. 534276Sgblack@eecs.umich.educlass ParamValue(object): 544276Sgblack@eecs.umich.edu 554276Sgblack@eecs.umich.edu cxx_predecls = [] 564276Sgblack@eecs.umich.edu swig_predecls = [] 574276Sgblack@eecs.umich.edu 584276Sgblack@eecs.umich.edu # default for printing to .ini file is regular string conversion. 594276Sgblack@eecs.umich.edu # will be overridden in some cases 604276Sgblack@eecs.umich.edu def ini_str(self): 614276Sgblack@eecs.umich.edu return str(self) 624276Sgblack@eecs.umich.edu 634276Sgblack@eecs.umich.edu # allows us to blithely call unproxy() on things without checking 644276Sgblack@eecs.umich.edu # if they're really proxies or not 654276Sgblack@eecs.umich.edu def unproxy(self, base): 664276Sgblack@eecs.umich.edu return self 674276Sgblack@eecs.umich.edu 684276Sgblack@eecs.umich.edu# Regular parameter description. 694276Sgblack@eecs.umich.educlass ParamDesc(object): 704276Sgblack@eecs.umich.edu def __init__(self, ptype_str, ptype, *args, **kwargs): 714276Sgblack@eecs.umich.edu self.ptype_str = ptype_str 724276Sgblack@eecs.umich.edu # remember ptype only if it is provided 734276Sgblack@eecs.umich.edu if ptype != None: 744276Sgblack@eecs.umich.edu self.ptype = ptype 754276Sgblack@eecs.umich.edu 764276Sgblack@eecs.umich.edu if args: 774276Sgblack@eecs.umich.edu if len(args) == 1: 784276Sgblack@eecs.umich.edu self.desc = args[0] 794276Sgblack@eecs.umich.edu elif len(args) == 2: 804276Sgblack@eecs.umich.edu self.default = args[0] 814276Sgblack@eecs.umich.edu self.desc = args[1] 824276Sgblack@eecs.umich.edu else: 834276Sgblack@eecs.umich.edu raise TypeError, 'too many arguments' 844276Sgblack@eecs.umich.edu 854276Sgblack@eecs.umich.edu if kwargs.has_key('desc'): 864276Sgblack@eecs.umich.edu assert(not hasattr(self, 'desc')) 874276Sgblack@eecs.umich.edu self.desc = kwargs['desc'] 884276Sgblack@eecs.umich.edu del kwargs['desc'] 894711Sgblack@eecs.umich.edu 904276Sgblack@eecs.umich.edu if kwargs.has_key('default'): 914276Sgblack@eecs.umich.edu assert(not hasattr(self, 'default')) 925238Sgblack@eecs.umich.edu self.default = kwargs['default'] 935238Sgblack@eecs.umich.edu del kwargs['default'] 945238Sgblack@eecs.umich.edu 955238Sgblack@eecs.umich.edu if kwargs: 965238Sgblack@eecs.umich.edu raise TypeError, 'extra unknown kwargs %s' % kwargs 975238Sgblack@eecs.umich.edu 985238Sgblack@eecs.umich.edu if not hasattr(self, 'desc'): 995238Sgblack@eecs.umich.edu raise TypeError, 'desc attribute missing' 1005238Sgblack@eecs.umich.edu 1015238Sgblack@eecs.umich.edu def __getattr__(self, attr): 1025238Sgblack@eecs.umich.edu if attr == 'ptype': 1035238Sgblack@eecs.umich.edu try: 1045238Sgblack@eecs.umich.edu ptype = eval(self.ptype_str, objects.__dict__) 1055238Sgblack@eecs.umich.edu if not isinstance(ptype, type): 1065238Sgblack@eecs.umich.edu raise NameError 1075238Sgblack@eecs.umich.edu self.ptype = ptype 1085238Sgblack@eecs.umich.edu return ptype 1095238Sgblack@eecs.umich.edu except NameError: 1105238Sgblack@eecs.umich.edu raise TypeError, \ 1115238Sgblack@eecs.umich.edu "Param qualifier '%s' is not a type" % self.ptype_str 1125238Sgblack@eecs.umich.edu raise AttributeError, "'%s' object has no attribute '%s'" % \ 1135238Sgblack@eecs.umich.edu (type(self).__name__, attr) 1145238Sgblack@eecs.umich.edu 1155238Sgblack@eecs.umich.edu def convert(self, value): 1165238Sgblack@eecs.umich.edu if isinstance(value, proxy.BaseProxy): 1175238Sgblack@eecs.umich.edu value.set_param_desc(self) 1185238Sgblack@eecs.umich.edu return value 1195238Sgblack@eecs.umich.edu if not hasattr(self, 'ptype') and isNullPointer(value): 1205238Sgblack@eecs.umich.edu # deferred evaluation of SimObject; continue to defer if 1215238Sgblack@eecs.umich.edu # we're just assigning a null pointer 1225238Sgblack@eecs.umich.edu return value 1235238Sgblack@eecs.umich.edu if isinstance(value, self.ptype): 1245238Sgblack@eecs.umich.edu return value 1255238Sgblack@eecs.umich.edu if isNullPointer(value) and isSimObjectClass(self.ptype): 1265238Sgblack@eecs.umich.edu return value 1275238Sgblack@eecs.umich.edu return self.ptype(value) 1285238Sgblack@eecs.umich.edu 1295238Sgblack@eecs.umich.edu def cxx_predecls(self): 1305238Sgblack@eecs.umich.edu return self.ptype.cxx_predecls 1315683Sgblack@eecs.umich.edu 1325238Sgblack@eecs.umich.edu def swig_predecls(self): 1335238Sgblack@eecs.umich.edu return self.ptype.swig_predecls 1345238Sgblack@eecs.umich.edu 1355238Sgblack@eecs.umich.edu def cxx_decl(self): 1365238Sgblack@eecs.umich.edu return '%s %s;' % (self.ptype.cxx_type, self.name) 1375238Sgblack@eecs.umich.edu 1385238Sgblack@eecs.umich.edu# Vector-valued parameter description. Just like ParamDesc, except 1395238Sgblack@eecs.umich.edu# that the value is a vector (list) of the specified type instead of a 1405291Sgblack@eecs.umich.edu# single value. 1415291Sgblack@eecs.umich.edu 1425291Sgblack@eecs.umich.educlass VectorParamValue(list): 1435291Sgblack@eecs.umich.edu def ini_str(self): 1445291Sgblack@eecs.umich.edu return ' '.join([v.ini_str() for v in self]) 1455291Sgblack@eecs.umich.edu 1465291Sgblack@eecs.umich.edu def unproxy(self, base): 1475291Sgblack@eecs.umich.edu return [v.unproxy(base) for v in self] 1485291Sgblack@eecs.umich.edu 1495292Sgblack@eecs.umich.educlass SimObjVector(VectorParamValue): 1505292Sgblack@eecs.umich.edu def print_ini(self): 1515292Sgblack@eecs.umich.edu for v in self: 1525292Sgblack@eecs.umich.edu v.print_ini() 1535292Sgblack@eecs.umich.edu 1545292Sgblack@eecs.umich.educlass VectorParamDesc(ParamDesc): 1555292Sgblack@eecs.umich.edu # Convert assigned value to appropriate type. If the RHS is not a 1565292Sgblack@eecs.umich.edu # list or tuple, it generates a single-element list. 1575292Sgblack@eecs.umich.edu def convert(self, value): 1585238Sgblack@eecs.umich.edu if isinstance(value, (list, tuple)): 1595238Sgblack@eecs.umich.edu # list: coerce each element into new list 1605359Sgblack@eecs.umich.edu tmp_list = [ ParamDesc.convert(self, v) for v in value ] 1615238Sgblack@eecs.umich.edu if isSimObjectSequence(tmp_list): 1625238Sgblack@eecs.umich.edu return SimObjVector(tmp_list) 1635238Sgblack@eecs.umich.edu else: 1644276Sgblack@eecs.umich.edu return VectorParamValue(tmp_list) 1654276Sgblack@eecs.umich.edu else: 1665789Sgblack@eecs.umich.edu # singleton: leave it be (could coerce to a single-element 1675789Sgblack@eecs.umich.edu # list here, but for some historical reason we don't... 1685789Sgblack@eecs.umich.edu return ParamDesc.convert(self, value) 1695789Sgblack@eecs.umich.edu 1705789Sgblack@eecs.umich.edu def cxx_predecls(self): 1715789Sgblack@eecs.umich.edu return ['#include <vector>'] + self.ptype.cxx_predecls 1725789Sgblack@eecs.umich.edu 1735789Sgblack@eecs.umich.edu def swig_predecls(self): 1745789Sgblack@eecs.umich.edu return ['%include "std_vector.i"'] + self.ptype.swig_predecls 1755789Sgblack@eecs.umich.edu 1765789Sgblack@eecs.umich.edu def cxx_decl(self): 1775789Sgblack@eecs.umich.edu return 'std::vector< %s > %s;' % (self.ptype.cxx_type, self.name) 1785789Sgblack@eecs.umich.edu 1795789Sgblack@eecs.umich.educlass ParamFactory(object): 1805789Sgblack@eecs.umich.edu def __init__(self, param_desc_class, ptype_str = None): 1815789Sgblack@eecs.umich.edu self.param_desc_class = param_desc_class 1825789Sgblack@eecs.umich.edu self.ptype_str = ptype_str 1835789Sgblack@eecs.umich.edu 1845789Sgblack@eecs.umich.edu def __getattr__(self, attr): 1855789Sgblack@eecs.umich.edu if self.ptype_str: 1865789Sgblack@eecs.umich.edu attr = self.ptype_str + '.' + attr 1875789Sgblack@eecs.umich.edu return ParamFactory(self.param_desc_class, attr) 1885789Sgblack@eecs.umich.edu 1895789Sgblack@eecs.umich.edu # E.g., Param.Int(5, "number of widgets") 1905789Sgblack@eecs.umich.edu def __call__(self, *args, **kwargs): 1915789Sgblack@eecs.umich.edu caller_frame = inspect.currentframe().f_back 1925789Sgblack@eecs.umich.edu ptype = None 1935789Sgblack@eecs.umich.edu try: 1945789Sgblack@eecs.umich.edu ptype = eval(self.ptype_str, 1955789Sgblack@eecs.umich.edu caller_frame.f_globals, caller_frame.f_locals) 1965789Sgblack@eecs.umich.edu if not isinstance(ptype, type): 1975789Sgblack@eecs.umich.edu raise TypeError, \ 1985789Sgblack@eecs.umich.edu "Param qualifier is not a type: %s" % ptype 1995789Sgblack@eecs.umich.edu except NameError: 2005789Sgblack@eecs.umich.edu # if name isn't defined yet, assume it's a SimObject, and 2015789Sgblack@eecs.umich.edu # try to resolve it later 2025789Sgblack@eecs.umich.edu pass 2035789Sgblack@eecs.umich.edu return self.param_desc_class(self.ptype_str, ptype, *args, **kwargs) 2045789Sgblack@eecs.umich.edu 2055789Sgblack@eecs.umich.eduParam = ParamFactory(ParamDesc) 2065789Sgblack@eecs.umich.eduVectorParam = ParamFactory(VectorParamDesc) 2075789Sgblack@eecs.umich.edu 2085789Sgblack@eecs.umich.edu##################################################################### 2095789Sgblack@eecs.umich.edu# 2105789Sgblack@eecs.umich.edu# Parameter Types 2115789Sgblack@eecs.umich.edu# 2125789Sgblack@eecs.umich.edu# Though native Python types could be used to specify parameter types 2135789Sgblack@eecs.umich.edu# (the 'ptype' field of the Param and VectorParam classes), it's more 2145789Sgblack@eecs.umich.edu# flexible to define our own set of types. This gives us more control 2155789Sgblack@eecs.umich.edu# over how Python expressions are converted to values (via the 2165789Sgblack@eecs.umich.edu# __init__() constructor) and how these values are printed out (via 2175789Sgblack@eecs.umich.edu# the __str__() conversion method). 2185789Sgblack@eecs.umich.edu# 2195789Sgblack@eecs.umich.edu##################################################################### 2205789Sgblack@eecs.umich.edu 2215789Sgblack@eecs.umich.edu# String-valued parameter. Just mixin the ParamValue class with the 2225789Sgblack@eecs.umich.edu# built-in str class. 2235789Sgblack@eecs.umich.educlass String(ParamValue,str): 2245789Sgblack@eecs.umich.edu cxx_type = 'std::string' 2255789Sgblack@eecs.umich.edu cxx_predecls = ['#include <string>'] 2265789Sgblack@eecs.umich.edu swig_predecls = ['%include "std_string.i"\n' + 2275789Sgblack@eecs.umich.edu '%apply const std::string& {std::string *};'] 2285789Sgblack@eecs.umich.edu pass 2295789Sgblack@eecs.umich.edu 2305789Sgblack@eecs.umich.edu# superclass for "numeric" parameter values, to emulate math 2315789Sgblack@eecs.umich.edu# operations in a type-safe way. e.g., a Latency times an int returns 2325789Sgblack@eecs.umich.edu# a new Latency object. 2335789Sgblack@eecs.umich.educlass NumericParamValue(ParamValue): 2345789Sgblack@eecs.umich.edu def __str__(self): 2355789Sgblack@eecs.umich.edu return str(self.value) 2365789Sgblack@eecs.umich.edu 2375789Sgblack@eecs.umich.edu def __float__(self): 2385789Sgblack@eecs.umich.edu return float(self.value) 2395789Sgblack@eecs.umich.edu 2405789Sgblack@eecs.umich.edu # hook for bounds checking 2415789Sgblack@eecs.umich.edu def _check(self): 2425789Sgblack@eecs.umich.edu return 2435789Sgblack@eecs.umich.edu 2445789Sgblack@eecs.umich.edu def __mul__(self, other): 2455789Sgblack@eecs.umich.edu newobj = self.__class__(self) 2465789Sgblack@eecs.umich.edu newobj.value *= other 2475789Sgblack@eecs.umich.edu newobj._check() 2485789Sgblack@eecs.umich.edu return newobj 2495789Sgblack@eecs.umich.edu 2505789Sgblack@eecs.umich.edu __rmul__ = __mul__ 2515789Sgblack@eecs.umich.edu 2525789Sgblack@eecs.umich.edu def __div__(self, other): 2535789Sgblack@eecs.umich.edu newobj = self.__class__(self) 2545789Sgblack@eecs.umich.edu newobj.value /= other 2555789Sgblack@eecs.umich.edu newobj._check() 2564712Sgblack@eecs.umich.edu return newobj 2574711Sgblack@eecs.umich.edu 2584712Sgblack@eecs.umich.edu def __sub__(self, other): 2595659Sgblack@eecs.umich.edu newobj = self.__class__(self) 2604712Sgblack@eecs.umich.edu newobj.value -= other 2614276Sgblack@eecs.umich.edu newobj._check() 2624276Sgblack@eecs.umich.edu return newobj 2634276Sgblack@eecs.umich.edu 2644276Sgblack@eecs.umich.edu# Metaclass for bounds-checked integer parameters. See CheckedInt. 2654276Sgblack@eecs.umich.educlass CheckedIntType(type): 2664276Sgblack@eecs.umich.edu def __init__(cls, name, bases, dict): 2674712Sgblack@eecs.umich.edu super(CheckedIntType, cls).__init__(name, bases, dict) 2684712Sgblack@eecs.umich.edu 2694730Sgblack@eecs.umich.edu # CheckedInt is an abstract base class, so we actually don't 2704760Sgblack@eecs.umich.edu # want to do any processing on it... the rest of this code is 2714730Sgblack@eecs.umich.edu # just for classes that derive from CheckedInt. 2725422Sgblack@eecs.umich.edu if name == 'CheckedInt': 2735422Sgblack@eecs.umich.edu return 2745422Sgblack@eecs.umich.edu 2754276Sgblack@eecs.umich.edu if not cls.cxx_predecls: 2764760Sgblack@eecs.umich.edu # most derived types require this, so we just do it here once 2774760Sgblack@eecs.umich.edu cls.cxx_predecls = ['#include "sim/host.hh"'] 2784760Sgblack@eecs.umich.edu 2795020Sgblack@eecs.umich.edu if not cls.swig_predecls: 2805020Sgblack@eecs.umich.edu # most derived types require this, so we just do it here once 2815020Sgblack@eecs.umich.edu cls.swig_predecls = ['%import "python/m5/swig/stdint.i"\n' + 2825020Sgblack@eecs.umich.edu '%import "sim/host.hh"'] 2835020Sgblack@eecs.umich.edu 2845020Sgblack@eecs.umich.edu if not (hasattr(cls, 'min') and hasattr(cls, 'max')): 2855020Sgblack@eecs.umich.edu if not (hasattr(cls, 'size') and hasattr(cls, 'unsigned')): 2865020Sgblack@eecs.umich.edu panic("CheckedInt subclass %s must define either\n" \ 2875020Sgblack@eecs.umich.edu " 'min' and 'max' or 'size' and 'unsigned'\n" \ 2885020Sgblack@eecs.umich.edu % name); 2895020Sgblack@eecs.umich.edu if cls.unsigned: 2905020Sgblack@eecs.umich.edu cls.min = 0 2915020Sgblack@eecs.umich.edu cls.max = 2 ** cls.size - 1 2925020Sgblack@eecs.umich.edu else: 2934760Sgblack@eecs.umich.edu cls.min = -(2 ** (cls.size - 1)) 2944760Sgblack@eecs.umich.edu cls.max = (2 ** (cls.size - 1)) - 1 2954760Sgblack@eecs.umich.edu 2965020Sgblack@eecs.umich.edu# Abstract superclass for bounds-checked integer parameters. This 2975020Sgblack@eecs.umich.edu# class is subclassed to generate parameter classes with specific 2985020Sgblack@eecs.umich.edu# bounds. Initialization of the min and max bounds is done in the 2995020Sgblack@eecs.umich.edu# metaclass CheckedIntType.__init__. 3005020Sgblack@eecs.umich.educlass CheckedInt(NumericParamValue): 3014760Sgblack@eecs.umich.edu __metaclass__ = CheckedIntType 3024760Sgblack@eecs.umich.edu 3034760Sgblack@eecs.umich.edu def _check(self): 3045020Sgblack@eecs.umich.edu if not self.min <= self.value <= self.max: 3055020Sgblack@eecs.umich.edu raise TypeError, 'Integer param out of bounds %d < %d < %d' % \ 3065029Sgblack@eecs.umich.edu (self.min, self.value, self.max) 3075029Sgblack@eecs.umich.edu 3085020Sgblack@eecs.umich.edu def __init__(self, value): 3095020Sgblack@eecs.umich.edu if isinstance(value, str): 3105020Sgblack@eecs.umich.edu self.value = convert.toInteger(value) 3115020Sgblack@eecs.umich.edu elif isinstance(value, (int, long, float)): 3124760Sgblack@eecs.umich.edu self.value = long(value) 3134760Sgblack@eecs.umich.edu self._check() 3144760Sgblack@eecs.umich.edu 3155030Sgblack@eecs.umich.educlass Int(CheckedInt): cxx_type = 'int'; size = 32; unsigned = False 3165030Sgblack@eecs.umich.educlass Unsigned(CheckedInt): cxx_type = 'unsigned'; size = 32; unsigned = True 3175020Sgblack@eecs.umich.edu 3185020Sgblack@eecs.umich.educlass Int8(CheckedInt): cxx_type = 'int8_t'; size = 8; unsigned = False 3194760Sgblack@eecs.umich.educlass UInt8(CheckedInt): cxx_type = 'uint8_t'; size = 8; unsigned = True 3204760Sgblack@eecs.umich.educlass Int16(CheckedInt): cxx_type = 'int16_t'; size = 16; unsigned = False 3214276Sgblack@eecs.umich.educlass UInt16(CheckedInt): cxx_type = 'uint16_t'; size = 16; unsigned = True 3224276Sgblack@eecs.umich.educlass Int32(CheckedInt): cxx_type = 'int32_t'; size = 32; unsigned = False 3235331Sgblack@eecs.umich.educlass UInt32(CheckedInt): cxx_type = 'uint32_t'; size = 32; unsigned = True 3245331Sgblack@eecs.umich.educlass Int64(CheckedInt): cxx_type = 'int64_t'; size = 64; unsigned = False 3255331Sgblack@eecs.umich.educlass UInt64(CheckedInt): cxx_type = 'uint64_t'; size = 64; unsigned = True 3265331Sgblack@eecs.umich.edu 3275331Sgblack@eecs.umich.educlass Counter(CheckedInt): cxx_type = 'Counter'; size = 64; unsigned = True 3285331Sgblack@eecs.umich.educlass Tick(CheckedInt): cxx_type = 'Tick'; size = 64; unsigned = True 3295331Sgblack@eecs.umich.educlass TcpPort(CheckedInt): cxx_type = 'uint16_t'; size = 16; unsigned = True 3305331Sgblack@eecs.umich.educlass UdpPort(CheckedInt): cxx_type = 'uint16_t'; size = 16; unsigned = True 3315331Sgblack@eecs.umich.edu 3325331Sgblack@eecs.umich.educlass Percent(CheckedInt): cxx_type = 'int'; min = 0; max = 100 3335331Sgblack@eecs.umich.edu 3345331Sgblack@eecs.umich.educlass Float(ParamValue, float): 3355331Sgblack@eecs.umich.edu pass 3365331Sgblack@eecs.umich.edu 3375331Sgblack@eecs.umich.educlass MemorySize(CheckedInt): 3384276Sgblack@eecs.umich.edu cxx_type = 'uint64_t' 3395020Sgblack@eecs.umich.edu size = 64 3405020Sgblack@eecs.umich.edu unsigned = True 3415020Sgblack@eecs.umich.edu def __init__(self, value): 3425296Sgblack@eecs.umich.edu if isinstance(value, MemorySize): 3435020Sgblack@eecs.umich.edu self.value = value.value 3445241Sgblack@eecs.umich.edu else: 3455020Sgblack@eecs.umich.edu self.value = convert.toMemorySize(value) 3465020Sgblack@eecs.umich.edu self._check() 3475020Sgblack@eecs.umich.edu 3485020Sgblack@eecs.umich.educlass MemorySize32(CheckedInt): 3495020Sgblack@eecs.umich.edu size = 32 3505020Sgblack@eecs.umich.edu unsigned = True 3515020Sgblack@eecs.umich.edu def __init__(self, value): 3525020Sgblack@eecs.umich.edu if isinstance(value, MemorySize): 3535020Sgblack@eecs.umich.edu self.value = value.value 3545020Sgblack@eecs.umich.edu else: 3555020Sgblack@eecs.umich.edu self.value = convert.toMemorySize(value) 3564276Sgblack@eecs.umich.edu self._check() 3575020Sgblack@eecs.umich.edu 3585020Sgblack@eecs.umich.educlass Addr(CheckedInt): 3595020Sgblack@eecs.umich.edu cxx_type = 'Addr' 3605031Sgblack@eecs.umich.edu cxx_predecls = ['#include "targetarch/isa_traits.hh"'] 3615031Sgblack@eecs.umich.edu size = 64 3625031Sgblack@eecs.umich.edu unsigned = True 3635031Sgblack@eecs.umich.edu def __init__(self, value): 3645020Sgblack@eecs.umich.edu if isinstance(value, Addr): 3655020Sgblack@eecs.umich.edu self.value = value.value 3665020Sgblack@eecs.umich.edu else: 3675020Sgblack@eecs.umich.edu try: 3685020Sgblack@eecs.umich.edu self.value = convert.toMemorySize(value) 3695020Sgblack@eecs.umich.edu except TypeError: 3705020Sgblack@eecs.umich.edu self.value = long(value) 3715020Sgblack@eecs.umich.edu self._check() 3725020Sgblack@eecs.umich.edu 3735020Sgblack@eecs.umich.edu 3745020Sgblack@eecs.umich.educlass MetaRange(type): 3755020Sgblack@eecs.umich.edu def __init__(cls, name, bases, dict): 3765020Sgblack@eecs.umich.edu super(MetaRange, cls).__init__(name, bases, dict) 3775020Sgblack@eecs.umich.edu if name == 'Range': 3785020Sgblack@eecs.umich.edu return 3795020Sgblack@eecs.umich.edu cls.cxx_type = 'Range< %s >' % cls.type.cxx_type 3805020Sgblack@eecs.umich.edu cls.cxx_predecls = \ 3815020Sgblack@eecs.umich.edu ['#include "base/range.hh"'] + cls.type.cxx_predecls 3825020Sgblack@eecs.umich.edu 3835020Sgblack@eecs.umich.educlass Range(ParamValue): 3845020Sgblack@eecs.umich.edu __metaclass__ = MetaRange 3855020Sgblack@eecs.umich.edu type = Int # default; can be overridden in subclasses 3865020Sgblack@eecs.umich.edu def __init__(self, *args, **kwargs): 3875020Sgblack@eecs.umich.edu def handle_kwargs(self, kwargs): 3885020Sgblack@eecs.umich.edu if 'end' in kwargs: 3895020Sgblack@eecs.umich.edu self.second = self.type(kwargs.pop('end')) 3905020Sgblack@eecs.umich.edu elif 'size' in kwargs: 3915020Sgblack@eecs.umich.edu self.second = self.first + self.type(kwargs.pop('size')) - 1 3925058Sgblack@eecs.umich.edu else: 3935020Sgblack@eecs.umich.edu raise TypeError, "Either end or size must be specified" 3945020Sgblack@eecs.umich.edu 3955020Sgblack@eecs.umich.edu if len(args) == 0: 3965020Sgblack@eecs.umich.edu self.first = self.type(kwargs.pop('start')) 3975046Sgblack@eecs.umich.edu handle_kwargs(self, kwargs) 3985046Sgblack@eecs.umich.edu 3995046Sgblack@eecs.umich.edu elif len(args) == 1: 4005046Sgblack@eecs.umich.edu if kwargs: 4015020Sgblack@eecs.umich.edu self.first = self.type(args[0]) 4025020Sgblack@eecs.umich.edu handle_kwargs(self, kwargs) 4035020Sgblack@eecs.umich.edu elif isinstance(args[0], Range): 4045020Sgblack@eecs.umich.edu self.first = self.type(args[0].first) 4054276Sgblack@eecs.umich.edu self.second = self.type(args[0].second) 4064276Sgblack@eecs.umich.edu else: 4075149Sgblack@eecs.umich.edu self.first = self.type(0) 4085409Sgblack@eecs.umich.edu self.second = self.type(args[0]) - 1 4095149Sgblack@eecs.umich.edu 4104712Sgblack@eecs.umich.edu elif len(args) == 2: 4114712Sgblack@eecs.umich.edu self.first = self.type(args[0]) 4124712Sgblack@eecs.umich.edu self.second = self.type(args[1]) 4134730Sgblack@eecs.umich.edu else: 4144712Sgblack@eecs.umich.edu raise TypeError, "Too many arguments specified" 4154276Sgblack@eecs.umich.edu 4164276Sgblack@eecs.umich.edu if kwargs: 4174712Sgblack@eecs.umich.edu raise TypeError, "too many keywords: %s" % kwargs.keys() 4184712Sgblack@eecs.umich.edu 4194712Sgblack@eecs.umich.edu def __str__(self): 4204712Sgblack@eecs.umich.edu return '%s:%s' % (self.first, self.second) 4214712Sgblack@eecs.umich.edu 4224712Sgblack@eecs.umich.educlass AddrRange(Range): 4234712Sgblack@eecs.umich.edu type = Addr 4244712Sgblack@eecs.umich.edu 4254276Sgblack@eecs.umich.educlass TickRange(Range): 4264760Sgblack@eecs.umich.edu type = Tick 4274760Sgblack@eecs.umich.edu 4284760Sgblack@eecs.umich.edu# Boolean parameter type. Python doesn't let you subclass bool, since 4294760Sgblack@eecs.umich.edu# it doesn't want to let you create multiple instances of True and 4304760Sgblack@eecs.umich.edu# False. Thus this is a little more complicated than String. 4314760Sgblack@eecs.umich.educlass Bool(ParamValue): 4324760Sgblack@eecs.umich.edu cxx_type = 'bool' 4334760Sgblack@eecs.umich.edu def __init__(self, value): 4344760Sgblack@eecs.umich.edu try: 4354760Sgblack@eecs.umich.edu self.value = convert.toBool(value) 4364760Sgblack@eecs.umich.edu except TypeError: 4374760Sgblack@eecs.umich.edu self.value = bool(value) 4384760Sgblack@eecs.umich.edu 4394760Sgblack@eecs.umich.edu def __str__(self): 4404760Sgblack@eecs.umich.edu return str(self.value) 4414760Sgblack@eecs.umich.edu 4424760Sgblack@eecs.umich.edu def ini_str(self): 4434760Sgblack@eecs.umich.edu if self.value: 4444760Sgblack@eecs.umich.edu return 'true' 4454760Sgblack@eecs.umich.edu return 'false' 4464760Sgblack@eecs.umich.edu 4474276Sgblack@eecs.umich.edudef IncEthernetAddr(addr, val = 1): 4485020Sgblack@eecs.umich.edu bytes = map(lambda x: int(x, 16), addr.split(':')) 4495020Sgblack@eecs.umich.edu bytes[5] += val 4505020Sgblack@eecs.umich.edu for i in (5, 4, 3, 2, 1): 4515020Sgblack@eecs.umich.edu val,rem = divmod(bytes[i], 256) 4525020Sgblack@eecs.umich.edu bytes[i] = rem 4535020Sgblack@eecs.umich.edu if val == 0: 4545020Sgblack@eecs.umich.edu break 4555020Sgblack@eecs.umich.edu bytes[i - 1] += val 4565020Sgblack@eecs.umich.edu assert(bytes[0] <= 255) 4575020Sgblack@eecs.umich.edu return ':'.join(map(lambda x: '%02x' % x, bytes)) 4585020Sgblack@eecs.umich.edu 4595020Sgblack@eecs.umich.educlass NextEthernetAddr(object): 4605020Sgblack@eecs.umich.edu addr = "00:90:00:00:00:01" 4615020Sgblack@eecs.umich.edu 4625020Sgblack@eecs.umich.edu def __init__(self, inc = 1): 4635020Sgblack@eecs.umich.edu self.value = NextEthernetAddr.addr 4645020Sgblack@eecs.umich.edu NextEthernetAddr.addr = IncEthernetAddr(NextEthernetAddr.addr, inc) 4655020Sgblack@eecs.umich.edu 4665020Sgblack@eecs.umich.educlass EthernetAddr(ParamValue): 4675020Sgblack@eecs.umich.edu cxx_type = 'Net::EthAddr' 4685020Sgblack@eecs.umich.edu cxx_predecls = ['#include "base/inet.hh"'] 4695020Sgblack@eecs.umich.edu swig_predecls = ['class Net::EthAddr;'] 4705020Sgblack@eecs.umich.edu def __init__(self, value): 4715020Sgblack@eecs.umich.edu if value == NextEthernetAddr: 4725020Sgblack@eecs.umich.edu self.value = value 4735020Sgblack@eecs.umich.edu return 4745052Sgblack@eecs.umich.edu 4755052Sgblack@eecs.umich.edu if not isinstance(value, str): 4765052Sgblack@eecs.umich.edu raise TypeError, "expected an ethernet address and didn't get one" 4775020Sgblack@eecs.umich.edu 4785020Sgblack@eecs.umich.edu bytes = value.split(':') 4795059Sgblack@eecs.umich.edu if len(bytes) != 6: 4805059Sgblack@eecs.umich.edu raise TypeError, 'invalid ethernet address %s' % value 4815059Sgblack@eecs.umich.edu 4825059Sgblack@eecs.umich.edu for byte in bytes: 4835059Sgblack@eecs.umich.edu if not 0 <= int(byte) <= 256: 4845059Sgblack@eecs.umich.edu raise TypeError, 'invalid ethernet address %s' % value 4855059Sgblack@eecs.umich.edu 4865020Sgblack@eecs.umich.edu self.value = value 4874276Sgblack@eecs.umich.edu 4885020Sgblack@eecs.umich.edu def unproxy(self, base): 4895020Sgblack@eecs.umich.edu if self.value == NextEthernetAddr: 4905020Sgblack@eecs.umich.edu self.addr = self.value().value 4915020Sgblack@eecs.umich.edu return self 4925020Sgblack@eecs.umich.edu 4935020Sgblack@eecs.umich.edu def __str__(self): 4945020Sgblack@eecs.umich.edu if self.value == NextEthernetAddr: 4955020Sgblack@eecs.umich.edu if hasattr(self, 'addr'): 4965020Sgblack@eecs.umich.edu return self.addr 4975020Sgblack@eecs.umich.edu else: 4985020Sgblack@eecs.umich.edu return "NextEthernetAddr (unresolved)" 4995020Sgblack@eecs.umich.edu else: 5005020Sgblack@eecs.umich.edu return self.value 5015020Sgblack@eecs.umich.edu 5025020Sgblack@eecs.umich.edu# Enumerated types are a little more complex. The user specifies the 5035020Sgblack@eecs.umich.edu# type as Enum(foo) where foo is either a list or dictionary of 5045020Sgblack@eecs.umich.edu# alternatives (typically strings, but not necessarily so). (In the 5055020Sgblack@eecs.umich.edu# long run, the integer value of the parameter will be the list index 5065020Sgblack@eecs.umich.edu# or the corresponding dictionary value. For now, since we only check 5075020Sgblack@eecs.umich.edu# that the alternative is valid and then spit it into a .ini file, 5085020Sgblack@eecs.umich.edu# there's not much point in using the dictionary.) 5095020Sgblack@eecs.umich.edu 5105020Sgblack@eecs.umich.edu# What Enum() must do is generate a new type encapsulating the 5115020Sgblack@eecs.umich.edu# provided list/dictionary so that specific values of the parameter 5125020Sgblack@eecs.umich.edu# can be instances of that type. We define two hidden internal 5135020Sgblack@eecs.umich.edu# classes (_ListEnum and _DictEnum) to serve as base classes, then 5145020Sgblack@eecs.umich.edu# derive the new type from the appropriate base class on the fly. 5155020Sgblack@eecs.umich.edu 5165020Sgblack@eecs.umich.edu 5175020Sgblack@eecs.umich.edu# Metaclass for Enum types 5185020Sgblack@eecs.umich.educlass MetaEnum(type): 5195020Sgblack@eecs.umich.edu def __init__(cls, name, bases, init_dict): 5205020Sgblack@eecs.umich.edu if init_dict.has_key('map'): 5215020Sgblack@eecs.umich.edu if not isinstance(cls.map, dict): 5225020Sgblack@eecs.umich.edu raise TypeError, "Enum-derived class attribute 'map' " \ 5235020Sgblack@eecs.umich.edu "must be of type dict" 5245047Sgblack@eecs.umich.edu # build list of value strings from map 5255047Sgblack@eecs.umich.edu cls.vals = cls.map.keys() 5265020Sgblack@eecs.umich.edu cls.vals.sort() 5275047Sgblack@eecs.umich.edu elif init_dict.has_key('vals'): 5285020Sgblack@eecs.umich.edu if not isinstance(cls.vals, list): 5295047Sgblack@eecs.umich.edu raise TypeError, "Enum-derived class attribute 'vals' " \ 5305020Sgblack@eecs.umich.edu "must be of type list" 5315020Sgblack@eecs.umich.edu # build string->value map from vals sequence 5325020Sgblack@eecs.umich.edu cls.map = {} 5335020Sgblack@eecs.umich.edu for idx,val in enumerate(cls.vals): 5344276Sgblack@eecs.umich.edu cls.map[val] = idx 5355020Sgblack@eecs.umich.edu else: 5365020Sgblack@eecs.umich.edu raise TypeError, "Enum-derived class must define "\ 5375020Sgblack@eecs.umich.edu "attribute 'map' or 'vals'" 5385020Sgblack@eecs.umich.edu 5395020Sgblack@eecs.umich.edu cls.cxx_type = name + '::Enum' 5405020Sgblack@eecs.umich.edu 5415020Sgblack@eecs.umich.edu super(MetaEnum, cls).__init__(name, bases, init_dict) 5425020Sgblack@eecs.umich.edu 5435020Sgblack@eecs.umich.edu # Generate C++ class declaration for this enum type. 5445020Sgblack@eecs.umich.edu # Note that we wrap the enum in a class/struct to act as a namespace, 5455020Sgblack@eecs.umich.edu # so that the enum strings can be brief w/o worrying about collisions. 5465020Sgblack@eecs.umich.edu def cxx_decl(cls): 5475020Sgblack@eecs.umich.edu s = 'struct %s {\n enum Enum {\n ' % cls.__name__ 5485020Sgblack@eecs.umich.edu s += ',\n '.join(['%s = %d' % (v,cls.map[v]) for v in cls.vals]) 5495020Sgblack@eecs.umich.edu s += '\n };\n};\n' 5505020Sgblack@eecs.umich.edu return s 5515020Sgblack@eecs.umich.edu 5525020Sgblack@eecs.umich.edu# Base class for enum types. 5535020Sgblack@eecs.umich.educlass Enum(ParamValue): 5545020Sgblack@eecs.umich.edu __metaclass__ = MetaEnum 5555020Sgblack@eecs.umich.edu vals = [] 5565020Sgblack@eecs.umich.edu 5575020Sgblack@eecs.umich.edu def __init__(self, value): 5585020Sgblack@eecs.umich.edu if value not in self.map: 5594276Sgblack@eecs.umich.edu raise TypeError, "Enum param got bad value '%s' (not in %s)" \ 5605020Sgblack@eecs.umich.edu % (value, self.vals) 5615020Sgblack@eecs.umich.edu self.value = value 5625020Sgblack@eecs.umich.edu 5635020Sgblack@eecs.umich.edu def __str__(self): 5645020Sgblack@eecs.umich.edu return self.value 5655020Sgblack@eecs.umich.edu 5665020Sgblack@eecs.umich.eduticks_per_sec = None 5675020Sgblack@eecs.umich.edu 5685020Sgblack@eecs.umich.edu# how big does a rounding error need to be before we warn about it? 5695020Sgblack@eecs.umich.edufrequency_tolerance = 0.001 # 0.1% 5705020Sgblack@eecs.umich.edu 5715020Sgblack@eecs.umich.edu# convert a floting-point # of ticks to integer, and warn if rounding 5725020Sgblack@eecs.umich.edu# discards too much precision 5735020Sgblack@eecs.umich.edudef tick_check(float_ticks): 5745020Sgblack@eecs.umich.edu if float_ticks == 0: 5755020Sgblack@eecs.umich.edu return 0 5765020Sgblack@eecs.umich.edu int_ticks = int(round(float_ticks)) 5775020Sgblack@eecs.umich.edu err = (float_ticks - int_ticks) / float_ticks 5785020Sgblack@eecs.umich.edu if err > frequency_tolerance: 5795020Sgblack@eecs.umich.edu print >> sys.stderr, "Warning: rounding error > tolerance" 5805020Sgblack@eecs.umich.edu print >> sys.stderr, " %f rounded to %d" % (float_ticks, int_ticks) 5815020Sgblack@eecs.umich.edu #raise ValueError 5825020Sgblack@eecs.umich.edu return int_ticks 5835020Sgblack@eecs.umich.edu 5845020Sgblack@eecs.umich.edudef getLatency(value): 5855020Sgblack@eecs.umich.edu if isinstance(value, Latency) or isinstance(value, Clock): 5865020Sgblack@eecs.umich.edu return value.value 5875020Sgblack@eecs.umich.edu elif isinstance(value, Frequency) or isinstance(value, RootClock): 5884276Sgblack@eecs.umich.edu return 1 / value.value 5895020Sgblack@eecs.umich.edu elif isinstance(value, str): 5905020Sgblack@eecs.umich.edu try: 5915020Sgblack@eecs.umich.edu return convert.toLatency(value) 5925020Sgblack@eecs.umich.edu except ValueError: 5935238Sgblack@eecs.umich.edu try: 5945238Sgblack@eecs.umich.edu return 1 / convert.toFrequency(value) 5955238Sgblack@eecs.umich.edu except ValueError: 5965238Sgblack@eecs.umich.edu pass # fall through 5975238Sgblack@eecs.umich.edu raise ValueError, "Invalid Frequency/Latency value '%s'" % value 5985238Sgblack@eecs.umich.edu 5995238Sgblack@eecs.umich.edu 6005238Sgblack@eecs.umich.educlass Latency(NumericParamValue): 6015238Sgblack@eecs.umich.edu cxx_type = 'Tick' 6025238Sgblack@eecs.umich.edu cxx_predecls = ['#include "sim/host.hh"'] 6035238Sgblack@eecs.umich.edu swig_predecls = ['%import "python/m5/swig/stdint.i"\n' + 6045238Sgblack@eecs.umich.edu '%import "sim/host.hh"'] 6055238Sgblack@eecs.umich.edu def __init__(self, value): 6065238Sgblack@eecs.umich.edu self.value = getLatency(value) 6075238Sgblack@eecs.umich.edu 6085238Sgblack@eecs.umich.edu def __getattr__(self, attr): 6095238Sgblack@eecs.umich.edu if attr in ('latency', 'period'): 6105238Sgblack@eecs.umich.edu return self 6115238Sgblack@eecs.umich.edu if attr == 'frequency': 6125238Sgblack@eecs.umich.edu return Frequency(self) 6135238Sgblack@eecs.umich.edu raise AttributeError, "Latency object has no attribute '%s'" % attr 6145238Sgblack@eecs.umich.edu 6155238Sgblack@eecs.umich.edu # convert latency to ticks 6165238Sgblack@eecs.umich.edu def ini_str(self): 6175238Sgblack@eecs.umich.edu return str(tick_check(self.value * ticks_per_sec)) 6185238Sgblack@eecs.umich.edu 6195238Sgblack@eecs.umich.educlass Frequency(NumericParamValue): 6205238Sgblack@eecs.umich.edu cxx_type = 'Tick' 6215238Sgblack@eecs.umich.edu cxx_predecls = ['#include "sim/host.hh"'] 6225238Sgblack@eecs.umich.edu swig_predecls = ['%import "python/m5/swig/stdint.i"\n' + 6235238Sgblack@eecs.umich.edu '%import "sim/host.hh"'] 6245238Sgblack@eecs.umich.edu def __init__(self, value): 6255238Sgblack@eecs.umich.edu self.value = 1 / getLatency(value) 6265238Sgblack@eecs.umich.edu 6275238Sgblack@eecs.umich.edu def __getattr__(self, attr): 6285238Sgblack@eecs.umich.edu if attr == 'frequency': 6295238Sgblack@eecs.umich.edu return self 6305238Sgblack@eecs.umich.edu if attr in ('latency', 'period'): 6315238Sgblack@eecs.umich.edu return Latency(self) 6325238Sgblack@eecs.umich.edu raise AttributeError, "Frequency object has no attribute '%s'" % attr 6335238Sgblack@eecs.umich.edu 6345238Sgblack@eecs.umich.edu # convert frequency to ticks per period 6355238Sgblack@eecs.umich.edu def ini_str(self): 6365238Sgblack@eecs.umich.edu return self.period.ini_str() 6375238Sgblack@eecs.umich.edu 6385238Sgblack@eecs.umich.edu# Just like Frequency, except ini_str() is absolute # of ticks per sec (Hz). 6395238Sgblack@eecs.umich.edu# We can't inherit from Frequency because we don't want it to be directly 6405238Sgblack@eecs.umich.edu# assignable to a regular Frequency parameter. 6415238Sgblack@eecs.umich.educlass RootClock(ParamValue): 6425238Sgblack@eecs.umich.edu cxx_type = 'Tick' 6435238Sgblack@eecs.umich.edu cxx_predecls = ['#include "sim/host.hh"'] 6445238Sgblack@eecs.umich.edu swig_predecls = ['%import "python/m5/swig/stdint.i"\n' + 6455020Sgblack@eecs.umich.edu '%import "sim/host.hh"'] 6465020Sgblack@eecs.umich.edu def __init__(self, value): 6475020Sgblack@eecs.umich.edu self.value = 1 / getLatency(value) 6485020Sgblack@eecs.umich.edu 6495020Sgblack@eecs.umich.edu def __getattr__(self, attr): 6505020Sgblack@eecs.umich.edu if attr == 'frequency': 6515020Sgblack@eecs.umich.edu return Frequency(self) 6525020Sgblack@eecs.umich.edu if attr in ('latency', 'period'): 6535020Sgblack@eecs.umich.edu return Latency(self) 6545020Sgblack@eecs.umich.edu raise AttributeError, "Frequency object has no attribute '%s'" % attr 6555020Sgblack@eecs.umich.edu 6565020Sgblack@eecs.umich.edu def ini_str(self): 6575020Sgblack@eecs.umich.edu return str(tick_check(self.value)) 6585238Sgblack@eecs.umich.edu 6595238Sgblack@eecs.umich.edu# A generic frequency and/or Latency value. Value is stored as a latency, 6605238Sgblack@eecs.umich.edu# but to avoid ambiguity this object does not support numeric ops (* or /). 6615238Sgblack@eecs.umich.edu# An explicit conversion to a Latency or Frequency must be made first. 6625238Sgblack@eecs.umich.educlass Clock(ParamValue): 6635238Sgblack@eecs.umich.edu cxx_type = 'Tick' 6645238Sgblack@eecs.umich.edu cxx_predecls = ['#include "sim/host.hh"'] 6655238Sgblack@eecs.umich.edu swig_predecls = ['%import "python/m5/swig/stdint.i"\n' + 6665238Sgblack@eecs.umich.edu '%import "sim/host.hh"'] 6675238Sgblack@eecs.umich.edu def __init__(self, value): 6685238Sgblack@eecs.umich.edu self.value = getLatency(value) 6695238Sgblack@eecs.umich.edu 6705238Sgblack@eecs.umich.edu def __getattr__(self, attr): 6715238Sgblack@eecs.umich.edu if attr == 'frequency': 6725238Sgblack@eecs.umich.edu return Frequency(self) 6735238Sgblack@eecs.umich.edu if attr in ('latency', 'period'): 6745238Sgblack@eecs.umich.edu return Latency(self) 6755238Sgblack@eecs.umich.edu raise AttributeError, "Frequency object has no attribute '%s'" % attr 6765238Sgblack@eecs.umich.edu 6775238Sgblack@eecs.umich.edu def ini_str(self): 6785238Sgblack@eecs.umich.edu return self.period.ini_str() 6795238Sgblack@eecs.umich.edu 6805238Sgblack@eecs.umich.educlass NetworkBandwidth(float,ParamValue): 6815238Sgblack@eecs.umich.edu cxx_type = 'float' 6825238Sgblack@eecs.umich.edu def __new__(cls, value): 6835238Sgblack@eecs.umich.edu val = convert.toNetworkBandwidth(value) / 8.0 6845238Sgblack@eecs.umich.edu return super(cls, NetworkBandwidth).__new__(cls, val) 6855238Sgblack@eecs.umich.edu 6865238Sgblack@eecs.umich.edu def __str__(self): 6875238Sgblack@eecs.umich.edu return str(self.val) 6885238Sgblack@eecs.umich.edu 6895238Sgblack@eecs.umich.edu def ini_str(self): 6905238Sgblack@eecs.umich.edu return '%f' % (ticks_per_sec / float(self)) 6915238Sgblack@eecs.umich.edu 6925238Sgblack@eecs.umich.educlass MemoryBandwidth(float,ParamValue): 6935238Sgblack@eecs.umich.edu cxx_type = 'float' 6945238Sgblack@eecs.umich.edu def __new__(self, value): 6955238Sgblack@eecs.umich.edu val = convert.toMemoryBandwidth(value) 6965238Sgblack@eecs.umich.edu return super(cls, MemoryBandwidth).__new__(cls, val) 6975238Sgblack@eecs.umich.edu 6985238Sgblack@eecs.umich.edu def __str__(self): 6995238Sgblack@eecs.umich.edu return str(self.val) 7005238Sgblack@eecs.umich.edu 7015238Sgblack@eecs.umich.edu def ini_str(self): 7025238Sgblack@eecs.umich.edu return '%f' % (ticks_per_sec / float(self)) 7035238Sgblack@eecs.umich.edu 7045238Sgblack@eecs.umich.edu# 7055238Sgblack@eecs.umich.edu# "Constants"... handy aliases for various values. 7065238Sgblack@eecs.umich.edu# 7075238Sgblack@eecs.umich.edu 7085238Sgblack@eecs.umich.edu# Special class for NULL pointers. Note the special check in 7095238Sgblack@eecs.umich.edu# make_param_value() above that lets these be assigned where a 7105020Sgblack@eecs.umich.edu# SimObject is required. 7115020Sgblack@eecs.umich.edu# only one copy of a particular node 7125020Sgblack@eecs.umich.educlass NullSimObject(object): 7135020Sgblack@eecs.umich.edu __metaclass__ = Singleton 7145020Sgblack@eecs.umich.edu 7155020Sgblack@eecs.umich.edu def __call__(cls): 7165020Sgblack@eecs.umich.edu return cls 7175020Sgblack@eecs.umich.edu 7185020Sgblack@eecs.umich.edu def _instantiate(self, parent = None, path = ''): 7195020Sgblack@eecs.umich.edu pass 7205020Sgblack@eecs.umich.edu 7214276Sgblack@eecs.umich.edu def ini_str(self): 7225020Sgblack@eecs.umich.edu return 'Null' 7235020Sgblack@eecs.umich.edu 7245020Sgblack@eecs.umich.edu def unproxy(self, base): 7255020Sgblack@eecs.umich.edu return self 7265020Sgblack@eecs.umich.edu 7275020Sgblack@eecs.umich.edu def set_path(self, parent, name): 7285020Sgblack@eecs.umich.edu pass 7295020Sgblack@eecs.umich.edu def __str__(self): 7305020Sgblack@eecs.umich.edu return 'Null' 7315020Sgblack@eecs.umich.edu 7325020Sgblack@eecs.umich.edu# The only instance you'll ever need... 7335020Sgblack@eecs.umich.eduNULL = NullSimObject() 7345020Sgblack@eecs.umich.edu 7355020Sgblack@eecs.umich.edudef isNullPointer(value): 7365020Sgblack@eecs.umich.edu return isinstance(value, NullSimObject) 7375020Sgblack@eecs.umich.edu 7385020Sgblack@eecs.umich.edu# Some memory range specifications use this as a default upper bound. 7395020Sgblack@eecs.umich.eduMaxAddr = Addr.max 7405020Sgblack@eecs.umich.eduMaxTick = Tick.max 7415020Sgblack@eecs.umich.eduAllMemory = AddrRange(0, MaxAddr) 7425020Sgblack@eecs.umich.edu 7435020Sgblack@eecs.umich.edu 7445020Sgblack@eecs.umich.edu##################################################################### 7455020Sgblack@eecs.umich.edu# 7465020Sgblack@eecs.umich.edu# Port objects 7475020Sgblack@eecs.umich.edu# 7485020Sgblack@eecs.umich.edu# Ports are used to interconnect objects in the memory system. 7495020Sgblack@eecs.umich.edu# 7505020Sgblack@eecs.umich.edu##################################################################### 7515020Sgblack@eecs.umich.edu 7524276Sgblack@eecs.umich.edu# Port reference: encapsulates a reference to a particular port on a 7534727Sgblack@eecs.umich.edu# particular SimObject. 7544727Sgblack@eecs.umich.educlass PortRef(object): 7554727Sgblack@eecs.umich.edu def __init__(self, simobj, name, isVec): 7564727Sgblack@eecs.umich.edu assert(isSimObject(simobj)) 7574727Sgblack@eecs.umich.edu self.simobj = simobj 7584727Sgblack@eecs.umich.edu self.name = name 7594727Sgblack@eecs.umich.edu self.index = -1 7604727Sgblack@eecs.umich.edu self.isVec = isVec # is this a vector port? 7614727Sgblack@eecs.umich.edu self.peer = None # not associated with another port yet 7624727Sgblack@eecs.umich.edu self.ccConnected = False # C++ port connection done? 7634727Sgblack@eecs.umich.edu 7644727Sgblack@eecs.umich.edu # Set peer port reference. Called via __setattr__ as a result of 7654727Sgblack@eecs.umich.edu # a port assignment, e.g., "obj1.port1 = obj2.port2". 7664727Sgblack@eecs.umich.edu def setPeer(self, other): 7674727Sgblack@eecs.umich.edu if self.isVec: 7684727Sgblack@eecs.umich.edu curMap = self.simobj._port_map.get(self.name, []) 7694727Sgblack@eecs.umich.edu self.index = len(curMap) 7704727Sgblack@eecs.umich.edu curMap.append(other) 7714727Sgblack@eecs.umich.edu else: 7724727Sgblack@eecs.umich.edu curMap = self.simobj._port_map.get(self.name) 7734727Sgblack@eecs.umich.edu if curMap and not self.isVec: 7744760Sgblack@eecs.umich.edu print "warning: overwriting port", self.simobj, self.name 7754760Sgblack@eecs.umich.edu curMap = other 7764760Sgblack@eecs.umich.edu self.simobj._port_map[self.name] = curMap 7774760Sgblack@eecs.umich.edu self.peer = other 7784760Sgblack@eecs.umich.edu 7794760Sgblack@eecs.umich.edu def clone(self, memo): 7804760Sgblack@eecs.umich.edu newRef = copy.copy(self) 7814760Sgblack@eecs.umich.edu assert(isSimObject(newRef.simobj)) 7824760Sgblack@eecs.umich.edu newRef.simobj = newRef.simobj(_memo=memo) 7834760Sgblack@eecs.umich.edu # Tricky: if I'm the *second* PortRef in the pair to be 7844760Sgblack@eecs.umich.edu # cloned, then my peer is still in the middle of its clone 7854760Sgblack@eecs.umich.edu # method, and thus hasn't returned to its owner's 7864760Sgblack@eecs.umich.edu # SimObject.__init__ to get installed in _port_map. As a 7874760Sgblack@eecs.umich.edu # result I have no way of finding the *new* peer object. So I 7884760Sgblack@eecs.umich.edu # mark myself as "waiting" for my peer, and I let the *first* 7894760Sgblack@eecs.umich.edu # PortRef clone call set up both peer pointers after I return. 7904760Sgblack@eecs.umich.edu newPeer = newRef.simobj._port_map.get(self.name) 7914760Sgblack@eecs.umich.edu if newPeer: 7924760Sgblack@eecs.umich.edu if self.isVec: 7934760Sgblack@eecs.umich.edu assert(self.index != -1) 7944276Sgblack@eecs.umich.edu newPeer = newPeer[self.index] 7954276Sgblack@eecs.umich.edu # other guy is all set up except for his peer pointer 7964712Sgblack@eecs.umich.edu assert(newPeer.peer == -1) # peer must be waiting for handshake 7974712Sgblack@eecs.umich.edu newPeer.peer = newRef 7985659Sgblack@eecs.umich.edu newRef.peer = newPeer 7995659Sgblack@eecs.umich.edu else: 8005659Sgblack@eecs.umich.edu # other guy is in clone; just wait for him to do the work 8015659Sgblack@eecs.umich.edu newRef.peer = -1 # mark as waiting for handshake 8025659Sgblack@eecs.umich.edu return newRef 8035659Sgblack@eecs.umich.edu 8045659Sgblack@eecs.umich.edu # Call C++ to create corresponding port connection between C++ objects 8055659Sgblack@eecs.umich.edu def ccConnect(self): 8065240Sgblack@eecs.umich.edu if self.ccConnected: # already done this 8074712Sgblack@eecs.umich.edu return 8084712Sgblack@eecs.umich.edu peer = self.peer 8094712Sgblack@eecs.umich.edu cc_main.connectPorts(self.simobj.getCCObject(), self.name, self.index, 8104712Sgblack@eecs.umich.edu peer.simobj.getCCObject(), peer.name, peer.index) 8114276Sgblack@eecs.umich.edu self.ccConnected = True 8124276Sgblack@eecs.umich.edu peer.ccConnected = True 8134712Sgblack@eecs.umich.edu 8144712Sgblack@eecs.umich.edu# Port description object. Like a ParamDesc object, this represents a 8154712Sgblack@eecs.umich.edu# logical port in the SimObject class, not a particular port on a 8165240Sgblack@eecs.umich.edu# SimObject instance. The latter are represented by PortRef objects. 8174712Sgblack@eecs.umich.educlass Port(object): 8184712Sgblack@eecs.umich.edu def __init__(self, desc): 8195238Sgblack@eecs.umich.edu self.desc = desc 8205238Sgblack@eecs.umich.edu self.isVec = False 8215238Sgblack@eecs.umich.edu 8225238Sgblack@eecs.umich.edu # Generate a PortRef for this port on the given SimObject with the 8235238Sgblack@eecs.umich.edu # given name 8245238Sgblack@eecs.umich.edu def makeRef(self, simobj, name): 8255238Sgblack@eecs.umich.edu return PortRef(simobj, name, self.isVec) 8265238Sgblack@eecs.umich.edu 8275238Sgblack@eecs.umich.edu # Connect an instance of this port (on the given SimObject with 8285238Sgblack@eecs.umich.edu # the given name) with the port described by the supplied PortRef 8295238Sgblack@eecs.umich.edu def connect(self, simobj, name, ref): 8305238Sgblack@eecs.umich.edu if not isinstance(ref, PortRef): 8315238Sgblack@eecs.umich.edu raise TypeError, \ 8325238Sgblack@eecs.umich.edu "assigning non-port reference port '%s'" % name 8335238Sgblack@eecs.umich.edu myRef = self.makeRef(simobj, name) 8344724Sgblack@eecs.umich.edu myRef.setPeer(ref) 8354276Sgblack@eecs.umich.edu ref.setPeer(myRef) 8364276Sgblack@eecs.umich.edu 8374864Sgblack@eecs.umich.edu# VectorPort description object. Like Port, but represents a vector 8384864Sgblack@eecs.umich.edu# of connections (e.g., as on a Bus). 8394712Sgblack@eecs.umich.educlass VectorPort(Port): 8405240Sgblack@eecs.umich.edu def __init__(self, desc): 8414712Sgblack@eecs.umich.edu Port.__init__(self, desc) 8424712Sgblack@eecs.umich.edu self.isVec = True 8434746Sgblack@eecs.umich.edu 8444746Sgblack@eecs.umich.edu 8454746Sgblack@eecs.umich.edu__all__ = ['Param', 'VectorParam', 8464746Sgblack@eecs.umich.edu 'Enum', 'Bool', 'String', 'Float', 8474746Sgblack@eecs.umich.edu 'Int', 'Unsigned', 'Int8', 'UInt8', 'Int16', 'UInt16', 8484276Sgblack@eecs.umich.edu 'Int32', 'UInt32', 'Int64', 'UInt64', 8494276Sgblack@eecs.umich.edu 'Counter', 'Addr', 'Tick', 'Percent', 8504712Sgblack@eecs.umich.edu 'TcpPort', 'UdpPort', 'EthernetAddr', 8515240Sgblack@eecs.umich.edu 'MemorySize', 'MemorySize32', 8525240Sgblack@eecs.umich.edu 'Latency', 'Frequency', 'RootClock', 'Clock', 8535240Sgblack@eecs.umich.edu 'NetworkBandwidth', 'MemoryBandwidth', 8545240Sgblack@eecs.umich.edu 'Range', 'AddrRange', 'TickRange', 8555240Sgblack@eecs.umich.edu 'MaxAddr', 'MaxTick', 'AllMemory', 8565240Sgblack@eecs.umich.edu 'NextEthernetAddr', 'NULL', 8575240Sgblack@eecs.umich.edu 'Port', 'VectorPort'] 8585240Sgblack@eecs.umich.edu 8595240Sgblack@eecs.umich.edu# see comment on imports at end of __init__.py. 8605240Sgblack@eecs.umich.edufrom SimObject import isSimObject, isSimObjectSequence, isSimObjectClass 8615240Sgblack@eecs.umich.eduimport proxy 8625240Sgblack@eecs.umich.eduimport objects 8635238Sgblack@eecs.umich.eduimport cc_main 8645332Sgblack@eecs.umich.edu