params.py revision 11498
15331Sgblack@eecs.umich.edu# Copyright (c) 2012-2014 ARM Limited 25331Sgblack@eecs.umich.edu# All rights reserved. 35331Sgblack@eecs.umich.edu# 45331Sgblack@eecs.umich.edu# The license below extends only to copyright in the software and shall 55331Sgblack@eecs.umich.edu# not be construed as granting a license to any other intellectual 65331Sgblack@eecs.umich.edu# property including but not limited to intellectual property relating 75331Sgblack@eecs.umich.edu# to a hardware implementation of the functionality of the software 85331Sgblack@eecs.umich.edu# licensed hereunder. You may use the software subject to the license 95331Sgblack@eecs.umich.edu# terms below provided that you ensure that this notice is replicated 105331Sgblack@eecs.umich.edu# unmodified and in its entirety in all distributions of the software, 115331Sgblack@eecs.umich.edu# modified or unmodified, in source code or in binary form. 125331Sgblack@eecs.umich.edu# 135331Sgblack@eecs.umich.edu# Copyright (c) 2004-2006 The Regents of The University of Michigan 145331Sgblack@eecs.umich.edu# Copyright (c) 2010-2011 Advanced Micro Devices, Inc. 155331Sgblack@eecs.umich.edu# All rights reserved. 165331Sgblack@eecs.umich.edu# 175331Sgblack@eecs.umich.edu# Redistribution and use in source and binary forms, with or without 185331Sgblack@eecs.umich.edu# modification, are permitted provided that the following conditions are 195331Sgblack@eecs.umich.edu# met: redistributions of source code must retain the above copyright 205331Sgblack@eecs.umich.edu# notice, this list of conditions and the following disclaimer; 215331Sgblack@eecs.umich.edu# redistributions in binary form must reproduce the above copyright 225331Sgblack@eecs.umich.edu# notice, this list of conditions and the following disclaimer in the 235331Sgblack@eecs.umich.edu# documentation and/or other materials provided with the distribution; 245331Sgblack@eecs.umich.edu# neither the name of the copyright holders nor the names of its 255331Sgblack@eecs.umich.edu# contributors may be used to endorse or promote products derived from 265331Sgblack@eecs.umich.edu# this software without specific prior written permission. 275331Sgblack@eecs.umich.edu# 285331Sgblack@eecs.umich.edu# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 295331Sgblack@eecs.umich.edu# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 304276Sgblack@eecs.umich.edu# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 314276Sgblack@eecs.umich.edu# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 324276Sgblack@eecs.umich.edu# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 334276Sgblack@eecs.umich.edu# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 344276Sgblack@eecs.umich.edu# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 354276Sgblack@eecs.umich.edu# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 364276Sgblack@eecs.umich.edu# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 374276Sgblack@eecs.umich.edu# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 384276Sgblack@eecs.umich.edu# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 394276Sgblack@eecs.umich.edu# 404276Sgblack@eecs.umich.edu# Authors: Steve Reinhardt 414276Sgblack@eecs.umich.edu# Nathan Binkert 424276Sgblack@eecs.umich.edu# Gabe Black 434276Sgblack@eecs.umich.edu# Andreas Hansson 444276Sgblack@eecs.umich.edu 454276Sgblack@eecs.umich.edu##################################################################### 464276Sgblack@eecs.umich.edu# 474276Sgblack@eecs.umich.edu# Parameter description classes 484276Sgblack@eecs.umich.edu# 494276Sgblack@eecs.umich.edu# The _params dictionary in each class maps parameter names to either 504276Sgblack@eecs.umich.edu# a Param or a VectorParam object. These objects contain the 514276Sgblack@eecs.umich.edu# parameter description string, the parameter type, and the default 524276Sgblack@eecs.umich.edu# value (if any). The convert() method on these objects is used to 534276Sgblack@eecs.umich.edu# force whatever value is assigned to the parameter to the appropriate 544276Sgblack@eecs.umich.edu# type. 554276Sgblack@eecs.umich.edu# 564276Sgblack@eecs.umich.edu# Note that the default values are loaded into the class's attribute 574276Sgblack@eecs.umich.edu# space when the parameter dictionary is initialized (in 584276Sgblack@eecs.umich.edu# MetaSimObject._new_param()); after that point they aren't used. 594276Sgblack@eecs.umich.edu# 604276Sgblack@eecs.umich.edu##################################################################### 614276Sgblack@eecs.umich.edu 624276Sgblack@eecs.umich.eduimport copy 634276Sgblack@eecs.umich.eduimport datetime 644276Sgblack@eecs.umich.eduimport re 654276Sgblack@eecs.umich.eduimport sys 664276Sgblack@eecs.umich.eduimport time 674276Sgblack@eecs.umich.eduimport math 684276Sgblack@eecs.umich.edu 694276Sgblack@eecs.umich.eduimport proxy 704276Sgblack@eecs.umich.eduimport ticks 714276Sgblack@eecs.umich.edufrom util import * 724276Sgblack@eecs.umich.edu 734276Sgblack@eecs.umich.edudef isSimObject(*args, **kwargs): 744276Sgblack@eecs.umich.edu return SimObject.isSimObject(*args, **kwargs) 754276Sgblack@eecs.umich.edu 764276Sgblack@eecs.umich.edudef isSimObjectSequence(*args, **kwargs): 774276Sgblack@eecs.umich.edu return SimObject.isSimObjectSequence(*args, **kwargs) 784276Sgblack@eecs.umich.edu 794276Sgblack@eecs.umich.edudef isSimObjectClass(*args, **kwargs): 804276Sgblack@eecs.umich.edu return SimObject.isSimObjectClass(*args, **kwargs) 814276Sgblack@eecs.umich.edu 824276Sgblack@eecs.umich.eduallParams = {} 834276Sgblack@eecs.umich.edu 844276Sgblack@eecs.umich.educlass MetaParamValue(type): 854276Sgblack@eecs.umich.edu def __new__(mcls, name, bases, dct): 864276Sgblack@eecs.umich.edu cls = super(MetaParamValue, mcls).__new__(mcls, name, bases, dct) 874276Sgblack@eecs.umich.edu assert name not in allParams 884276Sgblack@eecs.umich.edu allParams[name] = cls 894711Sgblack@eecs.umich.edu return cls 904276Sgblack@eecs.umich.edu 914276Sgblack@eecs.umich.edu 925238Sgblack@eecs.umich.edu# Dummy base class to identify types that are legitimate for SimObject 935238Sgblack@eecs.umich.edu# parameters. 945238Sgblack@eecs.umich.educlass ParamValue(object): 955238Sgblack@eecs.umich.edu __metaclass__ = MetaParamValue 965937Sgblack@eecs.umich.edu cmd_line_settable = False 975902Sgblack@eecs.umich.edu 985238Sgblack@eecs.umich.edu # Generate the code needed as a prerequisite for declaring a C++ 995238Sgblack@eecs.umich.edu # object of this type. Typically generates one or more #include 1005238Sgblack@eecs.umich.edu # statements. Used when declaring parameters of this type. 1015238Sgblack@eecs.umich.edu @classmethod 1025238Sgblack@eecs.umich.edu def cxx_predecls(cls, code): 1035238Sgblack@eecs.umich.edu pass 1045238Sgblack@eecs.umich.edu 1055238Sgblack@eecs.umich.edu # Generate the code needed as a prerequisite for including a 1065238Sgblack@eecs.umich.edu # reference to a C++ object of this type in a SWIG .i file. 1075238Sgblack@eecs.umich.edu # Typically generates one or more %import or %include statements. 1085238Sgblack@eecs.umich.edu @classmethod 1095238Sgblack@eecs.umich.edu def swig_predecls(cls, code): 1105238Sgblack@eecs.umich.edu pass 1115238Sgblack@eecs.umich.edu 1125238Sgblack@eecs.umich.edu # default for printing to .ini file is regular string conversion. 1135238Sgblack@eecs.umich.edu # will be overridden in some cases 1145238Sgblack@eecs.umich.edu def ini_str(self): 1155238Sgblack@eecs.umich.edu return str(self) 1165238Sgblack@eecs.umich.edu 1175238Sgblack@eecs.umich.edu # default for printing to .json file is regular string conversion. 1185238Sgblack@eecs.umich.edu # will be overridden in some cases, mostly to use native Python 1195238Sgblack@eecs.umich.edu # types where there are similar JSON types 1205238Sgblack@eecs.umich.edu def config_value(self): 1215238Sgblack@eecs.umich.edu return str(self) 1225238Sgblack@eecs.umich.edu 1235238Sgblack@eecs.umich.edu # Prerequisites for .ini parsing with cxx_ini_parse 1245238Sgblack@eecs.umich.edu @classmethod 1255238Sgblack@eecs.umich.edu def cxx_ini_predecls(cls, code): 1265238Sgblack@eecs.umich.edu pass 1275238Sgblack@eecs.umich.edu 1286055Sgblack@eecs.umich.edu # parse a .ini file entry for this param from string expression 1296054Sgblack@eecs.umich.edu # src into lvalue dest (of the param's C++ type) 1305238Sgblack@eecs.umich.edu @classmethod 1315683Sgblack@eecs.umich.edu def cxx_ini_parse(cls, code, src, dest, ret): 1325238Sgblack@eecs.umich.edu code('// Unhandled param type: %s' % cls.__name__) 1335238Sgblack@eecs.umich.edu code('%s false;' % ret) 1345238Sgblack@eecs.umich.edu 1355238Sgblack@eecs.umich.edu # allows us to blithely call unproxy() on things without checking 1365238Sgblack@eecs.umich.edu # if they're really proxies or not 1375238Sgblack@eecs.umich.edu def unproxy(self, base): 1385238Sgblack@eecs.umich.edu return self 1395238Sgblack@eecs.umich.edu 1405291Sgblack@eecs.umich.edu # Produce a human readable version of the stored value 1415291Sgblack@eecs.umich.edu def pretty_print(self, value): 1425291Sgblack@eecs.umich.edu return str(value) 1435291Sgblack@eecs.umich.edu 1445291Sgblack@eecs.umich.edu# Regular parameter description. 1455291Sgblack@eecs.umich.educlass ParamDesc(object): 1465291Sgblack@eecs.umich.edu def __init__(self, ptype_str, ptype, *args, **kwargs): 1475291Sgblack@eecs.umich.edu self.ptype_str = ptype_str 1485291Sgblack@eecs.umich.edu # remember ptype only if it is provided 1495292Sgblack@eecs.umich.edu if ptype != None: 1505292Sgblack@eecs.umich.edu self.ptype = ptype 1515292Sgblack@eecs.umich.edu 1525292Sgblack@eecs.umich.edu if args: 1535292Sgblack@eecs.umich.edu if len(args) == 1: 1545292Sgblack@eecs.umich.edu self.desc = args[0] 1555292Sgblack@eecs.umich.edu elif len(args) == 2: 1565292Sgblack@eecs.umich.edu self.default = args[0] 1575292Sgblack@eecs.umich.edu self.desc = args[1] 1586055Sgblack@eecs.umich.edu else: 1596054Sgblack@eecs.umich.edu raise TypeError, 'too many arguments' 1605359Sgblack@eecs.umich.edu 1615238Sgblack@eecs.umich.edu if kwargs.has_key('desc'): 1625238Sgblack@eecs.umich.edu assert(not hasattr(self, 'desc')) 1635238Sgblack@eecs.umich.edu self.desc = kwargs['desc'] 1644276Sgblack@eecs.umich.edu del kwargs['desc'] 1654276Sgblack@eecs.umich.edu 1665789Sgblack@eecs.umich.edu if kwargs.has_key('default'): 1675789Sgblack@eecs.umich.edu assert(not hasattr(self, 'default')) 1685789Sgblack@eecs.umich.edu self.default = kwargs['default'] 1695789Sgblack@eecs.umich.edu del kwargs['default'] 1705789Sgblack@eecs.umich.edu 1715789Sgblack@eecs.umich.edu if kwargs: 1725789Sgblack@eecs.umich.edu raise TypeError, 'extra unknown kwargs %s' % kwargs 1735789Sgblack@eecs.umich.edu 1745789Sgblack@eecs.umich.edu if not hasattr(self, 'desc'): 1755789Sgblack@eecs.umich.edu raise TypeError, 'desc attribute missing' 1765789Sgblack@eecs.umich.edu 1775789Sgblack@eecs.umich.edu def __getattr__(self, attr): 1785789Sgblack@eecs.umich.edu if attr == 'ptype': 1795789Sgblack@eecs.umich.edu ptype = SimObject.allClasses[self.ptype_str] 1805789Sgblack@eecs.umich.edu assert isSimObjectClass(ptype) 1815789Sgblack@eecs.umich.edu self.ptype = ptype 1825789Sgblack@eecs.umich.edu return ptype 1835789Sgblack@eecs.umich.edu 1845789Sgblack@eecs.umich.edu raise AttributeError, "'%s' object has no attribute '%s'" % \ 1855789Sgblack@eecs.umich.edu (type(self).__name__, attr) 1865789Sgblack@eecs.umich.edu 1875789Sgblack@eecs.umich.edu def example_str(self): 1885789Sgblack@eecs.umich.edu if hasattr(self.ptype, "ex_str"): 1895789Sgblack@eecs.umich.edu return self.ptype.ex_str 1905789Sgblack@eecs.umich.edu else: 1915789Sgblack@eecs.umich.edu return self.ptype_str 1925789Sgblack@eecs.umich.edu 1935789Sgblack@eecs.umich.edu # Is the param available to be exposed on the command line 1945789Sgblack@eecs.umich.edu def isCmdLineSettable(self): 1955789Sgblack@eecs.umich.edu if hasattr(self.ptype, "cmd_line_settable"): 1965789Sgblack@eecs.umich.edu return self.ptype.cmd_line_settable 1975789Sgblack@eecs.umich.edu else: 1985789Sgblack@eecs.umich.edu return False 1995789Sgblack@eecs.umich.edu 2005789Sgblack@eecs.umich.edu def convert(self, value): 2015789Sgblack@eecs.umich.edu if isinstance(value, proxy.BaseProxy): 2025789Sgblack@eecs.umich.edu value.set_param_desc(self) 2035789Sgblack@eecs.umich.edu return value 2045789Sgblack@eecs.umich.edu if not hasattr(self, 'ptype') and isNullPointer(value): 2055789Sgblack@eecs.umich.edu # deferred evaluation of SimObject; continue to defer if 2065789Sgblack@eecs.umich.edu # we're just assigning a null pointer 2075789Sgblack@eecs.umich.edu return value 2085789Sgblack@eecs.umich.edu if isinstance(value, self.ptype): 2095789Sgblack@eecs.umich.edu return value 2105789Sgblack@eecs.umich.edu if isNullPointer(value) and isSimObjectClass(self.ptype): 2115789Sgblack@eecs.umich.edu return value 2125789Sgblack@eecs.umich.edu return self.ptype(value) 2135789Sgblack@eecs.umich.edu 2145789Sgblack@eecs.umich.edu def pretty_print(self, value): 2155789Sgblack@eecs.umich.edu if isinstance(value, proxy.BaseProxy): 2165789Sgblack@eecs.umich.edu return str(value) 2175789Sgblack@eecs.umich.edu if isNullPointer(value): 2185789Sgblack@eecs.umich.edu return NULL 2195789Sgblack@eecs.umich.edu return self.ptype(value).pretty_print(value) 2205789Sgblack@eecs.umich.edu 2215789Sgblack@eecs.umich.edu def cxx_predecls(self, code): 2225789Sgblack@eecs.umich.edu code('#include <cstddef>') 2235789Sgblack@eecs.umich.edu self.ptype.cxx_predecls(code) 2245789Sgblack@eecs.umich.edu 2255789Sgblack@eecs.umich.edu def swig_predecls(self, code): 2265789Sgblack@eecs.umich.edu self.ptype.swig_predecls(code) 2275789Sgblack@eecs.umich.edu 2285789Sgblack@eecs.umich.edu def cxx_decl(self, code): 2295789Sgblack@eecs.umich.edu code('${{self.ptype.cxx_type}} ${{self.name}};') 2305789Sgblack@eecs.umich.edu 2315789Sgblack@eecs.umich.edu# Vector-valued parameter description. Just like ParamDesc, except 2325789Sgblack@eecs.umich.edu# that the value is a vector (list) of the specified type instead of a 2335789Sgblack@eecs.umich.edu# single value. 2345789Sgblack@eecs.umich.edu 2355789Sgblack@eecs.umich.educlass VectorParamValue(list): 2365789Sgblack@eecs.umich.edu __metaclass__ = MetaParamValue 2375789Sgblack@eecs.umich.edu def __setattr__(self, attr, value): 2385789Sgblack@eecs.umich.edu raise AttributeError, \ 2395789Sgblack@eecs.umich.edu "Not allowed to set %s on '%s'" % (attr, type(self).__name__) 2405789Sgblack@eecs.umich.edu 2415789Sgblack@eecs.umich.edu def config_value(self): 2425789Sgblack@eecs.umich.edu return [v.config_value() for v in self] 2435789Sgblack@eecs.umich.edu 2445789Sgblack@eecs.umich.edu def ini_str(self): 2455789Sgblack@eecs.umich.edu return ' '.join([v.ini_str() for v in self]) 2465789Sgblack@eecs.umich.edu 2475789Sgblack@eecs.umich.edu def getValue(self): 2485789Sgblack@eecs.umich.edu return [ v.getValue() for v in self ] 2495789Sgblack@eecs.umich.edu 2505789Sgblack@eecs.umich.edu def unproxy(self, base): 2515789Sgblack@eecs.umich.edu if len(self) == 1 and isinstance(self[0], proxy.AllProxy): 2525789Sgblack@eecs.umich.edu return self[0].unproxy(base) 2535789Sgblack@eecs.umich.edu else: 2545789Sgblack@eecs.umich.edu return [v.unproxy(base) for v in self] 2555789Sgblack@eecs.umich.edu 2564712Sgblack@eecs.umich.educlass SimObjectVector(VectorParamValue): 2575907Sgblack@eecs.umich.edu # support clone operation 2585907Sgblack@eecs.umich.edu def __call__(self, **kwargs): 2595907Sgblack@eecs.umich.edu return SimObjectVector([v(**kwargs) for v in self]) 2605907Sgblack@eecs.umich.edu 2615907Sgblack@eecs.umich.edu def clear_parent(self, old_parent): 2625907Sgblack@eecs.umich.edu for v in self: 2635907Sgblack@eecs.umich.edu v.clear_parent(old_parent) 2644712Sgblack@eecs.umich.edu 2655659Sgblack@eecs.umich.edu def set_parent(self, parent, name): 2664712Sgblack@eecs.umich.edu if len(self) == 1: 2675933Sgblack@eecs.umich.edu self[0].set_parent(parent, name) 2685908Sgblack@eecs.umich.edu else: 2695908Sgblack@eecs.umich.edu width = int(math.ceil(math.log(len(self))/math.log(10))) 2705908Sgblack@eecs.umich.edu for i,v in enumerate(self): 2715908Sgblack@eecs.umich.edu v.set_parent(parent, "%s%0*d" % (name, width, i)) 2725908Sgblack@eecs.umich.edu 2735908Sgblack@eecs.umich.edu def has_parent(self): 2745908Sgblack@eecs.umich.edu return reduce(lambda x,y: x and y, [v.has_parent() for v in self]) 2755908Sgblack@eecs.umich.edu 2765908Sgblack@eecs.umich.edu # return 'cpu0 cpu1' etc. for print_ini() 2774276Sgblack@eecs.umich.edu def get_name(self): 2784276Sgblack@eecs.umich.edu return ' '.join([v._name for v in self]) 2794712Sgblack@eecs.umich.edu 2804712Sgblack@eecs.umich.edu # By iterating through the constituent members of the vector here 2814730Sgblack@eecs.umich.edu # we can nicely handle iterating over all a SimObject's children 2824760Sgblack@eecs.umich.edu # without having to provide lots of special functions on 2834730Sgblack@eecs.umich.edu # SimObjectVector directly. 2845920Sgblack@eecs.umich.edu def descendants(self): 2855422Sgblack@eecs.umich.edu for v in self: 2865422Sgblack@eecs.umich.edu for obj in v.descendants(): 2874276Sgblack@eecs.umich.edu yield obj 2886576Sgblack@eecs.umich.edu 2896576Sgblack@eecs.umich.edu def get_config_as_dict(self): 2906576Sgblack@eecs.umich.edu a = [] 2916576Sgblack@eecs.umich.edu for v in self: 2926576Sgblack@eecs.umich.edu a.append(v.get_config_as_dict()) 2936576Sgblack@eecs.umich.edu return a 2946576Sgblack@eecs.umich.edu 2956576Sgblack@eecs.umich.edu # If we are replacing an item in the vector, make sure to set the 2966576Sgblack@eecs.umich.edu # parent reference of the new SimObject to be the same as the parent 2976576Sgblack@eecs.umich.edu # of the SimObject being replaced. Useful to have if we created 2986576Sgblack@eecs.umich.edu # a SimObjectVector of temporary objects that will be modified later in 2996576Sgblack@eecs.umich.edu # configuration scripts. 3006576Sgblack@eecs.umich.edu def __setitem__(self, key, value): 3016576Sgblack@eecs.umich.edu val = self[key] 3026576Sgblack@eecs.umich.edu if value.has_parent(): 3036576Sgblack@eecs.umich.edu warn("SimObject %s already has a parent" % value.get_name() +\ 3046576Sgblack@eecs.umich.edu " that is being overwritten by a SimObjectVector") 3056576Sgblack@eecs.umich.edu value.set_parent(val.get_parent(), val._name) 3065020Sgblack@eecs.umich.edu super(SimObjectVector, self).__setitem__(key, value) 3076576Sgblack@eecs.umich.edu 3086576Sgblack@eecs.umich.edu # Enumerate the params of each member of the SimObject vector. Creates 3096600Sgblack@eecs.umich.edu # strings that will allow indexing into the vector by the python code and 3106600Sgblack@eecs.umich.edu # allow it to be specified on the command line. 3116576Sgblack@eecs.umich.edu def enumerateParams(self, flags_dict = {}, 3126576Sgblack@eecs.umich.edu cmd_line_str = "", 3136576Sgblack@eecs.umich.edu access_str = ""): 3145020Sgblack@eecs.umich.edu if hasattr(self, "_paramEnumed"): 3156576Sgblack@eecs.umich.edu print "Cycle detected enumerating params at %s?!" % (cmd_line_str) 3166576Sgblack@eecs.umich.edu else: 3176576Sgblack@eecs.umich.edu x = 0 3186576Sgblack@eecs.umich.edu for vals in self: 3196576Sgblack@eecs.umich.edu # Each entry in the SimObjectVector should be an 3206576Sgblack@eecs.umich.edu # instance of a SimObject 3216576Sgblack@eecs.umich.edu flags_dict = vals.enumerateParams(flags_dict, 3226576Sgblack@eecs.umich.edu cmd_line_str + "%d." % x, 3236576Sgblack@eecs.umich.edu access_str + "[%d]." % x) 3246576Sgblack@eecs.umich.edu x = x + 1 3256576Sgblack@eecs.umich.edu 3266576Sgblack@eecs.umich.edu return flags_dict 3276576Sgblack@eecs.umich.edu 3286576Sgblack@eecs.umich.educlass VectorParamDesc(ParamDesc): 3296576Sgblack@eecs.umich.edu # Convert assigned value to appropriate type. If the RHS is not a 3306576Sgblack@eecs.umich.edu # list or tuple, it generates a single-element list. 3316576Sgblack@eecs.umich.edu def convert(self, value): 3326576Sgblack@eecs.umich.edu if isinstance(value, (list, tuple)): 3336576Sgblack@eecs.umich.edu # list: coerce each element into new list 3344760Sgblack@eecs.umich.edu tmp_list = [ ParamDesc.convert(self, v) for v in value ] 3356576Sgblack@eecs.umich.edu elif isinstance(value, str): 3366576Sgblack@eecs.umich.edu # If input is a csv string 3376576Sgblack@eecs.umich.edu tmp_list = [ ParamDesc.convert(self, v) \ 3386576Sgblack@eecs.umich.edu for v in value.strip('[').strip(']').split(',') ] 3396576Sgblack@eecs.umich.edu else: 3406576Sgblack@eecs.umich.edu # singleton: coerce to a single-element list 3416576Sgblack@eecs.umich.edu tmp_list = [ ParamDesc.convert(self, value) ] 3426576Sgblack@eecs.umich.edu 3436576Sgblack@eecs.umich.edu if isSimObjectSequence(tmp_list): 3446576Sgblack@eecs.umich.edu return SimObjectVector(tmp_list) 3456576Sgblack@eecs.umich.edu else: 3466576Sgblack@eecs.umich.edu return VectorParamValue(tmp_list) 3476576Sgblack@eecs.umich.edu 3486576Sgblack@eecs.umich.edu # Produce a human readable example string that describes 3496576Sgblack@eecs.umich.edu # how to set this vector parameter in the absence of a default 3506576Sgblack@eecs.umich.edu # value. 3514760Sgblack@eecs.umich.edu def example_str(self): 3526576Sgblack@eecs.umich.edu s = super(VectorParamDesc, self).example_str() 3536576Sgblack@eecs.umich.edu help_str = "[" + s + "," + s + ", ...]" 3546576Sgblack@eecs.umich.edu return help_str 3556576Sgblack@eecs.umich.edu 3566576Sgblack@eecs.umich.edu # Produce a human readable representation of the value of this vector param. 3576576Sgblack@eecs.umich.edu def pretty_print(self, value): 3586576Sgblack@eecs.umich.edu if isinstance(value, (list, tuple)): 3596576Sgblack@eecs.umich.edu tmp_list = [ ParamDesc.pretty_print(self, v) for v in value ] 3606576Sgblack@eecs.umich.edu elif isinstance(value, str): 3616576Sgblack@eecs.umich.edu tmp_list = [ ParamDesc.pretty_print(self, v) for v in value.split(',') ] 3626576Sgblack@eecs.umich.edu else: 3636576Sgblack@eecs.umich.edu tmp_list = [ ParamDesc.pretty_print(self, value) ] 3646576Sgblack@eecs.umich.edu 3656576Sgblack@eecs.umich.edu return tmp_list 3666576Sgblack@eecs.umich.edu 3676576Sgblack@eecs.umich.edu # This is a helper function for the new config system 3686576Sgblack@eecs.umich.edu def __call__(self, value): 3694760Sgblack@eecs.umich.edu if isinstance(value, (list, tuple)): 3704276Sgblack@eecs.umich.edu # list: coerce each element into new list 3715020Sgblack@eecs.umich.edu tmp_list = [ ParamDesc.convert(self, v) for v in value ] 3725020Sgblack@eecs.umich.edu elif isinstance(value, str): 3735020Sgblack@eecs.umich.edu # If input is a csv string 3745031Sgblack@eecs.umich.edu tmp_list = [ ParamDesc.convert(self, v) \ 3755031Sgblack@eecs.umich.edu for v in value.strip('[').strip(']').split(',') ] 3765031Sgblack@eecs.umich.edu else: 3775031Sgblack@eecs.umich.edu # singleton: coerce to a single-element list 3786563Sgblack@eecs.umich.edu tmp_list = [ ParamDesc.convert(self, value) ] 3795020Sgblack@eecs.umich.edu 3806606Sgblack@eecs.umich.edu return VectorParamValue(tmp_list) 3816606Sgblack@eecs.umich.edu 3826602Sgblack@eecs.umich.edu def swig_module_name(self): 3836602Sgblack@eecs.umich.edu return "%s_vector" % self.ptype_str 3845020Sgblack@eecs.umich.edu 3855020Sgblack@eecs.umich.edu def swig_predecls(self, code): 3865020Sgblack@eecs.umich.edu code('%import "${{self.swig_module_name()}}.i"') 3876563Sgblack@eecs.umich.edu 3886606Sgblack@eecs.umich.edu def swig_decl(self, code): 3896606Sgblack@eecs.umich.edu code('%module(package="m5.internal") ${{self.swig_module_name()}}') 3905020Sgblack@eecs.umich.edu code('%{') 3915020Sgblack@eecs.umich.edu self.ptype.cxx_predecls(code) 3925020Sgblack@eecs.umich.edu code('%}') 3935020Sgblack@eecs.umich.edu code() 3946564Sgblack@eecs.umich.edu # Make sure the SWIGPY_SLICE_ARG is defined through this inclusion 3956564Sgblack@eecs.umich.edu code('%include "std_container.i"') 3966563Sgblack@eecs.umich.edu code() 3975020Sgblack@eecs.umich.edu self.ptype.swig_predecls(code) 3986606Sgblack@eecs.umich.edu code() 3996606Sgblack@eecs.umich.edu code('%include "std_vector.i"') 4005058Sgblack@eecs.umich.edu code() 4016602Sgblack@eecs.umich.edu 4025020Sgblack@eecs.umich.edu ptype = self.ptype_str 4035020Sgblack@eecs.umich.edu cxx_type = self.ptype.cxx_type 4045020Sgblack@eecs.umich.edu 4055046Sgblack@eecs.umich.edu code('%template(vector_$ptype) std::vector< $cxx_type >;') 4065046Sgblack@eecs.umich.edu 4075046Sgblack@eecs.umich.edu def cxx_predecls(self, code): 4085046Sgblack@eecs.umich.edu code('#include <vector>') 4096606Sgblack@eecs.umich.edu self.ptype.cxx_predecls(code) 4105020Sgblack@eecs.umich.edu 4115020Sgblack@eecs.umich.edu def cxx_decl(self, code): 4125020Sgblack@eecs.umich.edu code('std::vector< ${{self.ptype.cxx_type}} > ${{self.name}};') 4134276Sgblack@eecs.umich.edu 4144276Sgblack@eecs.umich.educlass ParamFactory(object): 4155149Sgblack@eecs.umich.edu def __init__(self, param_desc_class, ptype_str = None): 4165409Sgblack@eecs.umich.edu self.param_desc_class = param_desc_class 4175149Sgblack@eecs.umich.edu self.ptype_str = ptype_str 4184712Sgblack@eecs.umich.edu 4195972Sgblack@eecs.umich.edu def __getattr__(self, attr): 4204712Sgblack@eecs.umich.edu if self.ptype_str: 4215972Sgblack@eecs.umich.edu attr = self.ptype_str + '.' + attr 4225972Sgblack@eecs.umich.edu return ParamFactory(self.param_desc_class, attr) 4235972Sgblack@eecs.umich.edu 4244712Sgblack@eecs.umich.edu # E.g., Param.Int(5, "number of widgets") 4254730Sgblack@eecs.umich.edu def __call__(self, *args, **kwargs): 4264712Sgblack@eecs.umich.edu ptype = None 4274276Sgblack@eecs.umich.edu try: 4284276Sgblack@eecs.umich.edu ptype = allParams[self.ptype_str] 4294712Sgblack@eecs.umich.edu except KeyError: 4304712Sgblack@eecs.umich.edu # if name isn't defined yet, assume it's a SimObject, and 4314712Sgblack@eecs.umich.edu # try to resolve it later 4324712Sgblack@eecs.umich.edu pass 4334712Sgblack@eecs.umich.edu return self.param_desc_class(self.ptype_str, ptype, *args, **kwargs) 4344712Sgblack@eecs.umich.edu 4354712Sgblack@eecs.umich.eduParam = ParamFactory(ParamDesc) 4364712Sgblack@eecs.umich.eduVectorParam = ParamFactory(VectorParamDesc) 4374276Sgblack@eecs.umich.edu 4384760Sgblack@eecs.umich.edu##################################################################### 4394760Sgblack@eecs.umich.edu# 4404760Sgblack@eecs.umich.edu# Parameter Types 4414760Sgblack@eecs.umich.edu# 4424760Sgblack@eecs.umich.edu# Though native Python types could be used to specify parameter types 4434760Sgblack@eecs.umich.edu# (the 'ptype' field of the Param and VectorParam classes), it's more 4444760Sgblack@eecs.umich.edu# flexible to define our own set of types. This gives us more control 4454760Sgblack@eecs.umich.edu# over how Python expressions are converted to values (via the 4464760Sgblack@eecs.umich.edu# __init__() constructor) and how these values are printed out (via 4474760Sgblack@eecs.umich.edu# the __str__() conversion method). 4484760Sgblack@eecs.umich.edu# 4494760Sgblack@eecs.umich.edu##################################################################### 4504760Sgblack@eecs.umich.edu 4514760Sgblack@eecs.umich.edu# String-valued parameter. Just mixin the ParamValue class with the 4524760Sgblack@eecs.umich.edu# built-in str class. 4534760Sgblack@eecs.umich.educlass String(ParamValue,str): 4544760Sgblack@eecs.umich.edu cxx_type = 'std::string' 4554760Sgblack@eecs.umich.edu cmd_line_settable = True 4564760Sgblack@eecs.umich.edu 4574760Sgblack@eecs.umich.edu @classmethod 4584760Sgblack@eecs.umich.edu def cxx_predecls(self, code): 4596576Sgblack@eecs.umich.edu code('#include <string>') 4606576Sgblack@eecs.umich.edu 4616576Sgblack@eecs.umich.edu @classmethod 4626593Sgblack@eecs.umich.edu def swig_predecls(cls, code): 4636576Sgblack@eecs.umich.edu code('%include "std_string.i"') 4646576Sgblack@eecs.umich.edu 4656576Sgblack@eecs.umich.edu def __call__(self, value): 4666576Sgblack@eecs.umich.edu self = value 4676576Sgblack@eecs.umich.edu return value 4686576Sgblack@eecs.umich.edu 4696576Sgblack@eecs.umich.edu @classmethod 4706576Sgblack@eecs.umich.edu def cxx_ini_parse(self, code, src, dest, ret): 4716576Sgblack@eecs.umich.edu code('%s = %s;' % (dest, src)) 4726576Sgblack@eecs.umich.edu code('%s true;' % ret) 4736576Sgblack@eecs.umich.edu 4746576Sgblack@eecs.umich.edu def getValue(self): 4756576Sgblack@eecs.umich.edu return self 4766576Sgblack@eecs.umich.edu 4776576Sgblack@eecs.umich.edu# superclass for "numeric" parameter values, to emulate math 4786576Sgblack@eecs.umich.edu# operations in a type-safe way. e.g., a Latency times an int returns 4796576Sgblack@eecs.umich.edu# a new Latency object. 4806593Sgblack@eecs.umich.educlass NumericParamValue(ParamValue): 4816576Sgblack@eecs.umich.edu def __str__(self): 4826576Sgblack@eecs.umich.edu return str(self.value) 4836576Sgblack@eecs.umich.edu 4846576Sgblack@eecs.umich.edu def __float__(self): 4856576Sgblack@eecs.umich.edu return float(self.value) 4866576Sgblack@eecs.umich.edu 4876576Sgblack@eecs.umich.edu def __long__(self): 4886576Sgblack@eecs.umich.edu return long(self.value) 4896576Sgblack@eecs.umich.edu 4905059Sgblack@eecs.umich.edu def __int__(self): 4915059Sgblack@eecs.umich.edu return int(self.value) 4926576Sgblack@eecs.umich.edu 4935059Sgblack@eecs.umich.edu # hook for bounds checking 4945059Sgblack@eecs.umich.edu def _check(self): 4955059Sgblack@eecs.umich.edu return 4965020Sgblack@eecs.umich.edu 4976576Sgblack@eecs.umich.edu def __mul__(self, other): 4986576Sgblack@eecs.umich.edu newobj = self.__class__(self) 4996576Sgblack@eecs.umich.edu newobj.value *= other 5006576Sgblack@eecs.umich.edu newobj._check() 5016576Sgblack@eecs.umich.edu return newobj 5026576Sgblack@eecs.umich.edu 5036576Sgblack@eecs.umich.edu __rmul__ = __mul__ 5046576Sgblack@eecs.umich.edu 5056576Sgblack@eecs.umich.edu def __div__(self, other): 5066576Sgblack@eecs.umich.edu newobj = self.__class__(self) 5076576Sgblack@eecs.umich.edu newobj.value /= other 5086576Sgblack@eecs.umich.edu newobj._check() 5096576Sgblack@eecs.umich.edu return newobj 5106576Sgblack@eecs.umich.edu 5116576Sgblack@eecs.umich.edu def __sub__(self, other): 5126576Sgblack@eecs.umich.edu newobj = self.__class__(self) 5136576Sgblack@eecs.umich.edu newobj.value -= other 5146606Sgblack@eecs.umich.edu newobj._check() 5156576Sgblack@eecs.umich.edu return newobj 5166576Sgblack@eecs.umich.edu 5176576Sgblack@eecs.umich.edu def config_value(self): 5186576Sgblack@eecs.umich.edu return self.value 5196576Sgblack@eecs.umich.edu 5206576Sgblack@eecs.umich.edu @classmethod 5216576Sgblack@eecs.umich.edu def cxx_ini_predecls(cls, code): 5226576Sgblack@eecs.umich.edu # Assume that base/str.hh will be included anyway 5236576Sgblack@eecs.umich.edu # code('#include "base/str.hh"') 5246576Sgblack@eecs.umich.edu pass 5256606Sgblack@eecs.umich.edu 5266576Sgblack@eecs.umich.edu # The default for parsing PODs from an .ini entry is to extract from an 5276576Sgblack@eecs.umich.edu # istringstream and let overloading choose the right type according to 5286576Sgblack@eecs.umich.edu # the dest type. 5296576Sgblack@eecs.umich.edu @classmethod 5306576Sgblack@eecs.umich.edu def cxx_ini_parse(self, code, src, dest, ret): 5316576Sgblack@eecs.umich.edu code('%s to_number(%s, %s);' % (ret, src, dest)) 5326576Sgblack@eecs.umich.edu 5336576Sgblack@eecs.umich.edu# Metaclass for bounds-checked integer parameters. See CheckedInt. 5346576Sgblack@eecs.umich.educlass CheckedIntType(MetaParamValue): 5356576Sgblack@eecs.umich.edu def __init__(cls, name, bases, dict): 5366576Sgblack@eecs.umich.edu super(CheckedIntType, cls).__init__(name, bases, dict) 5376576Sgblack@eecs.umich.edu 5386576Sgblack@eecs.umich.edu # CheckedInt is an abstract base class, so we actually don't 5396576Sgblack@eecs.umich.edu # want to do any processing on it... the rest of this code is 5406576Sgblack@eecs.umich.edu # just for classes that derive from CheckedInt. 5416576Sgblack@eecs.umich.edu if name == 'CheckedInt': 5426576Sgblack@eecs.umich.edu return 5435020Sgblack@eecs.umich.edu 5446576Sgblack@eecs.umich.edu if not (hasattr(cls, 'min') and hasattr(cls, 'max')): 5456576Sgblack@eecs.umich.edu if not (hasattr(cls, 'size') and hasattr(cls, 'unsigned')): 5466576Sgblack@eecs.umich.edu panic("CheckedInt subclass %s must define either\n" \ 5476576Sgblack@eecs.umich.edu " 'min' and 'max' or 'size' and 'unsigned'\n", 5486576Sgblack@eecs.umich.edu name); 5496576Sgblack@eecs.umich.edu if cls.unsigned: 5506576Sgblack@eecs.umich.edu cls.min = 0 5516576Sgblack@eecs.umich.edu cls.max = 2 ** cls.size - 1 5526576Sgblack@eecs.umich.edu else: 5536576Sgblack@eecs.umich.edu cls.min = -(2 ** (cls.size - 1)) 5546576Sgblack@eecs.umich.edu cls.max = (2 ** (cls.size - 1)) - 1 5556576Sgblack@eecs.umich.edu 5566576Sgblack@eecs.umich.edu# Abstract superclass for bounds-checked integer parameters. This 5576576Sgblack@eecs.umich.edu# class is subclassed to generate parameter classes with specific 5586576Sgblack@eecs.umich.edu# bounds. Initialization of the min and max bounds is done in the 5596576Sgblack@eecs.umich.edu# metaclass CheckedIntType.__init__. 5606576Sgblack@eecs.umich.educlass CheckedInt(NumericParamValue): 5616576Sgblack@eecs.umich.edu __metaclass__ = CheckedIntType 5626576Sgblack@eecs.umich.edu cmd_line_settable = True 5636576Sgblack@eecs.umich.edu 5646576Sgblack@eecs.umich.edu def _check(self): 5656576Sgblack@eecs.umich.edu if not self.min <= self.value <= self.max: 5666576Sgblack@eecs.umich.edu raise TypeError, 'Integer param out of bounds %d < %d < %d' % \ 5676576Sgblack@eecs.umich.edu (self.min, self.value, self.max) 5685020Sgblack@eecs.umich.edu 5696576Sgblack@eecs.umich.edu def __init__(self, value): 5706576Sgblack@eecs.umich.edu if isinstance(value, str): 5716576Sgblack@eecs.umich.edu self.value = convert.toInteger(value) 5726576Sgblack@eecs.umich.edu elif isinstance(value, (int, long, float, NumericParamValue)): 5736576Sgblack@eecs.umich.edu self.value = long(value) 5746576Sgblack@eecs.umich.edu else: 5756576Sgblack@eecs.umich.edu raise TypeError, "Can't convert object of type %s to CheckedInt" \ 5766576Sgblack@eecs.umich.edu % type(value).__name__ 5776576Sgblack@eecs.umich.edu self._check() 5786576Sgblack@eecs.umich.edu 5796576Sgblack@eecs.umich.edu def __call__(self, value): 5806576Sgblack@eecs.umich.edu self.__init__(value) 5816576Sgblack@eecs.umich.edu return value 5826576Sgblack@eecs.umich.edu 5836576Sgblack@eecs.umich.edu @classmethod 5846576Sgblack@eecs.umich.edu def cxx_predecls(cls, code): 5856576Sgblack@eecs.umich.edu # most derived types require this, so we just do it here once 5866576Sgblack@eecs.umich.edu code('#include "base/types.hh"') 5876576Sgblack@eecs.umich.edu 5886576Sgblack@eecs.umich.edu @classmethod 5896576Sgblack@eecs.umich.edu def swig_predecls(cls, code): 5906576Sgblack@eecs.umich.edu # most derived types require this, so we just do it here once 5916576Sgblack@eecs.umich.edu code('%import "stdint.i"') 5926576Sgblack@eecs.umich.edu code('%import "base/types.hh"') 5936576Sgblack@eecs.umich.edu 5946576Sgblack@eecs.umich.edu def getValue(self): 5956576Sgblack@eecs.umich.edu return long(self.value) 5966576Sgblack@eecs.umich.edu 5975020Sgblack@eecs.umich.educlass Int(CheckedInt): cxx_type = 'int'; size = 32; unsigned = False 5986584Sgblack@eecs.umich.educlass Unsigned(CheckedInt): cxx_type = 'unsigned'; size = 32; unsigned = True 5996584Sgblack@eecs.umich.edu 6006584Sgblack@eecs.umich.educlass Int8(CheckedInt): cxx_type = 'int8_t'; size = 8; unsigned = False 6016597Sgblack@eecs.umich.educlass UInt8(CheckedInt): cxx_type = 'uint8_t'; size = 8; unsigned = True 6026584Sgblack@eecs.umich.educlass Int16(CheckedInt): cxx_type = 'int16_t'; size = 16; unsigned = False 6036584Sgblack@eecs.umich.educlass UInt16(CheckedInt): cxx_type = 'uint16_t'; size = 16; unsigned = True 6046584Sgblack@eecs.umich.educlass Int32(CheckedInt): cxx_type = 'int32_t'; size = 32; unsigned = False 6056584Sgblack@eecs.umich.educlass UInt32(CheckedInt): cxx_type = 'uint32_t'; size = 32; unsigned = True 6066584Sgblack@eecs.umich.educlass Int64(CheckedInt): cxx_type = 'int64_t'; size = 64; unsigned = False 6076584Sgblack@eecs.umich.educlass UInt64(CheckedInt): cxx_type = 'uint64_t'; size = 64; unsigned = True 6086584Sgblack@eecs.umich.edu 6096584Sgblack@eecs.umich.educlass Counter(CheckedInt): cxx_type = 'Counter'; size = 64; unsigned = True 6106584Sgblack@eecs.umich.educlass Tick(CheckedInt): cxx_type = 'Tick'; size = 64; unsigned = True 6116584Sgblack@eecs.umich.educlass TcpPort(CheckedInt): cxx_type = 'uint16_t'; size = 16; unsigned = True 6126584Sgblack@eecs.umich.educlass UdpPort(CheckedInt): cxx_type = 'uint16_t'; size = 16; unsigned = True 6136584Sgblack@eecs.umich.edu 6146584Sgblack@eecs.umich.educlass Percent(CheckedInt): cxx_type = 'int'; min = 0; max = 100 6156584Sgblack@eecs.umich.edu 6166584Sgblack@eecs.umich.educlass Cycles(CheckedInt): 6175238Sgblack@eecs.umich.edu cxx_type = 'Cycles' 6186584Sgblack@eecs.umich.edu size = 64 6196584Sgblack@eecs.umich.edu unsigned = True 6206584Sgblack@eecs.umich.edu 6216584Sgblack@eecs.umich.edu def getValue(self): 6226584Sgblack@eecs.umich.edu from m5.internal.core import Cycles 6236584Sgblack@eecs.umich.edu return Cycles(self.value) 6246584Sgblack@eecs.umich.edu 6256584Sgblack@eecs.umich.edu @classmethod 6266584Sgblack@eecs.umich.edu def cxx_ini_predecls(cls, code): 6276584Sgblack@eecs.umich.edu # Assume that base/str.hh will be included anyway 6286584Sgblack@eecs.umich.edu # code('#include "base/str.hh"') 6296584Sgblack@eecs.umich.edu pass 6306584Sgblack@eecs.umich.edu 6316584Sgblack@eecs.umich.edu @classmethod 6326584Sgblack@eecs.umich.edu def cxx_ini_parse(cls, code, src, dest, ret): 6335238Sgblack@eecs.umich.edu code('uint64_t _temp;') 6346584Sgblack@eecs.umich.edu code('bool _ret = to_number(%s, _temp);' % src) 6356584Sgblack@eecs.umich.edu code('if (_ret)') 6366584Sgblack@eecs.umich.edu code(' %s = Cycles(_temp);' % dest) 6376584Sgblack@eecs.umich.edu code('%s _ret;' % ret) 6386584Sgblack@eecs.umich.edu 6396584Sgblack@eecs.umich.educlass Float(ParamValue, float): 6406584Sgblack@eecs.umich.edu cxx_type = 'double' 6416584Sgblack@eecs.umich.edu cmd_line_settable = True 6426584Sgblack@eecs.umich.edu 6436584Sgblack@eecs.umich.edu def __init__(self, value): 6446584Sgblack@eecs.umich.edu if isinstance(value, (int, long, float, NumericParamValue, Float, str)): 6456584Sgblack@eecs.umich.edu self.value = float(value) 6466584Sgblack@eecs.umich.edu else: 6476584Sgblack@eecs.umich.edu raise TypeError, "Can't convert object of type %s to Float" \ 6486584Sgblack@eecs.umich.edu % type(value).__name__ 6496584Sgblack@eecs.umich.edu 6506584Sgblack@eecs.umich.edu def __call__(self, value): 6516584Sgblack@eecs.umich.edu self.__init__(value) 6526584Sgblack@eecs.umich.edu return value 6535238Sgblack@eecs.umich.edu 6546584Sgblack@eecs.umich.edu def getValue(self): 6556584Sgblack@eecs.umich.edu return float(self.value) 6566584Sgblack@eecs.umich.edu 6576584Sgblack@eecs.umich.edu def config_value(self): 6585238Sgblack@eecs.umich.edu return self 6596584Sgblack@eecs.umich.edu 6606584Sgblack@eecs.umich.edu @classmethod 6616597Sgblack@eecs.umich.edu def cxx_ini_predecls(cls, code): 6626584Sgblack@eecs.umich.edu code('#include <sstream>') 6636584Sgblack@eecs.umich.edu 6646584Sgblack@eecs.umich.edu @classmethod 6656584Sgblack@eecs.umich.edu def cxx_ini_parse(self, code, src, dest, ret): 6666597Sgblack@eecs.umich.edu code('%s (std::istringstream(%s) >> %s).eof();' % (ret, src, dest)) 6676584Sgblack@eecs.umich.edu 6686584Sgblack@eecs.umich.educlass MemorySize(CheckedInt): 6696584Sgblack@eecs.umich.edu cxx_type = 'uint64_t' 6706584Sgblack@eecs.umich.edu ex_str = '512MB' 6716584Sgblack@eecs.umich.edu size = 64 6726584Sgblack@eecs.umich.edu unsigned = True 6736584Sgblack@eecs.umich.edu def __init__(self, value): 6746584Sgblack@eecs.umich.edu if isinstance(value, MemorySize): 6756584Sgblack@eecs.umich.edu self.value = value.value 6766584Sgblack@eecs.umich.edu else: 6776584Sgblack@eecs.umich.edu self.value = convert.toMemorySize(value) 6786584Sgblack@eecs.umich.edu self._check() 6796584Sgblack@eecs.umich.edu 6806584Sgblack@eecs.umich.educlass MemorySize32(CheckedInt): 6816584Sgblack@eecs.umich.edu cxx_type = 'uint32_t' 6825238Sgblack@eecs.umich.edu ex_str = '512MB' 6836584Sgblack@eecs.umich.edu size = 32 6846584Sgblack@eecs.umich.edu unsigned = True 6856584Sgblack@eecs.umich.edu def __init__(self, value): 6866584Sgblack@eecs.umich.edu if isinstance(value, MemorySize): 6876584Sgblack@eecs.umich.edu self.value = value.value 6886584Sgblack@eecs.umich.edu else: 6896584Sgblack@eecs.umich.edu self.value = convert.toMemorySize(value) 6906584Sgblack@eecs.umich.edu self._check() 6916584Sgblack@eecs.umich.edu 6926584Sgblack@eecs.umich.educlass Addr(CheckedInt): 6936584Sgblack@eecs.umich.edu cxx_type = 'Addr' 6946584Sgblack@eecs.umich.edu size = 64 6956584Sgblack@eecs.umich.edu unsigned = True 6966584Sgblack@eecs.umich.edu def __init__(self, value): 6976584Sgblack@eecs.umich.edu if isinstance(value, Addr): 6985238Sgblack@eecs.umich.edu self.value = value.value 6996584Sgblack@eecs.umich.edu else: 7006584Sgblack@eecs.umich.edu try: 7016584Sgblack@eecs.umich.edu # Often addresses are referred to with sizes. Ex: A device 7026584Sgblack@eecs.umich.edu # base address is at "512MB". Use toMemorySize() to convert 7036584Sgblack@eecs.umich.edu # these into addresses. If the address is not specified with a 7046584Sgblack@eecs.umich.edu # "size", an exception will occur and numeric translation will 7056584Sgblack@eecs.umich.edu # proceed below. 7066584Sgblack@eecs.umich.edu self.value = convert.toMemorySize(value) 7076584Sgblack@eecs.umich.edu except (TypeError, ValueError): 7086584Sgblack@eecs.umich.edu # Convert number to string and use long() to do automatic 7096584Sgblack@eecs.umich.edu # base conversion (requires base=0 for auto-conversion) 7106584Sgblack@eecs.umich.edu self.value = long(str(value), base=0) 7116584Sgblack@eecs.umich.edu 7126584Sgblack@eecs.umich.edu self._check() 7136584Sgblack@eecs.umich.edu def __add__(self, other): 7146584Sgblack@eecs.umich.edu if isinstance(other, Addr): 7156584Sgblack@eecs.umich.edu return self.value + other.value 7166584Sgblack@eecs.umich.edu else: 7176584Sgblack@eecs.umich.edu return self.value + other 7185238Sgblack@eecs.umich.edu def pretty_print(self, value): 7196584Sgblack@eecs.umich.edu try: 7206584Sgblack@eecs.umich.edu val = convert.toMemorySize(value) 7216584Sgblack@eecs.umich.edu except TypeError: 7226584Sgblack@eecs.umich.edu val = long(value) 7235238Sgblack@eecs.umich.edu return "0x%x" % long(val) 7246584Sgblack@eecs.umich.edu 7256584Sgblack@eecs.umich.educlass AddrRange(ParamValue): 7266597Sgblack@eecs.umich.edu cxx_type = 'AddrRange' 7276584Sgblack@eecs.umich.edu 7285238Sgblack@eecs.umich.edu def __init__(self, *args, **kwargs): 7296584Sgblack@eecs.umich.edu # Disable interleaving and hashing by default 7305020Sgblack@eecs.umich.edu self.intlvHighBit = 0 7316584Sgblack@eecs.umich.edu self.xorHighBit = 0 7326584Sgblack@eecs.umich.edu self.intlvBits = 0 7336584Sgblack@eecs.umich.edu self.intlvMatch = 0 7346584Sgblack@eecs.umich.edu 7356584Sgblack@eecs.umich.edu def handle_kwargs(self, kwargs): 7366584Sgblack@eecs.umich.edu # An address range needs to have an upper limit, specified 7376584Sgblack@eecs.umich.edu # either explicitly with an end, or as an offset using the 7386584Sgblack@eecs.umich.edu # size keyword. 7396584Sgblack@eecs.umich.edu if 'end' in kwargs: 7406584Sgblack@eecs.umich.edu self.end = Addr(kwargs.pop('end')) 7416584Sgblack@eecs.umich.edu elif 'size' in kwargs: 7426584Sgblack@eecs.umich.edu self.end = self.start + Addr(kwargs.pop('size')) - 1 7436584Sgblack@eecs.umich.edu else: 7446584Sgblack@eecs.umich.edu raise TypeError, "Either end or size must be specified" 7456584Sgblack@eecs.umich.edu 7466584Sgblack@eecs.umich.edu # Now on to the optional bit 7476584Sgblack@eecs.umich.edu if 'intlvHighBit' in kwargs: 7486584Sgblack@eecs.umich.edu self.intlvHighBit = int(kwargs.pop('intlvHighBit')) 7496584Sgblack@eecs.umich.edu if 'xorHighBit' in kwargs: 7506584Sgblack@eecs.umich.edu self.xorHighBit = int(kwargs.pop('xorHighBit')) 7516584Sgblack@eecs.umich.edu if 'intlvBits' in kwargs: 7526584Sgblack@eecs.umich.edu self.intlvBits = int(kwargs.pop('intlvBits')) 7536584Sgblack@eecs.umich.edu if 'intlvMatch' in kwargs: 7546584Sgblack@eecs.umich.edu self.intlvMatch = int(kwargs.pop('intlvMatch')) 7556584Sgblack@eecs.umich.edu 7566584Sgblack@eecs.umich.edu if len(args) == 0: 7576584Sgblack@eecs.umich.edu self.start = Addr(kwargs.pop('start')) 7586584Sgblack@eecs.umich.edu handle_kwargs(self, kwargs) 7596584Sgblack@eecs.umich.edu 7606584Sgblack@eecs.umich.edu elif len(args) == 1: 7615020Sgblack@eecs.umich.edu if kwargs: 7624727Sgblack@eecs.umich.edu self.start = Addr(args[0]) 7634727Sgblack@eecs.umich.edu handle_kwargs(self, kwargs) 7644727Sgblack@eecs.umich.edu elif isinstance(args[0], (list, tuple)): 7654727Sgblack@eecs.umich.edu self.start = Addr(args[0][0]) 7664727Sgblack@eecs.umich.edu self.end = Addr(args[0][1]) 7674727Sgblack@eecs.umich.edu else: 7684727Sgblack@eecs.umich.edu self.start = Addr(0) 7694727Sgblack@eecs.umich.edu self.end = Addr(args[0]) - 1 7704727Sgblack@eecs.umich.edu 7714727Sgblack@eecs.umich.edu elif len(args) == 2: 7724727Sgblack@eecs.umich.edu self.start = Addr(args[0]) 7734727Sgblack@eecs.umich.edu self.end = Addr(args[1]) 7744727Sgblack@eecs.umich.edu else: 7754727Sgblack@eecs.umich.edu raise TypeError, "Too many arguments specified" 7764727Sgblack@eecs.umich.edu 7774727Sgblack@eecs.umich.edu if kwargs: 7784727Sgblack@eecs.umich.edu raise TypeError, "Too many keywords: %s" % kwargs.keys() 7794727Sgblack@eecs.umich.edu 7804727Sgblack@eecs.umich.edu def __str__(self): 7814727Sgblack@eecs.umich.edu return '%s:%s' % (self.start, self.end) 7824760Sgblack@eecs.umich.edu 7834760Sgblack@eecs.umich.edu def size(self): 7844760Sgblack@eecs.umich.edu # Divide the size by the size of the interleaving slice 7854760Sgblack@eecs.umich.edu return (long(self.end) - long(self.start) + 1) >> self.intlvBits 7864760Sgblack@eecs.umich.edu 7874760Sgblack@eecs.umich.edu @classmethod 7884760Sgblack@eecs.umich.edu def cxx_predecls(cls, code): 7894760Sgblack@eecs.umich.edu Addr.cxx_predecls(code) 7904760Sgblack@eecs.umich.edu code('#include "base/addr_range.hh"') 7914760Sgblack@eecs.umich.edu 7924760Sgblack@eecs.umich.edu @classmethod 7934760Sgblack@eecs.umich.edu def swig_predecls(cls, code): 7944760Sgblack@eecs.umich.edu Addr.swig_predecls(code) 7954760Sgblack@eecs.umich.edu 7964760Sgblack@eecs.umich.edu @classmethod 7974760Sgblack@eecs.umich.edu def cxx_ini_predecls(cls, code): 7984760Sgblack@eecs.umich.edu code('#include <sstream>') 7994760Sgblack@eecs.umich.edu 8004760Sgblack@eecs.umich.edu @classmethod 8014760Sgblack@eecs.umich.edu def cxx_ini_parse(cls, code, src, dest, ret): 8024276Sgblack@eecs.umich.edu code('uint64_t _start, _end;') 8034276Sgblack@eecs.umich.edu code('char _sep;') 8044712Sgblack@eecs.umich.edu code('std::istringstream _stream(${src});') 8054712Sgblack@eecs.umich.edu code('_stream >> _start;') 8065659Sgblack@eecs.umich.edu code('_stream.get(_sep);') 8075659Sgblack@eecs.umich.edu code('_stream >> _end;') 8086052Sgblack@eecs.umich.edu code('bool _ret = !_stream.fail() &&' 8095659Sgblack@eecs.umich.edu '_stream.eof() && _sep == \':\';') 8105659Sgblack@eecs.umich.edu code('if (_ret)') 8115659Sgblack@eecs.umich.edu code(' ${dest} = AddrRange(_start, _end);') 8125659Sgblack@eecs.umich.edu code('${ret} _ret;') 8135659Sgblack@eecs.umich.edu 8145240Sgblack@eecs.umich.edu def getValue(self): 8156480Sgblack@eecs.umich.edu # Go from the Python class to the wrapped C++ class generated 8166480Sgblack@eecs.umich.edu # by swig 8174712Sgblack@eecs.umich.edu from m5.internal.range import AddrRange 8184712Sgblack@eecs.umich.edu 8194276Sgblack@eecs.umich.edu return AddrRange(long(self.start), long(self.end), 8204276Sgblack@eecs.umich.edu int(self.intlvHighBit), int(self.xorHighBit), 8214712Sgblack@eecs.umich.edu int(self.intlvBits), int(self.intlvMatch)) 8224712Sgblack@eecs.umich.edu 8234712Sgblack@eecs.umich.edu# Boolean parameter type. Python doesn't let you subclass bool, since 8245240Sgblack@eecs.umich.edu# it doesn't want to let you create multiple instances of True and 8255977Sgblack@eecs.umich.edu# False. Thus this is a little more complicated than String. 8266481Sgblack@eecs.umich.educlass Bool(ParamValue): 8275238Sgblack@eecs.umich.edu cxx_type = 'bool' 8285967Sgblack@eecs.umich.edu cmd_line_settable = True 8295967Sgblack@eecs.umich.edu 8305967Sgblack@eecs.umich.edu def __init__(self, value): 8316599Sgblack@eecs.umich.edu try: 8326598Sgblack@eecs.umich.edu self.value = convert.toBool(value) 8335967Sgblack@eecs.umich.edu except TypeError: 8345967Sgblack@eecs.umich.edu self.value = bool(value) 8355967Sgblack@eecs.umich.edu 8365923Sgblack@eecs.umich.edu def __call__(self, value): 8375238Sgblack@eecs.umich.edu self.__init__(value) 8385238Sgblack@eecs.umich.edu return value 8395967Sgblack@eecs.umich.edu 8405967Sgblack@eecs.umich.edu def getValue(self): 8415967Sgblack@eecs.umich.edu return bool(self.value) 8425967Sgblack@eecs.umich.edu 8435967Sgblack@eecs.umich.edu def __str__(self): 8445967Sgblack@eecs.umich.edu return str(self.value) 8455967Sgblack@eecs.umich.edu 8465967Sgblack@eecs.umich.edu # implement truth value testing for Bool parameters so that these params 8475238Sgblack@eecs.umich.edu # evaluate correctly during the python configuration phase 8485238Sgblack@eecs.umich.edu def __nonzero__(self): 8495238Sgblack@eecs.umich.edu return bool(self.value) 8504724Sgblack@eecs.umich.edu 8514276Sgblack@eecs.umich.edu def ini_str(self): 8526593Sgblack@eecs.umich.edu if self.value: 8536593Sgblack@eecs.umich.edu return 'true' 8546593Sgblack@eecs.umich.edu return 'false' 8556593Sgblack@eecs.umich.edu 8566593Sgblack@eecs.umich.edu def config_value(self): 8576593Sgblack@eecs.umich.edu return self.value 8586593Sgblack@eecs.umich.edu 8596593Sgblack@eecs.umich.edu @classmethod 8606593Sgblack@eecs.umich.edu def cxx_ini_predecls(cls, code): 8616593Sgblack@eecs.umich.edu # Assume that base/str.hh will be included anyway 8626593Sgblack@eecs.umich.edu # code('#include "base/str.hh"') 8636593Sgblack@eecs.umich.edu pass 8646593Sgblack@eecs.umich.edu 8656593Sgblack@eecs.umich.edu @classmethod 8666593Sgblack@eecs.umich.edu def cxx_ini_parse(cls, code, src, dest, ret): 8676593Sgblack@eecs.umich.edu code('%s to_bool(%s, %s);' % (ret, src, dest)) 8686593Sgblack@eecs.umich.edu 8695240Sgblack@eecs.umich.edudef IncEthernetAddr(addr, val = 1): 8705240Sgblack@eecs.umich.edu bytes = map(lambda x: int(x, 16), addr.split(':')) 8715240Sgblack@eecs.umich.edu bytes[5] += val 8725240Sgblack@eecs.umich.edu for i in (5, 4, 3, 2, 1): 8735240Sgblack@eecs.umich.edu val,rem = divmod(bytes[i], 256) 8745240Sgblack@eecs.umich.edu bytes[i] = rem 8755240Sgblack@eecs.umich.edu if val == 0: 8765240Sgblack@eecs.umich.edu break 8775240Sgblack@eecs.umich.edu bytes[i - 1] += val 8785240Sgblack@eecs.umich.edu assert(bytes[0] <= 255) 8795240Sgblack@eecs.umich.edu return ':'.join(map(lambda x: '%02x' % x, bytes)) 8806593Sgblack@eecs.umich.edu 8816593Sgblack@eecs.umich.edu_NextEthernetAddr = "00:90:00:00:00:01" 8826593Sgblack@eecs.umich.edudef NextEthernetAddr(): 8836593Sgblack@eecs.umich.edu global _NextEthernetAddr 8846593Sgblack@eecs.umich.edu 8856593Sgblack@eecs.umich.edu value = _NextEthernetAddr 8866593Sgblack@eecs.umich.edu _NextEthernetAddr = IncEthernetAddr(_NextEthernetAddr, 1) 8876593Sgblack@eecs.umich.edu return value 8885238Sgblack@eecs.umich.edu 8896576Sgblack@eecs.umich.educlass EthernetAddr(ParamValue): 8906576Sgblack@eecs.umich.edu cxx_type = 'Net::EthAddr' 8916576Sgblack@eecs.umich.edu ex_str = "00:90:00:00:00:01" 8926576Sgblack@eecs.umich.edu cmd_line_settable = True 8936576Sgblack@eecs.umich.edu 8946576Sgblack@eecs.umich.edu @classmethod 8956576Sgblack@eecs.umich.edu def cxx_predecls(cls, code): 8966576Sgblack@eecs.umich.edu code('#include "base/inet.hh"') 8976576Sgblack@eecs.umich.edu 8986576Sgblack@eecs.umich.edu @classmethod 8996576Sgblack@eecs.umich.edu def swig_predecls(cls, code): 9006576Sgblack@eecs.umich.edu code('%include "python/swig/inet.i"') 9016576Sgblack@eecs.umich.edu 9025238Sgblack@eecs.umich.edu def __init__(self, value): 9036576Sgblack@eecs.umich.edu if value == NextEthernetAddr: 9046576Sgblack@eecs.umich.edu self.value = value 9055238Sgblack@eecs.umich.edu return 9066576Sgblack@eecs.umich.edu 9076576Sgblack@eecs.umich.edu if not isinstance(value, str): 9086576Sgblack@eecs.umich.edu raise TypeError, "expected an ethernet address and didn't get one" 9096604Sgblack@eecs.umich.edu 9106590Sgblack@eecs.umich.edu bytes = value.split(':') 9116591Sgblack@eecs.umich.edu if len(bytes) != 6: 9126591Sgblack@eecs.umich.edu raise TypeError, 'invalid ethernet address %s' % value 9136597Sgblack@eecs.umich.edu 9146576Sgblack@eecs.umich.edu for byte in bytes: 9156576Sgblack@eecs.umich.edu if not 0 <= int(byte, base=16) <= 0xff: 9166576Sgblack@eecs.umich.edu raise TypeError, 'invalid ethernet address %s' % value 9176604Sgblack@eecs.umich.edu 9186576Sgblack@eecs.umich.edu self.value = value 9196576Sgblack@eecs.umich.edu 9206576Sgblack@eecs.umich.edu def __call__(self, value): 9216576Sgblack@eecs.umich.edu self.__init__(value) 9226604Sgblack@eecs.umich.edu return value 9236591Sgblack@eecs.umich.edu 9246591Sgblack@eecs.umich.edu def unproxy(self, base): 9256597Sgblack@eecs.umich.edu if self.value == NextEthernetAddr: 9266576Sgblack@eecs.umich.edu return EthernetAddr(self.value()) 9276576Sgblack@eecs.umich.edu return self 9286576Sgblack@eecs.umich.edu 9296576Sgblack@eecs.umich.edu def getValue(self): 9306604Sgblack@eecs.umich.edu from m5.internal.params import EthAddr 9316576Sgblack@eecs.umich.edu return EthAddr(self.value) 9326576Sgblack@eecs.umich.edu 9336576Sgblack@eecs.umich.edu def __str__(self): 9346576Sgblack@eecs.umich.edu return self.value 9355238Sgblack@eecs.umich.edu 9366576Sgblack@eecs.umich.edu def ini_str(self): 9376576Sgblack@eecs.umich.edu return self.value 9386576Sgblack@eecs.umich.edu 9396576Sgblack@eecs.umich.edu @classmethod 9405020Sgblack@eecs.umich.edu def cxx_ini_parse(self, code, src, dest, ret): 9416593Sgblack@eecs.umich.edu code('%s = Net::EthAddr(%s);' % (dest, src)) 9426593Sgblack@eecs.umich.edu code('%s true;' % ret) 9436593Sgblack@eecs.umich.edu 9446593Sgblack@eecs.umich.edu# When initializing an IpAddress, pass in an existing IpAddress, a string of 9456593Sgblack@eecs.umich.edu# the form "a.b.c.d", or an integer representing an IP. 9466593Sgblack@eecs.umich.educlass IpAddress(ParamValue): 9476593Sgblack@eecs.umich.edu cxx_type = 'Net::IpAddress' 9486593Sgblack@eecs.umich.edu ex_str = "127.0.0.1" 9496593Sgblack@eecs.umich.edu cmd_line_settable = True 9506593Sgblack@eecs.umich.edu 9516593Sgblack@eecs.umich.edu @classmethod 9526593Sgblack@eecs.umich.edu def cxx_predecls(cls, code): 9536593Sgblack@eecs.umich.edu code('#include "base/inet.hh"') 9546593Sgblack@eecs.umich.edu 9556593Sgblack@eecs.umich.edu @classmethod 9566593Sgblack@eecs.umich.edu def swig_predecls(cls, code): 9576593Sgblack@eecs.umich.edu code('%include "python/swig/inet.i"') 9586593Sgblack@eecs.umich.edu 9596593Sgblack@eecs.umich.edu def __init__(self, value): 9606593Sgblack@eecs.umich.edu if isinstance(value, IpAddress): 9616593Sgblack@eecs.umich.edu self.ip = value.ip 9626593Sgblack@eecs.umich.edu else: 9636593Sgblack@eecs.umich.edu try: 9646593Sgblack@eecs.umich.edu self.ip = convert.toIpAddress(value) 9656593Sgblack@eecs.umich.edu except TypeError: 9666593Sgblack@eecs.umich.edu self.ip = long(value) 9676593Sgblack@eecs.umich.edu self.verifyIp() 9686593Sgblack@eecs.umich.edu 9696593Sgblack@eecs.umich.edu def __call__(self, value): 9706593Sgblack@eecs.umich.edu self.__init__(value) 9716607Sgblack@eecs.umich.edu return value 9726593Sgblack@eecs.umich.edu 9736593Sgblack@eecs.umich.edu def __str__(self): 9746593Sgblack@eecs.umich.edu tup = [(self.ip >> i) & 0xff for i in (24, 16, 8, 0)] 9755020Sgblack@eecs.umich.edu return '%d.%d.%d.%d' % tuple(tup) 9766576Sgblack@eecs.umich.edu 9776576Sgblack@eecs.umich.edu def __eq__(self, other): 9786576Sgblack@eecs.umich.edu if isinstance(other, IpAddress): 9796580Sgblack@eecs.umich.edu return self.ip == other.ip 9806580Sgblack@eecs.umich.edu elif isinstance(other, str): 9816576Sgblack@eecs.umich.edu try: 9826576Sgblack@eecs.umich.edu return self.ip == convert.toIpAddress(other) 9836576Sgblack@eecs.umich.edu except: 9846576Sgblack@eecs.umich.edu return False 9856576Sgblack@eecs.umich.edu else: 9866576Sgblack@eecs.umich.edu return self.ip == other 9876576Sgblack@eecs.umich.edu 9886576Sgblack@eecs.umich.edu def __ne__(self, other): 9896576Sgblack@eecs.umich.edu return not (self == other) 9906580Sgblack@eecs.umich.edu 9916580Sgblack@eecs.umich.edu def verifyIp(self): 9926576Sgblack@eecs.umich.edu if self.ip < 0 or self.ip >= (1 << 32): 9936576Sgblack@eecs.umich.edu raise TypeError, "invalid ip address %#08x" % self.ip 9946576Sgblack@eecs.umich.edu 9956576Sgblack@eecs.umich.edu def getValue(self): 9966576Sgblack@eecs.umich.edu from m5.internal.params import IpAddress 9976576Sgblack@eecs.umich.edu return IpAddress(self.ip) 9986576Sgblack@eecs.umich.edu 9996576Sgblack@eecs.umich.edu# When initializing an IpNetmask, pass in an existing IpNetmask, a string of 10005020Sgblack@eecs.umich.edu# the form "a.b.c.d/n" or "a.b.c.d/e.f.g.h", or an ip and netmask as 10016588Sgblack@eecs.umich.edu# positional or keyword arguments. 10026588Sgblack@eecs.umich.educlass IpNetmask(IpAddress): 10036588Sgblack@eecs.umich.edu cxx_type = 'Net::IpNetmask' 10046588Sgblack@eecs.umich.edu ex_str = "127.0.0.0/24" 10056588Sgblack@eecs.umich.edu cmd_line_settable = True 10066588Sgblack@eecs.umich.edu 10076588Sgblack@eecs.umich.edu @classmethod 10086588Sgblack@eecs.umich.edu def cxx_predecls(cls, code): 10096588Sgblack@eecs.umich.edu code('#include "base/inet.hh"') 10106588Sgblack@eecs.umich.edu 10116588Sgblack@eecs.umich.edu @classmethod 10126588Sgblack@eecs.umich.edu def swig_predecls(cls, code): 10136588Sgblack@eecs.umich.edu code('%include "python/swig/inet.i"') 10146588Sgblack@eecs.umich.edu 10156588Sgblack@eecs.umich.edu def __init__(self, *args, **kwargs): 10166588Sgblack@eecs.umich.edu def handle_kwarg(self, kwargs, key, elseVal = None): 10176588Sgblack@eecs.umich.edu if key in kwargs: 10186588Sgblack@eecs.umich.edu setattr(self, key, kwargs.pop(key)) 10196588Sgblack@eecs.umich.edu elif elseVal: 10206588Sgblack@eecs.umich.edu setattr(self, key, elseVal) 10216588Sgblack@eecs.umich.edu else: 10226588Sgblack@eecs.umich.edu raise TypeError, "No value set for %s" % key 10236588Sgblack@eecs.umich.edu 10246588Sgblack@eecs.umich.edu if len(args) == 0: 10256588Sgblack@eecs.umich.edu handle_kwarg(self, kwargs, 'ip') 10266606Sgblack@eecs.umich.edu handle_kwarg(self, kwargs, 'netmask') 10276588Sgblack@eecs.umich.edu 10286588Sgblack@eecs.umich.edu elif len(args) == 1: 10296588Sgblack@eecs.umich.edu if kwargs: 10306588Sgblack@eecs.umich.edu if not 'ip' in kwargs and not 'netmask' in kwargs: 10316606Sgblack@eecs.umich.edu raise TypeError, "Invalid arguments" 10326588Sgblack@eecs.umich.edu handle_kwarg(self, kwargs, 'ip', args[0]) 10336588Sgblack@eecs.umich.edu handle_kwarg(self, kwargs, 'netmask', args[0]) 10346588Sgblack@eecs.umich.edu elif isinstance(args[0], IpNetmask): 10355022Sgblack@eecs.umich.edu self.ip = args[0].ip 10366576Sgblack@eecs.umich.edu self.netmask = args[0].netmask 10376576Sgblack@eecs.umich.edu else: 10386576Sgblack@eecs.umich.edu (self.ip, self.netmask) = convert.toIpNetmask(args[0]) 10396580Sgblack@eecs.umich.edu 10406580Sgblack@eecs.umich.edu elif len(args) == 2: 10416576Sgblack@eecs.umich.edu self.ip = args[0] 10426576Sgblack@eecs.umich.edu self.netmask = args[1] 10436576Sgblack@eecs.umich.edu else: 10446576Sgblack@eecs.umich.edu raise TypeError, "Too many arguments specified" 10456576Sgblack@eecs.umich.edu 10466576Sgblack@eecs.umich.edu if kwargs: 10476576Sgblack@eecs.umich.edu raise TypeError, "Too many keywords: %s" % kwargs.keys() 10486576Sgblack@eecs.umich.edu 10496576Sgblack@eecs.umich.edu self.verify() 10506580Sgblack@eecs.umich.edu 10516580Sgblack@eecs.umich.edu def __call__(self, value): 10526576Sgblack@eecs.umich.edu self.__init__(value) 10536576Sgblack@eecs.umich.edu return value 10546576Sgblack@eecs.umich.edu 10556576Sgblack@eecs.umich.edu def __str__(self): 10566576Sgblack@eecs.umich.edu return "%s/%d" % (super(IpNetmask, self).__str__(), self.netmask) 10576576Sgblack@eecs.umich.edu 10586576Sgblack@eecs.umich.edu def __eq__(self, other): 10596576Sgblack@eecs.umich.edu if isinstance(other, IpNetmask): 10605020Sgblack@eecs.umich.edu return self.ip == other.ip and self.netmask == other.netmask 10616586Sgblack@eecs.umich.edu elif isinstance(other, str): 10626586Sgblack@eecs.umich.edu try: 10636586Sgblack@eecs.umich.edu return (self.ip, self.netmask) == convert.toIpNetmask(other) 10646586Sgblack@eecs.umich.edu except: 10656586Sgblack@eecs.umich.edu return False 10666586Sgblack@eecs.umich.edu else: 10676586Sgblack@eecs.umich.edu return False 10686586Sgblack@eecs.umich.edu 10696586Sgblack@eecs.umich.edu def verify(self): 10706595Sgblack@eecs.umich.edu self.verifyIp() 10716586Sgblack@eecs.umich.edu if self.netmask < 0 or self.netmask > 32: 10726586Sgblack@eecs.umich.edu raise TypeError, "invalid netmask %d" % netmask 10736586Sgblack@eecs.umich.edu 10746586Sgblack@eecs.umich.edu def getValue(self): 10756586Sgblack@eecs.umich.edu from m5.internal.params import IpNetmask 10766586Sgblack@eecs.umich.edu return IpNetmask(self.ip, self.netmask) 10776586Sgblack@eecs.umich.edu 10786586Sgblack@eecs.umich.edu# When initializing an IpWithPort, pass in an existing IpWithPort, a string of 10796586Sgblack@eecs.umich.edu# the form "a.b.c.d:p", or an ip and port as positional or keyword arguments. 10806586Sgblack@eecs.umich.educlass IpWithPort(IpAddress): 10816595Sgblack@eecs.umich.edu cxx_type = 'Net::IpWithPort' 10826586Sgblack@eecs.umich.edu ex_str = "127.0.0.1:80" 10836586Sgblack@eecs.umich.edu cmd_line_settable = True 10846586Sgblack@eecs.umich.edu 10856586Sgblack@eecs.umich.edu @classmethod 10866586Sgblack@eecs.umich.edu def cxx_predecls(cls, code): 10876586Sgblack@eecs.umich.edu code('#include "base/inet.hh"') 10886586Sgblack@eecs.umich.edu 10896586Sgblack@eecs.umich.edu @classmethod 10905022Sgblack@eecs.umich.edu def swig_predecls(cls, code): 10916576Sgblack@eecs.umich.edu code('%include "python/swig/inet.i"') 10926576Sgblack@eecs.umich.edu 10936576Sgblack@eecs.umich.edu def __init__(self, *args, **kwargs): 10946580Sgblack@eecs.umich.edu def handle_kwarg(self, kwargs, key, elseVal = None): 10956580Sgblack@eecs.umich.edu if key in kwargs: 10966580Sgblack@eecs.umich.edu setattr(self, key, kwargs.pop(key)) 10976580Sgblack@eecs.umich.edu elif elseVal: 10986576Sgblack@eecs.umich.edu setattr(self, key, elseVal) 10996576Sgblack@eecs.umich.edu else: 11006576Sgblack@eecs.umich.edu raise TypeError, "No value set for %s" % key 11016576Sgblack@eecs.umich.edu 11026576Sgblack@eecs.umich.edu if len(args) == 0: 11036576Sgblack@eecs.umich.edu handle_kwarg(self, kwargs, 'ip') 11046576Sgblack@eecs.umich.edu handle_kwarg(self, kwargs, 'port') 11056580Sgblack@eecs.umich.edu 11066580Sgblack@eecs.umich.edu elif len(args) == 1: 11076580Sgblack@eecs.umich.edu if kwargs: 11086580Sgblack@eecs.umich.edu if not 'ip' in kwargs and not 'port' in kwargs: 11096576Sgblack@eecs.umich.edu raise TypeError, "Invalid arguments" 11106576Sgblack@eecs.umich.edu handle_kwarg(self, kwargs, 'ip', args[0]) 11116576Sgblack@eecs.umich.edu handle_kwarg(self, kwargs, 'port', args[0]) 11126576Sgblack@eecs.umich.edu elif isinstance(args[0], IpWithPort): 11136576Sgblack@eecs.umich.edu self.ip = args[0].ip 11146576Sgblack@eecs.umich.edu self.port = args[0].port 11155020Sgblack@eecs.umich.edu else: 11164276Sgblack@eecs.umich.edu (self.ip, self.port) = convert.toIpWithPort(args[0]) 11174276Sgblack@eecs.umich.edu 11184276Sgblack@eecs.umich.edu elif len(args) == 2: 11194276Sgblack@eecs.umich.edu self.ip = args[0] 11204276Sgblack@eecs.umich.edu self.port = args[1] 11214276Sgblack@eecs.umich.edu else: 11224276Sgblack@eecs.umich.edu raise TypeError, "Too many arguments specified" 1123 1124 if kwargs: 1125 raise TypeError, "Too many keywords: %s" % kwargs.keys() 1126 1127 self.verify() 1128 1129 def __call__(self, value): 1130 self.__init__(value) 1131 return value 1132 1133 def __str__(self): 1134 return "%s:%d" % (super(IpWithPort, self).__str__(), self.port) 1135 1136 def __eq__(self, other): 1137 if isinstance(other, IpWithPort): 1138 return self.ip == other.ip and self.port == other.port 1139 elif isinstance(other, str): 1140 try: 1141 return (self.ip, self.port) == convert.toIpWithPort(other) 1142 except: 1143 return False 1144 else: 1145 return False 1146 1147 def verify(self): 1148 self.verifyIp() 1149 if self.port < 0 or self.port > 0xffff: 1150 raise TypeError, "invalid port %d" % self.port 1151 1152 def getValue(self): 1153 from m5.internal.params import IpWithPort 1154 return IpWithPort(self.ip, self.port) 1155 1156time_formats = [ "%a %b %d %H:%M:%S %Z %Y", 1157 "%a %b %d %H:%M:%S %Y", 1158 "%Y/%m/%d %H:%M:%S", 1159 "%Y/%m/%d %H:%M", 1160 "%Y/%m/%d", 1161 "%m/%d/%Y %H:%M:%S", 1162 "%m/%d/%Y %H:%M", 1163 "%m/%d/%Y", 1164 "%m/%d/%y %H:%M:%S", 1165 "%m/%d/%y %H:%M", 1166 "%m/%d/%y"] 1167 1168 1169def parse_time(value): 1170 from time import gmtime, strptime, struct_time, time 1171 from datetime import datetime, date 1172 1173 if isinstance(value, struct_time): 1174 return value 1175 1176 if isinstance(value, (int, long)): 1177 return gmtime(value) 1178 1179 if isinstance(value, (datetime, date)): 1180 return value.timetuple() 1181 1182 if isinstance(value, str): 1183 if value in ('Now', 'Today'): 1184 return time.gmtime(time.time()) 1185 1186 for format in time_formats: 1187 try: 1188 return strptime(value, format) 1189 except ValueError: 1190 pass 1191 1192 raise ValueError, "Could not parse '%s' as a time" % value 1193 1194class Time(ParamValue): 1195 cxx_type = 'tm' 1196 1197 @classmethod 1198 def cxx_predecls(cls, code): 1199 code('#include <time.h>') 1200 1201 @classmethod 1202 def swig_predecls(cls, code): 1203 code('%include "python/swig/time.i"') 1204 1205 def __init__(self, value): 1206 self.value = parse_time(value) 1207 1208 def __call__(self, value): 1209 self.__init__(value) 1210 return value 1211 1212 def getValue(self): 1213 from m5.internal.params import tm 1214 1215 c_time = tm() 1216 py_time = self.value 1217 1218 # UNIX is years since 1900 1219 c_time.tm_year = py_time.tm_year - 1900; 1220 1221 # Python starts at 1, UNIX starts at 0 1222 c_time.tm_mon = py_time.tm_mon - 1; 1223 c_time.tm_mday = py_time.tm_mday; 1224 c_time.tm_hour = py_time.tm_hour; 1225 c_time.tm_min = py_time.tm_min; 1226 c_time.tm_sec = py_time.tm_sec; 1227 1228 # Python has 0 as Monday, UNIX is 0 as sunday 1229 c_time.tm_wday = py_time.tm_wday + 1 1230 if c_time.tm_wday > 6: 1231 c_time.tm_wday -= 7; 1232 1233 # Python starts at 1, Unix starts at 0 1234 c_time.tm_yday = py_time.tm_yday - 1; 1235 1236 return c_time 1237 1238 def __str__(self): 1239 return time.asctime(self.value) 1240 1241 def ini_str(self): 1242 return str(self) 1243 1244 def get_config_as_dict(self): 1245 assert false 1246 return str(self) 1247 1248 @classmethod 1249 def cxx_ini_predecls(cls, code): 1250 code('#include <time.h>') 1251 1252 @classmethod 1253 def cxx_ini_parse(cls, code, src, dest, ret): 1254 code('char *_parse_ret = strptime((${src}).c_str(),') 1255 code(' "%a %b %d %H:%M:%S %Y", &(${dest}));') 1256 code('${ret} _parse_ret && *_parse_ret == \'\\0\';'); 1257 1258# Enumerated types are a little more complex. The user specifies the 1259# type as Enum(foo) where foo is either a list or dictionary of 1260# alternatives (typically strings, but not necessarily so). (In the 1261# long run, the integer value of the parameter will be the list index 1262# or the corresponding dictionary value. For now, since we only check 1263# that the alternative is valid and then spit it into a .ini file, 1264# there's not much point in using the dictionary.) 1265 1266# What Enum() must do is generate a new type encapsulating the 1267# provided list/dictionary so that specific values of the parameter 1268# can be instances of that type. We define two hidden internal 1269# classes (_ListEnum and _DictEnum) to serve as base classes, then 1270# derive the new type from the appropriate base class on the fly. 1271 1272allEnums = {} 1273# Metaclass for Enum types 1274class MetaEnum(MetaParamValue): 1275 def __new__(mcls, name, bases, dict): 1276 assert name not in allEnums 1277 1278 cls = super(MetaEnum, mcls).__new__(mcls, name, bases, dict) 1279 allEnums[name] = cls 1280 return cls 1281 1282 def __init__(cls, name, bases, init_dict): 1283 if init_dict.has_key('map'): 1284 if not isinstance(cls.map, dict): 1285 raise TypeError, "Enum-derived class attribute 'map' " \ 1286 "must be of type dict" 1287 # build list of value strings from map 1288 cls.vals = cls.map.keys() 1289 cls.vals.sort() 1290 elif init_dict.has_key('vals'): 1291 if not isinstance(cls.vals, list): 1292 raise TypeError, "Enum-derived class attribute 'vals' " \ 1293 "must be of type list" 1294 # build string->value map from vals sequence 1295 cls.map = {} 1296 for idx,val in enumerate(cls.vals): 1297 cls.map[val] = idx 1298 else: 1299 raise TypeError, "Enum-derived class must define "\ 1300 "attribute 'map' or 'vals'" 1301 1302 cls.cxx_type = 'Enums::%s' % name 1303 1304 super(MetaEnum, cls).__init__(name, bases, init_dict) 1305 1306 # Generate C++ class declaration for this enum type. 1307 # Note that we wrap the enum in a class/struct to act as a namespace, 1308 # so that the enum strings can be brief w/o worrying about collisions. 1309 def cxx_decl(cls, code): 1310 wrapper_name = cls.wrapper_name 1311 wrapper = 'struct' if cls.wrapper_is_struct else 'namespace' 1312 name = cls.__name__ if cls.enum_name is None else cls.enum_name 1313 idem_macro = '__ENUM__%s__%s__' % (wrapper_name, name) 1314 1315 code('''\ 1316#ifndef $idem_macro 1317#define $idem_macro 1318 1319$wrapper $wrapper_name { 1320 enum $name { 1321''') 1322 code.indent(2) 1323 for val in cls.vals: 1324 code('$val = ${{cls.map[val]}},') 1325 code('Num_$name = ${{len(cls.vals)}}') 1326 code.dedent(2) 1327 code(' };') 1328 1329 if cls.wrapper_is_struct: 1330 code(' static const char *${name}Strings[Num_${name}];') 1331 code('};') 1332 else: 1333 code('extern const char *${name}Strings[Num_${name}];') 1334 code('}') 1335 1336 code() 1337 code('#endif // $idem_macro') 1338 1339 def cxx_def(cls, code): 1340 wrapper_name = cls.wrapper_name 1341 file_name = cls.__name__ 1342 name = cls.__name__ if cls.enum_name is None else cls.enum_name 1343 1344 code('#include "enums/$file_name.hh"') 1345 if cls.wrapper_is_struct: 1346 code('const char *${wrapper_name}::${name}Strings' 1347 '[Num_${name}] =') 1348 else: 1349 code('namespace Enums {') 1350 code.indent(1) 1351 code(' const char *${name}Strings[Num_${name}] =') 1352 1353 code('{') 1354 code.indent(1) 1355 for val in cls.vals: 1356 code('"$val",') 1357 code.dedent(1) 1358 code('};') 1359 1360 if not cls.wrapper_is_struct: 1361 code('} // namespace $wrapper_name') 1362 code.dedent(1) 1363 1364 def swig_decl(cls, code): 1365 name = cls.__name__ 1366 code('''\ 1367%module(package="m5.internal") enum_$name 1368 1369%{ 1370#include "enums/$name.hh" 1371%} 1372 1373%include "enums/$name.hh" 1374''') 1375 1376 1377# Base class for enum types. 1378class Enum(ParamValue): 1379 __metaclass__ = MetaEnum 1380 vals = [] 1381 cmd_line_settable = True 1382 1383 # The name of the wrapping namespace or struct 1384 wrapper_name = 'Enums' 1385 1386 # If true, the enum is wrapped in a struct rather than a namespace 1387 wrapper_is_struct = False 1388 1389 # If not None, use this as the enum name rather than this class name 1390 enum_name = None 1391 1392 def __init__(self, value): 1393 if value not in self.map: 1394 raise TypeError, "Enum param got bad value '%s' (not in %s)" \ 1395 % (value, self.vals) 1396 self.value = value 1397 1398 def __call__(self, value): 1399 self.__init__(value) 1400 return value 1401 1402 @classmethod 1403 def cxx_predecls(cls, code): 1404 code('#include "enums/$0.hh"', cls.__name__) 1405 1406 @classmethod 1407 def swig_predecls(cls, code): 1408 code('%import "python/m5/internal/enum_$0.i"', cls.__name__) 1409 1410 @classmethod 1411 def cxx_ini_parse(cls, code, src, dest, ret): 1412 code('if (false) {') 1413 for elem_name in cls.map.iterkeys(): 1414 code('} else if (%s == "%s") {' % (src, elem_name)) 1415 code.indent() 1416 code('%s = Enums::%s;' % (dest, elem_name)) 1417 code('%s true;' % ret) 1418 code.dedent() 1419 code('} else {') 1420 code(' %s false;' % ret) 1421 code('}') 1422 1423 def getValue(self): 1424 return int(self.map[self.value]) 1425 1426 def __str__(self): 1427 return self.value 1428 1429# how big does a rounding error need to be before we warn about it? 1430frequency_tolerance = 0.001 # 0.1% 1431 1432class TickParamValue(NumericParamValue): 1433 cxx_type = 'Tick' 1434 ex_str = "1MHz" 1435 cmd_line_settable = True 1436 1437 @classmethod 1438 def cxx_predecls(cls, code): 1439 code('#include "base/types.hh"') 1440 1441 @classmethod 1442 def swig_predecls(cls, code): 1443 code('%import "stdint.i"') 1444 code('%import "base/types.hh"') 1445 1446 def __call__(self, value): 1447 self.__init__(value) 1448 return value 1449 1450 def getValue(self): 1451 return long(self.value) 1452 1453 @classmethod 1454 def cxx_ini_predecls(cls, code): 1455 code('#include <sstream>') 1456 1457 # Ticks are expressed in seconds in JSON files and in plain 1458 # Ticks in .ini files. Switch based on a config flag 1459 @classmethod 1460 def cxx_ini_parse(self, code, src, dest, ret): 1461 code('${ret} to_number(${src}, ${dest});') 1462 1463class Latency(TickParamValue): 1464 ex_str = "100ns" 1465 1466 def __init__(self, value): 1467 if isinstance(value, (Latency, Clock)): 1468 self.ticks = value.ticks 1469 self.value = value.value 1470 elif isinstance(value, Frequency): 1471 self.ticks = value.ticks 1472 self.value = 1.0 / value.value 1473 elif value.endswith('t'): 1474 self.ticks = True 1475 self.value = int(value[:-1]) 1476 else: 1477 self.ticks = False 1478 self.value = convert.toLatency(value) 1479 1480 def __call__(self, value): 1481 self.__init__(value) 1482 return value 1483 1484 def __getattr__(self, attr): 1485 if attr in ('latency', 'period'): 1486 return self 1487 if attr == 'frequency': 1488 return Frequency(self) 1489 raise AttributeError, "Latency object has no attribute '%s'" % attr 1490 1491 def getValue(self): 1492 if self.ticks or self.value == 0: 1493 value = self.value 1494 else: 1495 value = ticks.fromSeconds(self.value) 1496 return long(value) 1497 1498 def config_value(self): 1499 return self.getValue() 1500 1501 # convert latency to ticks 1502 def ini_str(self): 1503 return '%d' % self.getValue() 1504 1505class Frequency(TickParamValue): 1506 ex_str = "1GHz" 1507 1508 def __init__(self, value): 1509 if isinstance(value, (Latency, Clock)): 1510 if value.value == 0: 1511 self.value = 0 1512 else: 1513 self.value = 1.0 / value.value 1514 self.ticks = value.ticks 1515 elif isinstance(value, Frequency): 1516 self.value = value.value 1517 self.ticks = value.ticks 1518 else: 1519 self.ticks = False 1520 self.value = convert.toFrequency(value) 1521 1522 def __call__(self, value): 1523 self.__init__(value) 1524 return value 1525 1526 def __getattr__(self, attr): 1527 if attr == 'frequency': 1528 return self 1529 if attr in ('latency', 'period'): 1530 return Latency(self) 1531 raise AttributeError, "Frequency object has no attribute '%s'" % attr 1532 1533 # convert latency to ticks 1534 def getValue(self): 1535 if self.ticks or self.value == 0: 1536 value = self.value 1537 else: 1538 value = ticks.fromSeconds(1.0 / self.value) 1539 return long(value) 1540 1541 def config_value(self): 1542 return self.getValue() 1543 1544 def ini_str(self): 1545 return '%d' % self.getValue() 1546 1547# A generic Frequency and/or Latency value. Value is stored as a 1548# latency, just like Latency and Frequency. 1549class Clock(TickParamValue): 1550 def __init__(self, value): 1551 if isinstance(value, (Latency, Clock)): 1552 self.ticks = value.ticks 1553 self.value = value.value 1554 elif isinstance(value, Frequency): 1555 self.ticks = value.ticks 1556 self.value = 1.0 / value.value 1557 elif value.endswith('t'): 1558 self.ticks = True 1559 self.value = int(value[:-1]) 1560 else: 1561 self.ticks = False 1562 self.value = convert.anyToLatency(value) 1563 1564 def __call__(self, value): 1565 self.__init__(value) 1566 return value 1567 1568 def __str__(self): 1569 return "%s" % Latency(self) 1570 1571 def __getattr__(self, attr): 1572 if attr == 'frequency': 1573 return Frequency(self) 1574 if attr in ('latency', 'period'): 1575 return Latency(self) 1576 raise AttributeError, "Frequency object has no attribute '%s'" % attr 1577 1578 def getValue(self): 1579 return self.period.getValue() 1580 1581 def config_value(self): 1582 return self.period.config_value() 1583 1584 def ini_str(self): 1585 return self.period.ini_str() 1586 1587class Voltage(float,ParamValue): 1588 cxx_type = 'double' 1589 ex_str = "1V" 1590 cmd_line_settable = True 1591 1592 def __new__(cls, value): 1593 # convert to voltage 1594 val = convert.toVoltage(value) 1595 return super(cls, Voltage).__new__(cls, val) 1596 1597 def __call__(self, value): 1598 val = convert.toVoltage(value) 1599 self.__init__(val) 1600 return value 1601 1602 def __str__(self): 1603 return str(self.getValue()) 1604 1605 def getValue(self): 1606 value = float(self) 1607 return value 1608 1609 def ini_str(self): 1610 return '%f' % self.getValue() 1611 1612 @classmethod 1613 def cxx_ini_predecls(cls, code): 1614 code('#include <sstream>') 1615 1616 @classmethod 1617 def cxx_ini_parse(self, code, src, dest, ret): 1618 code('%s (std::istringstream(%s) >> %s).eof();' % (ret, src, dest)) 1619 1620class Current(float, ParamValue): 1621 cxx_type = 'double' 1622 ex_str = "1mA" 1623 cmd_line_settable = False 1624 1625 def __new__(cls, value): 1626 # convert to current 1627 val = convert.toCurrent(value) 1628 return super(cls, Current).__new__(cls, val) 1629 1630 def __call__(self, value): 1631 val = convert.toCurrent(value) 1632 self.__init__(val) 1633 return value 1634 1635 def __str__(self): 1636 return str(self.getValue()) 1637 1638 def getValue(self): 1639 value = float(self) 1640 return value 1641 1642 def ini_str(self): 1643 return '%f' % self.getValue() 1644 1645 @classmethod 1646 def cxx_ini_predecls(cls, code): 1647 code('#include <sstream>') 1648 1649 @classmethod 1650 def cxx_ini_parse(self, code, src, dest, ret): 1651 code('%s (std::istringstream(%s) >> %s).eof();' % (ret, src, dest)) 1652 1653class NetworkBandwidth(float,ParamValue): 1654 cxx_type = 'float' 1655 ex_str = "1Gbps" 1656 cmd_line_settable = True 1657 1658 def __new__(cls, value): 1659 # convert to bits per second 1660 val = convert.toNetworkBandwidth(value) 1661 return super(cls, NetworkBandwidth).__new__(cls, val) 1662 1663 def __str__(self): 1664 return str(self.val) 1665 1666 def __call__(self, value): 1667 val = convert.toNetworkBandwidth(value) 1668 self.__init__(val) 1669 return value 1670 1671 def getValue(self): 1672 # convert to seconds per byte 1673 value = 8.0 / float(self) 1674 # convert to ticks per byte 1675 value = ticks.fromSeconds(value) 1676 return float(value) 1677 1678 def ini_str(self): 1679 return '%f' % self.getValue() 1680 1681 def config_value(self): 1682 return '%f' % self.getValue() 1683 1684 @classmethod 1685 def cxx_ini_predecls(cls, code): 1686 code('#include <sstream>') 1687 1688 @classmethod 1689 def cxx_ini_parse(self, code, src, dest, ret): 1690 code('%s (std::istringstream(%s) >> %s).eof();' % (ret, src, dest)) 1691 1692class MemoryBandwidth(float,ParamValue): 1693 cxx_type = 'float' 1694 ex_str = "1GB/s" 1695 cmd_line_settable = True 1696 1697 def __new__(cls, value): 1698 # convert to bytes per second 1699 val = convert.toMemoryBandwidth(value) 1700 return super(cls, MemoryBandwidth).__new__(cls, val) 1701 1702 def __call__(self, value): 1703 val = convert.toMemoryBandwidth(value) 1704 self.__init__(val) 1705 return value 1706 1707 def getValue(self): 1708 # convert to seconds per byte 1709 value = float(self) 1710 if value: 1711 value = 1.0 / float(self) 1712 # convert to ticks per byte 1713 value = ticks.fromSeconds(value) 1714 return float(value) 1715 1716 def ini_str(self): 1717 return '%f' % self.getValue() 1718 1719 def config_value(self): 1720 return '%f' % self.getValue() 1721 1722 @classmethod 1723 def cxx_ini_predecls(cls, code): 1724 code('#include <sstream>') 1725 1726 @classmethod 1727 def cxx_ini_parse(self, code, src, dest, ret): 1728 code('%s (std::istringstream(%s) >> %s).eof();' % (ret, src, dest)) 1729 1730# 1731# "Constants"... handy aliases for various values. 1732# 1733 1734# Special class for NULL pointers. Note the special check in 1735# make_param_value() above that lets these be assigned where a 1736# SimObject is required. 1737# only one copy of a particular node 1738class NullSimObject(object): 1739 __metaclass__ = Singleton 1740 1741 def __call__(cls): 1742 return cls 1743 1744 def _instantiate(self, parent = None, path = ''): 1745 pass 1746 1747 def ini_str(self): 1748 return 'Null' 1749 1750 def unproxy(self, base): 1751 return self 1752 1753 def set_path(self, parent, name): 1754 pass 1755 1756 def __str__(self): 1757 return 'Null' 1758 1759 def config_value(self): 1760 return None 1761 1762 def getValue(self): 1763 return None 1764 1765# The only instance you'll ever need... 1766NULL = NullSimObject() 1767 1768def isNullPointer(value): 1769 return isinstance(value, NullSimObject) 1770 1771# Some memory range specifications use this as a default upper bound. 1772MaxAddr = Addr.max 1773MaxTick = Tick.max 1774AllMemory = AddrRange(0, MaxAddr) 1775 1776 1777##################################################################### 1778# 1779# Port objects 1780# 1781# Ports are used to interconnect objects in the memory system. 1782# 1783##################################################################### 1784 1785# Port reference: encapsulates a reference to a particular port on a 1786# particular SimObject. 1787class PortRef(object): 1788 def __init__(self, simobj, name, role): 1789 assert(isSimObject(simobj) or isSimObjectClass(simobj)) 1790 self.simobj = simobj 1791 self.name = name 1792 self.role = role 1793 self.peer = None # not associated with another port yet 1794 self.ccConnected = False # C++ port connection done? 1795 self.index = -1 # always -1 for non-vector ports 1796 1797 def __str__(self): 1798 return '%s.%s' % (self.simobj, self.name) 1799 1800 def __len__(self): 1801 # Return the number of connected ports, i.e. 0 is we have no 1802 # peer and 1 if we do. 1803 return int(self.peer != None) 1804 1805 # for config.ini, print peer's name (not ours) 1806 def ini_str(self): 1807 return str(self.peer) 1808 1809 # for config.json 1810 def get_config_as_dict(self): 1811 return {'role' : self.role, 'peer' : str(self.peer)} 1812 1813 def __getattr__(self, attr): 1814 if attr == 'peerObj': 1815 # shorthand for proxies 1816 return self.peer.simobj 1817 raise AttributeError, "'%s' object has no attribute '%s'" % \ 1818 (self.__class__.__name__, attr) 1819 1820 # Full connection is symmetric (both ways). Called via 1821 # SimObject.__setattr__ as a result of a port assignment, e.g., 1822 # "obj1.portA = obj2.portB", or via VectorPortElementRef.__setitem__, 1823 # e.g., "obj1.portA[3] = obj2.portB". 1824 def connect(self, other): 1825 if isinstance(other, VectorPortRef): 1826 # reference to plain VectorPort is implicit append 1827 other = other._get_next() 1828 if self.peer and not proxy.isproxy(self.peer): 1829 fatal("Port %s is already connected to %s, cannot connect %s\n", 1830 self, self.peer, other); 1831 self.peer = other 1832 if proxy.isproxy(other): 1833 other.set_param_desc(PortParamDesc()) 1834 elif isinstance(other, PortRef): 1835 if other.peer is not self: 1836 other.connect(self) 1837 else: 1838 raise TypeError, \ 1839 "assigning non-port reference '%s' to port '%s'" \ 1840 % (other, self) 1841 1842 # Allow a master/slave port pair to be spliced between 1843 # a port and its connected peer. Useful operation for connecting 1844 # instrumentation structures into a system when it is necessary 1845 # to connect the instrumentation after the full system has been 1846 # constructed. 1847 def splice(self, new_master_peer, new_slave_peer): 1848 if self.peer and not proxy.isproxy(self.peer): 1849 if isinstance(new_master_peer, PortRef) and \ 1850 isinstance(new_slave_peer, PortRef): 1851 old_peer = self.peer 1852 if self.role == 'SLAVE': 1853 self.peer = new_master_peer 1854 old_peer.peer = new_slave_peer 1855 new_master_peer.connect(self) 1856 new_slave_peer.connect(old_peer) 1857 elif self.role == 'MASTER': 1858 self.peer = new_slave_peer 1859 old_peer.peer = new_master_peer 1860 new_slave_peer.connect(self) 1861 new_master_peer.connect(old_peer) 1862 else: 1863 panic("Port %s has unknown role, "+\ 1864 "cannot splice in new peers\n", self) 1865 else: 1866 raise TypeError, \ 1867 "Splicing non-port references '%s','%s' to port '%s'"\ 1868 % (new_peer, peers_new_peer, self) 1869 else: 1870 fatal("Port %s not connected, cannot splice in new peers\n", self) 1871 1872 def clone(self, simobj, memo): 1873 if memo.has_key(self): 1874 return memo[self] 1875 newRef = copy.copy(self) 1876 memo[self] = newRef 1877 newRef.simobj = simobj 1878 assert(isSimObject(newRef.simobj)) 1879 if self.peer and not proxy.isproxy(self.peer): 1880 peerObj = self.peer.simobj(_memo=memo) 1881 newRef.peer = self.peer.clone(peerObj, memo) 1882 assert(not isinstance(newRef.peer, VectorPortRef)) 1883 return newRef 1884 1885 def unproxy(self, simobj): 1886 assert(simobj is self.simobj) 1887 if proxy.isproxy(self.peer): 1888 try: 1889 realPeer = self.peer.unproxy(self.simobj) 1890 except: 1891 print "Error in unproxying port '%s' of %s" % \ 1892 (self.name, self.simobj.path()) 1893 raise 1894 self.connect(realPeer) 1895 1896 # Call C++ to create corresponding port connection between C++ objects 1897 def ccConnect(self): 1898 from m5.internal.pyobject import connectPorts 1899 1900 if self.role == 'SLAVE': 1901 # do nothing and let the master take care of it 1902 return 1903 1904 if self.ccConnected: # already done this 1905 return 1906 peer = self.peer 1907 if not self.peer: # nothing to connect to 1908 return 1909 1910 # check that we connect a master to a slave 1911 if self.role == peer.role: 1912 raise TypeError, \ 1913 "cannot connect '%s' and '%s' due to identical role '%s'" \ 1914 % (peer, self, self.role) 1915 1916 try: 1917 # self is always the master and peer the slave 1918 connectPorts(self.simobj.getCCObject(), self.name, self.index, 1919 peer.simobj.getCCObject(), peer.name, peer.index) 1920 except: 1921 print "Error connecting port %s.%s to %s.%s" % \ 1922 (self.simobj.path(), self.name, 1923 peer.simobj.path(), peer.name) 1924 raise 1925 self.ccConnected = True 1926 peer.ccConnected = True 1927 1928# A reference to an individual element of a VectorPort... much like a 1929# PortRef, but has an index. 1930class VectorPortElementRef(PortRef): 1931 def __init__(self, simobj, name, role, index): 1932 PortRef.__init__(self, simobj, name, role) 1933 self.index = index 1934 1935 def __str__(self): 1936 return '%s.%s[%d]' % (self.simobj, self.name, self.index) 1937 1938# A reference to a complete vector-valued port (not just a single element). 1939# Can be indexed to retrieve individual VectorPortElementRef instances. 1940class VectorPortRef(object): 1941 def __init__(self, simobj, name, role): 1942 assert(isSimObject(simobj) or isSimObjectClass(simobj)) 1943 self.simobj = simobj 1944 self.name = name 1945 self.role = role 1946 self.elements = [] 1947 1948 def __str__(self): 1949 return '%s.%s[:]' % (self.simobj, self.name) 1950 1951 def __len__(self): 1952 # Return the number of connected peers, corresponding the the 1953 # length of the elements. 1954 return len(self.elements) 1955 1956 # for config.ini, print peer's name (not ours) 1957 def ini_str(self): 1958 return ' '.join([el.ini_str() for el in self.elements]) 1959 1960 # for config.json 1961 def get_config_as_dict(self): 1962 return {'role' : self.role, 1963 'peer' : [el.ini_str() for el in self.elements]} 1964 1965 def __getitem__(self, key): 1966 if not isinstance(key, int): 1967 raise TypeError, "VectorPort index must be integer" 1968 if key >= len(self.elements): 1969 # need to extend list 1970 ext = [VectorPortElementRef(self.simobj, self.name, self.role, i) 1971 for i in range(len(self.elements), key+1)] 1972 self.elements.extend(ext) 1973 return self.elements[key] 1974 1975 def _get_next(self): 1976 return self[len(self.elements)] 1977 1978 def __setitem__(self, key, value): 1979 if not isinstance(key, int): 1980 raise TypeError, "VectorPort index must be integer" 1981 self[key].connect(value) 1982 1983 def connect(self, other): 1984 if isinstance(other, (list, tuple)): 1985 # Assign list of port refs to vector port. 1986 # For now, append them... not sure if that's the right semantics 1987 # or if it should replace the current vector. 1988 for ref in other: 1989 self._get_next().connect(ref) 1990 else: 1991 # scalar assignment to plain VectorPort is implicit append 1992 self._get_next().connect(other) 1993 1994 def clone(self, simobj, memo): 1995 if memo.has_key(self): 1996 return memo[self] 1997 newRef = copy.copy(self) 1998 memo[self] = newRef 1999 newRef.simobj = simobj 2000 assert(isSimObject(newRef.simobj)) 2001 newRef.elements = [el.clone(simobj, memo) for el in self.elements] 2002 return newRef 2003 2004 def unproxy(self, simobj): 2005 [el.unproxy(simobj) for el in self.elements] 2006 2007 def ccConnect(self): 2008 [el.ccConnect() for el in self.elements] 2009 2010# Port description object. Like a ParamDesc object, this represents a 2011# logical port in the SimObject class, not a particular port on a 2012# SimObject instance. The latter are represented by PortRef objects. 2013class Port(object): 2014 # Generate a PortRef for this port on the given SimObject with the 2015 # given name 2016 def makeRef(self, simobj): 2017 return PortRef(simobj, self.name, self.role) 2018 2019 # Connect an instance of this port (on the given SimObject with 2020 # the given name) with the port described by the supplied PortRef 2021 def connect(self, simobj, ref): 2022 self.makeRef(simobj).connect(ref) 2023 2024 # No need for any pre-declarations at the moment as we merely rely 2025 # on an unsigned int. 2026 def cxx_predecls(self, code): 2027 pass 2028 2029 # Declare an unsigned int with the same name as the port, that 2030 # will eventually hold the number of connected ports (and thus the 2031 # number of elements for a VectorPort). 2032 def cxx_decl(self, code): 2033 code('unsigned int port_${{self.name}}_connection_count;') 2034 2035class MasterPort(Port): 2036 # MasterPort("description") 2037 def __init__(self, *args): 2038 if len(args) == 1: 2039 self.desc = args[0] 2040 self.role = 'MASTER' 2041 else: 2042 raise TypeError, 'wrong number of arguments' 2043 2044class SlavePort(Port): 2045 # SlavePort("description") 2046 def __init__(self, *args): 2047 if len(args) == 1: 2048 self.desc = args[0] 2049 self.role = 'SLAVE' 2050 else: 2051 raise TypeError, 'wrong number of arguments' 2052 2053# VectorPort description object. Like Port, but represents a vector 2054# of connections (e.g., as on a XBar). 2055class VectorPort(Port): 2056 def __init__(self, *args): 2057 self.isVec = True 2058 2059 def makeRef(self, simobj): 2060 return VectorPortRef(simobj, self.name, self.role) 2061 2062class VectorMasterPort(VectorPort): 2063 # VectorMasterPort("description") 2064 def __init__(self, *args): 2065 if len(args) == 1: 2066 self.desc = args[0] 2067 self.role = 'MASTER' 2068 VectorPort.__init__(self, *args) 2069 else: 2070 raise TypeError, 'wrong number of arguments' 2071 2072class VectorSlavePort(VectorPort): 2073 # VectorSlavePort("description") 2074 def __init__(self, *args): 2075 if len(args) == 1: 2076 self.desc = args[0] 2077 self.role = 'SLAVE' 2078 VectorPort.__init__(self, *args) 2079 else: 2080 raise TypeError, 'wrong number of arguments' 2081 2082# 'Fake' ParamDesc for Port references to assign to the _pdesc slot of 2083# proxy objects (via set_param_desc()) so that proxy error messages 2084# make sense. 2085class PortParamDesc(object): 2086 __metaclass__ = Singleton 2087 2088 ptype_str = 'Port' 2089 ptype = Port 2090 2091baseEnums = allEnums.copy() 2092baseParams = allParams.copy() 2093 2094def clear(): 2095 global allEnums, allParams 2096 2097 allEnums = baseEnums.copy() 2098 allParams = baseParams.copy() 2099 2100__all__ = ['Param', 'VectorParam', 2101 'Enum', 'Bool', 'String', 'Float', 2102 'Int', 'Unsigned', 'Int8', 'UInt8', 'Int16', 'UInt16', 2103 'Int32', 'UInt32', 'Int64', 'UInt64', 2104 'Counter', 'Addr', 'Tick', 'Percent', 2105 'TcpPort', 'UdpPort', 'EthernetAddr', 2106 'IpAddress', 'IpNetmask', 'IpWithPort', 2107 'MemorySize', 'MemorySize32', 2108 'Latency', 'Frequency', 'Clock', 'Voltage', 2109 'NetworkBandwidth', 'MemoryBandwidth', 2110 'AddrRange', 2111 'MaxAddr', 'MaxTick', 'AllMemory', 2112 'Time', 2113 'NextEthernetAddr', 'NULL', 2114 'MasterPort', 'SlavePort', 2115 'VectorMasterPort', 'VectorSlavePort'] 2116 2117import SimObject 2118